From 85769d6e7777af783dc2ccd32c7478a556da89dc Mon Sep 17 00:00:00 2001 From: Alejandro Suarez Hernandez <asuarez@iri.upc.edu> Date: Mon, 2 Oct 2017 21:34:25 +0200 Subject: [PATCH] SimpleQuery class --- src/CMakeLists.txt | 4 +-- src/examples/CMakeLists.txt | 6 ++++ src/examples/queries_test.cpp | 47 ++++++++++++++++++++++++++++ src/examples/types_test.cpp | 16 +++++++++- src/queries.cpp | 58 +++++++++++++++++++++++++++++++++++ src/queries.h | 47 ++++++++++++++++++++++++++++ src/types.cpp | 3 +- src/types.h | 6 ++-- 8 files changed, 181 insertions(+), 6 deletions(-) create mode 100644 src/examples/queries_test.cpp create mode 100644 src/queries.cpp create mode 100644 src/queries.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f26028..c60988e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,7 +1,7 @@ # driver source files -SET(sources imagine-planner.cpp types.cpp) +SET(sources imagine-planner.cpp types.cpp queries.cpp) # application header files -SET(headers imagine-planner.h types.h) +SET(headers imagine-planner.h types.h queries.h) # Boost FIND_PACKAGE(Boost COMPONENTS system filesystem unit_test_framework REQUIRED) # Swi-pl diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index 1d47022..27851e0 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -10,4 +10,10 @@ TARGET_LINK_LIBRARIES(types_test ${Boost_SYSTEM_LIBRARY} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) +ADD_EXECUTABLE(queries_test queries_test.cpp) +TARGET_LINK_LIBRARIES(queries_test + imagine-planner + ${Boost_FILESYSTEM_LIBRARY} + ${Boost_SYSTEM_LIBRARY} + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}) diff --git a/src/examples/queries_test.cpp b/src/examples/queries_test.cpp new file mode 100644 index 0000000..e520790 --- /dev/null +++ b/src/examples/queries_test.cpp @@ -0,0 +1,47 @@ +#define BOOST_TEST_MODULE Types Test +#define BOOST_TEST_DYN_LINK +#include <boost/test/unit_test.hpp> + +#include "queries.h" +#include <iostream> +using namespace imagine_planner; + +#if 0 // Set to 1 if __PRETTY_FUNCTION__ macro is not available +#define __PRETTY_FUNCTION__ __func__ +#endif + +#if 1 +#define INFO(x)\ + std::cout << "\e[1m\e[32m\e[4m" << __PRETTY_FUNCTION__ << " [" << __LINE__ << "]" << "\e[24m: " << x << "\e[0m" << std::endl; +#else +#define INFO(x) +#endif + +BOOST_AUTO_TEST_CASE(simple_query_test_sat) +{ + PlanState state({Predicate("p","a","b"), Predicate("p","a","c"), + Predicate("p","d","a"), Predicate("q","w"), Predicate("q", "s")}); + INFO(state); + SimpleQuery q1(state, Predicate("p", "a", "X")); + SimpleQuery q2(state, Predicate("q", "w")); + BOOST_REQUIRE(q1.next_solution()); + BOOST_CHECK_EQUAL(q1.get_solution().to_str(), "{\n X -> b\n}"); + BOOST_REQUIRE(q1.next_solution()); + BOOST_CHECK_EQUAL(q1.get_solution().to_str(), "{\n X -> c\n}"); + BOOST_REQUIRE(not q1.next_solution()); + BOOST_REQUIRE(q2.next_solution()); + BOOST_CHECK_EQUAL(q2.get_solution().to_str(), "{}"); + BOOST_CHECK(not q1.next_solution()); +} + +BOOST_AUTO_TEST_CASE(simple_query_test_unsat) +{ + PlanState state({Predicate("p","a","b"), Predicate("p","a","c"), + Predicate("p","d","a"), Predicate("q","w"), Predicate("q", "s")}); + INFO(state); + SimpleQuery q1(state, Predicate("p", "c", "X")); + SimpleQuery q2(state, Predicate("p", "a", "d")); + BOOST_REQUIRE(not q1.next_solution()); + BOOST_REQUIRE(not q2.next_solution()); +} + diff --git a/src/examples/types_test.cpp b/src/examples/types_test.cpp index f2d8c65..e220a3b 100644 --- a/src/examples/types_test.cpp +++ b/src/examples/types_test.cpp @@ -241,6 +241,20 @@ BOOST_AUTO_TEST_CASE(substitution_test) BOOST_AUTO_TEST_CASE(planstate_test) { PlanState state({Predicate("p", "x", "y"), Predicate("q", "y"), Predicate("r")}); - INFO(state); + PlanState state_(state), state__(state); + PlanState state2(state); + state__.remove(Predicate("p", "x", "y")); + state2.put(Predicate("q", "z")); + INFO("state: " << state << " (" << state.hash() << ')'); + INFO("state_: " << state_ << " (" << state_.hash() << ')'); + INFO("state__: " << state__ << " (" << state__.hash() << ')'); + INFO("state2: " << state2 << " (" << state2.hash() << ')'); + BOOST_CHECK_EQUAL(state, state_); + BOOST_CHECK_NE(state, state__); + BOOST_CHECK_NE(state, state2); + BOOST_CHECK(state.subset_of(state2)); + BOOST_CHECK(state__.subset_of(state)); + BOOST_CHECK(not state.subset_of(state__)); + BOOST_CHECK(not state2.subset_of(state)); } diff --git a/src/queries.cpp b/src/queries.cpp new file mode 100644 index 0000000..b6ddecd --- /dev/null +++ b/src/queries.cpp @@ -0,0 +1,58 @@ +#include "queries.h" + +namespace imagine_planner +{ + +bool SimpleQuery::unify(const Predicate& goal) +{ + assignment_.clear(); + if (goal.arity() != target_.arity()) return false; + if (goal.get_name() != target_.get_name()) return false; + for (int idx = 0; idx < goal.arity(); ++idx) + { + const TermWrapper& term1 = target_.get_arguments()[idx]; + const TermWrapper& term2 = goal.get_arguments()[idx]; + if (term1.is_ground()) + { + if (term1 != term2) return false; + } + else if (const Term* assig = assignment_.get(term1.to_str())) + { + if (*assig != *term2.get_term()) return false; + } + else + { + assignment_.put(term1.to_str(), term2); + } + } + return true; +} + +SimpleQuery::SimpleQuery(const PlanState& state, const Predicate& target) : + state_(state), target_(target) +{ + cursor_ = state_.begin(); +} + +bool SimpleQuery::next_solution() +{ + if (cursor_ != state_.end() and target_.is_ground()) + { + cursor_ = state_.end(); + return state_.has(target_); + } + + while (cursor_ != state_.end()) + { + if (unify(*cursor_)) + { + ++cursor_; + return true; + } + ++cursor_; + } + return false; +} + +} + diff --git a/src/queries.h b/src/queries.h new file mode 100644 index 0000000..2750220 --- /dev/null +++ b/src/queries.h @@ -0,0 +1,47 @@ +#ifndef _LIBIMAGINE_PLANNER_QUERIES_H_ +#define _LIBIMAGINE_PLANNER_QUERIES_H_ + +#include "types.h" + +namespace imagine_planner +{ + +class Query +{ + public: + virtual ~Query() {}; + + virtual bool next_solution() =0; + + virtual const Substitution& get_solution() const=0; +}; + +class SimpleQuery : public Query +{ + private: + const PlanState& state_; + Predicate target_; + Substitution assignment_; + PlanState::CIter cursor_; + + bool unify(const Predicate& goal); + + public: + SimpleQuery(const PlanState& state, const Predicate& target); + + virtual bool next_solution() override; + + const Substitution& get_solution() const { return assignment_; } + +}; + +class NotQuery : public Query +{ + private: + Query q_; +}; + +} /* end namespace imagine-planner */ + +#endif + diff --git a/src/types.cpp b/src/types.cpp index 7ed05af..704e501 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -109,6 +109,8 @@ TermWrapper::~TermWrapper() delete term_; } +TermV create_term_v() { return TermV(); } + // Predicate Predicate::Predicate(const std::string& name, const TermV& arguments) : @@ -306,7 +308,6 @@ std::size_t PlanState::hash() const return acc; } - bool PlanState::subset_of(const PlanState& other) const { if (predicates_.size() > other.predicates_.size()) return false; diff --git a/src/types.h b/src/types.h index ce5a13a..24b9f45 100644 --- a/src/types.h +++ b/src/types.h @@ -191,7 +191,7 @@ class TermWrapper : public Stringifiable, typedef std::vector<TermWrapper> TermV; -TermV create_term_v() { return TermV(); } +TermV create_term_v(); template <typename First, typename... Args> TermV create_term_v(const First& fst, Args... args) @@ -261,6 +261,8 @@ class Substitution : public Stringifiable void remove(const std::string& varname); + void clear() { sigma_.clear(); } + void operator+=(const Substitution& other); void operator-=(const Substitution& other); @@ -355,6 +357,6 @@ struct hash<imagine_planner::Hashable> std::size_t operator()(const imagine_planner::Hashable& hashable) const; }; -} +} /* end std namespace */ #endif -- GitLab