Added translation for preconditions of PDDL actions.

This commit is contained in:
Patrick Lühne 2016-06-13 02:38:56 +02:00
parent 680206b40b
commit e2b8fd2880
3 changed files with 184 additions and 56 deletions

View File

@ -34,7 +34,9 @@ class TranslatorASP
void translateProblem() const; 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; const Description &m_description;
std::ostream &m_ostream; std::ostream &m_ostream;

View File

@ -63,8 +63,8 @@ std::unique_ptr<Derived> Binary<Derived>::parse(Context &context,
// Assume that expression identifier (imply, exists, etc.) is already parsed // Assume that expression identifier (imply, exists, etc.) is already parsed
// Parse arguments of the expression // Parse arguments of the expression
expression->setArgument<0>(parseExpression(context, expressionContext)); expression->Binary<Derived>::setArgument<0>(parseExpression(context, expressionContext));
expression->setArgument<1>(parseExpression(context, expressionContext)); expression->Binary<Derived>::setArgument<1>(parseExpression(context, expressionContext));
parser.expect<std::string>(")"); parser.expect<std::string>(")");

View File

@ -2,6 +2,7 @@
#include <plasp/pddl/expressions/And.h> #include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Not.h> #include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/utils/IO.h> #include <plasp/utils/IO.h>
#include <plasp/utils/TranslatorException.h> #include <plasp/utils/TranslatorException.h>
@ -57,17 +58,19 @@ void TranslatorASP::checkSupport() const
throw utils::TranslatorException("Only primitive types supported currently"); throw utils::TranslatorException("Only primitive types supported currently");
}); });
if (action->precondition())
{
// Check that all preconditions are "and" expressions or single predicates // Check that all preconditions are "and" expressions or single predicates
if (action->precondition().expressionType() != Expression::Type::And if (action->precondition()->expressionType() != Expression::Type::And
&& action->precondition().expressionType() != Expression::Type::Predicate) && action->precondition()->expressionType() != Expression::Type::Predicate)
{ {
throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action preconditions currently"); throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action preconditions currently");
} }
// Check that "and" expression in preconditions contains single predicates only // Check that "and" expression in preconditions contains single predicates only
if (action->precondition().expressionType() == Expression::Type::And) if (action->precondition()->expressionType() == Expression::Type::And)
{ {
const auto &precondition = dynamic_cast<const expressions::And &>(action->precondition()); const auto &precondition = dynamic_cast<const expressions::And &>(*action->precondition());
const auto &preconditionArguments = precondition.arguments(); const auto &preconditionArguments = precondition.arguments();
std::for_each(preconditionArguments.cbegin(), preconditionArguments.cend(), std::for_each(preconditionArguments.cbegin(), preconditionArguments.cend(),
@ -77,35 +80,37 @@ void TranslatorASP::checkSupport() const
throw utils::TranslatorException("Only predicates supported in preconditions currently"); throw utils::TranslatorException("Only predicates supported in preconditions currently");
}); });
} }
}
if (action->effect())
{
// Check that all effects are "and" expressions // Check that all effects are "and" expressions
if (action->effect().expressionType() != Expression::Type::And if (action->effect()->expressionType() != Expression::Type::And
&& action->effect().expressionType() != Expression::Type::Predicate) && action->effect()->expressionType() != Expression::Type::Predicate)
{ {
throw utils::TranslatorException("Only \"and\" expressions and single predicates supported as action effects currently"); 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 // Check that "and" expression in effect contains single predicates or negated predicates only
if (action->effect().expressionType() == Expression::Type::And) if (action->effect()->expressionType() == Expression::Type::And)
{ {
const auto &effect = dynamic_cast<const expressions::And &>(action->effect()); const auto &effect = dynamic_cast<const expressions::And &>(*action->effect());
const auto &effectArguments = effect.arguments(); const auto &effectArguments = effect.arguments();
std::for_each(effectArguments.cbegin(), effectArguments.cend(), std::for_each(effectArguments.cbegin(), effectArguments.cend(),
[&](const auto &argument) [&](const auto *argument)
{ {
const Expression *expression = argument.get(); if (argument->expressionType() == Expression::Type::Not)
if (expression->expressionType() == Expression::Type::Not)
{ {
const auto &notExpression = dynamic_cast<const expressions::Not &>(*expression); const auto &notExpression = dynamic_cast<const expressions::Not &>(*argument);
expression = &notExpression.argument(); argument = notExpression.argument();
} }
if (expression->expressionType() != Expression::Type::Predicate) if (argument->expressionType() != Expression::Type::Predicate)
throw utils::TranslatorException("Only predicates and negated predicates supported in effects currently"); 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(); 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; m_ostream << std::endl;
@ -246,24 +255,91 @@ void TranslatorASP::translateActions() const
const auto &actions = m_description.domain().actions(); 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(), std::for_each(actions.cbegin(), actions.cend(),
[&](const auto &action) [&](const auto &action)
{ {
m_ostream << std::endl; 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<const expressions::Predicate &>(literal));
m_ostream << ", true";
}
// Assuming that "not" expression may only contain a predicate
else if (literal.expressionType() == Expression::Type::Not)
{
const auto &notExpression = dynamic_cast<const expressions::Not &>(literal);
const auto &predicate = dynamic_cast<const expressions::Predicate &>(*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<const expressions::And &>(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()) if (variables.empty())
return; return;
@ -280,7 +356,17 @@ void TranslatorASP::translateVariables(const expressions::Variables &variables)
m_ostream << utils::escapeASPVariable(variable.name()); 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++) 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<const expressions::Constant &>(**i);
m_ostream << "constant(" << constant.name() << ")";
}
else if ((*i)->expressionType() == Expression::Type::Variable)
{
const auto &variable = dynamic_cast<const expressions::Variable &>(**i);
m_ostream << utils::escapeASPVariable(variable.name());
}
else
throw utils::TranslatorException("Only variables and constants supported in predicates");
}
m_ostream << "))";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateProblem() const void TranslatorASP::translateProblem() const
{ {
m_ostream m_ostream