diff --git a/include/plasp/pddl/expressions/NAry.h b/include/plasp/pddl/expressions/NAry.h index 3122ef0..1c749e3 100644 --- a/include/plasp/pddl/expressions/NAry.h +++ b/include/plasp/pddl/expressions/NAry.h @@ -178,7 +178,7 @@ inline ExpressionPointer NAry::simplified() } // TODO: recognize tautologies - // TODO: introduce handle boolean values + // TODO: introduce/handle boolean values return this; } diff --git a/include/plasp/pddl/expressions/Quantified.h b/include/plasp/pddl/expressions/Quantified.h index 15aa954..e7a1701 100644 --- a/include/plasp/pddl/expressions/Quantified.h +++ b/include/plasp/pddl/expressions/Quantified.h @@ -31,8 +31,12 @@ class Quantified: public ExpressionCRTP void setArgument(ExpressionPointer argument); ExpressionPointer argument() const; + Variables &variables(); + const Variables &variables() const; + ExpressionPointer reduced() override; ExpressionPointer negationNormalized() override; + ExpressionPointer simplified() override; void print(std::ostream &ostream) const override; @@ -98,6 +102,22 @@ ExpressionPointer Quantified::argument() const //////////////////////////////////////////////////////////////////////////////////////////////////// +template +Variables &Quantified::variables() +{ + return m_variables; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +const Variables &Quantified::variables() const +{ + return m_variables; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + template inline ExpressionPointer Quantified::reduced() { @@ -118,17 +138,43 @@ inline ExpressionPointer Quantified::negationNormalized() //////////////////////////////////////////////////////////////////////////////////////////////////// +template +inline ExpressionPointer Quantified::simplified() +{ + m_argument = m_argument->simplified(); + + // Associate same-type children, such as (forall (?x) (forall (?y) (...))) + if (m_argument->expressionType() != Derived::ExpressionType) + return this; + + auto &quantifiedExpression = dynamic_cast(*m_argument); + + BOOST_ASSERT(!quantifiedExpression.arguments().empty()); + + // Unify variables + m_variables.insert(m_variables.end(), quantifiedExpression.variables().begin(), quantifiedExpression.variables().end()); + + // Move child expression up + m_argument = quantifiedExpression.argument(); + + // TODO: introduce/handle boolean values + + return this; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + template inline void Quantified::print(std::ostream &ostream) const { - ostream << "(" << Derived::Identifier << "("; + ostream << "(" << Derived::Identifier << " ("; for (size_t i = 0; i < m_variables.size(); i++) { if (i > 0) ostream << " "; - ostream << m_variables[i]->name(); + m_variables[i]->print(ostream); } ostream << ") "; diff --git a/include/plasp/pddl/expressions/Variable.h b/include/plasp/pddl/expressions/Variable.h index 654d0b4..7b6d890 100644 --- a/include/plasp/pddl/expressions/Variable.h +++ b/include/plasp/pddl/expressions/Variable.h @@ -27,6 +27,9 @@ class Variable: public ExpressionCRTP Variables &variables); public: + Variable(); + Variable(std::string name); + void setName(std::string name); const std::string &name() const; @@ -42,8 +45,6 @@ class Variable: public ExpressionCRTP static void parseDeclaration(Context &context, Variables ¶meters); private: - Variable(); - bool m_isDirty; std::string m_name; diff --git a/src/plasp/pddl/expressions/Variable.cpp b/src/plasp/pddl/expressions/Variable.cpp index 67a72a8..bc609d0 100644 --- a/src/plasp/pddl/expressions/Variable.cpp +++ b/src/plasp/pddl/expressions/Variable.cpp @@ -26,8 +26,15 @@ namespace expressions //////////////////////////////////////////////////////////////////////////////////////////////////// Variable::Variable() +: m_isDirty{false} +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Variable::Variable(std::string name) : m_isDirty{false}, - m_type{nullptr} + m_name{name} { } @@ -180,8 +187,13 @@ bool Variable::isDirty() const void Variable::print(std::ostream &ostream) const { - // TODO: implement correctly - ostream << "()"; + ostream << "?" << m_name; + + if (m_type) + { + ostream << " - "; + m_type->print(ostream); + } } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/tests/TestPDDLNormalization.cpp b/tests/TestPDDLNormalization.cpp index 1747eac..a2d7274 100644 --- a/tests/TestPDDLNormalization.cpp +++ b/tests/TestPDDLNormalization.cpp @@ -2,9 +2,12 @@ #include #include +#include +#include #include #include #include +#include using namespace plasp::pddl; @@ -155,3 +158,31 @@ TEST(PDDLNormalizationTests, DoubleNegationInner) ASSERT_EQ(output.str(), "(or (not (a)) (not (b)) (not (c)))"); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST(PDDLNormalizationTests, SimplifyNestedForAll) +{ + auto v1 = expressions::VariablePointer(new expressions::Variable("x")); + auto v2 = expressions::VariablePointer(new expressions::Variable("y")); + auto v3 = expressions::VariablePointer(new expressions::Variable("z")); + auto v4 = expressions::VariablePointer(new expressions::Variable("u")); + auto v5 = expressions::VariablePointer(new expressions::Variable("v")); + auto v6 = expressions::VariablePointer(new expressions::Variable("w")); + + auto f1 = expressions::ForAllPointer(new expressions::ForAll); + auto f2 = expressions::ForAllPointer(new expressions::ForAll); + + auto d = expressions::DummyPointer(new expressions::Dummy("a")); + + f1->variables() = {v1, v2, v3}; + f2->variables() = {v4, v5, v6}; + + f1->setArgument(f2); + f2->setArgument(d); + + std::stringstream output; + f1->normalized()->print(output); + + ASSERT_EQ(output.str(), "(forall (?x ?y ?z ?u ?v ?w) (a))"); +}