From c95a832018b38e5eee0b9121fbcac5ad962de4cb Mon Sep 17 00:00:00 2001 From: Samuel Stante Date: Wed, 17 Jul 2024 15:59:26 +0200 Subject: [PATCH] add r_til_c test and fix parser --- src/core/elements/roles/til_c.cpp | 27 ++++++- src/core/parsers/syntactic/parser_def.hpp | 6 +- src/generator/rules/roles/til_c.cpp | 1 + tests/core/CMakeLists.txt | 1 + tests/core/r_til_c.cpp | 90 +++++++++++++++++++++++ 5 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 tests/core/r_til_c.cpp diff --git a/src/core/elements/roles/til_c.cpp b/src/core/elements/roles/til_c.cpp index 59e0dfe5..faa92e8d 100644 --- a/src/core/elements/roles/til_c.cpp +++ b/src/core/elements/roles/til_c.cpp @@ -5,8 +5,31 @@ namespace dlplan::core void TilCRole::compute_result(const RoleDenotation &role_denot, const ConceptDenotation &concept_denot, RoleDenotation &result) const { - //TODO - result = role_denot; + auto concept_object_indicies = concept_denot.to_vector(); + + std::unordered_set current(concept_object_indicies.begin(), concept_object_indicies.end()), next; + std::unordered_set visited(concept_object_indicies.begin(), concept_object_indicies.end()); + + std::unordered_map> inv_edges; + + for(auto& pair : role_denot.to_vector()) { + auto& [from, to] = pair; + inv_edges[to].insert(from); + } + + while(current.size() > 0) { + for(auto& to : current) { + for(auto& from : inv_edges[to]) { + if(! visited.contains(from)) { + result.insert(std::make_pair(from, to)); + next.insert(from); + } + } + } + visited.insert(next.begin(), next.end()); + current = next; + next.clear(); + } } RoleDenotation TilCRole::evaluate_impl(const State &state, DenotationsCaches &caches) const diff --git a/src/core/parsers/syntactic/parser_def.hpp b/src/core/parsers/syntactic/parser_def.hpp index 26191a6f..dbe52b5f 100644 --- a/src/core/parsers/syntactic/parser_def.hpp +++ b/src/core/parsers/syntactic/parser_def.hpp @@ -298,6 +298,8 @@ namespace dlplan::core::parser const auto restrict_role_def = lit("r_restrict") > lit('(') > role > lit(',') > concept_ > lit(')'); + const auto til_c_role_def = lit("r_til_c") > lit('(') > role > lit(',') > concept_ > lit(')'); + // Note: Need this semantic action to synthesize the empty struct const auto top_role_def = lit("r_top") >> x3::attr(ast::TopRole{}); @@ -316,7 +318,7 @@ namespace dlplan::core::parser const auto numerical_root_def = eps > numerical; // Note: non recursive comes first, i.e., primitive_role - const auto role_def = primitive_role | and_role | compose_role | diff_role | identity_role | inverse_role | not_role | or_role | restrict_role | top_role | transitive_closure_role | transitive_reflexive_closure_role; + const auto role_def = primitive_role | and_role | compose_role | diff_role | identity_role | inverse_role | not_role | or_role | restrict_role | til_c_role | top_role | transitive_closure_role | transitive_reflexive_closure_role; const auto role_root_def = eps > role; const auto concept_or_role_def = concept_ | role; @@ -336,7 +338,7 @@ namespace dlplan::core::parser empty_boolean, inclusion_boolean, nullary_boolean, all_concept, and_concept, bot_concept, diff_concept, equal_concept, not_concept, one_of_concept, or_concept, primitive_concept, projection_concept, some_concept, subset_concept, top_concept, concept_distance_numerical, count_numerical, role_distance_numerical, sum_concept_distance_numerical, sum_role_distance_numerical, - and_role, compose_role, diff_role, identity_role, inverse_role, not_role, or_role, primitive_role, restrict_role, top_role, transitive_closure_role, transitive_reflexive_closure_role) + and_role, compose_role, diff_role, identity_role, inverse_role, not_role, or_role, primitive_role, restrict_role, til_c_role, top_role, transitive_closure_role, transitive_reflexive_closure_role) /////////////////////////////////////////////////////////////////////////// // Annotation and Error handling diff --git a/src/generator/rules/roles/til_c.cpp b/src/generator/rules/roles/til_c.cpp index 18d5216b..753f9f00 100644 --- a/src/generator/rules/roles/til_c.cpp +++ b/src/generator/rules/roles/til_c.cpp @@ -7,6 +7,7 @@ namespace dlplan::generator::rules { void TilCRole::generate_impl(const core::States& states, int target_complexity, GeneratorData& data, core::DenotationsCaches& caches) { + return; //TODO if (target_complexity == 3) { diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 5a1d3811..5c95a00e 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -31,6 +31,7 @@ target_sources( r_inverse.cpp r_identity.cpp r_restrict.cpp + r_til_c.cpp r_not.cpp r_primitive.cpp r_top.cpp diff --git a/tests/core/r_til_c.cpp b/tests/core/r_til_c.cpp new file mode 100644 index 00000000..6132918d --- /dev/null +++ b/tests/core/r_til_c.cpp @@ -0,0 +1,90 @@ +#include + +#include "../utils/denotation.h" + +#include "../../include/dlplan/core.h" + +#include + +using namespace dlplan::core; + + +namespace dlplan::tests::core { + +TEST(DLPTests, RoleTilC) { + auto vocabulary = std::make_shared(); + auto predicate_0 = vocabulary->add_predicate("role", 2); + auto predicate_1 = vocabulary->add_predicate("concept", 1); + auto instance = std::make_shared(0, vocabulary); + auto atom_0 = instance->add_atom("role", {"A", "B"}); + auto atom_1 = instance->add_atom("role", {"B", "C"}); + auto atom_2 = instance->add_atom("role", {"C", "D"}); + auto atom_3 = instance->add_atom("concept", {"D"}); + + State state_0(0, instance, {atom_0, atom_1, atom_2, atom_3}); + + SyntacticElementFactory factory(vocabulary); + + auto role = factory.parse_role("r_til_c(r_primitive(role,0,1),c_primitive(concept,0))"); + std::cout << role->evaluate(state_0); + EXPECT_EQ(role->evaluate(state_0), create_role_denotation(*instance, {{"A", "B"},{"B", "C"},{"C", "D"}})); +} + +TEST(DLPTests, RoleTilCWithGrid) { + auto vocabulary = std::make_shared(); + auto predicate_0 = vocabulary->add_predicate("role", 2); + auto predicate_1 = vocabulary->add_predicate("concept", 1); + auto instance = std::make_shared(0, vocabulary); + + std::vector atoms; + + auto cell_str = [](int x, int y) { + std::stringstream ss; + ss << "C_" << x << "_" << y; + return ss.str(); + }; + + auto add = [&](int from_x, int from_y, int to_x, int to_y) { + auto atom = instance->add_atom("role", {cell_str(from_x, from_y), cell_str(to_x, to_y)}); + atoms.push_back(atom); + }; + + int size_x = 3, size_y = 3; + for(int y = 0; y < size_y; y++) { + for(int x = 0; x < size_x; x++) { + if(x > 0) add(x, y, x - 1, y); + if(x < size_x - 1) add(x, y, x + 1, y); + if(y > 0) add(x, y, x, y - 1); + if(y < size_y - 1) add(x, y, x, y + 1); + } + } + + atoms.push_back(instance->add_atom("concept", {cell_str(0, 0)})); + atoms.push_back(instance->add_atom("concept", {cell_str(size_x - 1, 0)})); + + State state_0(0, instance, atoms); + + SyntacticElementFactory factory(vocabulary); + + auto role = factory.parse_role("r_til_c(r_primitive(role,0,1),c_primitive(concept,0))"); + EXPECT_EQ(role->evaluate(state_0), create_role_denotation(*instance, { + {cell_str(0, 1), cell_str(0, 0)}, + {cell_str(0, 2), cell_str(0, 1)}, + + {cell_str(1, 0), cell_str(0, 0)}, + {cell_str(1, 0), cell_str(2, 0)}, + + {cell_str(1, 1), cell_str(0, 1)}, + {cell_str(1, 1), cell_str(1, 0)}, + {cell_str(1, 1), cell_str(2, 1)}, + + {cell_str(1, 2), cell_str(1, 1)}, + {cell_str(1, 2), cell_str(0, 2)}, + {cell_str(1, 2), cell_str(2, 2)}, + + {cell_str(2, 1), cell_str(2, 0)}, + {cell_str(2, 2), cell_str(2, 1)}, + })); +} + +}