Commit 741010d5 authored by Alejandro Suarez Hernandez's avatar Alejandro Suarez Hernandez
Browse files

added orquery

parent 9f4ea3d3
......@@ -90,6 +90,8 @@ BOOST_AUTO_TEST_CASE(test_parse_complex_expressions)
std::string str2("at(X, Y), at(Z, Y), !=(boat, X)");
std::string str3("fixes(X, Y), \\+(precedes(_1, X), occluded_by(X, _2))");
std::string str4("\\+(\\+q(X), \\+q(Y), \\+r())");
std::string str5("(\\+q(X), q(Y)); \\+r()");
std::string str6("\\+(\\+q(X); \\+q(Y)), \\+r()");
Query::Ptr q1 = parse_query(str1);
BOOST_REQUIRE(q1);
BOOST_CHECK_EQUAL(q1->to_str(), "at(X,Y),at(Z,Y)");
......@@ -102,6 +104,12 @@ BOOST_AUTO_TEST_CASE(test_parse_complex_expressions)
Query::Ptr q4 = parse_query(str4);
BOOST_REQUIRE(q4);
BOOST_CHECK_EQUAL(q4->to_str(), "\\+(\\+q(X),\\+q(Y),\\+r())");
Query::Ptr q5 = parse_query(str5);
BOOST_REQUIRE(q5);
BOOST_CHECK_EQUAL(q5->to_str(), "(\\+q(X),q(Y));\\+r()");
Query::Ptr q6 = parse_query(str6);
BOOST_REQUIRE(q6);
BOOST_CHECK_EQUAL(q6->to_str(), "\\+(\\+q(X);\\+q(Y)),\\+r()");
}
BOOST_AUTO_TEST_CASE(test_parse_effects)
......
......@@ -57,7 +57,7 @@ BOOST_AUTO_TEST_CASE(simple_query_test_sat)
{
auto state = PlanState::create({Predicate("p","a","b"), Predicate("p","a","c"),
Predicate("p","d","a"), Predicate("q","w"), Predicate("q", "s")});
INFO(state);
INFO(*state);
Query::Ptr q1 = SimpleQuery(Predicate("p", "a", "X")).bind(state);
Query::Ptr q2 = SimpleQuery(Predicate("q", "w")).bind(state);
INFO("q1: " << *q1 << ", q2: " << *q2);
......@@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE(simple_query_test_unsat)
{
auto state = PlanState::create({Predicate("p","a","b"), Predicate("p","a","c"),
Predicate("p","d","a"), Predicate("q","w"), Predicate("q", "s")});
INFO(state);
INFO(*state);
Query::Ptr q1 = SimpleQuery(Predicate("p", "c", "X")).bind(state);
Query::Ptr q2 = SimpleQuery(Predicate("p", "a", "d")).bind(state);
INFO("q1: " << *q1 << ", q2: " << *q2);
......@@ -87,7 +87,7 @@ BOOST_AUTO_TEST_CASE(not_query_test)
{
auto state = PlanState::create({Predicate("p","a","b"), Predicate("p","a","c"),
Predicate("p","d","a"), Predicate("q","w"), Predicate("q", "s")});
INFO(state);
INFO(*state);
Query::Ptr q1 = std::make_shared<SimpleQuery>(Predicate("p", "a", "X"));
Query::Ptr q2 = std::make_shared<SimpleQuery>(Predicate("p", "Z", "d"));
Query::Ptr q1neg = NotQuery(q1).bind(state);
......@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(and_query_test_sat)
{
auto state = PlanState::create({Predicate("p","a","b"), Predicate("p","a","c"),
Predicate("p", "b", "d"), Predicate("p","d","a"), Predicate("q","b")});
INFO("state: " << state);
INFO("state: " << *state);
Query::Ptr q1 = std::make_shared<SimpleQuery>(Predicate("p", "X", "Y"));
Query::Ptr q2 = std::make_shared<SimpleQuery>(Predicate("q", "X"));
Query::Ptr not1 = std::make_shared<NotQuery>(q2);
......@@ -116,3 +116,36 @@ BOOST_AUTO_TEST_CASE(and_query_test_sat)
BOOST_REQUIRE(not and1->next_solution());
}
BOOST_AUTO_TEST_CASE(or_query_test_sat)
{
auto state = PlanState::create({Predicate("p","a","b"), Predicate("p","a","c"),
Predicate("p", "b", "d"), Predicate("p","d","a"), Predicate("q","b")});
INFO("state: " << *state);
Query::Ptr q1 = std::make_shared<SimpleQuery>(Predicate("p", "X", "X"));
Query::Ptr q2 = std::make_shared<SimpleQuery>(Predicate("q", "X"));
Query::Ptr q3 = std::make_shared<SimpleQuery>(Predicate("p", "X", "_"));
Query::Ptr or1 = OrQuery(q1, q2).bind(state);
Query::Ptr or2 = OrQuery(q1, q3).bind(state);
INFO("or1: " << *or1);
INFO("or2: " << *or2);
BOOST_REQUIRE(or1->next_solution());
BOOST_CHECK_EQUAL(or1->get_solution().to_str(), "{}");
BOOST_REQUIRE(not or1->next_solution());
BOOST_REQUIRE(or2->next_solution());
BOOST_CHECK_EQUAL(or2->get_solution().to_str(), "{}");
BOOST_REQUIRE(not or2->next_solution());
}
BOOST_AUTO_TEST_CASE(or_query_test_unsat)
{
auto state = PlanState::create({Predicate("p","a","b"), Predicate("p","a","c"),
Predicate("p", "b", "d"), Predicate("p","d","a"), Predicate("q","b")});
INFO("state: " << *state);
Query::Ptr q1 = std::make_shared<SimpleQuery>(Predicate("p", "X", "X"));
Query::Ptr q2 = std::make_shared<SimpleQuery>(Predicate("q", "b"));
Query::Ptr not1 = std::make_shared<NotQuery>(q2);
Query::Ptr or1 = OrQuery(q1, not1).bind(state);
INFO("or1: " << *or1);
BOOST_REQUIRE(not or1->next_solution());
}
......@@ -62,6 +62,11 @@ TokenV decompose(const std::string& in)
tokens.push_back({"COMMA", ""});
++cursor;
}
else if (in_clean[cursor] == ';')
{
tokens.push_back({"SEMICOLON", ""});
++cursor;
}
else
{
std::size_t end = in_clean.find_first_of(",()\\", cursor);
......@@ -153,7 +158,8 @@ Predicate::Ptr parse_predicate(const TokenV& tokens, std::size_t& cursor)
Query::Ptr parse_query(const TokenV& tokens, std::size_t& cursor)
{
enum State {EXPECTING_PRED_OR_PAR, EXPECTING_PAR_EXPR,
EXPECTING_PAR_CLOSE, EXPECTING_COMMA_OR_END, EXPECTING_END_EXPR, OK, KO};
EXPECTING_PAR_CLOSE, EXPECTING_PUNCT_OR_END, EXPECTING_AND_2ND,
EXPECTING_OR_2ND, OK, KO};
State state = EXPECTING_PRED_OR_PAR;
bool negated = false;
Query::Ptr query = nullptr;
......@@ -181,7 +187,7 @@ Query::Ptr parse_query(const TokenV& tokens, std::size_t& cursor)
query = std::make_shared<SimpleQuery>(*predicate);
}
if (negated) query = std::make_shared<NotQuery>(query);
state = EXPECTING_COMMA_OR_END;
state = EXPECTING_PUNCT_OR_END;
}
else if (token.first == "PAR_OPEN")
{
......@@ -201,26 +207,37 @@ Query::Ptr parse_query(const TokenV& tokens, std::size_t& cursor)
case EXPECTING_PAR_CLOSE:
if (token.first == "PAR_CLOSE")
{
state = EXPECTING_COMMA_OR_END;
state = EXPECTING_PUNCT_OR_END;
++idx;
}
else state = KO;
break;
case EXPECTING_COMMA_OR_END:
case EXPECTING_PUNCT_OR_END:
if (token.first == "COMMA")
{
state = EXPECTING_END_EXPR;
state = EXPECTING_AND_2ND;
++idx;
}
else if (token.first == "SEMICOLON")
{
state = EXPECTING_OR_2ND;
++idx;
}
else state = OK;
break;
case EXPECTING_END_EXPR:
case EXPECTING_AND_2ND:
if (Query::Ptr query_snd = parse_query(tokens, idx))
{
query = std::make_shared<AndQuery>(query, query_snd);
state = OK;
}
break;
case EXPECTING_OR_2ND:
if (Query::Ptr query_snd = parse_query(tokens, idx))
{
query = std::make_shared<OrQuery>(query, query_snd);
state = OK;
}
default:
/* do nothing */
break;
......
......@@ -122,7 +122,8 @@ bool SimpleQuery::unify(const Predicate& goal)
std::string NotQuery::to_str() const
{
if (std::dynamic_pointer_cast<const AndQuery>(neg_))
if (std::dynamic_pointer_cast<const AndQuery>(neg_) or
std::dynamic_pointer_cast<const OrQuery>(neg_))
{
return std::string("\\+(") + neg_->to_str() + ')';
}
......@@ -140,7 +141,7 @@ bool NotQuery::next_solution()
Query::Ptr NotQuery::bind(const PlanState::Ptr& state) const
{
return std::make_shared<NotQuery>(neg_->bind(state));
}
}
void NotQuery::reset(const Substitution& sigma0)
{
......@@ -150,11 +151,26 @@ void NotQuery::reset(const Substitution& sigma0)
}
//// AndQuery methods
// AndQuery methods
std::string AndQuery::to_str() const
{
return q1_->to_str() + ',' + q2_->to_str();
std::string fst_part = q1_->to_str(), snd_part = q2_->to_str();
if (not (std::dynamic_pointer_cast<const AndQuery>(q1_) or
std::dynamic_pointer_cast<const ComparisonQuery>(q1_) or
std::dynamic_pointer_cast<const SimpleQuery>(q1_) or
std::dynamic_pointer_cast<const NotQuery>(q1_)))
{
fst_part = '(' + fst_part + ')';
}
if (not (std::dynamic_pointer_cast<const AndQuery>(q2_) or
std::dynamic_pointer_cast<const ComparisonQuery>(q2_) or
std::dynamic_pointer_cast<const SimpleQuery>(q2_) or
std::dynamic_pointer_cast<const NotQuery>(q2_)))
{
snd_part = '(' + snd_part + ')';
}
return fst_part + ',' + snd_part;
}
bool AndQuery::next_solution()
......@@ -186,6 +202,51 @@ Query::Ptr AndQuery::bind(const PlanState::Ptr& state) const
void AndQuery::reset(const Substitution& sigma0)
{
q1_->reset(sigma0);
first_fixed_ = false;
}
// OrQuery methods
std::string OrQuery::to_str() const
{
std::string fst_part = q1_->to_str(), snd_part = q2_->to_str();
if (not (std::dynamic_pointer_cast<const OrQuery>(q1_) or
std::dynamic_pointer_cast<const ComparisonQuery>(q1_) or
std::dynamic_pointer_cast<const SimpleQuery>(q1_) or
std::dynamic_pointer_cast<const NotQuery>(q1_)))
{
fst_part = '(' + fst_part + ')';
}
if (not (std::dynamic_pointer_cast<const OrQuery>(q2_) or
std::dynamic_pointer_cast<const ComparisonQuery>(q2_) or
std::dynamic_pointer_cast<const SimpleQuery>(q2_) or
std::dynamic_pointer_cast<const NotQuery>(q2_)))
{
snd_part = '(' + snd_part + ')';
}
return fst_part + ';' + snd_part;
}
bool OrQuery::next_solution()
{
if (done_) return false;
done_ = true;
if (q1_->next_solution()) return true;
q2_->reset(sigma_); // reset q2_ lazily
return q2_->next_solution();
}
Query::Ptr OrQuery::bind(const PlanState::Ptr& state) const
{
return std::make_shared<OrQuery>(q1_->bind(state), q2_->bind(state));
}
void OrQuery::reset(const Substitution& sigma0)
{
q1_->reset(sigma0);
// no need to reset q2_ now, we can wait until the first query fails.
sigma_ = sigma0;
done_ = false;
}
}
......
......@@ -11,6 +11,7 @@ class ComparisonQuery;
class SimpleQuery;
class NotQuery;
class AndQuery;
class OrQuery;
class Query : public Stringifiable
......@@ -18,6 +19,7 @@ class Query : public Stringifiable
public:
typedef std::shared_ptr<Query> Ptr;
typedef std::shared_ptr<const Query> ConstPtr;
virtual bool next_solution() =0;
......@@ -42,6 +44,7 @@ class ComparisonQuery : public Query
public:
typedef std::shared_ptr<ComparisonQuery> Ptr;
typedef std::shared_ptr<const ComparisonQuery> ConstPtr;
ComparisonQuery(const Predicate& cmp);
......@@ -65,6 +68,7 @@ class SimpleQuery : public Query
public:
typedef std::shared_ptr<SimpleQuery> Ptr;
typedef std::shared_ptr<const SimpleQuery> ConstPtr;
SimpleQuery(const Predicate& pattern) : pattern_(pattern) {}
......@@ -86,11 +90,13 @@ class SimpleQuery : public Query
bool unify(const Predicate& goal);
};
class NotQuery : public Query
{
public:
typedef std::shared_ptr<NotQuery> Ptr;
typedef std::shared_ptr<const NotQuery> ConstPtr;
NotQuery(const Query::Ptr& neg) : neg_(neg), done_(false) {}
......@@ -108,11 +114,13 @@ class NotQuery : public Query
bool done_;
};
class AndQuery : public Query
{
public:
typedef std::shared_ptr<NotQuery> Ptr;
typedef std::shared_ptr<AndQuery> Ptr;
typedef std::shared_ptr<const AndQuery> ConstPtr;
AndQuery(const Query::Ptr& q1, const Query::Ptr& q2) :
q1_(q1), q2_(q2), first_fixed_(false) {}
......@@ -131,6 +139,33 @@ class AndQuery : public Query
bool first_fixed_;
};
class OrQuery : public Query
{
public:
typedef std::shared_ptr<OrQuery> Ptr;
typedef std::shared_ptr<const OrQuery> ConstPtr;
OrQuery(const Query::Ptr& q1, const Query::Ptr& q2) :
q1_(q1), q2_(q2), done_(false) {}
virtual std::string to_str() const override;
virtual bool next_solution() override;
Query::Ptr bind(const PlanState::Ptr& state) const override;
virtual void reset(const Substitution& sigma0) override;
private:
Query::Ptr q1_, q2_;
bool done_;
};
} /* end namespace imagine-planner */
#endif
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment