Implemented choice rules.

This commit is contained in:
Patrick Lühne 2017-03-06 15:40:23 +01:00
parent c819eeabfc
commit 70cb79b233
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
3 changed files with 57 additions and 5 deletions

View File

@ -19,12 +19,16 @@ struct Context
void reset() void reset()
{ {
headTerms.clear(); headTerms.clear();
isChoiceRule = false;
numberOfHeadLiterals = 0;
auxiliaryBodyLiteralID = 1; auxiliaryBodyLiteralID = 1;
} }
output::Logger logger; output::Logger logger;
std::vector<const Clingo::AST::Term *> headTerms; std::vector<const Clingo::AST::Term *> headTerms;
bool isChoiceRule = false;
size_t numberOfHeadLiterals = 0;
size_t auxiliaryBodyLiteralID = 1; size_t auxiliaryBodyLiteralID = 1;
}; };

View File

@ -86,15 +86,20 @@ struct LiteralCollectFunctionTermsVisitor
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: rename, because not only terms are collected anymore
struct HeadLiteralCollectFunctionTermsVisitor struct HeadLiteralCollectFunctionTermsVisitor
{ {
void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context) void visit(const Clingo::AST::Literal &literal, const Clingo::AST::HeadLiteral &, Context &context)
{ {
context.numberOfHeadLiterals = 1;
literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, context); literal.data.accept(LiteralCollectFunctionTermsVisitor(), literal, context);
} }
void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context) void visit(const Clingo::AST::Disjunction &disjunction, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
{ {
context.numberOfHeadLiterals = disjunction.elements.size();
for (const auto &conditionalLiteral : disjunction.elements) for (const auto &conditionalLiteral : disjunction.elements)
{ {
if (!conditionalLiteral.condition.empty()) if (!conditionalLiteral.condition.empty())
@ -104,9 +109,21 @@ struct HeadLiteralCollectFunctionTermsVisitor
} }
} }
void visit(const Clingo::AST::Aggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context) void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
{ {
throwErrorAtLocation(headLiteral.location, "“aggregate” head literals currently unsupported", context); context.isChoiceRule = true;
context.numberOfHeadLiterals = aggregate.elements.size();
if (aggregate.left_guard || aggregate.right_guard)
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards not allowed", context);
for (const auto &conditionalLiteral : aggregate.elements)
{
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional literals in aggregates currently unsupported", context);
conditionalLiteral.literal.data.accept(LiteralCollectFunctionTermsVisitor(), conditionalLiteral.literal, context);
}
} }
void visit(const Clingo::AST::HeadAggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context) void visit(const Clingo::AST::HeadAggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
@ -244,9 +261,23 @@ struct HeadLiteralPrintSubstitutedVisitor
} }
} }
void visit(const Clingo::AST::Aggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context) void visit(const Clingo::AST::Aggregate &aggregate, const Clingo::AST::HeadLiteral &headLiteral, Context &context)
{ {
throwErrorAtLocation(headLiteral.location, "“aggregate” head literals currently unsupported", context); if (aggregate.left_guard || aggregate.right_guard)
throwErrorAtLocation(headLiteral.location, "aggregates with left or right guards not allowed", context);
for (auto i = aggregate.elements.cbegin(); i != aggregate.elements.cend(); i++)
{
const auto &conditionalLiteral = *i;
if (!conditionalLiteral.condition.empty())
throwErrorAtLocation(headLiteral.location, "conditional head literals currently unsupported", context);
if (i != aggregate.elements.cbegin())
context.logger.outputStream() << " " << Clingo::AST::BinaryOperator::Or << " ";
visit(conditionalLiteral.literal, headLiteral, context);
}
} }
void visit(const Clingo::AST::HeadAggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context) void visit(const Clingo::AST::HeadAggregate &, const Clingo::AST::HeadLiteral &headLiteral, Context &context)

View File

@ -53,7 +53,7 @@ struct StatementVisitor
} }
} }
if (rule.body.empty() && context.headTerms.empty()) if (rule.body.empty() && context.headTerms.empty() && !context.isChoiceRule)
outputStream << Clingo::AST::Boolean({true}); outputStream << Clingo::AST::Boolean({true});
else else
{ {
@ -72,6 +72,23 @@ struct StatementVisitor
} }
} }
// Handle choice rules
if (context.isChoiceRule)
{
const bool isFirstOutput = rule.body.empty() && context.headTerms.empty();
if (!isFirstOutput)
outputStream << " " << Clingo::AST::BinaryOperator::And << " ";
if (context.numberOfHeadLiterals > 1 && !isFirstOutput)
outputStream << "(";
rule.head.data.accept(HeadLiteralPrintSubstitutedVisitor(), rule.head, context);
if (context.numberOfHeadLiterals > 1 && !isFirstOutput)
outputStream << ")";
}
outputStream << " " << output::Operator("->") << " "; outputStream << " " << output::Operator("->") << " ";
// Print consequent of the implication // Print consequent of the implication