diff --git a/lib/pddl/tests/TestNormalization.cpp b/lib/pddl/tests/TestNormalization.cpp new file mode 100644 index 0000000..6b95127 --- /dev/null +++ b/lib/pddl/tests/TestNormalization.cpp @@ -0,0 +1,99 @@ +#include + +#include + +#include +#include +#include + +namespace fs = std::experimental::filesystem; + +const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST_CASE("[normalization] A simple PDDL description is preserved by normalization", "[normalization]") +{ + pddl::Tokenizer tokenizer; + pddl::Context context(std::move(tokenizer), ignoreWarnings); + + const auto domainFile = fs::path("data") / "normalization" / "normalization-1.pddl"; + context.tokenizer.read(domainFile); + auto description = pddl::parseDescription(context); + const auto normalizedDescription = pddl::normalize(std::move(description)); + + const auto &types = normalizedDescription.domain->types; + + REQUIRE(types.size() == 2); + + CHECK(types[0]->name == "block"); + CHECK(types[1]->name == "gripper"); + + const auto &predicates = normalizedDescription.domain->predicates; + + REQUIRE(predicates.size() == 3); + + CHECK(predicates[0]->name == "test-predicate-0"); + CHECK(predicates[0]->parameters.size() == 0); + CHECK(predicates[2]->name == "test-predicate-2"); + REQUIRE(predicates[2]->parameters.size() == 2); + CHECK(predicates[2]->parameters[0]->name == "x"); + REQUIRE(predicates[2]->parameters[0]->type); + CHECK(predicates[2]->parameters[0]->type.value().get()->declaration == types[0].get()); + CHECK(predicates[2]->parameters[1]->name == "y"); + REQUIRE(predicates[2]->parameters[1]->type); + CHECK(predicates[2]->parameters[1]->type.value().get()->declaration == types[1].get()); + + const auto &actions = normalizedDescription.domain->actions; + + REQUIRE(actions.size() == 2); + + CHECK(actions[0]->name == "test-action-1"); + CHECK(actions[0]->parameters.size() == 1); + CHECK(actions[0]->parameters[0]->name == "x"); + CHECK(actions[0]->parameters[0]->type.value().get()->declaration == types[0].get()); + CHECK(actions[0]->precondition.value().get().get().get()->declaration == predicates[1].get()); + CHECK(actions[0]->effect.value().get().get().get()->declaration == predicates[1].get()); + CHECK(actions[1]->name == "test-action-2"); + CHECK(actions[1]->parameters.size() == 2); + CHECK(actions[1]->parameters[0]->name == "x"); + CHECK(actions[1]->parameters[0]->type.value().get()->declaration == types[0].get()); + CHECK(actions[1]->parameters[1]->name == "y"); + CHECK(actions[1]->parameters[1]->type.value().get()->declaration == types[1].get()); + const auto &pre1And = actions[1]->precondition.value().get>(); + REQUIRE(pre1And->arguments.size() == 2); + const auto &pre1And1Not = pre1And->arguments[0].get>(); + CHECK(pre1And1Not->argument.get()->declaration == predicates[0].get()); + CHECK(pre1And->arguments[1].get().get()->declaration == predicates[2].get()); + + const auto &objects = normalizedDescription.problem.value()->objects; + + REQUIRE(objects.size() == 6); + + CHECK(objects[0]->name == "a"); + CHECK(objects[0]->type.value().get()->declaration == types[0].get()); + CHECK(objects[5]->name == "f"); + CHECK(objects[5]->type.value().get()->declaration == types[1].get()); + + const auto &initialState = normalizedDescription.problem.value()->initialState; + + REQUIRE(initialState.facts.size() == 5); + + CHECK(initialState.facts[0].get().get()->declaration == predicates[0].get()); + const auto &fact4 = initialState.facts[4].get().get(); + CHECK(fact4->declaration == predicates[2].get()); + REQUIRE(fact4->arguments.size() == 2); + CHECK(fact4->arguments[0].get()->declaration == objects[2].get()); + CHECK(fact4->arguments[1].get()->declaration == objects[5].get()); + + const auto &goal = normalizedDescription.problem.value()->goal.value(); + const auto &goalAnd = goal.get>(); + CHECK(goalAnd->arguments[0].get().get()->declaration == predicates[0].get()); + const auto &goalAnd1Not = goalAnd->arguments[1].get>(); + CHECK(goalAnd1Not->argument.get()->declaration == predicates[1].get()); + const auto &goalAnd2 = goalAnd->arguments[2].get().get(); + CHECK(goalAnd2->declaration == predicates[2].get()); + REQUIRE(goalAnd2->arguments.size() == 2); + CHECK(goalAnd2->arguments[0].get()->declaration == objects[1].get()); + CHECK(goalAnd2->arguments[1].get()->declaration == objects[5].get()); +} diff --git a/tests/data/normalization/normalization-1.pddl b/tests/data/normalization/normalization-1.pddl new file mode 100644 index 0000000..76ccdb2 --- /dev/null +++ b/tests/data/normalization/normalization-1.pddl @@ -0,0 +1,45 @@ +; tests that a simple PDDL description is preserved by normalization +(define (domain test-normalization) + (:requirements :typing) + (:types block gripper) + + (:predicates + (test-predicate-0) + (test-predicate-1 ?x - block) + (test-predicate-2 ?x - block ?y - gripper)) + + (:action test-action-1 + :parameters + (?x - block) + :precondition + (test-predicate-1 ?x) + :effect + (test-predicate-1 ?x)) + + (:action test-action-2 + :parameters + (?x - block ?y - gripper) + :precondition + (and + (not (test-predicate-0)) + (test-predicate-2 ?x ?y)) + :effect + (test-predicate-2 ?x ?y)) +) + +(define (problem test-normalization) + (:domain test-normalization) + + (:objects a b c d - block e f - gripper) + + (:init + (test-predicate-0) + (test-predicate-1 a) + (test-predicate-1 d) + (test-predicate-2 a e) + (test-predicate-2 c f)) + + (:goal (and + (test-predicate-0) + (not (test-predicate-1 d)) + (test-predicate-2 b f))))