diff --git a/src/anthem/HiddenPredicateElimination.cpp b/src/anthem/HiddenPredicateElimination.cpp index a3c72d8..31ed6c4 100644 --- a/src/anthem/HiddenPredicateElimination.cpp +++ b/src/anthem/HiddenPredicateElimination.cpp @@ -124,36 +124,40 @@ struct DetectCircularDependcyVisitor : public ast::RecursiveFormulaVisitor ...)” -PredicateReplacement findReplacement(const ast::PredicateSignature &predicateSignature, const ast::ForAll &forAll) +// Finds the replacement for predicates of the form “p(X1, ..., Xn) <-> q(X1, ..., Xn)” +PredicateReplacement findReplacement(const ast::PredicateSignature &predicateSignature, const ast::Predicate &predicate) { // Declare variable used, only used in debug mode (void)(predicateSignature); - // Form: “forall X1, ..., Xn p(X1, ..., Xn)” + assert(ast::matches(predicate, predicateSignature)); + // Replace with “#true” - if (forAll.argument.is()) - { - assert(ast::matches(forAll.argument.get(), predicateSignature)); + return {predicate, ast::Formula::make(true)}; +} - return {forAll.argument.get(), ast::Formula::make(true)}; - } +//////////////////////////////////////////////////////////////////////////////////////////////////// + +// Finds the replacement for predicates of the form “p(X1, ..., Xn) <-> not q(X1, ..., Xn)” +PredicateReplacement findReplacement(const ast::PredicateSignature &predicateSignature, const ast::Not ¬_) +{ + // Declare variable used, only used in debug mode + (void)(predicateSignature); + + assert(not_.argument.is()); + assert(ast::matches(not_.argument.get(), predicateSignature)); - // Form: “forall X1, ..., Xn (p(X1, ..., Xn) <-> ...)” // Replace with “#false” - if (forAll.argument.is()) - { - auto ¬Argument = forAll.argument.get().argument; + return {not_.argument.get(), ast::Formula::make(false)}; +} - assert(notArgument.is()); - assert(ast::matches(notArgument.get(), predicateSignature)); +//////////////////////////////////////////////////////////////////////////////////////////////////// - return {notArgument.get(), ast::Formula::make(false)}; - } - - assert(forAll.argument.is()); - - const auto &biconditional = forAll.argument.get(); +// Finds the replacement for predicates of the form “forall X1, ..., Xn (p(X1, ..., Xn) <-> ...)” +PredicateReplacement findReplacement(const ast::PredicateSignature &predicateSignature, const ast::Biconditional &biconditional) +{ + // Declare variable used, only used in debug mode + (void)(predicateSignature); assert(biconditional.left.is()); assert(ast::matches(biconditional.left.get(), predicateSignature)); @@ -167,19 +171,17 @@ PredicateReplacement findReplacement(const ast::PredicateSignature &predicateSig // Finds a replacement for a predicate that should be hidden PredicateReplacement findReplacement(const ast::PredicateSignature &predicateSignature, const ast::Formula &completedPredicateDefinition) { + // TODO: refactor if (completedPredicateDefinition.is()) - return findReplacement(predicateSignature, completedPredicateDefinition.get()); + return findReplacement(predicateSignature, completedPredicateDefinition.get().argument); + else if (completedPredicateDefinition.is()) + return findReplacement(predicateSignature, completedPredicateDefinition.get()); else if (completedPredicateDefinition.is()) - return {completedPredicateDefinition.get(), ast::Formula::make(true)}; + return findReplacement(predicateSignature, completedPredicateDefinition.get()); else if (completedPredicateDefinition.is()) - { - const auto ¬Argument = completedPredicateDefinition.get().argument; - assert(notArgument.is()); + return findReplacement(predicateSignature, completedPredicateDefinition.get()); - return {notArgument.get(), ast::Formula::make(false)}; - } - - throw CompletionException("invalid completed predicate definition for predicate “" + predicateSignature.name + "/" + std::to_string(predicateSignature.arity) + "”"); + throw CompletionException("unsupported completed definition for predicate “" + predicateSignature.name + "/" + std::to_string(predicateSignature.arity) + "” for hiding predicates"); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/tests/TestHiddenPredicateElimination.cpp b/tests/TestHiddenPredicateElimination.cpp index fa7a6b5..624768b 100644 --- a/tests/TestHiddenPredicateElimination.cpp +++ b/tests/TestHiddenPredicateElimination.cpp @@ -151,4 +151,24 @@ TEST_CASE("[hidden predicate elimination] Hidden predicates are correctly elimin CHECK(output.str() == "forall V1 (a(V1) <-> exists U1 (c(V1) = c(U1) and U1 in 1..4))\n"); } + + SECTION("simple propositions are hidden correctly") + { + input << + "p :- q.\n" + "q :- not r.\n" + "{s; t} :- p.\n" + ":- s, not t.\n" + ":- p, q, r.\n" + "#show s/0.\n" + "#show t/0."; + anthem::translate("input", input, context); + + // TODO: simplify further + CHECK(output.str() == + "(s <-> (not #false and s))\n" + "(t <-> (not #false and t))\n" + "not (s and not t)\n" + "not (not #false and not #false and #false)\n"); + } }