From 6355921e59a4aa5f7f796ec7cd11f589025d7059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Thu, 8 Dec 2016 00:52:09 +0100 Subject: [PATCH] Implemented preconditions for derived predicates. --- .../plasp/pddl/expressions/DerivedPredicate.h | 6 + include/plasp/pddl/expressions/Quantified.h | 2 +- include/plasp/pddl/translation/Precondition.h | 75 ++++++++ include/plasp/pddl/translation/Primitives.h | 117 +++++++++++++ src/CMakeLists.txt | 6 + src/plasp/pddl/TranslatorASP.cpp | 161 +++++------------- src/plasp/pddl/expressions/And.cpp | 2 +- .../pddl/expressions/DerivedPredicate.cpp | 14 ++ src/plasp/pddl/expressions/Not.cpp | 2 +- src/plasp/pddl/expressions/Or.cpp | 2 +- 10 files changed, 263 insertions(+), 124 deletions(-) create mode 100644 include/plasp/pddl/translation/Precondition.h create mode 100644 include/plasp/pddl/translation/Primitives.h diff --git a/include/plasp/pddl/expressions/DerivedPredicate.h b/include/plasp/pddl/expressions/DerivedPredicate.h index 2ff0c38..c143f07 100644 --- a/include/plasp/pddl/expressions/DerivedPredicate.h +++ b/include/plasp/pddl/expressions/DerivedPredicate.h @@ -26,6 +26,10 @@ class DerivedPredicate: public ExpressionCRTP // TODO: consider implementing parsing functions for compatibility with older PDDL versions public: + explicit DerivedPredicate(size_t id); + + size_t id() const; + void setPreconditions(std::vector &&preconditions); const std::vector &preconditions() const; @@ -38,6 +42,8 @@ class DerivedPredicate: public ExpressionCRTP private: void collectParameters(); + size_t m_id; + // The arguments are interpreted as a disjunction of conjunctions std::vector m_preconditions; diff --git a/include/plasp/pddl/expressions/Quantified.h b/include/plasp/pddl/expressions/Quantified.h index f7a8f17..92f8d9e 100644 --- a/include/plasp/pddl/expressions/Quantified.h +++ b/include/plasp/pddl/expressions/Quantified.h @@ -197,7 +197,7 @@ inline ExpressionPointer QuantifiedCRTP::simplified() template inline ExpressionPointer QuantifiedCRTP::decomposed(DerivedPredicates &derivedPredicates) { - derivedPredicates.emplace_back(new DerivedPredicate()); + derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size())); auto &derivedPredicate = derivedPredicates.back(); m_argument = m_argument->decomposed(derivedPredicates); diff --git a/include/plasp/pddl/translation/Precondition.h b/include/plasp/pddl/translation/Precondition.h new file mode 100644 index 0000000..a826d63 --- /dev/null +++ b/include/plasp/pddl/translation/Precondition.h @@ -0,0 +1,75 @@ +#ifndef __PLASP__PDDL__TRANSLATION__PRECONDITION_H +#define __PLASP__PDDL__TRANSLATION__PRECONDITION_H + +#include +#include +#include + +namespace plasp +{ +namespace pddl +{ +namespace translation +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Precondition +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +void translatePreconditionDisjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, const std::vector &preconditionDisjunction); +template +void translatePreconditionConjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, size_t disjunctionID, const Expressions &preconditionConjunction); +template +void translatePrecondition(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, size_t disjunctionID, const Expression &precondition); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +inline void translatePreconditionDisjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, const std::vector &preconditionDisjunction) +{ + for (size_t i = 0; i < preconditionDisjunction.size(); i++) + translatePreconditionConjunction(outputStream, objectType, printObjectName, i, preconditionDisjunction[i]); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +inline void translatePreconditionConjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, size_t disjunctionID, const Expressions &preconditionConjunction) +{ + for (size_t i = 0; i < preconditionConjunction.size(); i++) + translatePrecondition(outputStream, objectType, printObjectName, disjunctionID, *preconditionConjunction[i]); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +inline void translatePrecondition(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, size_t disjunctionID, const Expression &precondition) +{ + outputStream << std::endl << output::Function("precondition") << "("; + + printObjectName(outputStream); + + outputStream + << ", " << output::Keyword("disjunct") + << "(" << output::Number(disjunctionID) + << "), "; + + translateLiteral(outputStream, precondition); + + outputStream << ") :- " << output::Function(objectType.c_str()) << "("; + + printObjectName(outputStream); + + outputStream << ")."; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} + +#endif diff --git a/include/plasp/pddl/translation/Primitives.h b/include/plasp/pddl/translation/Primitives.h new file mode 100644 index 0000000..bb026a6 --- /dev/null +++ b/include/plasp/pddl/translation/Primitives.h @@ -0,0 +1,117 @@ +#ifndef __PLASP__PDDL__TRANSLATION__PRIMITIVES_H +#define __PLASP__PDDL__TRANSLATION__PRIMITIVES_H + +#include +#include +#include +#include +#include + +namespace plasp +{ +namespace pddl +{ +namespace translation +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Primitives +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate); +void translateLiteral(output::ColorStream &outputStream, const Expression &literal); + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate) +{ + const auto &arguments = predicate.arguments(); + + if (arguments.empty()) + { + outputStream << output::String(predicate.name().c_str()); + + return; + } + + outputStream << "(" << output::String(predicate.name().c_str()); + + for (const auto &argument : arguments) + { + outputStream << ", "; + + if (argument->is()) + { + const auto &constant = argument->as(); + + outputStream << output::Keyword("constant") << "(" << output::String(constant.name().c_str()) << ")"; + } + else if (argument->is()) + { + const auto &variable = argument->as(); + + outputStream << output::Variable(variable.name().c_str()); + } + else + throw output::TranslatorException("only variables and constants supported in predicates currently"); + } + + outputStream << ")"; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void translateLiteral(output::ColorStream &outputStream, const Expression &literal) +{ + // Translate single predicate + if (literal.is()) + { + const auto &predicate = literal.as(); + + outputStream << output::Keyword("variable") << "("; + translation::translatePredicate(outputStream, predicate); + outputStream << "), " << output::Keyword("value") << "("; + translation::translatePredicate(outputStream, predicate); + outputStream << ", " << output::Boolean("true") << ")"; + } + // Assuming that "not" expression may only contain a predicate + else if (literal.is()) + { + const auto ¬Expression = literal.as(); + + if (notExpression.argument()->expressionType() != Expression::Type::Predicate) + throw output::TranslatorException("only negations of primitive predicates supported as literals currently"); + + const auto &predicate = notExpression.argument()->as(); + + outputStream << output::Keyword("variable") << "("; + translation::translatePredicate(outputStream, predicate); + outputStream << "), " << output::Keyword("value") << "("; + translation::translatePredicate(outputStream, predicate); + outputStream << ", " << output::Boolean("false") << ")"; + } + else if (literal.is()) + { + const auto &derivedPredicate = literal.as(); + + /*m_outputStream << output::Keyword("variable") << "("; + translation::translatePredicate(predicate); + m_outputStream << "), " << output::Keyword("value") << "("; + translation::translatePredicate(predicate); + m_outputStream << ", " << output::Boolean("true") << ")";*/ + + outputStream << "(derived predicate)"; + } + else + throw output::TranslatorException("only primitive predicates and their negations supported as literals currently"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} +} + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e74262f..209ea8b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,9 @@ file(GLOB pddl_headers "../include/plasp/pddl/*.h") file(GLOB pddl_expressions_sources "plasp/pddl/expressions/*.cpp") file(GLOB pddl_expressions_headers "../include/plasp/pddl/expressions/*.h") +file(GLOB pddl_translation_sources "plasp/pddl/translation/*.cpp") +file(GLOB pddl_translation_headers "../include/plasp/pddl/translation/*.h") + file(GLOB sas_sources "plasp/sas/*.cpp") file(GLOB sas_headers "../include/plasp/sas/*.h") @@ -36,6 +39,9 @@ set(sources ${pddl_expressions_sources} ${pddl_expressions_headers} + ${pddl_translation_sources} + ${pddl_translation_headers} + ${sas_sources} ${sas_headers} diff --git a/src/plasp/pddl/TranslatorASP.cpp b/src/plasp/pddl/TranslatorASP.cpp index 737f107..0e0a442 100644 --- a/src/plasp/pddl/TranslatorASP.cpp +++ b/src/plasp/pddl/TranslatorASP.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include namespace plasp { @@ -23,8 +25,6 @@ template void translateVariablesHead(output::ColorStream &outputStream, const T &variables); template void translateVariablesBody(output::ColorStream &outputStream, const T &variables); -void translateLiteral(output::ColorStream &outputStream, const Expression &literal); -void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate); //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -204,43 +204,49 @@ void TranslatorASP::translateDerivedPredicates() const const auto &derivedPredicates = m_description.domain().derivedPredicates(); - const auto printDerivedPredicateName = - [&](const auto &derivedPredicate) - { - if (derivedPredicate->parameters().empty()) + for (const auto &derivedPredicate : derivedPredicates) + { + const auto printDerivedPredicateName = + [&derivedPredicate](output::ColorStream &outputStream) { - // TODO: implement - //m_outputStream << output::String(derivedPredicate->name().c_str()); - m_outputStream << ""; + outputStream << output::Keyword("derivedVariable") << "("; - return; - } + const auto id = derivedPredicate->id(); - // TODO: implement - //m_outputStream << output::String(derivedPredicate->name().c_str()); - m_outputStream << ""; - translateVariablesHead(m_outputStream, derivedPredicate->parameters()); - m_outputStream << ")"; - }; + if (derivedPredicate->parameters().empty()) + { + outputStream << output::Number(id) << ")"; + return; + } - std::for_each(derivedPredicates.cbegin(), derivedPredicates.cend(), - [&](const auto &predicate) - { - m_outputStream - << std::endl - << output::Function("variable") << "(" - << output::Keyword("derived") << "("; + outputStream << "(" << output::Number(id); + translateVariablesHead(outputStream, derivedPredicate->parameters()); + outputStream << "))"; + }; - printDerivedPredicateName(predicate); + m_outputStream << std::endl << output::Function("derivedVariable") << "("; - m_outputStream << "))"; + printDerivedPredicateName(m_outputStream); - translateVariablesBody(m_outputStream, predicate->parameters()); + m_outputStream << ")"; - m_outputStream << "."; - }); + translateVariablesBody(m_outputStream, derivedPredicate->parameters()); - m_outputStream << std::endl; + m_outputStream << "."; + + translation::translatePreconditionDisjunction(m_outputStream, "derivedVariable", printDerivedPredicateName, derivedPredicate->preconditions()); + + m_outputStream << std::endl; + } + + m_outputStream + << std::endl + << output::Function("contains") << "(" + << output::Keyword("derivedVariable") << "(" << output::Variable("X") << "), " + << output::Keyword("value") << "(" << output::Variable("X") << ", " << output::Variable("B") << ")) :- " + << output::Function("variable") << "(" << output::Keyword("derivedVariable") << "(" << output::Variable("X") << ")), " + << output::Function("boolean") << "(" << output::Variable("B") << ")." + << std::endl; } //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -283,7 +289,7 @@ void TranslatorASP::translateActions() const m_outputStream << ", "; - translateLiteral(m_outputStream, literal); + translation::translateLiteral(m_outputStream, literal); m_outputStream << ") :- " << output::Function("action") << "("; @@ -450,91 +456,6 @@ void translateVariablesBody(output::ColorStream &outputStream, const T &variable //////////////////////////////////////////////////////////////////////////////////////////////////// -void translateLiteral(output::ColorStream &outputStream, const Expression &literal) -{ - // Translate single predicate - if (literal.is()) - { - const auto &predicate = literal.as(); - - outputStream << output::Keyword("variable") << "("; - translatePredicate(outputStream, predicate); - outputStream << "), " << output::Keyword("value") << "("; - translatePredicate(outputStream, predicate); - outputStream << ", " << output::Boolean("true") << ")"; - } - // Assuming that "not" expression may only contain a predicate - else if (literal.is()) - { - const auto ¬Expression = literal.as(); - - if (notExpression.argument()->expressionType() != Expression::Type::Predicate) - throw output::TranslatorException("only negations of primitive predicates supported as literals currently"); - - const auto &predicate = notExpression.argument()->as(); - - outputStream << output::Keyword("variable") << "("; - translatePredicate(outputStream, predicate); - outputStream << "), " << output::Keyword("value") << "("; - translatePredicate(outputStream, predicate); - outputStream << ", " << output::Boolean("false") << ")"; - } - else if (literal.is()) - { - const auto &derivedPredicate = literal.as(); - - /*m_outputStream << output::Keyword("variable") << "("; - this->translatePredicate(predicate); - m_outputStream << "), " << output::Keyword("value") << "("; - this->translatePredicate(predicate); - m_outputStream << ", " << output::Boolean("true") << ")";*/ - - outputStream << "(derived predicate)"; - } - else - throw output::TranslatorException("only primitive predicates and their negations supported as literals currently"); -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate) -{ - const auto &arguments = predicate.arguments(); - - if (arguments.empty()) - { - outputStream << output::String(predicate.name().c_str()); - - return; - } - - outputStream << "(" << output::String(predicate.name().c_str()); - - for (const auto &argument : arguments) - { - outputStream << ", "; - - if (argument->is()) - { - const auto &constant = argument->as(); - - outputStream << output::Keyword("constant") << "(" << output::String(constant.name().c_str()) << ")"; - } - else if (argument->is()) - { - const auto &variable = argument->as(); - - outputStream << output::Variable(variable.name().c_str()); - } - else - throw output::TranslatorException("only variables and constants supported in predicates currently"); - } - - outputStream << ")"; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// - void TranslatorASP::translateProblem() const { BOOST_ASSERT(m_description.containsProblem()); @@ -579,9 +500,9 @@ void TranslatorASP::translateInitialState() const const auto &predicate = fact->as(); m_outputStream << output::Keyword("variable") << "("; - translatePredicate(m_outputStream, predicate); + translation::translatePredicate(m_outputStream, predicate); m_outputStream << "), " << output::Keyword("value") << "("; - translatePredicate(m_outputStream, predicate); + translation::translatePredicate(m_outputStream, predicate); m_outputStream << ", " << output::Boolean("true") << ")"; } // Assuming that "not" expression may only contain a predicate @@ -625,7 +546,7 @@ void TranslatorASP::translateGoal() const { m_outputStream << std::endl << output::Function("goal") << "("; - translateLiteral(m_outputStream, goal); + translation::translateLiteral(m_outputStream, goal); m_outputStream << ")."; } @@ -638,7 +559,7 @@ void TranslatorASP::translateGoal() const { m_outputStream << std::endl << output::Function("goal") << "("; - translateLiteral(m_outputStream, *argument); + translation::translateLiteral(m_outputStream, *argument); m_outputStream << ")."; }); diff --git a/src/plasp/pddl/expressions/And.cpp b/src/plasp/pddl/expressions/And.cpp index 77cf11d..38d07c3 100644 --- a/src/plasp/pddl/expressions/And.cpp +++ b/src/plasp/pddl/expressions/And.cpp @@ -25,7 +25,7 @@ const std::string And::Identifier = "and"; ExpressionPointer And::decomposed(DerivedPredicates &derivedPredicates) { - derivedPredicates.emplace_back(new DerivedPredicate()); + derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size())); auto &derivedPredicate = derivedPredicates.back(); for (auto &argument : m_arguments) diff --git a/src/plasp/pddl/expressions/DerivedPredicate.cpp b/src/plasp/pddl/expressions/DerivedPredicate.cpp index bd88cb3..2decbbe 100644 --- a/src/plasp/pddl/expressions/DerivedPredicate.cpp +++ b/src/plasp/pddl/expressions/DerivedPredicate.cpp @@ -16,6 +16,20 @@ namespace expressions // //////////////////////////////////////////////////////////////////////////////////////////////////// +DerivedPredicate::DerivedPredicate(size_t id) +: m_id{id} +{ +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +size_t DerivedPredicate::id() const +{ + return m_id; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void DerivedPredicate::setPreconditions(std::vector &&preconditions) { m_preconditions = std::move(preconditions); diff --git a/src/plasp/pddl/expressions/Not.cpp b/src/plasp/pddl/expressions/Not.cpp index d6a9957..fd77570 100644 --- a/src/plasp/pddl/expressions/Not.cpp +++ b/src/plasp/pddl/expressions/Not.cpp @@ -107,7 +107,7 @@ ExpressionPointer Not::decomposed(DerivedPredicates &derivedPredicates) if (m_argument->is() || m_argument->is()) return this; - derivedPredicates.emplace_back(new DerivedPredicate()); + derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size())); auto &derivedPredicate = derivedPredicates.back(); // Move this expression’s arguments to the derived predicate diff --git a/src/plasp/pddl/expressions/Or.cpp b/src/plasp/pddl/expressions/Or.cpp index 1adc06a..98fc5d6 100644 --- a/src/plasp/pddl/expressions/Or.cpp +++ b/src/plasp/pddl/expressions/Or.cpp @@ -23,7 +23,7 @@ const std::string Or::Identifier = "or"; ExpressionPointer Or::decomposed(DerivedPredicates &derivedPredicates) { - derivedPredicates.emplace_back(new DerivedPredicate()); + derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size())); auto &derivedPredicate = derivedPredicates.back(); std::vector preconditions;