diff --git a/src/anthem/Simplification.cpp b/src/anthem/Simplification.cpp index cd3b6d5..1774504 100644 --- a/src/anthem/Simplification.cpp +++ b/src/anthem/Simplification.cpp @@ -466,6 +466,52 @@ struct SimplificationRuleImplicationFromDisjunction //////////////////////////////////////////////////////////////////////////////////////////////////// +struct SimplificationRuleNegatedComparison +{ + static constexpr const auto Description = "(not F [comparison] G) === (F [negated comparison] G)"; + + static SimplificationResult apply(ast::Formula &formula) + { + if (!formula.is()) + return SimplificationResult::Unchanged; + + auto ¬_ = formula.get(); + + if (!not_.argument.is()) + return SimplificationResult::Unchanged; + + auto &comparison = not_.argument.get(); + + switch (comparison.operator_) + { + case ast::Comparison::Operator::GreaterThan: + comparison.operator_ = ast::Comparison::Operator::LessEqual; + break; + case ast::Comparison::Operator::LessThan: + comparison.operator_ = ast::Comparison::Operator::GreaterEqual; + break; + case ast::Comparison::Operator::LessEqual: + comparison.operator_ = ast::Comparison::Operator::GreaterThan; + break; + case ast::Comparison::Operator::GreaterEqual: + comparison.operator_ = ast::Comparison::Operator::LessThan; + break; + case ast::Comparison::Operator::NotEqual: + comparison.operator_ = ast::Comparison::Operator::Equal; + break; + case ast::Comparison::Operator::Equal: + comparison.operator_ = ast::Comparison::Operator::NotEqual; + break; + } + + formula = std::move(comparison); + + return SimplificationResult::Simplified; + } +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + const auto simplifyWithDefaultRules = simplify < @@ -479,7 +525,8 @@ const auto simplifyWithDefaultRules = SimplificationRuleInWithPrimitiveArguments, SimplificationRuleSubsumptionInBiconditionals, SimplificationRuleDeMorganForConjunctions, - SimplificationRuleImplicationFromDisjunction + SimplificationRuleImplicationFromDisjunction, + SimplificationRuleNegatedComparison >; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/tests/TestCompletion.cpp b/tests/TestCompletion.cpp index eebcb01..f675df4 100644 --- a/tests/TestCompletion.cpp +++ b/tests/TestCompletion.cpp @@ -176,4 +176,12 @@ TEST_CASE("[completion] Rules are completed", "[completion]") CHECK(output.str() == "forall V1, V2, V3 (p(V1, V2, V3) <-> #true)\n"); } + + SECTION("negated comparisons") + { + input << ":- color(V, C1), color(V, C2), C1 != C2."; + anthem::translate("input", input, context); + + 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"); + } }