From 263b611a7bc16512426217ce840e4db275b7ff50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Mon, 5 Sep 2016 00:37:43 +0200 Subject: [PATCH] Implemented simplification of directly nested n-ary expressions of the same type. --- include/plasp/pddl/Expression.h | 1 + include/plasp/pddl/expressions/NAry.h | 37 ++++++++++++++++++++++----- src/plasp/pddl/Expression.cpp | 9 ++++++- tests/TestPDDLNormalization.cpp | 33 ++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/include/plasp/pddl/Expression.h b/include/plasp/pddl/Expression.h index 5da342f..862f63d 100644 --- a/include/plasp/pddl/Expression.h +++ b/include/plasp/pddl/Expression.h @@ -112,6 +112,7 @@ class Expression ExpressionPointer normalized(); virtual ExpressionPointer reduced(); virtual ExpressionPointer negationNormalized(); + virtual ExpressionPointer simplified(); ExpressionPointer negated(); virtual void print(std::ostream &ostream) const = 0; diff --git a/include/plasp/pddl/expressions/NAry.h b/include/plasp/pddl/expressions/NAry.h index 66760c6..befc097 100644 --- a/include/plasp/pddl/expressions/NAry.h +++ b/include/plasp/pddl/expressions/NAry.h @@ -35,6 +35,7 @@ class NAry: public ExpressionCRTP ExpressionPointer reduced() override; ExpressionPointer negationNormalized() override; + ExpressionPointer simplified() override; void print(std::ostream &ostream) const override; @@ -145,19 +146,41 @@ inline ExpressionPointer NAry::negationNormalized() m_arguments[i] = m_arguments[i]->negationNormalized(); } - /*// Unify same-type children - for (size_t i = 0; i < m_arguments.size(); i++) + return this; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +inline ExpressionPointer NAry::simplified() +{ + // Associate same-type children, such as (a && (b && c)) == (a && b && c) + for (size_t i = 0; i < m_arguments.size();) { + m_arguments[i] = m_arguments[i]->simplified(); + if (m_arguments[i]->expressionType() != Derived::ExpressionType) + { + i++; continue; + } - auto &nAryExpression = dynamic_cast(*m_arguments[i]); + auto child = m_arguments[i]; + auto &nAryExpression = dynamic_cast(*child); - m_arguments.reserve(m_arguments.size() + nAryExpression.arguments().size()); + BOOST_ASSERT(!nAryExpression.arguments().empty()); - m_arguments.emplace_back(nAryExpression.arguments()); - m_arguments.erase(const_iterator __position) - }*/ + // Remove former child by replacing it with the first one of the child + m_arguments[i] = nAryExpression.arguments().front(); + + // Reserve space for new arguments + m_arguments.reserve(m_arguments.size() + nAryExpression.arguments().size() - 1); + + // Copy all but first element + m_arguments.insert(m_arguments.end(), nAryExpression.arguments().begin() + 1, nAryExpression.arguments().end()); + } + + // TODO: recognize tautologies return this; } diff --git a/src/plasp/pddl/Expression.cpp b/src/plasp/pddl/Expression.cpp index 2d2a5e2..4cc2030 100644 --- a/src/plasp/pddl/Expression.cpp +++ b/src/plasp/pddl/Expression.cpp @@ -26,7 +26,7 @@ namespace pddl ExpressionPointer Expression::normalized() { - return reduced()->negationNormalized(); + return reduced()->negationNormalized()->simplified(); } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -45,6 +45,13 @@ ExpressionPointer Expression::negationNormalized() //////////////////////////////////////////////////////////////////////////////////////////////////// +ExpressionPointer Expression::simplified() +{ + return this; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + ExpressionPointer Expression::negated() { if (expressionType() == Type::Not) diff --git a/tests/TestPDDLNormalization.cpp b/tests/TestPDDLNormalization.cpp index a05c0cc..1747eac 100644 --- a/tests/TestPDDLNormalization.cpp +++ b/tests/TestPDDLNormalization.cpp @@ -10,7 +10,7 @@ using namespace plasp::pddl; //////////////////////////////////////////////////////////////////////////////////////////////////// -TEST(PDDLNormalizationTests, Reduced) +TEST(PDDLNormalizationTests, Reduce) { auto n1 = expressions::NotPointer(new expressions::Not); auto n2 = expressions::NotPointer(new expressions::Not); @@ -38,6 +38,36 @@ TEST(PDDLNormalizationTests, Reduced) //////////////////////////////////////////////////////////////////////////////////////////////////// +TEST(PDDLNormalizationTests, Simplify) +{ + auto a1 = expressions::AndPointer(new expressions::And); + auto a2 = expressions::AndPointer(new expressions::And); + auto o1 = expressions::OrPointer(new expressions::Or); + auto o2 = expressions::OrPointer(new expressions::Or); + + a1->addArgument(new expressions::Dummy("a")); + a1->addArgument(new expressions::Dummy("b")); + a1->addArgument(a2); + + a2->addArgument(new expressions::Dummy("c")); + a2->addArgument(new expressions::Dummy("d")); + a2->addArgument(o1); + + o1->addArgument(new expressions::Dummy("e")); + o1->addArgument(new expressions::Dummy("f")); + o1->addArgument(o2); + + o2->addArgument(new expressions::Dummy("g")); + o2->addArgument(new expressions::Dummy("h")); + + std::stringstream output; + a1->simplified()->print(output); + + ASSERT_EQ(output.str(), "(and (a) (b) (c) (d) (or (e) (f) (g) (h)))"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + TEST(PDDLNormalizationTests, Implication) { auto i = expressions::ImplyPointer(new expressions::Imply); @@ -85,7 +115,6 @@ TEST(PDDLNormalizationTests, DeMorganNegativeConjunction) ASSERT_EQ(output.str(), "(or (not (a)) (not (b)) (not (c)))"); } - //////////////////////////////////////////////////////////////////////////////////////////////////// TEST(PDDLNormalizationTests, DeMorganNegativeDisjunction)