Implemented De Morgan’s rules for normalization purposes.
This commit is contained in:
parent
6aaf7c039d
commit
c9ecd0c020
@ -30,6 +30,7 @@ class NAry: public ExpressionCRTP<Derived>
|
|||||||
public:
|
public:
|
||||||
void setArgument(size_t i, ExpressionPointer argument);
|
void setArgument(size_t i, ExpressionPointer argument);
|
||||||
void addArgument(ExpressionPointer argument);
|
void addArgument(ExpressionPointer argument);
|
||||||
|
Expressions &arguments();
|
||||||
const Expressions &arguments() const;
|
const Expressions &arguments() const;
|
||||||
|
|
||||||
ExpressionPointer normalized() override;
|
ExpressionPointer normalized() override;
|
||||||
@ -108,6 +109,14 @@ const Expressions &NAry<Derived>::arguments() const
|
|||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<class Derived>
|
||||||
|
Expressions &NAry<Derived>::arguments()
|
||||||
|
{
|
||||||
|
return m_arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class Derived>
|
template<class Derived>
|
||||||
inline ExpressionPointer NAry<Derived>::normalized()
|
inline ExpressionPointer NAry<Derived>::normalized()
|
||||||
{
|
{
|
||||||
|
@ -30,11 +30,11 @@ ExpressionPointer Imply::normalized()
|
|||||||
m_arguments[1] = m_arguments[1]->normalized();
|
m_arguments[1] = m_arguments[1]->normalized();
|
||||||
|
|
||||||
auto notArgument0 = NotPointer(new Not);
|
auto notArgument0 = NotPointer(new Not);
|
||||||
notArgument0->setArgument(m_arguments[0]);
|
notArgument0->setArgument(std::move(m_arguments[0]));
|
||||||
|
|
||||||
auto orExpression = OrPointer(new Or);
|
auto orExpression = OrPointer(new Or);
|
||||||
orExpression->addArgument(notArgument0);
|
orExpression->addArgument(std::move(notArgument0));
|
||||||
orExpression->addArgument(m_arguments[1]);
|
orExpression->addArgument(std::move(m_arguments[1]));
|
||||||
|
|
||||||
auto normalizedOrExpression = orExpression->normalized();
|
auto normalizedOrExpression = orExpression->normalized();
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
#include <plasp/pddl/expressions/Not.h>
|
#include <plasp/pddl/expressions/Not.h>
|
||||||
|
|
||||||
|
#include <plasp/pddl/expressions/And.h>
|
||||||
|
#include <plasp/pddl/expressions/Or.h>
|
||||||
|
|
||||||
namespace plasp
|
namespace plasp
|
||||||
{
|
{
|
||||||
namespace pddl
|
namespace pddl
|
||||||
@ -48,6 +51,34 @@ ExpressionPointer Not::normalized()
|
|||||||
|
|
||||||
m_argument = m_argument->normalized();
|
m_argument = m_argument->normalized();
|
||||||
|
|
||||||
|
// De Morgan for negative conjunctions
|
||||||
|
if (m_argument->expressionType() == Expression::Type::And)
|
||||||
|
{
|
||||||
|
auto &andExpression = dynamic_cast<And &>(*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<Or &>(*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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <plasp/pddl/expressions/And.h>
|
||||||
#include <plasp/pddl/expressions/Dummy.h>
|
#include <plasp/pddl/expressions/Dummy.h>
|
||||||
#include <plasp/pddl/expressions/Imply.h>
|
#include <plasp/pddl/expressions/Imply.h>
|
||||||
#include <plasp/pddl/expressions/Not.h>
|
#include <plasp/pddl/expressions/Not.h>
|
||||||
@ -53,3 +54,86 @@ TEST(PDDLNormalizationTests, DoubleNegation)
|
|||||||
ASSERT_EQ(normalized.get(), dp);
|
ASSERT_EQ(normalized.get(), dp);
|
||||||
ASSERT_TRUE(dp->isNormalized());
|
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<expressions::Or &>(*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<expressions::Not &>(*o.arguments()[0]);
|
||||||
|
const auto &n2 = dynamic_cast<expressions::Not &>(*o.arguments()[1]);
|
||||||
|
const auto &n3 = dynamic_cast<expressions::Not &>(*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<expressions::And &>(*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<expressions::Not &>(*a.arguments()[0]);
|
||||||
|
const auto &n2 = dynamic_cast<expressions::Not &>(*a.arguments()[1]);
|
||||||
|
const auto &n3 = dynamic_cast<expressions::Not &>(*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());
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user