diff --git a/lib/pddl/tests/TestNormalization.cpp b/lib/pddl/tests/TestNormalization.cpp index 5df794c..8f2a2bb 100644 --- a/lib/pddl/tests/TestNormalization.cpp +++ b/lib/pddl/tests/TestNormalization.cpp @@ -224,3 +224,79 @@ TEST_CASE("[normalization] Universal quantifiers are correctly reduced", "[norma CHECK(dp->declaration->parameters[1]->name == "y"); } } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("[normalization] Negations are correctly normalized", "[normalization]") +{ + pddl::Tokenizer tokenizer; + pddl::Context context(std::move(tokenizer), ignoreWarnings); + + const auto domainFile = fs::path("data") / "normalization" / "normalization-4.pddl"; + context.tokenizer.read(domainFile); + auto description = pddl::parseDescription(context); + const auto normalizedDescription = pddl::normalize(std::move(description)); + + const auto &actions = normalizedDescription.domain->actions; + + SECTION("multiple negations are correctly eliminated") + { + const auto &p1 = actions[0]->precondition.value().get().get().get(); + CHECK(p1->declaration->name == "test-predicate-1"); + REQUIRE(p1->arguments.size() == 1); + CHECK(p1->arguments[0].get()->declaration->name == "x"); + + const auto &p2 = actions[1]->precondition.value().get().get>()->argument.get(); + CHECK(p2->declaration->name == "test-predicate-1"); + REQUIRE(p2->arguments.size() == 1); + CHECK(p2->arguments[0].get()->declaration->name == "x"); + } + + SECTION("“exists” statements with negations are correctly normalized") + { + const auto &dp = actions[2]->precondition.value().get().get>()->argument.get(); + CHECK(dp->declaration->existentialParameters.size() == 2); + const auto &dpp = dp->declaration->precondition.value().get().get().get(); + CHECK(dpp->declaration->name == "test-predicate-2"); + } + + SECTION("“forall” statements with negations are correctly normalized") + { + const auto &dp = actions[3]->precondition.value().get().get().get(); + CHECK(dp->declaration->existentialParameters.size() == 2); + const auto &dpp = dp->declaration->precondition.value().get().get().get(); + CHECK(dpp->declaration->name == "test-predicate-2"); + } + + SECTION("negations introduced by reduction are correctly normalized") + { + const auto &d = actions[4]->precondition.value().get().get().get(); + const auto &do_ = d->declaration->precondition.value().get>(); + REQUIRE(do_->arguments.size() == 2); + const auto &do1 = do_->arguments[0].get().get(); + REQUIRE(do1->declaration->name == "test-predicate-0"); + const auto &do2 = do_->arguments[1].get().get(); + REQUIRE(do2->declaration->name == "test-predicate-1"); + } + + SECTION("negated disjunctions are correctly normalized") + { + const auto &a = actions[5]->precondition.value().get>(); + REQUIRE(a->arguments.size() == 2); + const auto &a1 = a->arguments[0].get().get(); + REQUIRE(a1->declaration->name == "test-predicate-0"); + const auto &a2 = a->arguments[1].get().get(); + REQUIRE(a2->declaration->name == "test-predicate-1"); + } + + SECTION("negated conjunctions are correctly normalized") + { + const auto &d = actions[6]->precondition.value().get().get().get(); + const auto &do_ = d->declaration->precondition.value().get>(); + REQUIRE(do_->arguments.size() == 2); + const auto &do1 = do_->arguments[0].get().get(); + REQUIRE(do1->declaration->name == "test-predicate-0"); + const auto &do2 = do_->arguments[1].get().get(); + REQUIRE(do2->declaration->name == "test-predicate-1"); + } +} diff --git a/tests/data/normalization/normalization-4.pddl b/tests/data/normalization/normalization-4.pddl new file mode 100644 index 0000000..a2b1e22 --- /dev/null +++ b/tests/data/normalization/normalization-4.pddl @@ -0,0 +1,80 @@ +; tests that negations are correctly normalized +(define (domain test-normalization) + (:predicates + (test-predicate-0) + (test-predicate-1 ?x) + (test-predicate-2 ?x ?y)) + + ; multiple negations + (:action test-action-1 + :parameters + (?x) + :precondition + (not (not (not (not (not (not (test-predicate-1 ?x))))))) + :effect + (test-predicate-1 ?x)) + + ; multiple negations + (:action test-action-2 + :parameters + (?x) + :precondition + (not (not (not (not (not (test-predicate-1 ?x)))))) + :effect + (test-predicate-1 ?x)) + + ; negated “exists” statement + (:action test-action-3 + :parameters + (?x) + :precondition + (not (exists + (?x ?y) + (not (not (test-predicate-2 ?x ?y))))) + :effect + (test-predicate-1 ?x)) + + ; negated “forall” statement + (:action test-action-4 + :parameters + (?x) + :precondition + (not (forall + (?x ?y) + (not (not (not (test-predicate-2 ?x ?y)))))) + :effect + (test-predicate-1 ?x)) + + ; negations introduced by reduction + (:action test-action-5 + :parameters + (?x) + :precondition + (imply + (not (test-predicate-0)) + (test-predicate-1 ?x)) + :effect + (test-predicate-1 ?x)) + + ; negated disjunction + (:action test-action-6 + :parameters + (?x) + :precondition + (not (imply + (test-predicate-0) + (not (test-predicate-1 ?x)))) + :effect + (test-predicate-1 ?x)) + + ; negated conjunction + (:action test-action-7 + :parameters + (?x) + :precondition + (not (and + (not (test-predicate-0)) + (not (test-predicate-1 ?x)))) + :effect + (test-predicate-1 ?x)) +)