From c9ecd0c0205f2e5f2f70991822fd3e0f69f7c117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Sun, 4 Sep 2016 20:49:22 +0200 Subject: [PATCH] =?UTF-8?q?Implemented=20De=20Morgan=E2=80=99s=20rules=20f?= =?UTF-8?q?or=20normalization=20purposes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/plasp/pddl/expressions/NAry.h | 9 +++ src/plasp/pddl/expressions/Imply.cpp | 6 +- src/plasp/pddl/expressions/Not.cpp | 31 ++++++++++ tests/TestPDDLNormalization.cpp | 84 +++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 3 deletions(-) diff --git a/include/plasp/pddl/expressions/NAry.h b/include/plasp/pddl/expressions/NAry.h index 3c5a0ae..a296199 100644 --- a/include/plasp/pddl/expressions/NAry.h +++ b/include/plasp/pddl/expressions/NAry.h @@ -30,6 +30,7 @@ class NAry: public ExpressionCRTP public: void setArgument(size_t i, ExpressionPointer argument); void addArgument(ExpressionPointer argument); + Expressions &arguments(); const Expressions &arguments() const; ExpressionPointer normalized() override; @@ -108,6 +109,14 @@ const Expressions &NAry::arguments() const //////////////////////////////////////////////////////////////////////////////////////////////////// +template +Expressions &NAry::arguments() +{ + return m_arguments; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + template inline ExpressionPointer NAry::normalized() { diff --git a/src/plasp/pddl/expressions/Imply.cpp b/src/plasp/pddl/expressions/Imply.cpp index d0e9adc..e64f47f 100644 --- a/src/plasp/pddl/expressions/Imply.cpp +++ b/src/plasp/pddl/expressions/Imply.cpp @@ -30,11 +30,11 @@ ExpressionPointer Imply::normalized() m_arguments[1] = m_arguments[1]->normalized(); auto notArgument0 = NotPointer(new Not); - notArgument0->setArgument(m_arguments[0]); + notArgument0->setArgument(std::move(m_arguments[0])); auto orExpression = OrPointer(new Or); - orExpression->addArgument(notArgument0); - orExpression->addArgument(m_arguments[1]); + orExpression->addArgument(std::move(notArgument0)); + orExpression->addArgument(std::move(m_arguments[1])); auto normalizedOrExpression = orExpression->normalized(); diff --git a/src/plasp/pddl/expressions/Not.cpp b/src/plasp/pddl/expressions/Not.cpp index 5b35557..a6ff9b1 100644 --- a/src/plasp/pddl/expressions/Not.cpp +++ b/src/plasp/pddl/expressions/Not.cpp @@ -1,5 +1,8 @@ #include +#include +#include + namespace plasp { namespace pddl @@ -48,6 +51,34 @@ ExpressionPointer Not::normalized() m_argument = m_argument->normalized(); + // De Morgan for negative conjunctions + if (m_argument->expressionType() == Expression::Type::And) + { + auto &andExpression = dynamic_cast(*m_argument); + auto orExpression = OrPointer(new Or); + + orExpression->arguments().reserve(andExpression.arguments().size()); + + for (size_t i = 0; i < andExpression.arguments().size(); i++) + orExpression->addArgument(andExpression.arguments()[i]->negated()); + + return orExpression->normalized(); + } + + // De Morgan for negative disjunctions + if (m_argument->expressionType() == Expression::Type::Or) + { + auto &orExpression = dynamic_cast(*m_argument); + auto andExpression = AndPointer(new And); + + andExpression->arguments().reserve(orExpression.arguments().size()); + + for (size_t i = 0; i < orExpression.arguments().size(); i++) + andExpression->addArgument(orExpression.arguments()[i]->negated()); + + return andExpression->normalized(); + } + return this; } diff --git a/tests/TestPDDLNormalization.cpp b/tests/TestPDDLNormalization.cpp index b174adb..1954171 100644 --- a/tests/TestPDDLNormalization.cpp +++ b/tests/TestPDDLNormalization.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -53,3 +54,86 @@ TEST(PDDLNormalizationTests, DoubleNegation) ASSERT_EQ(normalized.get(), dp); ASSERT_TRUE(dp->isNormalized()); } + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST(PDDLNormalizationTests, DeMorganNegativeConjunction) +{ + auto d1 = expressions::DummyPointer(new expressions::Dummy); + const auto d1p = d1.get(); + auto d2 = expressions::DummyPointer(new expressions::Dummy); + const auto d2p = d2.get(); + auto d3 = expressions::DummyPointer(new expressions::Dummy); + const auto d3p = d3.get(); + + auto a = expressions::AndPointer(new expressions::And); + a->addArgument(d1); + a->addArgument(d2); + a->addArgument(d3); + + auto n = expressions::NotPointer(new expressions::Not); + n->setArgument(a); + + auto normalized = n->normalized(); + + ASSERT_EQ(normalized->expressionType(), Expression::Type::Or); + + const auto &o = dynamic_cast(*normalized); + + ASSERT_EQ(o.arguments()[0]->expressionType(), Expression::Type::Not); + ASSERT_EQ(o.arguments()[1]->expressionType(), Expression::Type::Not); + ASSERT_EQ(o.arguments()[2]->expressionType(), Expression::Type::Not); + + const auto &n1 = dynamic_cast(*o.arguments()[0]); + const auto &n2 = dynamic_cast(*o.arguments()[1]); + const auto &n3 = dynamic_cast(*o.arguments()[2]); + + ASSERT_EQ(n1.argument().get(), d1p); + ASSERT_EQ(n2.argument().get(), d2p); + ASSERT_EQ(n3.argument().get(), d3p); + ASSERT_TRUE(d1p->isNormalized()); + ASSERT_TRUE(d2p->isNormalized()); + ASSERT_TRUE(d3p->isNormalized()); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST(PDDLNormalizationTests, DeMorganNegativeDisjunction) +{ + auto d1 = expressions::DummyPointer(new expressions::Dummy); + const auto d1p = d1.get(); + auto d2 = expressions::DummyPointer(new expressions::Dummy); + const auto d2p = d2.get(); + auto d3 = expressions::DummyPointer(new expressions::Dummy); + const auto d3p = d3.get(); + + auto o = expressions::OrPointer(new expressions::Or); + o->addArgument(d1); + o->addArgument(d2); + o->addArgument(d3); + + auto n = expressions::NotPointer(new expressions::Not); + n->setArgument(o); + + auto normalized = n->normalized(); + + ASSERT_EQ(normalized->expressionType(), Expression::Type::And); + + const auto &a = dynamic_cast(*normalized); + + ASSERT_EQ(a.arguments()[0]->expressionType(), Expression::Type::Not); + ASSERT_EQ(a.arguments()[1]->expressionType(), Expression::Type::Not); + ASSERT_EQ(a.arguments()[2]->expressionType(), Expression::Type::Not); + + const auto &n1 = dynamic_cast(*a.arguments()[0]); + const auto &n2 = dynamic_cast(*a.arguments()[1]); + const auto &n3 = dynamic_cast(*a.arguments()[2]); + + ASSERT_EQ(n1.argument().get(), d1p); + ASSERT_EQ(n2.argument().get(), d2p); + ASSERT_EQ(n3.argument().get(), d3p); + ASSERT_TRUE(d1p->isNormalized()); + ASSERT_TRUE(d2p->isNormalized()); + ASSERT_TRUE(d3p->isNormalized()); +}