Support modulus operation (absolute value)
This adds support for computing the absolute value of a term along with an according unit test.
This commit is contained in:
parent
0608748349
commit
8c250f5c59
@ -5,7 +5,7 @@
|
||||
### Features
|
||||
|
||||
* more and advanced simplification rules
|
||||
* adds support for exponentiation operator
|
||||
* adds support for exponentiation (power) and modulus (absolute value)
|
||||
* new examples: prime numbers, permutation generator, and graph coloring (extended)
|
||||
|
||||
## 0.1.7 (2018-04-08)
|
||||
|
@ -293,6 +293,30 @@ struct String
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct UnaryOperation
|
||||
{
|
||||
enum class Operator
|
||||
{
|
||||
Absolute
|
||||
};
|
||||
|
||||
explicit UnaryOperation(Operator operator_, Term &&argument)
|
||||
: operator_{operator_},
|
||||
argument{std::move(argument)}
|
||||
{
|
||||
}
|
||||
|
||||
UnaryOperation(const UnaryOperation &other) = delete;
|
||||
UnaryOperation &operator=(const UnaryOperation &other) = delete;
|
||||
UnaryOperation(UnaryOperation &&other) noexcept = default;
|
||||
UnaryOperation &operator=(UnaryOperation &&other) noexcept = default;
|
||||
|
||||
Operator operator_;
|
||||
Term argument;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct Variable
|
||||
{
|
||||
explicit Variable(VariableDeclaration *declaration)
|
||||
|
@ -37,6 +37,7 @@ struct Or;
|
||||
struct Predicate;
|
||||
struct SpecialInteger;
|
||||
struct String;
|
||||
struct UnaryOperation;
|
||||
struct Variable;
|
||||
struct VariableDeclaration;
|
||||
using VariableDeclarationPointer = std::unique_ptr<VariableDeclaration>;
|
||||
@ -68,6 +69,7 @@ using Term = Clingo::Variant<
|
||||
Interval,
|
||||
SpecialInteger,
|
||||
String,
|
||||
UnaryOperation,
|
||||
Variable>;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -165,6 +165,14 @@ struct RecursiveTermVisitor
|
||||
return T::accept(string, term, std::forward<Arguments>(arguments)...);
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
ReturnType visit(UnaryOperation &unaryOperation, Term &term, Arguments &&... arguments)
|
||||
{
|
||||
unaryOperation.argument.accept(*this, unaryOperation.argument, std::forward<Arguments>(arguments)...);
|
||||
|
||||
return T::accept(unaryOperation, term, std::forward<Arguments>(arguments)...);
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
ReturnType visit(Variable &variable, Term &term, Arguments &&... arguments)
|
||||
{
|
||||
|
@ -382,6 +382,19 @@ struct TermEqualityVisitor
|
||||
: Tristate::False;
|
||||
}
|
||||
|
||||
Tristate visit(const UnaryOperation &unaryOperation, const Term &otherTerm)
|
||||
{
|
||||
if (!otherTerm.is<UnaryOperation>())
|
||||
return Tristate::Unknown;
|
||||
|
||||
const auto &otherUnaryOperation = otherTerm.get<UnaryOperation>();
|
||||
|
||||
if (unaryOperation.operator_ != otherUnaryOperation.operator_)
|
||||
return Tristate::Unknown;
|
||||
|
||||
return equal(unaryOperation.argument, otherUnaryOperation.argument);
|
||||
}
|
||||
|
||||
Tristate visit(const Variable &variable, const Term &otherTerm)
|
||||
{
|
||||
if (!otherTerm.is<Variable>())
|
||||
|
@ -48,6 +48,23 @@ ast::BinaryOperation::Operator translate(Clingo::AST::BinaryOperator binaryOpera
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::UnaryOperation::Operator translate(Clingo::AST::UnaryOperator unaryOperator, const Clingo::AST::Term &term)
|
||||
{
|
||||
switch (unaryOperator)
|
||||
{
|
||||
case Clingo::AST::UnaryOperator::Absolute:
|
||||
return ast::UnaryOperation::Operator::Absolute;
|
||||
case Clingo::AST::UnaryOperator::Minus:
|
||||
throw TranslationException(term.location, "binary operation “minus” currently unsupported");
|
||||
case Clingo::AST::UnaryOperator::Negation:
|
||||
throw TranslationException(term.location, "binary operation “negation” currently unsupported");
|
||||
}
|
||||
|
||||
throw TranslationException(term.location, "unknown unary operation");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ast::Term translate(const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -106,12 +123,6 @@ struct TermTranslateVisitor
|
||||
return ast::Term::make<ast::Variable>(ruleContext.freeVariables.back().get());
|
||||
}
|
||||
|
||||
std::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &, const Clingo::AST::Term &term, RuleContext &, const ast::VariableStack &)
|
||||
{
|
||||
throw TranslationException(term.location, "“unary operation” terms currently unsupported");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<ast::Term> visit(const Clingo::AST::BinaryOperation &binaryOperation, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
const auto operator_ = translate(binaryOperation.binary_operator, term);
|
||||
@ -121,6 +132,14 @@ struct TermTranslateVisitor
|
||||
return ast::Term::make<ast::BinaryOperation>(operator_, std::move(left), std::move(right));
|
||||
}
|
||||
|
||||
std::optional<ast::Term> visit(const Clingo::AST::UnaryOperation &unaryOperation, const Clingo::AST::Term &term, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
const auto operator_ = translate(unaryOperation.unary_operator, term);
|
||||
auto argument = translate(unaryOperation.argument, ruleContext, variableStack);
|
||||
|
||||
return ast::Term::make<ast::UnaryOperation>(operator_, std::move(argument));
|
||||
}
|
||||
|
||||
std::optional<ast::Term> visit(const Clingo::AST::Interval &interval, const Clingo::AST::Term &, RuleContext &ruleContext, const ast::VariableStack &variableStack)
|
||||
{
|
||||
auto left = translate(interval.left, ruleContext, variableStack);
|
||||
|
@ -53,6 +53,7 @@ output::ColorStream &print(output::ColorStream &stream, const Interval &interval
|
||||
output::ColorStream &print(output::ColorStream &stream, const Predicate &predicate, PrintContext &printContext);
|
||||
output::ColorStream &print(output::ColorStream &stream, const SpecialInteger &specialInteger, PrintContext &printContext);
|
||||
output::ColorStream &print(output::ColorStream &stream, const String &string, PrintContext &printContext);
|
||||
output::ColorStream &print(output::ColorStream &stream, const UnaryOperation &unaryOperation, PrintContext &printContext);
|
||||
output::ColorStream &print(output::ColorStream &stream, const Variable &variable, PrintContext &printContext);
|
||||
output::ColorStream &print(output::ColorStream &stream, const VariableDeclaration &variableDeclaration, PrintContext &printContext);
|
||||
|
||||
@ -282,6 +283,29 @@ inline output::ColorStream &print(output::ColorStream &stream, const String &str
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline output::ColorStream &print(output::ColorStream &stream, const UnaryOperation &unaryOperation, PrintContext &printContext)
|
||||
{
|
||||
switch (unaryOperation.operator_)
|
||||
{
|
||||
case UnaryOperation::Operator::Absolute:
|
||||
stream << "|";
|
||||
break;
|
||||
}
|
||||
|
||||
print(stream, unaryOperation.argument, printContext);
|
||||
|
||||
switch (unaryOperation.operator_)
|
||||
{
|
||||
case UnaryOperation::Operator::Absolute:
|
||||
stream << "|";
|
||||
break;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline output::ColorStream &print(output::ColorStream &stream, const Variable &variable, PrintContext &printContext)
|
||||
{
|
||||
assert(variable.declaration != nullptr);
|
||||
|
@ -159,6 +159,13 @@ String prepareCopy(const String &other)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnaryOperation prepareCopy(const UnaryOperation &other)
|
||||
{
|
||||
return UnaryOperation(other.operator_, prepareCopy(other.argument));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Variable prepareCopy(const Variable &other)
|
||||
{
|
||||
return Variable(other.declaration);
|
||||
@ -320,6 +327,12 @@ struct FixDanglingVariablesInTermVisitor
|
||||
{
|
||||
}
|
||||
|
||||
template <class... Arguments>
|
||||
void visit(UnaryOperation &unaryOperation, Arguments &&... arguments)
|
||||
{
|
||||
unaryOperation.argument.accept(*this, std::forward<Arguments>(arguments)...);
|
||||
}
|
||||
|
||||
void visit(Variable &variable, ScopedFormula &scopedFormula, VariableStack &variableStack,
|
||||
std::map<VariableDeclaration *, VariableDeclaration *> &replacements)
|
||||
{
|
||||
|
@ -178,6 +178,11 @@ struct CollectFreeVariablesVisitor
|
||||
{
|
||||
}
|
||||
|
||||
void visit(UnaryOperation &unaryOperation, VariableStack &variableStack, std::vector<VariableDeclaration *> &freeVariables)
|
||||
{
|
||||
unaryOperation.argument.accept(*this, variableStack, freeVariables);
|
||||
}
|
||||
|
||||
void visit(Variable &variable, VariableStack &variableStack, std::vector<VariableDeclaration *> &freeVariables)
|
||||
{
|
||||
if (variableStack.contains(*variable.declaration))
|
||||
|
@ -184,4 +184,12 @@ TEST_CASE("[completion] Rules are completed", "[completion]")
|
||||
|
||||
CHECK(output.str() == "forall V1, V2 not color(V1, V2)\nforall U1, U2, U3 (not color(U1, U2) or not color(U1, U3) or U2 = U3)\n");
|
||||
}
|
||||
|
||||
SECTION("absolute value operation")
|
||||
{
|
||||
input << "adj(X, Y) :- X = 1..n, Y = 1..n, |X - Y| = 1.";
|
||||
anthem::translate("input", input, context);
|
||||
|
||||
CHECK(output.str() == "forall V1, V2 (adj(V1, V2) <-> (V1 in 1..n and V2 in 1..n and |(V1 - V2)| = 1))\n");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user