Started implementing translation for derived predicates.
This commit is contained in:
@@ -88,10 +88,10 @@ const Expression *Action::effect() const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Action::normalize()
|
||||
void Action::normalize(expressions::DerivedPredicates &derivedPredicates)
|
||||
{
|
||||
// Normalize preconditions and effects
|
||||
m_precondition = m_precondition->normalized();
|
||||
m_precondition = m_precondition->normalized()->decomposed(derivedPredicates);
|
||||
m_effect = m_effect->normalized();
|
||||
|
||||
// Normalize parameter names
|
||||
|
@@ -438,9 +438,9 @@ void Domain::normalize()
|
||||
});
|
||||
|
||||
std::for_each(m_actions.begin(), m_actions.end(),
|
||||
[](auto &action)
|
||||
[&](auto &action)
|
||||
{
|
||||
action->normalize();
|
||||
action->normalize(m_derivedPredicates);
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -37,7 +37,7 @@ ExpressionPointer Expression::copy()
|
||||
|
||||
ExpressionPointer Expression::normalized()
|
||||
{
|
||||
return reduced()->negationNormalized()->prenex()->simplified()->disjunctionNormalized()->simplified();
|
||||
return reduced()->simplified()->existentiallyQuantified()->simplified();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -49,17 +49,11 @@ ExpressionPointer Expression::reduced()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Expression::negationNormalized()
|
||||
ExpressionPointer Expression::existentiallyQuantified()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Expression::prenex(Expression::Type)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -106,16 +100,9 @@ ExpressionPointer Expression::simplified()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Expression::disjunctionNormalized()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
[[ noreturn ]] ExpressionPointer Expression::decomposed(expressions::DerivedPredicates &)
|
||||
{
|
||||
throw output::TranslatorException("Expression is not in first-order negation normal form and cannot be decomposed");
|
||||
throw output::TranslatorException("expression cannot be decomposed (not normalized)");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -137,6 +124,14 @@ ExpressionPointer Expression::negated()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// TODO: implement better (visitor pattern?)
|
||||
void Expression::collectParameters(std::set<expressions::VariablePointer> &)
|
||||
{
|
||||
throw output::TranslatorException("expression parameters could not be collected (expression not normalized)");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext &expressionContext);
|
||||
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext);
|
||||
|
||||
|
@@ -19,6 +19,15 @@ namespace pddl
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class T>
|
||||
void translateVariablesHead(output::ColorStream &outputStream, const T &variables);
|
||||
template<class T>
|
||||
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);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TranslatorASP::TranslatorASP(Description &description, output::ColorStream &outputStream)
|
||||
: m_description(description),
|
||||
m_outputStream(outputStream)
|
||||
@@ -65,6 +74,13 @@ void TranslatorASP::translateDomain() const
|
||||
translatePredicates();
|
||||
}
|
||||
|
||||
// Derived predicates
|
||||
if (!domain.derivedPredicates().empty())
|
||||
{
|
||||
m_outputStream << std::endl;
|
||||
translateDerivedPredicates();
|
||||
}
|
||||
|
||||
// Actions
|
||||
if (!domain.actions().empty())
|
||||
{
|
||||
@@ -146,7 +162,7 @@ void TranslatorASP::translatePredicates() const
|
||||
}
|
||||
|
||||
m_outputStream << "(" << output::String(predicate->name().c_str());
|
||||
this->translateVariablesHead(predicate->arguments());
|
||||
translateVariablesHead(m_outputStream, predicate->arguments());
|
||||
m_outputStream << ")";
|
||||
};
|
||||
|
||||
@@ -162,7 +178,65 @@ void TranslatorASP::translatePredicates() const
|
||||
|
||||
m_outputStream << "))";
|
||||
|
||||
this->translateVariablesBody(predicate->arguments());
|
||||
translateVariablesBody(m_outputStream, predicate->arguments());
|
||||
|
||||
m_outputStream << ".";
|
||||
});
|
||||
|
||||
m_outputStream
|
||||
<< std::endl << std::endl
|
||||
<< output::Function("boolean") << "(" << output::Boolean("true") << ")." << std::endl
|
||||
<< output::Function("boolean") << "(" << output::Boolean("false") << ")." << std::endl
|
||||
<< std::endl
|
||||
<< output::Function("contains") << "("
|
||||
<< output::Keyword("variable") << "(" << output::Variable("X") << "), "
|
||||
<< output::Keyword("value") << "(" << output::Variable("X") << ", " << output::Variable("B") << ")) :- "
|
||||
<< output::Function("variable") << "(" << output::Keyword("variable") << "(" << output::Variable("X") << ")), "
|
||||
<< output::Function("boolean") << "(" << output::Variable("B") << ")."
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateDerivedPredicates() const
|
||||
{
|
||||
m_outputStream << output::Heading2("derived predicates");
|
||||
|
||||
const auto &derivedPredicates = m_description.domain().derivedPredicates();
|
||||
|
||||
const auto printDerivedPredicateName =
|
||||
[&](const auto &derivedPredicate)
|
||||
{
|
||||
if (derivedPredicate->parameters().empty())
|
||||
{
|
||||
// TODO: implement
|
||||
//m_outputStream << output::String(derivedPredicate->name().c_str());
|
||||
m_outputStream << "<derived>";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: implement
|
||||
//m_outputStream << output::String(derivedPredicate->name().c_str());
|
||||
m_outputStream << "<derived>";
|
||||
translateVariablesHead(m_outputStream, derivedPredicate->parameters());
|
||||
m_outputStream << ")";
|
||||
};
|
||||
|
||||
std::for_each(derivedPredicates.cbegin(), derivedPredicates.cend(),
|
||||
[&](const auto &predicate)
|
||||
{
|
||||
m_outputStream
|
||||
<< std::endl
|
||||
<< output::Function("variable") << "("
|
||||
<< output::Keyword("variable") << "(";
|
||||
|
||||
printDerivedPredicateName(predicate);
|
||||
|
||||
m_outputStream << "))";
|
||||
|
||||
// TODO: implement
|
||||
//translateVariablesBody(m_outputStream, predicate->arguments());
|
||||
|
||||
m_outputStream << ".";
|
||||
});
|
||||
@@ -201,15 +275,14 @@ void TranslatorASP::translateActions() const
|
||||
}
|
||||
|
||||
m_outputStream << "(" << output::String(action.name().c_str());
|
||||
this->translateVariablesHead(action.parameters());
|
||||
translateVariablesHead(m_outputStream, action.parameters());
|
||||
m_outputStream << "))";
|
||||
};
|
||||
|
||||
std::for_each(actions.cbegin(), actions.cend(),
|
||||
[&](const auto &action)
|
||||
{
|
||||
// TODO: rename
|
||||
const auto translateLiteral =
|
||||
const auto translateExpression =
|
||||
[&](const auto &ruleHead, const auto &literal, bool enumerateEffects = false)
|
||||
{
|
||||
m_outputStream << std::endl << output::Function(ruleHead) << "(";
|
||||
@@ -222,7 +295,7 @@ void TranslatorASP::translateActions() const
|
||||
|
||||
m_outputStream << ", ";
|
||||
|
||||
this->translateLiteral(literal);
|
||||
translateLiteral(m_outputStream, literal);
|
||||
|
||||
m_outputStream << ") :- " << output::Function("action") << "(";
|
||||
|
||||
@@ -238,7 +311,7 @@ void TranslatorASP::translateActions() const
|
||||
printActionName(*action);
|
||||
m_outputStream << ")";
|
||||
|
||||
this->translateVariablesBody(action->parameters());
|
||||
translateVariablesBody(m_outputStream, action->parameters());
|
||||
|
||||
m_outputStream << ".";
|
||||
|
||||
@@ -247,24 +320,29 @@ void TranslatorASP::translateActions() const
|
||||
{
|
||||
const auto &precondition = *action->precondition();
|
||||
|
||||
if (precondition.expressionType() == Expression::Type::Predicate
|
||||
|| precondition.expressionType() == Expression::Type::Not)
|
||||
switch (precondition.expressionType())
|
||||
{
|
||||
translateLiteral("precondition", precondition);
|
||||
}
|
||||
// Assuming a conjunction
|
||||
else
|
||||
{
|
||||
if (precondition.expressionType() != Expression::Type::And)
|
||||
throw output::TranslatorException("only “and” expressions and (negated) predicates supported as action preconditions currently");
|
||||
case Expression::Type::And:
|
||||
{
|
||||
const auto &andExpression = dynamic_cast<const expressions::And &>(precondition);
|
||||
|
||||
const auto &andExpression = dynamic_cast<const expressions::And &>(precondition);
|
||||
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
|
||||
[&](const auto argument)
|
||||
{
|
||||
translateExpression("precondition", *argument);
|
||||
});
|
||||
|
||||
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
|
||||
[&](const auto argument)
|
||||
{
|
||||
translateLiteral("precondition", *argument);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Expression::Type::Predicate:
|
||||
case Expression::Type::Not:
|
||||
case Expression::Type::DerivedPredicate:
|
||||
{
|
||||
translateExpression("precondition", precondition);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw output::TranslatorException("only “and” expressions and (negated) predicates supported as action preconditions currently (" + std::to_string((int)precondition.expressionType()) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +354,7 @@ void TranslatorASP::translateActions() const
|
||||
if (effect.expressionType() == Expression::Type::Predicate
|
||||
|| effect.expressionType() == Expression::Type::Not)
|
||||
{
|
||||
translateLiteral("postcondition", effect, true);
|
||||
translateExpression("postcondition", effect, true);
|
||||
}
|
||||
// Assuming a conjunction
|
||||
else
|
||||
@@ -289,7 +367,7 @@ void TranslatorASP::translateActions() const
|
||||
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
|
||||
[&](const auto argument)
|
||||
{
|
||||
translateLiteral("postcondition", *argument, true);
|
||||
translateExpression("postcondition", *argument, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -332,7 +410,8 @@ void TranslatorASP::translateConstants(const std::string &heading, const express
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateVariablesHead(const expressions::Variables &variables) const
|
||||
template<class T>
|
||||
void translateVariablesHead(output::ColorStream &outputStream, const T &variables)
|
||||
{
|
||||
if (variables.empty())
|
||||
return;
|
||||
@@ -341,25 +420,26 @@ void TranslatorASP::translateVariablesHead(const expressions::Variables &variabl
|
||||
{
|
||||
const auto &variable = **i;
|
||||
|
||||
m_outputStream << ", " << output::Variable(variable.name().c_str());
|
||||
outputStream << ", " << output::Variable(variable.name().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateVariablesBody(const expressions::Variables &variables) const
|
||||
template<class T>
|
||||
void translateVariablesBody(output::ColorStream &outputStream, const T &variables)
|
||||
{
|
||||
if (variables.empty())
|
||||
return;
|
||||
|
||||
m_outputStream << " :- ";
|
||||
outputStream << " :- ";
|
||||
|
||||
for (auto i = variables.cbegin(); i != variables.cend(); i++)
|
||||
{
|
||||
const auto &variable = **i;
|
||||
|
||||
if (i != variables.cbegin())
|
||||
m_outputStream << ", ";
|
||||
outputStream << ", ";
|
||||
|
||||
if (variable.type() != nullptr)
|
||||
{
|
||||
@@ -368,13 +448,13 @@ void TranslatorASP::translateVariablesBody(const expressions::Variables &variabl
|
||||
|
||||
const auto &type = dynamic_cast<const expressions::PrimitiveType &>(*variable.type());
|
||||
|
||||
m_outputStream << output::Function("has") << "("
|
||||
outputStream << output::Function("has") << "("
|
||||
<< output::Variable(variable.name().c_str()) << ", "
|
||||
<< output::Keyword("type") << "(" << output::String(type.name().c_str()) << "))";
|
||||
}
|
||||
else
|
||||
{
|
||||
m_outputStream << output::Function("has") << "("
|
||||
outputStream << output::Function("has") << "("
|
||||
<< output::Variable(variable.name().c_str()) << ", "
|
||||
<< output::Keyword("type") << "(" << output::String("object") << "))";
|
||||
}
|
||||
@@ -383,18 +463,18 @@ void TranslatorASP::translateVariablesBody(const expressions::Variables &variabl
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translateLiteral(const Expression &literal) const
|
||||
void translateLiteral(output::ColorStream &outputStream, const Expression &literal)
|
||||
{
|
||||
// Translate single predicate
|
||||
if (literal.expressionType() == Expression::Type::Predicate)
|
||||
{
|
||||
const auto &predicate = dynamic_cast<const expressions::Predicate &>(literal);
|
||||
|
||||
m_outputStream << output::Keyword("variable") << "(";
|
||||
this->translatePredicate(predicate);
|
||||
m_outputStream << "), " << output::Keyword("value") << "(";
|
||||
this->translatePredicate(predicate);
|
||||
m_outputStream << ", " << output::Boolean("true") << ")";
|
||||
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.expressionType() == Expression::Type::Not)
|
||||
@@ -406,11 +486,23 @@ void TranslatorASP::translateLiteral(const Expression &literal) const
|
||||
|
||||
const auto &predicate = dynamic_cast<const expressions::Predicate &>(*notExpression.argument());
|
||||
|
||||
m_outputStream << output::Keyword("variable") << "(";
|
||||
outputStream << output::Keyword("variable") << "(";
|
||||
translatePredicate(outputStream, predicate);
|
||||
outputStream << "), " << output::Keyword("value") << "(";
|
||||
translatePredicate(outputStream, predicate);
|
||||
outputStream << ", " << output::Boolean("false") << ")";
|
||||
}
|
||||
else if (literal.expressionType() == Expression::Type::DerivedPredicate)
|
||||
{
|
||||
const auto &derivedPredicate = dynamic_cast<const expressions::DerivedPredicate &>(literal);
|
||||
|
||||
/*m_outputStream << output::Keyword("variable") << "(";
|
||||
this->translatePredicate(predicate);
|
||||
m_outputStream << "), " << output::Keyword("value") << "(";
|
||||
this->translatePredicate(predicate);
|
||||
m_outputStream << ", " << output::Boolean("false") << ")";
|
||||
m_outputStream << ", " << output::Boolean("true") << ")";*/
|
||||
|
||||
outputStream << "(derived predicate)";
|
||||
}
|
||||
else
|
||||
throw output::TranslatorException("only primitive predicates and their negations supported as literals currently");
|
||||
@@ -418,40 +510,40 @@ void TranslatorASP::translateLiteral(const Expression &literal) const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TranslatorASP::translatePredicate(const expressions::Predicate &predicate) const
|
||||
void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate)
|
||||
{
|
||||
const auto &arguments = predicate.arguments();
|
||||
|
||||
if (arguments.empty())
|
||||
{
|
||||
m_outputStream << output::String(predicate.name().c_str());
|
||||
outputStream << output::String(predicate.name().c_str());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_outputStream << "(" << output::String(predicate.name().c_str());
|
||||
outputStream << "(" << output::String(predicate.name().c_str());
|
||||
|
||||
for (auto i = arguments.cbegin(); i != arguments.cend(); i++)
|
||||
{
|
||||
m_outputStream << ", ";
|
||||
outputStream << ", ";
|
||||
|
||||
if ((*i)->expressionType() == Expression::Type::Constant)
|
||||
{
|
||||
const auto &constant = dynamic_cast<const expressions::Constant &>(**i);
|
||||
|
||||
m_outputStream << output::Keyword("constant") << "(" << output::String(constant.name().c_str()) << ")";
|
||||
outputStream << output::Keyword("constant") << "(" << output::String(constant.name().c_str()) << ")";
|
||||
}
|
||||
else if ((*i)->expressionType() == Expression::Type::Variable)
|
||||
{
|
||||
const auto &variable = dynamic_cast<const expressions::Variable &>(**i);
|
||||
|
||||
m_outputStream << output::Variable(variable.name().c_str());
|
||||
outputStream << output::Variable(variable.name().c_str());
|
||||
}
|
||||
else
|
||||
throw output::TranslatorException("only variables and constants supported in predicates currently");
|
||||
}
|
||||
|
||||
m_outputStream << ")";
|
||||
outputStream << ")";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -501,9 +593,9 @@ void TranslatorASP::translateInitialState() const
|
||||
const auto &predicate = dynamic_cast<const expressions::Predicate &>(*fact);
|
||||
|
||||
m_outputStream << output::Keyword("variable") << "(";
|
||||
this->translatePredicate(predicate);
|
||||
translatePredicate(m_outputStream, predicate);
|
||||
m_outputStream << "), " << output::Keyword("value") << "(";
|
||||
this->translatePredicate(predicate);
|
||||
translatePredicate(m_outputStream, predicate);
|
||||
m_outputStream << ", " << output::Boolean("true") << ")";
|
||||
}
|
||||
// Assuming that "not" expression may only contain a predicate
|
||||
@@ -548,7 +640,7 @@ void TranslatorASP::translateGoal() const
|
||||
{
|
||||
m_outputStream << std::endl << output::Function("goal") << "(";
|
||||
|
||||
translateLiteral(goal);
|
||||
translateLiteral(m_outputStream, goal);
|
||||
|
||||
m_outputStream << ").";
|
||||
}
|
||||
@@ -561,7 +653,7 @@ void TranslatorASP::translateGoal() const
|
||||
{
|
||||
m_outputStream << std::endl << output::Function("goal") << "(";
|
||||
|
||||
this->translateLiteral(*argument);
|
||||
translateLiteral(m_outputStream, *argument);
|
||||
|
||||
m_outputStream << ").";
|
||||
});
|
||||
|
@@ -23,70 +23,18 @@ const std::string And::Identifier = "and";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer And::disjunctionNormalized()
|
||||
{
|
||||
for (size_t i = 0; i < m_arguments.size(); i++)
|
||||
{
|
||||
BOOST_ASSERT(m_arguments[i]);
|
||||
|
||||
m_arguments[i] = m_arguments[i]->disjunctionNormalized();
|
||||
}
|
||||
|
||||
const auto match = std::find_if(m_arguments.begin(), m_arguments.end(),
|
||||
[](const auto &argument)
|
||||
{
|
||||
return argument->expressionType() == Expression::Type::Or;
|
||||
});
|
||||
|
||||
if (match == m_arguments.end())
|
||||
return this;
|
||||
|
||||
auto orExpression = OrPointer(dynamic_cast<expressions::Or *>(match->get()));
|
||||
const size_t orExpressionIndex = match - m_arguments.begin();
|
||||
|
||||
// Apply the distributive law
|
||||
// Copy this and expression for each argument of the or expression
|
||||
for (size_t i = 0; i < orExpression->arguments().size(); i++)
|
||||
{
|
||||
auto newAndExpression = new expressions::And;
|
||||
newAndExpression->arguments().resize(m_arguments.size());
|
||||
|
||||
for (size_t j = 0; j < m_arguments.size(); j++)
|
||||
{
|
||||
if (j == orExpressionIndex)
|
||||
newAndExpression->arguments()[j] = orExpression->arguments()[i]->copy();
|
||||
else
|
||||
newAndExpression->arguments()[j] = m_arguments[j]->copy();
|
||||
}
|
||||
|
||||
// Replace the respective argument with the new, recursively normalized and expression
|
||||
orExpression->arguments()[i] = newAndExpression->disjunctionNormalized();
|
||||
}
|
||||
|
||||
return orExpression;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer And::decomposed(DerivedPredicates &derivedPredicates)
|
||||
{
|
||||
// Check that all children are simple or negated predicates
|
||||
std::for_each(m_arguments.begin(), m_arguments.end(),
|
||||
[&](auto &argument)
|
||||
{
|
||||
if (argument->expressionType() == Expression::Type::Not)
|
||||
{
|
||||
argument = argument->decomposed(derivedPredicates);
|
||||
return;
|
||||
}
|
||||
derivedPredicates.emplace_back(new DerivedPredicate());
|
||||
auto &derivedPredicate = derivedPredicates.back();
|
||||
|
||||
if (argument->expressionType() != Expression::Type::Predicate)
|
||||
return;
|
||||
for (auto &argument : m_arguments)
|
||||
argument = argument->decomposed(derivedPredicates);
|
||||
|
||||
throw output::TranslatorException("Expression is not in first-order negation normal form and cannot be decomposed");
|
||||
});
|
||||
// Move this expression’s arguments to the derived predicate
|
||||
derivedPredicate->setPreconditions({m_arguments});
|
||||
|
||||
return this;
|
||||
return derivedPredicate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -54,28 +54,17 @@ ExpressionPointer At::reduced()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer At::negationNormalized()
|
||||
ExpressionPointer At::existentiallyQuantified()
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
|
||||
m_argument = m_argument->negationNormalized();
|
||||
m_argument = m_argument->existentiallyQuantified();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer At::prenex(Expression::Type lastExpressionType)
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
|
||||
m_argument = m_argument->prenex(lastExpressionType);
|
||||
|
||||
return Expression::moveUpQuantifiers(this, m_argument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer At::simplified()
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
@@ -87,13 +76,9 @@ ExpressionPointer At::simplified()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer At::disjunctionNormalized()
|
||||
void At::collectParameters(std::set<VariablePointer> ¶meters)
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
|
||||
m_argument = m_argument->disjunctionNormalized();
|
||||
|
||||
return this;
|
||||
m_argument->collectParameters(parameters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -16,39 +16,97 @@ namespace expressions
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DerivedPredicate::DerivedPredicate(size_t id)
|
||||
: m_id{id}
|
||||
void DerivedPredicate::setPreconditions(std::vector<Expressions> &&preconditions)
|
||||
{
|
||||
m_preconditions = std::move(preconditions);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
size_t DerivedPredicate::id() const
|
||||
const std::vector<Expressions> &DerivedPredicate::preconditions() const
|
||||
{
|
||||
return m_id;
|
||||
return m_preconditions;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DerivedPredicate::setArgument(ExpressionPointer argument)
|
||||
void DerivedPredicate::collectParameters()
|
||||
{
|
||||
m_argument = argument;
|
||||
for (const auto &conjunction : m_preconditions)
|
||||
for (const auto &precondition : conjunction)
|
||||
precondition->collectParameters(m_parameters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer DerivedPredicate::argument() const
|
||||
const std::set<VariablePointer> &DerivedPredicate::parameters() const
|
||||
{
|
||||
return m_argument;
|
||||
return m_parameters;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DerivedPredicate::collectParameters(std::set<VariablePointer> ¶meters)
|
||||
{
|
||||
for (auto &conjunction : m_preconditions)
|
||||
for (auto &precondition : conjunction)
|
||||
precondition->collectParameters(m_parameters);
|
||||
|
||||
// Copy in order not to interfere with potentially bound variables in parent expressions
|
||||
parameters = m_parameters;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void DerivedPredicate::print(std::ostream &ostream) const
|
||||
{
|
||||
ostream << "(:derived <no name> ";
|
||||
m_argument->print(ostream);
|
||||
ostream << ")";
|
||||
ostream << "(:derived <no name>";
|
||||
|
||||
BOOST_ASSERT(m_preconditions.size() > 0);
|
||||
|
||||
const auto printConjunction =
|
||||
[&ostream](const auto &conjunction)
|
||||
{
|
||||
if (conjunction.size() == 0)
|
||||
{
|
||||
conjunction.front()->print(ostream);
|
||||
return;
|
||||
}
|
||||
|
||||
ostream << "(and";
|
||||
|
||||
for (const auto &precondition : conjunction)
|
||||
{
|
||||
ostream << " ";
|
||||
precondition->print(ostream);
|
||||
}
|
||||
|
||||
ostream << ")";
|
||||
};
|
||||
|
||||
if (m_preconditions.size() == 1)
|
||||
{
|
||||
const auto &conjunction = m_preconditions.front();
|
||||
|
||||
BOOST_ASSERT(conjunction.size() > 0);
|
||||
|
||||
printConjunction(conjunction);
|
||||
|
||||
ostream << ")";
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ostream << " (or";
|
||||
|
||||
for (const auto conjunction : m_preconditions)
|
||||
{
|
||||
ostream << " ";
|
||||
|
||||
printConjunction(conjunction);
|
||||
}
|
||||
|
||||
ostream << "))";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -20,15 +20,6 @@ const std::string Exists::Identifier = "exists";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Exists::decomposed(DerivedPredicates &derivedPredicates)
|
||||
{
|
||||
m_argument = m_argument->decomposed(derivedPredicates);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,8 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include <plasp/pddl/expressions/DerivedPredicate.h>
|
||||
#include <plasp/pddl/expressions/Exists.h>
|
||||
#include <plasp/pddl/expressions/Not.h>
|
||||
|
||||
namespace plasp
|
||||
{
|
||||
@@ -22,14 +23,16 @@ const std::string ForAll::Identifier = "forall";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer ForAll::decomposed(DerivedPredicates &derivedPredicates)
|
||||
ExpressionPointer ForAll::existentiallyQuantified()
|
||||
{
|
||||
auto derivedPredicate = DerivedPredicatePointer(new DerivedPredicate(derivedPredicates.size()));
|
||||
derivedPredicates.push_back(derivedPredicate);
|
||||
auto existsExpression = ExistsPointer(new Exists());
|
||||
auto notExpression = NotPointer(new Not());
|
||||
|
||||
derivedPredicate->setArgument(this);
|
||||
notExpression->setArgument(m_argument->existentiallyQuantified());
|
||||
existsExpression->setArgument(notExpression);
|
||||
existsExpression->variables() = std::move(m_variables);
|
||||
|
||||
return derivedPredicate;
|
||||
return existsExpression;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@@ -62,113 +62,61 @@ ExpressionPointer Not::reduced()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Not::negationNormalized()
|
||||
ExpressionPointer Not::existentiallyQuantified()
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
|
||||
// Remove immediate double negations
|
||||
if (m_argument->expressionType() == Expression::Type::Not)
|
||||
{
|
||||
auto &argument = dynamic_cast<Not &>(*m_argument);
|
||||
|
||||
return argument.m_argument->negationNormalized();
|
||||
}
|
||||
|
||||
// Normalize argument
|
||||
m_argument = m_argument->negationNormalized();
|
||||
|
||||
// Remove double negations occurring after normalizing the argument
|
||||
if (m_argument->expressionType() == Expression::Type::Not)
|
||||
{
|
||||
auto &argument = dynamic_cast<Not &>(*m_argument);
|
||||
|
||||
return argument.m_argument;
|
||||
}
|
||||
|
||||
// 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->negationNormalized();
|
||||
}
|
||||
|
||||
// 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->negationNormalized();
|
||||
}
|
||||
|
||||
// De Morgen for existential quantifiers
|
||||
if (m_argument->expressionType() == Expression::Type::Exists)
|
||||
{
|
||||
auto &existsExpression = dynamic_cast<Exists &>(*m_argument);
|
||||
auto forAllExpression = ForAllPointer(new ForAll);
|
||||
|
||||
forAllExpression->setArgument(existsExpression.argument()->negated());
|
||||
|
||||
return forAllExpression->negationNormalized();
|
||||
}
|
||||
|
||||
// De Morgen for universal quantifiers
|
||||
if (m_argument->expressionType() == Expression::Type::ForAll)
|
||||
{
|
||||
auto &forAllExpression = dynamic_cast<ForAll &>(*m_argument);
|
||||
auto existsExpression = ExistsPointer(new Exists);
|
||||
|
||||
existsExpression->setArgument(forAllExpression.argument()->negated());
|
||||
|
||||
return existsExpression->negationNormalized();
|
||||
}
|
||||
m_argument = m_argument->existentiallyQuantified();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Not::prenex(Expression::Type lastExpressionType)
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
|
||||
m_argument = m_argument->prenex(lastExpressionType);
|
||||
|
||||
return Expression::moveUpQuantifiers(this, m_argument);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Not::simplified()
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
|
||||
m_argument = m_argument->simplified();
|
||||
|
||||
// Remove double negations
|
||||
if (m_argument->expressionType() == Expression::Type::Not)
|
||||
{
|
||||
const auto ¬Expression = dynamic_cast<expressions::Not &>(*m_argument);
|
||||
|
||||
return notExpression.argument();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Not::disjunctionNormalized()
|
||||
void Not::collectParameters(std::set<VariablePointer> ¶meters)
|
||||
{
|
||||
BOOST_ASSERT(m_argument);
|
||||
m_argument->collectParameters(parameters);
|
||||
}
|
||||
|
||||
m_argument = m_argument->disjunctionNormalized();
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
return this;
|
||||
ExpressionPointer Not::decomposed(DerivedPredicates &derivedPredicates)
|
||||
{
|
||||
m_argument = m_argument->decomposed(derivedPredicates);
|
||||
|
||||
// Predicates and derived predicates can be directly negated
|
||||
if (m_argument->expressionType() == Expression::Type::Predicate
|
||||
|| m_argument->expressionType() == Expression::Type::DerivedPredicate)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
derivedPredicates.emplace_back(new DerivedPredicate());
|
||||
auto &derivedPredicate = derivedPredicates.back();
|
||||
|
||||
// Move this expression’s arguments to the derived predicate
|
||||
derivedPredicate->setPreconditions({{this}});
|
||||
|
||||
return derivedPredicate;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -184,19 +132,6 @@ void Not::print(std::ostream &ostream) const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Not::decomposed(DerivedPredicates &)
|
||||
{
|
||||
if (m_argument->expressionType() != Expression::Type::Not
|
||||
&& m_argument->expressionType() != Expression::Type::Predicate)
|
||||
{
|
||||
throw output::TranslatorException("Expression is not in first-order negation normal form and cannot be decomposed");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include <plasp/pddl/expressions/Or.h>
|
||||
|
||||
#include <plasp/output/TranslatorException.h>
|
||||
#include <plasp/pddl/expressions/And.h>
|
||||
#include <plasp/pddl/expressions/DerivedPredicate.h>
|
||||
|
||||
namespace plasp
|
||||
@@ -21,17 +23,38 @@ const std::string Or::Identifier = "or";
|
||||
|
||||
ExpressionPointer Or::decomposed(DerivedPredicates &derivedPredicates)
|
||||
{
|
||||
// Check that all children are simple or negated predicates
|
||||
std::for_each(m_arguments.begin(), m_arguments.end(),
|
||||
[&](auto &argument)
|
||||
derivedPredicates.emplace_back(new DerivedPredicate());
|
||||
auto &derivedPredicate = derivedPredicates.back();
|
||||
|
||||
std::vector<Expressions> preconditions;
|
||||
|
||||
for (auto &argument : m_arguments)
|
||||
{
|
||||
Expressions conjunction;
|
||||
|
||||
// “and” expressions can directly be inlined into the derived predicate
|
||||
if (argument->expressionType() == Expression::Type::And)
|
||||
{
|
||||
argument = argument->decomposed(derivedPredicates);
|
||||
});
|
||||
const auto &andExpression = dynamic_cast<expressions::And &>(*argument);
|
||||
|
||||
auto derivedPredicate = DerivedPredicatePointer(new DerivedPredicate(derivedPredicates.size()));
|
||||
derivedPredicates.push_back(derivedPredicate);
|
||||
conjunction = std::move(andExpression.arguments());
|
||||
|
||||
derivedPredicate->setArgument(this);
|
||||
for (auto &argument : conjunction)
|
||||
argument = argument->decomposed(derivedPredicates);
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
conjunction.emplace_back(argument->decomposed(derivedPredicates));
|
||||
break;
|
||||
}
|
||||
|
||||
// Move this expression’s arguments to the derived predicate
|
||||
preconditions.emplace_back(std::move(conjunction));
|
||||
}
|
||||
|
||||
derivedPredicate->setPreconditions(std::move(preconditions));
|
||||
|
||||
return derivedPredicate;
|
||||
}
|
||||
|
@@ -156,6 +156,22 @@ bool Predicate::isDeclared() const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExpressionPointer Predicate::decomposed(expressions::DerivedPredicates &)
|
||||
{
|
||||
// Predicates cannot be further decomposed
|
||||
return this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Predicate::collectParameters(std::set<VariablePointer> ¶meters)
|
||||
{
|
||||
for (const auto &argument : m_arguments)
|
||||
argument->collectParameters(parameters);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const std::string &Predicate::name() const
|
||||
{
|
||||
return m_name;
|
||||
|
@@ -143,33 +143,6 @@ void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expre
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
VariablePointer Variable::parseAndFind(Context &context, const ExpressionContext &expressionContext)
|
||||
{
|
||||
auto &parser = context.parser;
|
||||
|
||||
parser.skipWhiteSpace();
|
||||
|
||||
parser.expect<std::string>("?");
|
||||
|
||||
const auto variableName = parser.parseIdentifier();
|
||||
|
||||
const auto &variables = expressionContext.parameters;
|
||||
|
||||
const auto match = std::find_if(variables.cbegin(), variables.cend(),
|
||||
[&](const auto &variable)
|
||||
{
|
||||
return variable->name() == variableName;
|
||||
});
|
||||
|
||||
if (match == variables.cend())
|
||||
throw input::ParserException(parser.location(), "parameter “" + variableName + "” used but never declared");
|
||||
|
||||
return match->get();
|
||||
}*/
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Variable::setName(std::string name)
|
||||
{
|
||||
m_name = name;
|
||||
@@ -212,6 +185,13 @@ bool Variable::isDirty() const
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Variable::collectParameters(std::set<VariablePointer> ¶meters)
|
||||
{
|
||||
parameters.emplace(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Variable::print(std::ostream &ostream) const
|
||||
{
|
||||
ostream << "?" << m_name;
|
||||
|
Reference in New Issue
Block a user