From e2b8fd2880d7eae66a74cd53efe2927bdb7477a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Mon, 13 Jun 2016 02:38:56 +0200 Subject: [PATCH] Added translation for preconditions of PDDL actions. --- include/plasp/pddl/TranslatorASP.h | 4 +- include/plasp/pddl/expressions/Binary.h | 6 +- src/plasp/pddl/TranslatorASP.cpp | 230 ++++++++++++++++++------ 3 files changed, 184 insertions(+), 56 deletions(-) diff --git a/include/plasp/pddl/TranslatorASP.h b/include/plasp/pddl/TranslatorASP.h index c011838..534732a 100644 --- a/include/plasp/pddl/TranslatorASP.h +++ b/include/plasp/pddl/TranslatorASP.h @@ -34,7 +34,9 @@ class TranslatorASP void translateProblem() const; - void translateVariables(const expressions::Variables &variables) const; + void translateVariablesHead(const expressions::Variables &variables) const; + void translateVariablesBody(const expressions::Variables &variables) const; + void translatePredicate(const expressions::Predicate &predicate) const; const Description &m_description; std::ostream &m_ostream; diff --git a/include/plasp/pddl/expressions/Binary.h b/include/plasp/pddl/expressions/Binary.h index c4fced2..23d625c 100644 --- a/include/plasp/pddl/expressions/Binary.h +++ b/include/plasp/pddl/expressions/Binary.h @@ -36,7 +36,7 @@ class Binary: public ExpressionCRTP void setArgument(const Expression *argument); template void setArgument(ExpressionPointer &&argument); - + std::array m_arguments; std::array m_argumentStorage; }; @@ -63,8 +63,8 @@ std::unique_ptr Binary::parse(Context &context, // Assume that expression identifier (imply, exists, etc.) is already parsed // Parse arguments of the expression - expression->setArgument<0>(parseExpression(context, expressionContext)); - expression->setArgument<1>(parseExpression(context, expressionContext)); + expression->Binary::setArgument<0>(parseExpression(context, expressionContext)); + expression->Binary::setArgument<1>(parseExpression(context, expressionContext)); parser.expect(")"); diff --git a/src/plasp/pddl/TranslatorASP.cpp b/src/plasp/pddl/TranslatorASP.cpp index 305f6cc..af45d8d 100644 --- a/src/plasp/pddl/TranslatorASP.cpp +++ b/src/plasp/pddl/TranslatorASP.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -57,54 +58,58 @@ void TranslatorASP::checkSupport() const throw utils::TranslatorException("Only primitive types supported currently"); }); - // Check that all preconditions are "and" expressions or single predicates - if (action->precondition().expressionType() != Expression::Type::And - && action->precondition().expressionType() != Expression::Type::Predicate) + if (action->precondition()) { - throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action preconditions currently"); - } + // Check that all preconditions are "and" expressions or single predicates + if (action->precondition()->expressionType() != Expression::Type::And + && action->precondition()->expressionType() != Expression::Type::Predicate) + { + throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action preconditions currently"); + } - // Check that "and" expression in preconditions contains single predicates only - if (action->precondition().expressionType() == Expression::Type::And) - { - const auto &precondition = dynamic_cast(action->precondition()); - const auto &preconditionArguments = precondition.arguments(); + // Check that "and" expression in preconditions contains single predicates only + if (action->precondition()->expressionType() == Expression::Type::And) + { + const auto &precondition = dynamic_cast(*action->precondition()); + const auto &preconditionArguments = precondition.arguments(); - std::for_each(preconditionArguments.cbegin(), preconditionArguments.cend(), - [&](const auto &argument) - { - if (argument->expressionType() != Expression::Type::Predicate) - throw utils::TranslatorException("Only predicates supported in preconditions currently"); - }); - } - - // Check that all effects are "and" expressions - if (action->effect().expressionType() != Expression::Type::And - && action->effect().expressionType() != Expression::Type::Predicate) - { - throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action effects currently"); - } - - // Check that "and" expression in effect contains single predicates or negated predicates only - if (action->effect().expressionType() == Expression::Type::And) - { - const auto &effect = dynamic_cast(action->effect()); - const auto &effectArguments = effect.arguments(); - - std::for_each(effectArguments.cbegin(), effectArguments.cend(), - [&](const auto &argument) - { - const Expression *expression = argument.get(); - - if (expression->expressionType() == Expression::Type::Not) + std::for_each(preconditionArguments.cbegin(), preconditionArguments.cend(), + [&](const auto &argument) { - const auto ¬Expression = dynamic_cast(*expression); - expression = ¬Expression.argument(); - } + if (argument->expressionType() != Expression::Type::Predicate) + throw utils::TranslatorException("Only predicates supported in preconditions currently"); + }); + } + } - if (expression->expressionType() != Expression::Type::Predicate) - throw utils::TranslatorException("Only predicates and negated predicates supported in effects currently"); - }); + if (action->effect()) + { + // Check that all effects are "and" expressions + if (action->effect()->expressionType() != Expression::Type::And + && action->effect()->expressionType() != Expression::Type::Predicate) + { + throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action effects currently"); + } + + // Check that "and" expression in effect contains single predicates or negated predicates only + if (action->effect()->expressionType() == Expression::Type::And) + { + const auto &effect = dynamic_cast(*action->effect()); + const auto &effectArguments = effect.arguments(); + + std::for_each(effectArguments.cbegin(), effectArguments.cend(), + [&](const auto *argument) + { + if (argument->expressionType() == Expression::Type::Not) + { + const auto ¬Expression = dynamic_cast(*argument); + argument = notExpression.argument(); + } + + if (argument->expressionType() != Expression::Type::Predicate) + throw utils::TranslatorException("Only predicates and negated predicates supported in effects currently"); + }); + } } }); } @@ -230,9 +235,13 @@ void TranslatorASP::translatePredicates() const m_ostream << "predicate(" << predicate->name(); - this->translateVariables(predicate->arguments()); + this->translateVariablesHead(predicate->arguments()); - m_ostream << ")."; + m_ostream << ")"; + + this->translateVariablesBody(predicate->arguments()); + + m_ostream << "."; }); m_ostream << std::endl; @@ -246,24 +255,91 @@ void TranslatorASP::translateActions() const const auto &actions = m_description.domain().actions(); + const auto printActionName = + [&](const auto &action) + { + m_ostream << "action(" << action.name(); + + this->translateVariablesHead(action.parameters()); + + m_ostream << ")"; + }; + std::for_each(actions.cbegin(), actions.cend(), [&](const auto &action) { m_ostream << std::endl; - m_ostream << "action(" << action->name(); + // Name + printActionName(*action); - this->translateVariables(action->parameters()); + this->translateVariablesBody(action->parameters()); - m_ostream << ")."; + m_ostream << "."; + + const auto translateLiteral = + [&](const auto &ruleHead, const auto &literal) + { + m_ostream << std::endl; + m_ostream << ruleHead << "("; + + printActionName(*action); + + m_ostream << ", "; + + // Translate single predicate + if (literal.expressionType() == Expression::Type::Predicate) + { + this->translatePredicate(dynamic_cast(literal)); + m_ostream << ", true"; + } + // Assuming that "not" expression may only contain a predicate + else if (literal.expressionType() == Expression::Type::Not) + { + const auto ¬Expression = dynamic_cast(literal); + const auto &predicate = dynamic_cast(*notExpression.argument()); + + this->translatePredicate(predicate); + m_ostream << ", false"; + } + + m_ostream << ") :- "; + + printActionName(*action); + + m_ostream << "."; + }; + + // Precondition + if (action->precondition()) + { + const auto &precondition = *action->precondition(); + + if (precondition.expressionType() == Expression::Type::Predicate + || precondition.expressionType() == Expression::Type::Not) + { + translateLiteral("precondition", precondition); + } + // Assuming a conjunction + else + { + const auto &andExpression = dynamic_cast(precondition); + + std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(), + [&](const auto *argument) + { + translateLiteral("precondition", *argument); + }); + } + } + + m_ostream << std::endl; }); - - m_ostream << std::endl; } //////////////////////////////////////////////////////////////////////////////////////////////////// -void TranslatorASP::translateVariables(const expressions::Variables &variables) const +void TranslatorASP::translateVariablesHead(const expressions::Variables &variables) const { if (variables.empty()) return; @@ -280,7 +356,17 @@ void TranslatorASP::translateVariables(const expressions::Variables &variables) m_ostream << utils::escapeASPVariable(variable.name()); } - m_ostream << ")) :- "; + m_ostream << ")"; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +void TranslatorASP::translateVariablesBody(const expressions::Variables &variables) const +{ + if (variables.empty()) + return; + + m_ostream << " :- "; for (auto i = variables.cbegin(); i != variables.cend(); i++) { @@ -296,6 +382,46 @@ void TranslatorASP::translateVariables(const expressions::Variables &variables) //////////////////////////////////////////////////////////////////////////////////////////////////// +void TranslatorASP::translatePredicate(const expressions::Predicate &predicate) const +{ + m_ostream << "predicate(" << predicate.name(); + + const auto &arguments = predicate.arguments(); + + if (arguments.empty()) + { + m_ostream << ")"; + return; + } + + m_ostream << "("; + + for (auto i = arguments.cbegin(); i != arguments.cend(); i++) + { + if (i != arguments.cbegin()) + m_ostream << ", "; + + if ((*i)->expressionType() == Expression::Type::Constant) + { + const auto &constant = dynamic_cast(**i); + + m_ostream << "constant(" << constant.name() << ")"; + } + else if ((*i)->expressionType() == Expression::Type::Variable) + { + const auto &variable = dynamic_cast(**i); + + m_ostream << utils::escapeASPVariable(variable.name()); + } + else + throw utils::TranslatorException("Only variables and constants supported in predicates"); + } + + m_ostream << "))"; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void TranslatorASP::translateProblem() const { m_ostream