patrick
/
plasp
Archived
1
0
Fork 0

Reimplemented plasp with PDDL parsing library.

This commit is contained in:
Patrick Lühne 2017-06-20 01:53:55 +02:00
parent 9c7532bd9d
commit e345fd60fd
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
76 changed files with 459 additions and 7080 deletions

View File

@ -7,6 +7,8 @@ set(includes
${Boost_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/lib/tokenize/include
${PROJECT_SOURCE_DIR}/lib/variant/include
${PROJECT_SOURCE_DIR}/lib/pddlparse/include
)
set(sources

View File

@ -4,10 +4,14 @@
#include <boost/program_options.hpp>
#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>
#include <plasp/LanguageDetection.h>
#include <plasp/output/ColorStream.h>
#include <plasp/output/Logger.h>
#include <plasp/output/Priority.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/Description.h>
#include <plasp/pddl/TranslatorASP.h>
#include <plasp/sas/Description.h>
#include <plasp/sas/TranslatorASP.h>
@ -148,9 +152,15 @@ int main(int argc, char **argv)
if (language == plasp::Language::Type::PDDL)
{
auto context = plasp::pddl::Context(std::move(tokenizer), logger);
auto description = plasp::pddl::Description::fromContext(context);
const auto translator = plasp::pddl::TranslatorASP(description, logger.outputStream());
const auto logWarning =
[&](const auto &location, const auto &warning)
{
logger.log(plasp::output::Priority::Warning, location, warning);
};
auto context = pddl::Context(std::move(tokenizer), logWarning);
auto description = pddl::parseDescription(context);
const auto translator = plasp::pddl::TranslatorASP(std::move(description), logger.outputStream());
translator.translate();
}
else if (language == plasp::Language::Type::SAS)

View File

@ -1,51 +0,0 @@
#ifndef __PLASP__PDDL__ACTION_H
#define __PLASP__PDDL__ACTION_H
#include <vector>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Variable.h>
#include <tokenize/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Action
{
public:
static void parseDeclaration(Context &context, Domain &domain);
public:
const std::string &name() const;
const expressions::Variables &parameters() const;
const Expression *precondition() const;
const Expression *effect() const;
void normalize(expressions::DerivedPredicates &derivedPredicates);
private:
Action() = default;
std::string m_name;
expressions::Variables m_parameters;
ExpressionPointer m_precondition;
ExpressionPointer m_effect;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,57 +0,0 @@
#ifndef __PLASP__PDDL__CONSISTENCY_EXCEPTION_H
#define __PLASP__PDDL__CONSISTENCY_EXCEPTION_H
#include <exception>
#include <string>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ConsistencyException
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ConsistencyException: public std::exception
{
public:
explicit ConsistencyException()
: ConsistencyException("unspecified consistency error")
{
}
explicit ConsistencyException(const char *message)
: ConsistencyException(static_cast<std::string>(message))
{
}
explicit ConsistencyException(const std::string &message)
: m_message{message}
{
}
~ConsistencyException() throw()
{
}
const char *what() const throw()
{
if (m_message.empty())
return "unspecified consistency error";
return m_message.c_str();
}
private:
std::string m_message;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,59 +0,0 @@
#ifndef __PLASP__PDDL__CONTEXT_H
#define __PLASP__PDDL__CONTEXT_H
#include <memory>
#include <unordered_map>
#include <vector>
#include <plasp/output/Logger.h>
#include <plasp/pddl/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Context
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context
{
public:
Context() = default;
~Context() = default;
explicit Context(Tokenizer &&otherTokenizer, output::Logger &otherLogger)
: tokenizer{std::move(otherTokenizer)},
logger(otherLogger)
{
}
Context(const Context &other) = delete;
Context &operator=(const Context &other) = delete;
Context(Context &&other)
: tokenizer(std::move(other.tokenizer)),
logger(other.logger)
{
}
Context &operator=(Context &&other) = delete;
constexpr static const char *auxiliaryPrefix()
{
return "__plasp_";
}
Tokenizer tokenizer;
output::Logger &logger;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,60 +0,0 @@
#ifndef __PLASP__PDDL__DESCRIPTION_H
#define __PLASP__PDDL__DESCRIPTION_H
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/Problem.h>
#include <tokenize/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Description
{
public:
static Description fromContext(Context &context);
static Description fromStream(std::istream &istream, Context &context);
static Description fromFile(const std::string &path, Context &context);
static Description fromFiles(const std::vector<std::string> &paths, Context &context);
public:
Context &context();
const Context &context() const;
const Domain &domain() const;
bool containsProblem() const;
const Problem &problem() const;
void normalize();
private:
Description(Context &context);
void parse();
void findSections();
void checkConsistency();
Context &m_context;
tokenize::StreamPosition m_domainPosition;
std::unique_ptr<Domain> m_domain;
tokenize::StreamPosition m_problemPosition;
std::unique_ptr<Problem> m_problem;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,101 +0,0 @@
#ifndef __PLASP__PDDL__DOMAIN_H
#define __PLASP__PDDL__DOMAIN_H
#include <plasp/pddl/Action.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Requirement.h>
#include <plasp/pddl/Tokenizer.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/DerivedPredicate.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Domain
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Domain
{
public:
Domain(Context &context);
public:
void findSections();
void parse();
void setName(std::string name);
const std::string &name() const;
const Requirements &requirements() const;
bool hasRequirement(Requirement::Type requirementType) const;
void checkRequirement(Requirement::Type requirementType);
expressions::PrimitiveTypes &types();
const expressions::PrimitiveTypes &types() const;
expressions::Constants &constants();
const expressions::Constants &constants() const;
expressions::PredicateDeclarations &predicates();
const expressions::PredicateDeclarations &predicates() const;
std::vector<std::unique_ptr<Action>> &actions();
const std::vector<std::unique_ptr<Action>> &actions() const;
expressions::DerivedPredicates &derivedPredicates();
const expressions::DerivedPredicates &derivedPredicates() const;
void checkConsistency();
void normalize();
private:
void parseSection();
void parseRequirementSection();
void computeDerivedRequirements();
void parseTypeSection();
void parseConstantSection();
void parsePredicateSection();
void parseActionSection();
Context &m_context;
std::string m_name;
tokenize::StreamPosition m_requirementsPosition;
Requirements m_requirements;
tokenize::StreamPosition m_typesPosition;
expressions::PrimitiveTypes m_types;
tokenize::StreamPosition m_constantsPosition;
expressions::Constants m_constants;
tokenize::StreamPosition m_predicatesPosition;
expressions::PredicateDeclarations m_predicates;
std::vector<tokenize::StreamPosition> m_actionPositions;
std::vector<std::unique_ptr<Action>> m_actions;
expressions::DerivedPredicates m_derivedPredicates;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,237 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSION_H
#define __PLASP__PDDL__EXPRESSION_H
#include <iosfwd>
#include <set>
#include <boost/intrusive_ptr.hpp>
#include <tokenize/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Expression
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context;
class Domain;
class ExpressionContext;
class ExpressionVisitor;
class Problem;
class Expression;
using ExpressionPointer = boost::intrusive_ptr<Expression>;
using Expressions = std::vector<ExpressionPointer>;
namespace expressions
{
class And;
using AndPointer = boost::intrusive_ptr<And>;
class At;
using AtPointer = boost::intrusive_ptr<At>;
class Constant;
using ConstantPointer = boost::intrusive_ptr<Constant>;
using Constants = std::vector<ConstantPointer>;
class DerivedPredicate;
using DerivedPredicatePointer = boost::intrusive_ptr<DerivedPredicate>;
using DerivedPredicates = std::vector<DerivedPredicatePointer>;
class Dummy;
using DummyPointer = boost::intrusive_ptr<Dummy>;
class Either;
using EitherPointer = boost::intrusive_ptr<Either>;
class Exists;
using ExistsPointer = boost::intrusive_ptr<Exists>;
class ForAll;
using ForAllPointer = boost::intrusive_ptr<ForAll>;
class Imply;
using ImplyPointer = boost::intrusive_ptr<Imply>;
class Not;
using NotPointer = boost::intrusive_ptr<Not>;
class Or;
using OrPointer = boost::intrusive_ptr<Or>;
class Predicate;
using PredicatePointer = boost::intrusive_ptr<Predicate>;
using Predicates = std::vector<PredicatePointer>;
class PredicateDeclaration;
using PredicateDeclarationPointer = boost::intrusive_ptr<PredicateDeclaration>;
using PredicateDeclarations = std::vector<PredicateDeclarationPointer>;
class PrimitiveType;
using PrimitiveTypePointer = boost::intrusive_ptr<PrimitiveType>;
using PrimitiveTypes = std::vector<PrimitiveTypePointer>;
class Quantified;
using QuantifiedPointer = boost::intrusive_ptr<Quantified>;
template<class Type>
class Reference;
template<class Type>
using ReferencePointer = boost::intrusive_ptr<Reference<Type>>;
class Unsupported;
using UnsupportedPointer = boost::intrusive_ptr<Unsupported>;
class Variable;
using VariablePointer = boost::intrusive_ptr<Variable>;
using Variables = std::vector<VariablePointer>;
class When;
using WhenPointer = boost::intrusive_ptr<When>;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
class Expression
{
public:
enum class Type
{
And,
At,
Binary,
Constant,
DerivedPredicate,
Dummy,
Either,
Exists,
ForAll,
Imply,
Not,
Or,
PredicateDeclaration,
Predicate,
PrimitiveType,
Reference,
Unsupported,
Variable,
When,
};
public:
virtual ~Expression() = default;
virtual Type expressionType() const = 0;
template<class T>
bool is() const;
template<class T>
T &as();
template<class T>
const T &as() const;
virtual ExpressionPointer copy();
// Transform into a normal form as used for the translation to ASP
ExpressionPointer normalized();
// Reduce the set of used expressions (eliminates implications, for instance)
virtual ExpressionPointer reduced();
// Transform such that only existential (and no universal) quantifiers are used
virtual ExpressionPointer existentiallyQuantified();
// Simplify the expression equivalently
virtual ExpressionPointer simplified();
// Decompose expression into derived predicates (eliminate recursively nested expressions)
virtual ExpressionPointer decomposed(expressions::DerivedPredicates &derivedPredicates);
// Negate the expression
ExpressionPointer negated();
virtual void collectParameters(std::set<expressions::VariablePointer> &parameters);
virtual void print(std::ostream &ostream) const = 0;
private:
friend void intrusive_ptr_add_ref(Expression *expression);
friend void intrusive_ptr_release(Expression *expression);
size_t m_referenceCount = 0;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
bool Expression::is() const
{
return expressionType() == T::ExpressionType;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
T &Expression::as()
{
return dynamic_cast<T &>(*this);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class T>
const T &Expression::as() const
{
return dynamic_cast<const T &>(*this);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void intrusive_ptr_add_ref(Expression *expression)
{
expression->m_referenceCount++;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void intrusive_ptr_release(Expression *expression)
{
if (--expression->m_referenceCount == 0)
delete expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class ExpressionCRTP: public Expression
{
public:
Type expressionType() const override final
{
return Derived::ExpressionType;
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseLiteral(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parsePreconditionExpression(Context &context,
ExpressionContext &expressionContext);
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext);
ExpressionPointer parseEffectExpression(Context &context,
ExpressionContext &expressionContext);
ExpressionPointer parseConditionalEffectExpression(Context &context,
ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,39 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSION_CONTEXT_H
#define __PLASP__PDDL__EXPRESSION_CONTEXT_H
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Requirement.h>
#include <plasp/pddl/VariableStack.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ExpressionContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ExpressionContext
{
public:
ExpressionContext(Domain &domain);
ExpressionContext(Domain &domain, Problem *problem);
bool hasRequirement(Requirement::Type requirementType) const;
void checkRequirement(Requirement::Type requirementType) const;
Domain &domain;
Problem *problem;
VariableStack variables;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,45 +0,0 @@
#ifndef __PLASP__PDDL__IO_H
#define __PLASP__PDDL__IO_H
#include <iostream>
#include <plasp/pddl/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// IO
//
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void skipSection(Tokenizer &tokenizer)
{
size_t openParentheses = 1;
while (true)
{
const auto character = tokenizer.currentCharacter();
tokenizer.advance();
if (character == '(')
openParentheses++;
else if (character == ')')
{
openParentheses--;
if (openParentheses == 0)
return;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,35 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__INITIAL_STATE_H
#define __PLASP__PDDL__EXPRESSIONS__INITIAL_STATE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// InitialState
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class InitialState
{
public:
static std::unique_ptr<InitialState> parseDeclaration(Context &context,
ExpressionContext &expressionContext);
public:
const Expressions &facts() const;
private:
Expressions m_facts;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,87 +0,0 @@
#ifndef __PLASP__PDDL__PROBLEM_H
#define __PLASP__PDDL__PROBLEM_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/InitialState.h>
#include <plasp/pddl/Requirement.h>
#include <plasp/pddl/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Problem
{
public:
Problem(Context &context, Domain &domain);
void findSections();
void parse();
Domain &domain();
const Domain &domain() const;
const std::string &name() const;
const Requirements &requirements() const;
bool hasRequirement(Requirement::Type requirementType) const;
void checkRequirement(Requirement::Type requirementType);
expressions::Constants &objects();
const expressions::Constants &objects() const;
InitialState &initialState();
const InitialState &initialState() const;
const Expression &goal() const;
void checkConsistency();
void normalize();
private:
void parseRequirementSection();
void computeDerivedRequirements();
void parseDomainSection();
void parseObjectSection();
void parseInitialStateSection();
void parseGoalSection();
Context &m_context;
Domain &m_domain;
std::string m_name;
tokenize::StreamPosition m_domainPosition;
tokenize::StreamPosition m_requirementsPosition;
Requirements m_requirements;
tokenize::StreamPosition m_objectsPosition;
expressions::Constants m_objects;
tokenize::StreamPosition m_initialStatePosition;
std::unique_ptr<InitialState> m_initialState;
tokenize::StreamPosition m_goalPosition;
ExpressionPointer m_goal;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,72 +0,0 @@
#ifndef __PLASP__PDDL__REQUIREMENT_H
#define __PLASP__PDDL__REQUIREMENT_H
#include <vector>
#include <plasp/pddl/Context.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirement
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Requirement;
using Requirements = std::vector<Requirement>;
////////////////////////////////////////////////////////////////////////////////////////////////////
class Requirement
{
public:
enum class Type
{
STRIPS,
Typing,
NegativePreconditions,
DisjunctivePreconditions,
Equality,
ExistentialPreconditions,
UniversalPreconditions,
QuantifiedPreconditions,
ConditionalEffects,
Fluents,
NumericFluents,
ObjectFluents,
ADL,
DurativeActions,
DurationInequalities,
ContinuousEffects,
DerivedPredicates,
TimedInitialLiterals,
Preferences,
Constraints,
ActionCosts,
GoalUtilities
};
static Requirement parse(Context &context);
public:
Requirement(Type type);
Type type() const;
std::string toPDDL() const;
std::string toASP() const;
private:
Type m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,54 +0,0 @@
#ifndef __PLASP__PDDL__TOKENIZER_H
#define __PLASP__PDDL__TOKENIZER_H
#include <tokenize/Tokenizer.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Tokenizer
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class PDDLTokenizerPolicy
{
public:
static char transformCharacter(char c) noexcept
{
return std::tolower(c);
}
static bool isWhiteSpaceCharacter(char c)
{
return std::iswspace(c);
}
static bool isBlankCharacter(char c)
{
return std::isblank(c);
}
static bool isIdentifierCharacter(char c)
{
return c != '?'
&& c != '('
&& c != ')'
&& c != ';'
&& std::isgraph(c);
}
};
////////////////////////////////////////////////////////////////////////////////////////////////////
using Tokenizer = tokenize::Tokenizer<PDDLTokenizerPolicy>;
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,9 +1,10 @@
#ifndef __PLASP__PDDL__TRANSLATOR_ASP_H
#define __PLASP__PDDL__TRANSLATOR_ASP_H
#include <plasp/pddl/Description.h>
#include <plasp/output/ColorStream.h>
#include <iosfwd>
#include <pddlparse/ASTForward.h>
#include <pddlparse/Parse.h>
namespace plasp
{
@ -19,7 +20,7 @@ namespace pddl
class TranslatorASP
{
public:
explicit TranslatorASP(Description &description, output::ColorStream &outputStream);
explicit TranslatorASP(const ::pddl::ast::Description &description, output::ColorStream &outputStream);
void translate() const;
@ -27,15 +28,14 @@ class TranslatorASP
void translateDomain() const;
void translateTypes() const;
void translatePredicates() const;
void translateDerivedPredicates() const;
void translateActions() const;
void translateProblem() const;
void translateInitialState() const;
void translateGoal() const;
void translateConstants(const std::string &heading, const expressions::Constants &constants) const;
void translateConstants(const std::string &heading, const ::pddl::ast::ConstantDeclarations &constants) const;
Description &m_description;
const ::pddl::ast::Description &m_description;
output::ColorStream &m_outputStream;
};

View File

@ -1,34 +0,0 @@
#ifndef __PLASP__PDDL__VARIABLE_STACK_H
#define __PLASP__PDDL__VARIABLE_STACK_H
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VariableStack
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class VariableStack
{
public:
void push(expressions::Variables *variables);
void pop();
expressions::VariablePointer parseAndFind(Context &context);
private:
std::vector<expressions::Variables *> m_variableStack;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,36 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__AND_H
#define __PLASP__PDDL__EXPRESSIONS__AND_H
#include <plasp/pddl/expressions/NAry.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// And
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class And: public NAry<And>
{
public:
static const Expression::Type ExpressionType = Expression::Type::And;
static const std::string Identifier;
public:
ExpressionPointer decomposed(DerivedPredicates &derivedPredicates) override;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,112 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__AT_H
#define __PLASP__PDDL__EXPRESSIONS__AT_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// At
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class At: public ExpressionCRTP<At>
{
public:
static const Expression::Type ExpressionType = Expression::Type::At;
template<typename ExpressionParser>
static AtPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
static const size_t TimePointStart = std::numeric_limits<size_t>::max();
static const size_t TimePointEnd = std::numeric_limits<size_t>::max() - 1;
public:
At();
ExpressionPointer copy() override;
size_t timePoint() const;
void setArgument(ExpressionPointer argument);
ExpressionPointer argument() const;
ExpressionPointer reduced() override;
ExpressionPointer existentiallyQuantified() override;
ExpressionPointer simplified() override;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
protected:
size_t m_timePoint;
ExpressionPointer m_argument;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
AtPointer At::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("(")
|| !tokenizer.testIdentifierAndSkip("at"))
{
tokenizer.seek(position);
return nullptr;
}
size_t timePoint;
const auto timePointPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("start"))
timePoint = TimePointStart;
else if (tokenizer.testIdentifierAndSkip("end"))
timePoint = TimePointEnd;
else if (tokenizer.probeNumber())
{
tokenizer.seek(timePointPosition);
timePoint = tokenizer.get<size_t>();
}
else
{
tokenizer.seek(position);
return nullptr;
}
auto expression = AtPointer(new At);
expression->m_timePoint = timePoint;
tokenizer.skipWhiteSpace();
// Parse argument
expression->setArgument(parseExpression(context, expressionContext));
tokenizer.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,195 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__BINARY_H
#define __PLASP__PDDL__EXPRESSIONS__BINARY_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Exists.h>
#include <plasp/pddl/expressions/ForAll.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Binary
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class Binary: public ExpressionCRTP<Derived>
{
public:
template<typename ExpressionParser>
static boost::intrusive_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
ExpressionPointer copy() override;
void setArgument(size_t i, ExpressionPointer argument);
std::array<ExpressionPointer, 2> &arguments();
const std::array<ExpressionPointer, 2> &arguments() const;
ExpressionPointer reduced() override;
ExpressionPointer existentiallyQuantified() override;
ExpressionPointer simplified() override;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
protected:
std::array<ExpressionPointer, 2> m_arguments;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
boost::intrusive_ptr<Derived> Binary<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("(")
|| !tokenizer.testIdentifierAndSkip(Derived::Identifier))
{
tokenizer.seek(position);
return nullptr;
}
auto expression = boost::intrusive_ptr<Derived>(new Derived);
// Parse arguments of the expression
expression->Binary<Derived>::setArgument(0, parseExpression(context, expressionContext));
expression->Binary<Derived>::setArgument(1, parseExpression(context, expressionContext));
tokenizer.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
ExpressionPointer Binary<Derived>::copy()
{
auto result = new Derived;
for (size_t i = 0; i < m_arguments.size(); i++)
result->m_arguments[i] = m_arguments[i]->copy();
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
void Binary<Derived>::setArgument(size_t i, ExpressionPointer expression)
{
BOOST_ASSERT_MSG(i <= m_arguments.size(), "Index out of range");
m_arguments[i] = expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
std::array<ExpressionPointer, 2> &Binary<Derived>::arguments()
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const std::array<ExpressionPointer, 2> &Binary<Derived>::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer Binary<Derived>::reduced()
{
for (auto &argument : m_arguments)
{
BOOST_ASSERT(argument);
argument = argument->reduced();
}
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer Binary<Derived>::existentiallyQuantified()
{
for (auto &argument : m_arguments)
{
BOOST_ASSERT(argument);
argument = argument->existentiallyQuantified();
}
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer Binary<Derived>::simplified()
{
for (auto &argument : m_arguments)
{
BOOST_ASSERT(argument);
argument = argument->simplified();
}
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline void Binary<Derived>::collectParameters(std::set<VariablePointer> &parameters)
{
for (const auto &argument : m_arguments)
argument->collectParameters(parameters);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline void Binary<Derived>::print(std::ostream &ostream) const
{
ostream << "(" << Derived::Identifier;
std::for_each(m_arguments.begin(), m_arguments.end(),
[&](auto &argument)
{
ostream << " ";
argument->print(ostream);
});
ostream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,64 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__CONSTANT_H
#define __PLASP__PDDL__EXPRESSIONS__CONSTANT_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Constant: public ExpressionCRTP<Constant>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Constant;
static void parseTypedDeclaration(Context &context, Domain &domain);
static void parseTypedDeclarations(Context &context, Domain &domain);
static void parseTypedDeclaration(Context &context, Problem &problem);
static void parseTypedDeclarations(Context &context, Problem &problem);
static ConstantPointer parseAndFind(Context &context, const Domain &domain);
static ConstantPointer parseAndFind(Context &context, const Problem &problem);
public:
const std::string &name() const;
PrimitiveTypePointer type() const;
void print(std::ostream &ostream) const override;
private:
static ConstantPointer parseDeclaration(Context &context);
static void parseTypedDeclaration(Context &context, Domain &domain, Constants &constants);
static ConstantPointer parseAndFind(const std::string &constantName, const Constants &constants);
Constant();
void setDirty(bool isDirty = true);
bool isDirty() const;
void setType(PrimitiveTypePointer parentType);
bool m_isDirty;
std::string m_name;
PrimitiveTypePointer m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,59 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__DERIVED_PREDICATE_H
#define __PLASP__PDDL__EXPRESSIONS__DERIVED_PREDICATE_H
#include <set>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DerivedPredicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class DerivedPredicate: public ExpressionCRTP<DerivedPredicate>
{
public:
static const Expression::Type ExpressionType = Expression::Type::DerivedPredicate;
// 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<Expressions> &&preconditions);
const std::vector<Expressions> &preconditions() const;
const std::set<VariablePointer> &parameters() const;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
private:
void collectParameters();
size_t m_id;
// The arguments are interpreted as a disjunction of conjunctions
std::vector<Expressions> m_preconditions;
std::set<VariablePointer> m_parameters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,39 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__DUMMY_H
#define __PLASP__PDDL__EXPRESSIONS__DUMMY_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Dummy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Dummy: public ExpressionCRTP<Dummy>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Dummy;
public:
Dummy(std::string name);
void print(std::ostream &ostream) const override;
private:
std::string m_name;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,33 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__EITHER_H
#define __PLASP__PDDL__EXPRESSIONS__EITHER_H
#include <plasp/pddl/expressions/NAry.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Either
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Either: public NAry<Either>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Either;
static const std::string Identifier;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,33 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__EXISTS_H
#define __PLASP__PDDL__EXPRESSIONS__EXISTS_H
#include <plasp/pddl/expressions/Quantified.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Exists
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Exists: public QuantifiedCRTP<Exists>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Exists;
static const std::string Identifier;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,36 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__FOR_ALL_H
#define __PLASP__PDDL__EXPRESSIONS__FOR_ALL_H
#include <plasp/pddl/expressions/Quantified.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ForAll
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class ForAll: public QuantifiedCRTP<ForAll>
{
public:
static const Expression::Type ExpressionType = Expression::Type::ForAll;
static const std::string Identifier;
public:
ExpressionPointer existentiallyQuantified() override;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,36 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__IMPLY_H
#define __PLASP__PDDL__EXPRESSIONS__IMPLY_H
#include <plasp/pddl/expressions/Binary.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Imply
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Imply: public Binary<Imply>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Imply;
static const std::string Identifier;
public:
ExpressionPointer reduced() override;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,239 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__N_ARY_H
#define __PLASP__PDDL__EXPRESSIONS__N_ARY_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/expressions/Exists.h>
#include <plasp/pddl/expressions/ForAll.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// NAry
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class NAry: public ExpressionCRTP<Derived>
{
public:
template<typename ExpressionParser>
static boost::intrusive_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
ExpressionPointer copy() override;
void setArgument(size_t i, ExpressionPointer argument);
void addArgument(ExpressionPointer argument);
Expressions &arguments();
const Expressions &arguments() const;
ExpressionPointer reduced() override;
ExpressionPointer existentiallyQuantified() override;
ExpressionPointer simplified() override;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
protected:
Expressions m_arguments;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
boost::intrusive_ptr<Derived> NAry<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("(")
|| !tokenizer.testIdentifierAndSkip(Derived::Identifier))
{
tokenizer.seek(position);
return nullptr;
}
auto expression = boost::intrusive_ptr<Derived>(new Derived);
tokenizer.skipWhiteSpace();
// Parse arguments of the expression
while (tokenizer.currentCharacter() != ')')
{
expression->addArgument(parseExpression(context, expressionContext));
tokenizer.skipWhiteSpace();
}
if (expression->m_arguments.empty())
context.logger.log(output::Priority::Warning, tokenizer, "" + Derived::Identifier + "” expressions should not be empty");
tokenizer.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
ExpressionPointer NAry<Derived>::copy()
{
auto result = new Derived;
result->m_arguments.resize(m_arguments.size());
for (size_t i = 0; i < m_arguments.size(); i++)
result->m_arguments[i] = m_arguments[i]->copy();
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
void NAry<Derived>::setArgument(size_t i, ExpressionPointer expression)
{
BOOST_ASSERT_MSG(i <= m_arguments.size(), "Index out of range");
m_arguments[i] = expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
void NAry<Derived>::addArgument(ExpressionPointer argument)
{
if (!argument)
return;
m_arguments.emplace_back(argument);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
const Expressions &NAry<Derived>::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
Expressions &NAry<Derived>::arguments()
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer NAry<Derived>::reduced()
{
for (auto &argument : m_arguments)
{
BOOST_ASSERT(argument);
argument = argument->reduced();
}
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer NAry<Derived>::existentiallyQuantified()
{
for (auto &argument : m_arguments)
{
BOOST_ASSERT(argument);
argument = argument->existentiallyQuantified();
}
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer NAry<Derived>::simplified()
{
// Associate same-type children, such as (a && (b && c)) == (a && b && c)
for (size_t i = 0; i < m_arguments.size();)
{
auto &argument = m_arguments[i];
argument = argument->simplified();
if (argument->expressionType() != Derived::ExpressionType)
{
i++;
continue;
}
auto &nAryExpression = argument->template as<Derived>();
BOOST_ASSERT(!nAryExpression.arguments().empty());
// Remove former child by replacing it with the first one of the child
m_arguments[i] = nAryExpression.arguments().front();
// Reserve space for new arguments
m_arguments.reserve(m_arguments.size() + nAryExpression.arguments().size() - 1);
// Copy all but first element
m_arguments.insert(m_arguments.end(), nAryExpression.arguments().begin() + 1, nAryExpression.arguments().end());
}
// TODO: recognize tautologies
// TODO: introduce/handle boolean values
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline void NAry<Derived>::collectParameters(std::set<VariablePointer> &parameters)
{
for (const auto &argument : m_arguments)
argument->collectParameters(parameters);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline void NAry<Derived>::print(std::ostream &ostream) const
{
ostream << "(" << Derived::Identifier;
for (const auto &argument : m_arguments)
{
ostream << " ";
argument->print(ostream);
}
ostream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,85 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__NOT_H
#define __PLASP__PDDL__EXPRESSIONS__NOT_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Not
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Not: public ExpressionCRTP<Not>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Not;
template<typename ExpressionParser>
static NotPointer parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression);
public:
Not();
ExpressionPointer copy() override;
void setArgument(ExpressionPointer argument);
ExpressionPointer argument() const;
ExpressionPointer reduced() override;
ExpressionPointer existentiallyQuantified() override;
ExpressionPointer simplified() override;
ExpressionPointer decomposed(DerivedPredicates &derivedPredicates) override;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
protected:
ExpressionPointer m_argument;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ExpressionParser>
NotPointer Not::parse(Context &context, ExpressionContext &expressionContext,
ExpressionParser parseExpression)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("(")
|| !tokenizer.testIdentifierAndSkip("not"))
{
tokenizer.seek(position);
return nullptr;
}
auto expression = NotPointer(new Not);
tokenizer.skipWhiteSpace();
// Parse argument
expression->setArgument(parseExpression(context, expressionContext));
tokenizer.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,36 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__OR_H
#define __PLASP__PDDL__EXPRESSIONS__OR_H
#include <plasp/pddl/expressions/NAry.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Or
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Or: public NAry<Or>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Or;
static const std::string Identifier;
public:
ExpressionPointer decomposed(DerivedPredicates &derivedPredicates) override;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,56 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__PREDICATE_H
#define __PLASP__PDDL__EXPRESSIONS__PREDICATE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Predicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Predicate: public ExpressionCRTP<Predicate>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Predicate;
static PredicatePointer parse(Context &context, ExpressionContext &expressionContext);
static PredicatePointer parse(Context &context, const Problem &problem);
public:
const std::string &name() const;
const Expressions &arguments() const;
bool isDeclared() const;
ExpressionPointer decomposed(DerivedPredicates &derivedPredicates) override;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
private:
Predicate();
void setDeclared();
bool m_isDeclared;
std::string m_name;
Expressions m_arguments;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,53 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__PREDICATE_DECLARATION_H
#define __PLASP__PDDL__EXPRESSIONS__PREDICATE_DECLARATION_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PredicateDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class PredicateDeclaration: public ExpressionCRTP<PredicateDeclaration>
{
public:
static const Expression::Type ExpressionType = Expression::Type::PredicateDeclaration;
static void parse(Context &context, Domain &domain);
public:
const std::string &name() const;
const Variables &parameters() const;
bool isDeclared() const;
void normalizeParameterNames();
void print(std::ostream &ostream) const override;
private:
PredicateDeclaration();
void setDeclared();
bool m_isDeclared;
std::string m_name;
Variables m_parameters;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,55 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__PRIMITIVE_TYPE_H
#define __PLASP__PDDL__EXPRESSIONS__PRIMITIVE_TYPE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveType
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class PrimitiveType: public ExpressionCRTP<PrimitiveType>
{
public:
static const Expression::Type ExpressionType = Expression::Type::PrimitiveType;
static void parseDeclaration(Context &context, Domain &domain);
static void parseTypedDeclaration(Context &context, Domain &domain);
static PrimitiveTypePointer parseAndFind(Context &context, Domain &domain);
public:
PrimitiveType();
PrimitiveType(std::string name);
const std::string &name() const;
const PrimitiveTypes &parentTypes() const;
void print(std::ostream &ostream) const override;
private:
void setDirty(bool isDirty = true);
bool isDirty() const;
bool m_isDirty;
std::string m_name;
PrimitiveTypes m_parentTypes;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,250 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__QUANTIFIED_H
#define __PLASP__PDDL__EXPRESSIONS__QUANTIFIED_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/DerivedPredicate.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Quantified
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Quantified: public Expression
{
public:
void setArgument(ExpressionPointer argument);
ExpressionPointer argument() const;
Variables &variables();
const Variables &variables() const;
protected:
Variables m_variables;
ExpressionPointer m_argument;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
class QuantifiedCRTP: public Quantified
{
public:
template<typename ExpressionParser>
static boost::intrusive_ptr<Derived> parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression);
public:
Type expressionType() const override final
{
return Derived::ExpressionType;
}
ExpressionPointer copy() override;
ExpressionPointer reduced() override;
ExpressionPointer existentiallyQuantified() override;
ExpressionPointer simplified() override;
ExpressionPointer decomposed(DerivedPredicates &derivedPredicates) override;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
template<typename ExpressionParser>
boost::intrusive_ptr<Derived> QuantifiedCRTP<Derived>::parse(Context &context,
ExpressionContext &expressionContext, ExpressionParser parseExpression)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("(")
|| !tokenizer.testIdentifierAndSkip(Derived::Identifier))
{
tokenizer.seek(position);
return nullptr;
}
auto expression = boost::intrusive_ptr<Derived>(new Derived);
// Parse variable list
tokenizer.expect<std::string>("(");
Variable::parseTypedDeclarations(context, expressionContext, expression->m_variables);
tokenizer.expect<std::string>(")");
// Push newly parsed variables to the stack
expressionContext.variables.push(&expression->m_variables);
// Parse argument of the expression
expression->Quantified::setArgument(parseExpression(context, expressionContext));
// Clean up variable stack
expressionContext.variables.pop();
tokenizer.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
ExpressionPointer QuantifiedCRTP<Derived>::copy()
{
auto result = new Derived;
result->m_argument = m_argument->copy();
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void Quantified::setArgument(ExpressionPointer expression)
{
m_argument = expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline ExpressionPointer Quantified::argument() const
{
return m_argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline Variables &Quantified::variables()
{
return m_variables;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline const Variables &Quantified::variables() const
{
return m_variables;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer QuantifiedCRTP<Derived>::reduced()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->reduced();
// Child quantifiers may not move before this quantifier, the order matters
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer QuantifiedCRTP<Derived>::existentiallyQuantified()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->existentiallyQuantified();
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer QuantifiedCRTP<Derived>::simplified()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->simplified();
// Associate same-type children, such as (forall (?x) (forall (?y) (...)))
if (m_argument->expressionType() != Derived::ExpressionType)
return this;
auto &quantifiedExpression = m_argument->template as<Derived>();
// Unify variables
m_variables.insert(m_variables.end(), quantifiedExpression.variables().begin(), quantifiedExpression.variables().end());
// Move child expression up
m_argument = quantifiedExpression.argument();
// TODO: introduce/handle boolean values
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline ExpressionPointer QuantifiedCRTP<Derived>::decomposed(DerivedPredicates &derivedPredicates)
{
derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size()));
auto derivedPredicate = derivedPredicates.back();
m_argument = m_argument->decomposed(derivedPredicates);
derivedPredicate->setPreconditions({{this}});
return derivedPredicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline void QuantifiedCRTP<Derived>::collectParameters(std::set<VariablePointer> &parameters)
{
m_argument->collectParameters(parameters);
// Remove bound variables
for (const auto &variable : m_variables)
parameters.erase(variable);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class Derived>
inline void QuantifiedCRTP<Derived>::print(std::ostream &ostream) const
{
ostream << "(" << Derived::Identifier << " (";
for (size_t i = 0; i < m_variables.size(); i++)
{
if (i > 0)
ostream << " ";
m_variables[i]->print(ostream);
}
ostream << ") ";
m_argument->print(ostream);
ostream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,28 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__TYPE_H
#define __PLASP__PDDL__EXPRESSIONS__TYPE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Type
//
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveTypePointer parseExistingPrimitiveType(Context &context,
ExpressionContext &expressionContext);
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,42 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__UNSUPPORTED_H
#define __PLASP__PDDL__EXPRESSIONS__UNSUPPORTED_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Unsupported
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Unsupported: public ExpressionCRTP<Unsupported>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Unsupported;
static UnsupportedPointer parse(Context &context);
public:
const std::string &type() const;
void print(std::ostream &ostream) const override;
private:
std::string m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,63 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__VARIABLE_H
#define __PLASP__PDDL__EXPRESSIONS__VARIABLE_H
#include <plasp/pddl/Expression.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Variable: public ExpressionCRTP<Variable>
{
public:
static const Expression::Type ExpressionType = Expression::Type::Variable;
static void parseTypedDeclaration(Context &context, ExpressionContext &expressionContext,
Variables &variables);
static void parseTypedDeclarations(Context &context, ExpressionContext &expressionContext,
Variables &variables);
public:
Variable();
Variable(std::string name);
void setName(std::string name);
const std::string &name() const;
void setType(ExpressionPointer type);
ExpressionPointer type() const;
void setDirty(bool isDirty = true);
bool isDirty() const;
void collectParameters(std::set<VariablePointer> &parameters) override;
void print(std::ostream &ostream) const override;
private:
static void parseDeclaration(Context &context, Variables &parameters);
private:
bool m_isDirty;
std::string m_name;
ExpressionPointer m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -1,67 +0,0 @@
#ifndef __PLASP__PDDL__EXPRESSIONS__WHEN_H
#define __PLASP__PDDL__EXPRESSIONS__WHEN_H
#include <plasp/pddl/expressions/Binary.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// When
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class When: public Binary<When>
{
public:
static const Expression::Type ExpressionType = Expression::Type::When;
static const std::string Identifier;
template<typename ConditionExpressionParser, typename ImplicationExpressionParser>
static WhenPointer parse(Context &context, ExpressionContext &expressionContext,
ConditionExpressionParser parseConditionExpression,
ImplicationExpressionParser parseImplicationExpression);
};
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename ConditionExpressionParser, typename ImplicationExpressionParser>
WhenPointer When::parse(Context &context, ExpressionContext &expressionContext,
ConditionExpressionParser parseConditionExpression,
ImplicationExpressionParser parseImplicationExpression)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("(")
|| !tokenizer.testIdentifierAndSkip(Identifier))
{
tokenizer.seek(position);
return nullptr;
}
auto expression = WhenPointer(new When);
// Parse arguments of the expression
expression->setArgument(0, parseConditionExpression(context, expressionContext));
expression->setArgument(1, parseImplicationExpression(context, expressionContext));
tokenizer.expect<std::string>(")");
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}
#endif

View File

@ -0,0 +1,79 @@
#ifndef __PLASP__PDDL__TRANSLATION__EFFECT_H
#define __PLASP__PDDL__TRANSLATION__EFFECT_H
#include <pddlparse/AST.h>
#include <plasp/output/Formatting.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/translation/Predicate.h>
#include <plasp/pddl/translation/Primitives.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Effect
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename PrintObjectName>
inline void translateEffect(output::ColorStream &outputStream, const ::pddl::ast::Effect &effect, const std::string &objectType, PrintObjectName printObjectName)
{
const auto handleUnsupported =
[](const auto &)
{
throw output::TranslatorException("only “and” expressions and (negated) predicates supported as action effects currently");
};
const auto handlePredicate =
[&](const ::pddl::ast::PredicatePointer &predicate, bool isPositive = true)
{
outputStream << std::endl << output::Function("postcondition") << "(";
printObjectName();
outputStream
<< ", " << output::Keyword("effect") << "("
<< output::Reserved("unconditional") << ")"
<< ", ";
translatePredicateToVariable(outputStream, *predicate, isPositive);
outputStream << ") :- " << output::Function(objectType.c_str()) << "(";
printObjectName();
outputStream << ").";
};
const auto handleAtomicFormula =
[&](const ::pddl::ast::AtomicFormula &atomicFormula)
{
atomicFormula.match(handlePredicate, handleUnsupported);
};
const auto handleNot =
[&](const ::pddl::ast::NotPointer<::pddl::ast::Effect> &not_)
{
if (!not_->argument.is<::pddl::ast::AtomicFormula>() || !not_->argument.get<::pddl::ast::AtomicFormula>().is<::pddl::ast::PredicatePointer>())
handleUnsupported(not_);
const auto &predicate = not_->argument.get<::pddl::ast::AtomicFormula>().get<::pddl::ast::PredicatePointer>();
handlePredicate(predicate, false);
};
const auto handleAnd =
[&](const ::pddl::ast::AndPointer<::pddl::ast::Effect> &and_)
{
for (const auto &argument : and_->arguments)
translateEffect(outputStream, argument, objectType, printObjectName);
};
effect.match(handleAtomicFormula, handleNot, handleAnd, handleUnsupported);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -0,0 +1,72 @@
#ifndef __PLASP__PDDL__TRANSLATION__GOAL_H
#define __PLASP__PDDL__TRANSLATION__GOAL_H
#include <pddlparse/AST.h>
#include <plasp/output/Formatting.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/translation/Predicate.h>
#include <plasp/pddl/translation/Primitives.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Goal
//
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void translateGoal(output::ColorStream &outputStream, const ::pddl::ast::Goal &goal)
{
const auto handleUnsupported =
[](const auto &)
{
throw output::TranslatorException("only “and” expressions and (negated) predicates supported as goals currently");
};
const auto handlePredicate =
[&](const ::pddl::ast::PredicatePointer &predicate, bool isPositive = true)
{
outputStream << std::endl << output::Function("goal") << "(";
// TODO: assert that goal is variable-free
translatePredicateToVariable(outputStream, *predicate, isPositive);
outputStream << ").";
};
const auto handleAtomicFormula =
[&](const ::pddl::ast::AtomicFormula &atomicFormula)
{
atomicFormula.match(handlePredicate, handleUnsupported);
};
const auto handleNot =
[&](const ::pddl::ast::NotPointer<::pddl::ast::Goal> &not_)
{
if (!not_->argument.is<::pddl::ast::AtomicFormula>() || !not_->argument.get<::pddl::ast::AtomicFormula>().is<::pddl::ast::PredicatePointer>())
handleUnsupported(not_);
const auto &predicate = not_->argument.get<::pddl::ast::AtomicFormula>().get<::pddl::ast::PredicatePointer>();
handlePredicate(predicate, false);
};
const auto handleAnd =
[&](const ::pddl::ast::AndPointer<::pddl::ast::Goal> &and_)
{
for (const auto &argument : and_->arguments)
translateGoal(outputStream, argument);
};
goal.match(handleAtomicFormula, handleNot, handleAnd, handleUnsupported);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -1,16 +1,18 @@
#ifndef __PLASP__PDDL__TRANSLATION__PRECONDITION_H
#define __PLASP__PDDL__TRANSLATION__PRECONDITION_H
#include <pddlparse/AST.h>
#include <plasp/output/Formatting.h>
#include <plasp/pddl/Description.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/translation/Predicate.h>
#include <plasp/pddl/translation/Primitives.h>
namespace plasp
{
namespace pddl
{
namespace translation
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -18,57 +20,56 @@ namespace translation
//
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class PrintObjectName>
void translatePreconditionDisjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, const std::vector<Expressions> &preconditionDisjunction);
template<class PrintObjectName>
void translatePreconditionConjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, size_t disjunctionID, const Expressions &preconditionConjunction);
template<class PrintObjectName>
void translatePrecondition(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, size_t disjunctionID, const Expression &precondition);
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class PrintObjectName>
inline void translatePreconditionDisjunction(output::ColorStream &outputStream, const std::string &objectType, PrintObjectName printObjectName, const std::vector<Expressions> &preconditionDisjunction)
template<typename PrintObjectName>
inline void translatePrecondition(output::ColorStream &outputStream, const ::pddl::ast::Precondition &precondition, const std::string &objectType, PrintObjectName printObjectName)
{
for (size_t i = 0; i < preconditionDisjunction.size(); i++)
translatePreconditionConjunction(outputStream, objectType, printObjectName, i, preconditionDisjunction[i]);
const auto handleUnsupported =
[](const auto &)
{
throw output::TranslatorException("only “and” expressions and (negated) predicates supported as action preconditions currently");
};
const auto handlePredicate =
[&](const ::pddl::ast::PredicatePointer &predicate, bool isPositive = true)
{
outputStream << std::endl << output::Function("precondition") << "(";
printObjectName();
outputStream << ", ";
translatePredicateToVariable(outputStream, *predicate, isPositive);
outputStream << ") :- " << output::Function(objectType.c_str()) << "(";
printObjectName();
outputStream << ").";
};
const auto handleAtomicFormula =
[&](const ::pddl::ast::AtomicFormula &atomicFormula)
{
atomicFormula.match(handlePredicate, handleUnsupported);
};
const auto handleNot =
[&](const ::pddl::ast::NotPointer<::pddl::ast::Precondition> &not_)
{
if (!not_->argument.is<::pddl::ast::AtomicFormula>() || !not_->argument.get<::pddl::ast::AtomicFormula>().is<::pddl::ast::PredicatePointer>())
handleUnsupported(not_);
const auto &predicate = not_->argument.get<::pddl::ast::AtomicFormula>().get<::pddl::ast::PredicatePointer>();
handlePredicate(predicate, false);
};
const auto handleAnd =
[&](const ::pddl::ast::AndPointer<::pddl::ast::Precondition> &and_)
{
for (const auto &argument : and_->arguments)
translatePrecondition(outputStream, argument, objectType, printObjectName);
};
precondition.match(handleAtomicFormula, handleNot, handleAnd, handleUnsupported);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
template<class PrintObjectName>
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<class PrintObjectName>
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<decltype(disjunctionID)>(disjunctionID)
<< "), ";
translateLiteral(outputStream, precondition);
outputStream << ") :- " << output::Function(objectType.c_str()) << "(";
printObjectName(outputStream);
outputStream << ").";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,20 +1,18 @@
#ifndef __PLASP__PDDL__TRANSLATION__PREDICATE_H
#define __PLASP__PDDL__TRANSLATION__PREDICATE_H
#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>
#include <plasp/output/Formatting.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/DerivedPredicate.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/Variable.h>
#include <plasp/pddl/translation/Primitives.h>
#include <plasp/pddl/translation/Variables.h>
namespace plasp
{
namespace pddl
{
namespace translation
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -22,44 +20,46 @@ namespace translation
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate);
void translateDerivedPredicate(output::ColorStream &outputStream, const expressions::DerivedPredicate &derivedPredicate);
void printPredicateName(output::ColorStream &outputStream, const expressions::PredicateDeclaration &predicateDeclaration);
void printDerivedPredicateName(output::ColorStream &outputStream, const expressions::DerivedPredicate &derivedPredicate);
void translatePredicate(output::ColorStream &outputStream, const ::pddl::ast::Predicate &predicate);
void translatePredicateDeclaration(output::ColorStream &outputStream, const ::pddl::ast::PredicateDeclaration &predicateDeclaration);
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void translatePredicate(output::ColorStream &outputStream, const expressions::Predicate &predicate)
inline void translatePredicate(output::ColorStream &outputStream, const ::pddl::ast::Predicate &predicate)
{
const auto &arguments = predicate.arguments();
const auto &arguments = predicate.arguments;
if (arguments.empty())
{
outputStream << output::String(predicate.name().c_str());
outputStream << *predicate.declaration;
return;
}
outputStream << "(" << output::String(predicate.name().c_str());
outputStream << "(" << *predicate.declaration;
for (const auto &argument : arguments)
{
outputStream << ", ";
if (argument->is<expressions::Constant>())
{
const auto &constant = argument->as<expressions::Constant>();
const auto handleConstant =
[&](const ::pddl::ast::ConstantPointer &constant)
{
outputStream << output::Keyword("constant") << "(" << *constant << ")";
};
outputStream << output::Keyword("constant") << "(" << output::String(constant.name().c_str()) << ")";
}
else if (argument->is<expressions::Variable>())
{
const auto &variable = argument->as<expressions::Variable>();
const auto handleVariable =
[&](const ::pddl::ast::VariablePointer &variable)
{
outputStream << *variable;
};
outputStream << output::Variable(variable.name().c_str());
}
else
throw output::TranslatorException("only variables and constants supported in predicates currently");
const auto handleUnsupported =
[&](const auto &)
{
throw output::TranslatorException("only variables and constants supported in predicates currently");
};
argument.match(handleConstant, handleVariable, handleUnsupported);
}
outputStream << ")";
@ -67,64 +67,41 @@ inline void translatePredicate(output::ColorStream &outputStream, const expressi
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void translateDerivedPredicate(output::ColorStream &outputStream, const expressions::DerivedPredicate &derivedPredicate)
{
const auto &parameters = derivedPredicate.parameters();
const auto id = derivedPredicate.id();
if (parameters.empty())
{
outputStream << output::Number<decltype(id)>(id);
return;
}
outputStream << "(" << output::Number<decltype(id)>(id);
for (const auto &parameter : parameters)
outputStream << ", " << output::Variable(parameter->name().c_str());
outputStream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void printPredicateName(output::ColorStream &outputStream, const expressions::PredicateDeclaration &predicateDeclaration)
inline void translatePredicateDeclaration(output::ColorStream &outputStream, const ::pddl::ast::PredicateDeclaration &predicateDeclaration)
{
outputStream << output::Keyword("variable") << "(";
if (predicateDeclaration.parameters().empty())
if (predicateDeclaration.parameters.empty())
{
outputStream << output::String(predicateDeclaration.name().c_str()) << ")";
outputStream << predicateDeclaration << ")";
return;
}
outputStream << "(" << output::String(predicateDeclaration.name().c_str());
translation::translateVariablesForRuleHead(outputStream, predicateDeclaration.parameters());
outputStream << "(" << predicateDeclaration;
translateVariablesForRuleHead(outputStream, predicateDeclaration.parameters);
outputStream << "))";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void printDerivedPredicateName(output::ColorStream &outputStream, const expressions::DerivedPredicate &derivedPredicate)
void translatePredicateToVariable(output::ColorStream &outputStream, const ::pddl::ast::Predicate &predicate, bool isPositive = true)
{
outputStream << output::Keyword("derivedVariable") << "(";
outputStream << output::Keyword("variable") << "(";
translatePredicate(outputStream, predicate);
outputStream << "), " << output::Keyword("value") << "(";
translatePredicate(outputStream, predicate);
outputStream << ", ";
const auto id = derivedPredicate.id();
if (isPositive)
outputStream << output::Boolean("true");
else
outputStream << output::Boolean("false");
if (derivedPredicate.parameters().empty())
{
outputStream << output::Number<decltype(id)>(id) << ")";
return;
}
outputStream << "(" << output::Number<decltype(id)>(id);
translation::translateVariablesForRuleHead(outputStream, derivedPredicate.parameters());
outputStream << "))";
outputStream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,19 +1,15 @@
#ifndef __PLASP__PDDL__TRANSLATION__PRIMITIVES_H
#define __PLASP__PDDL__TRANSLATION__PRIMITIVES_H
#include <pddlparse/AST.h>
#include <plasp/output/Formatting.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/Description.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/translation/Predicate.h>
namespace plasp
{
namespace pddl
{
namespace translation
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -21,56 +17,91 @@ namespace translation
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void translateLiteral(output::ColorStream &outputStream, const Expression &literal);
////////////////////////////////////////////////////////////////////////////////////////////////////
inline void translateLiteral(output::ColorStream &outputStream, const Expression &literal)
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::ConstantDeclaration &constantDeclaration)
{
// Translate single predicate
if (literal.is<expressions::Predicate>())
{
const auto &predicate = literal.as<expressions::Predicate>();
assert(!constantDeclaration.name.empty());
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<expressions::Not>())
{
const auto &notExpression = literal.as<expressions::Not>();
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<expressions::Predicate>();
outputStream << output::Keyword("variable") << "(";
translation::translatePredicate(outputStream, predicate);
outputStream << "), " << output::Keyword("value") << "(";
translation::translatePredicate(outputStream, predicate);
outputStream << ", " << output::Boolean("false") << ")";
}
else if (literal.is<expressions::DerivedPredicate>())
{
const auto &derivedPredicate = literal.as<expressions::DerivedPredicate>();
outputStream << output::Keyword("derivedVariable") << "(";
translation::translateDerivedPredicate(outputStream, derivedPredicate);
outputStream << "), " << output::Keyword("value") << "(";
translation::translateDerivedPredicate(outputStream, derivedPredicate);
outputStream << ", " << output::Boolean("true") << ")";
}
else
throw output::TranslatorException("only primitive predicates and their negations supported as literals currently");
return (stream << output::String(constantDeclaration.name.c_str()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::Constant &constant)
{
assert(constant.declaration != nullptr);
return (stream << *constant.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::PrimitiveTypeDeclaration &primitiveTypeDeclaration)
{
assert(!primitiveTypeDeclaration.name.empty());
return (stream << output::String(primitiveTypeDeclaration.name.c_str()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::PrimitiveType &primitiveType)
{
assert(primitiveType.declaration != nullptr);
return (stream << *primitiveType.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, ::pddl::ast::VariableDeclaration &variableDeclaration)
{
assert(!variableDeclaration.name.empty());
assert(std::isalpha(variableDeclaration.name[0]));
if (!std::isupper(variableDeclaration.name[0]))
variableDeclaration.name[0] = std::toupper(variableDeclaration.name[0]);
return (stream
<< output::Format({output::Color::Green, output::FontWeight::Bold})
<< variableDeclaration.name
<< output::ResetFormat());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
inline output::ColorStream &operator<<(output::ColorStream &stream, ::pddl::ast::Variable &variable)
{
assert(variable.declaration != nullptr);
return (stream << *variable.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: move to appropriate header
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::Action &action)
{
return (stream << output::String(action.name.c_str()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: move to appropriate header
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::PredicateDeclaration &predicateDeclaration)
{
return (stream << output::String(predicateDeclaration.name.c_str()));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: move to appropriate header
inline output::ColorStream &operator<<(output::ColorStream &stream, const ::pddl::ast::Predicate &predicate)
{
return (stream << *predicate.declaration);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,6 +1,9 @@
#ifndef __PLASP__PDDL__TRANSLATION__VARIABLES_H
#define __PLASP__PDDL__TRANSLATION__VARIABLES_H
#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>
#include <plasp/output/Formatting.h>
#include <plasp/output/TranslatorException.h>
@ -8,8 +11,6 @@ namespace plasp
{
namespace pddl
{
namespace translation
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
@ -30,12 +31,8 @@ inline void translateVariablesForRuleHead(output::ColorStream &outputStream, con
if (variables.empty())
return;
for (auto i = variables.cbegin(); i != variables.cend(); i++)
{
const auto &variable = **i;
outputStream << ", " << output::Variable(variable.name().c_str());
}
for (const auto &variable : variables)
outputStream << ", " << *variable;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -48,28 +45,25 @@ inline void translateVariablesForRuleBody(output::ColorStream &outputStream, con
outputStream << " :- ";
for (auto i = variables.cbegin(); i != variables.cend(); i++)
for (const auto &variable : variables)
{
const auto &variable = **i;
if (i != variables.cbegin())
if (variable.get() != variables.begin()->get())
outputStream << ", ";
if (variable.type() != nullptr)
if (variable->type)
{
if (variable.type()->expressionType() != Expression::Type::PrimitiveType)
if (!variable->type.value().template is<::pddl::ast::PrimitiveTypePointer>())
throw output::TranslatorException("only primitive types supported currently");
const auto &type = variable.type()->template as<expressions::PrimitiveType>();
const auto &type = variable->type.value().template get<::pddl::ast::PrimitiveTypePointer>();
outputStream << output::Function("has") << "("
<< output::Variable(variable.name().c_str()) << ", "
<< output::Keyword("type") << "(" << output::String(type.name().c_str()) << "))";
<< *variable << ", " << output::Keyword("type") << "(" << *type << "))";
}
else
{
outputStream << output::Function("has") << "("
<< output::Variable(variable.name().c_str()) << ", "
<< *variable << ", "
<< output::Keyword("type") << "(" << output::String("object") << "))";
}
}
@ -77,7 +71,6 @@ inline void translateVariablesForRuleBody(output::ColorStream &outputStream, con
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -28,6 +28,8 @@ set(includes
${Boost_INCLUDE_DIRS}
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/lib/tokenize/include
${PROJECT_SOURCE_DIR}/lib/variant/include
${PROJECT_SOURCE_DIR}/lib/pddlparse/include
)
set(sources
@ -59,6 +61,7 @@ set(sources
set(libraries
${Boost_LIBRARIES}
tokenize
pddlparse
pthread
)

View File

@ -1,118 +0,0 @@
#include <plasp/pddl/Action.h>
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/Type.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Action
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void Action::parseDeclaration(Context &context, Domain &domain)
{
auto &tokenizer = context.tokenizer;
auto action = std::make_unique<Action>(Action());
action->m_name = tokenizer.getIdentifier();
tokenizer.expect<std::string>(":parameters");
tokenizer.expect<std::string>("(");
ExpressionContext expressionContext(domain);
expressionContext.variables.push(&action->m_parameters);
// Read parameters
expressions::Variable::parseTypedDeclarations(context, expressionContext, action->m_parameters);
tokenizer.expect<std::string>(")");
// Parse preconditions and effects
while (!tokenizer.testAndReturn(')'))
{
tokenizer.expect<std::string>(":");
if (tokenizer.testIdentifierAndSkip("precondition"))
action->m_precondition = parsePreconditionExpression(context, expressionContext);
else if (tokenizer.testIdentifierAndSkip("effect"))
action->m_effect = parseEffectExpression(context, expressionContext);
tokenizer.skipWhiteSpace();
}
// Store new action
expressionContext.domain.actions().emplace_back(std::move(action));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Action::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Variables &Action::parameters() const
{
return m_parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Action::precondition() const
{
BOOST_ASSERT(m_precondition);
return m_precondition.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression *Action::effect() const
{
BOOST_ASSERT(m_effect);
return m_effect.get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Action::normalize(expressions::DerivedPredicates &derivedPredicates)
{
// Normalize preconditions and effects
m_precondition = m_precondition->normalized()->decomposed(derivedPredicates);
{
m_precondition->print(std::cout);
// TODO: refactor
std::set<expressions::VariablePointer> parameters;
m_precondition->collectParameters(parameters);
}
m_effect = m_effect->normalized();
{
// TODO: refactor
std::set<expressions::VariablePointer> parameters;
m_effect->collectParameters(parameters);
}
// Normalize parameter names
for (size_t i = 0; i < m_parameters.size(); i++)
m_parameters[i]->setName("X" + std::to_string(i));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,220 +0,0 @@
#include <plasp/pddl/Description.h>
#include <fstream>
#include <sstream>
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/IO.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Description::Description(Context &context)
: m_context(context),
m_domainPosition{tokenize::InvalidStreamPosition},
m_domain{std::make_unique<Domain>(Domain(m_context))},
m_problemPosition{tokenize::InvalidStreamPosition}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromContext(Context &context)
{
Description description(context);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromStream(std::istream &istream, Context &context)
{
Description description(context);
description.m_context.tokenizer.read("std::cin", istream);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromFile(const std::string &path, Context &context)
{
Description description(context);
description.m_context.tokenizer.read(path);
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Description Description::fromFiles(const std::vector<std::string> &paths, Context &context)
{
BOOST_ASSERT(!paths.empty());
// TODO: handle dirty context objects (for instance, reused context objects in unit tests)
Description description(context);
std::for_each(paths.cbegin(), paths.cend(),
[&](const auto &path)
{
description.m_context.tokenizer.read(path);
});
description.parse();
return description;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Context &Description::context()
{
return m_context;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Context &Description::context() const
{
return m_context;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Domain &Description::domain() const
{
BOOST_ASSERT(m_domain);
return *m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Description::containsProblem() const
{
return m_problem.get() != nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Problem &Description::problem() const
{
BOOST_ASSERT(m_problem);
return *m_problem;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::parse()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.removeComments(";", "\n", false);
// First, determine the locations of domain and problem
findSections();
if (m_domainPosition == tokenize::InvalidStreamPosition)
throw ConsistencyException("no PDDL domain specified");
tokenizer.seek(m_domainPosition);
m_domain->parse();
if (m_problemPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_problemPosition);
m_problem->parse();
}
checkConsistency();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::findSections()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.skipWhiteSpace();
while (!tokenizer.atEnd())
{
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("define");
tokenizer.expect<std::string>("(");
if (tokenizer.testAndSkip<std::string>("domain"))
{
if (m_domainPosition != tokenize::InvalidStreamPosition)
throw tokenize::TokenizerException(tokenizer, "PDDL description may not contain two domains");
m_domainPosition = position;
tokenizer.seek(position);
m_domain->findSections();
}
else if (tokenizer.testAndSkip<std::string>("problem"))
{
if (m_problemPosition != tokenize::InvalidStreamPosition)
throw tokenize::TokenizerException(tokenizer, "PDDL description may currently not contain two problems");
m_problem = std::make_unique<Problem>(Problem(m_context, *m_domain));
m_problemPosition = position;
tokenizer.seek(position);
m_problem->findSections();
}
else
{
const auto sectionIdentifier = tokenizer.get<std::string>();
throw tokenize::TokenizerException(tokenizer, "unknown PDDL section “" + sectionIdentifier + "");
}
tokenizer.skipWhiteSpace();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::checkConsistency()
{
m_domain->checkConsistency();
m_problem->checkConsistency();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Description::normalize()
{
m_domain->normalize();
if (m_problem)
m_problem->normalize();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,451 +0,0 @@
#include <plasp/pddl/Domain.h>
#include <algorithm>
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/expressions/Variable.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Domain
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain::Domain(Context &context)
: m_context(context),
m_requirementsPosition{tokenize::InvalidStreamPosition},
m_typesPosition{tokenize::InvalidStreamPosition},
m_constantsPosition{tokenize::InvalidStreamPosition},
m_predicatesPosition{tokenize::InvalidStreamPosition}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::findSections()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("define");
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("domain");
m_name = tokenizer.getIdentifier();
tokenizer.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(value);
throw tokenize::TokenizerException(tokenizer, "only one “:" + sectionName + "” section allowed");
}
sectionPosition = value;
};
tokenizer.skipWhiteSpace();
// Find sections
while (tokenizer.currentCharacter() != ')')
{
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
const auto sectionIdentifierPosition = tokenizer.position();
// Save the tokenizer position of the individual sections for later parsing
if (tokenizer.testIdentifierAndSkip("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("types"))
setSectionPosition("types", m_typesPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("constants"))
setSectionPosition("constants", m_constantsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("predicates"))
setSectionPosition("predicates", m_predicatesPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("action"))
{
m_actionPositions.emplace_back(-1);
setSectionPosition("action", m_actionPositions.back(), position);
}
else if (tokenizer.testIdentifierAndSkip("functions")
|| tokenizer.testIdentifierAndSkip("constraints")
|| tokenizer.testIdentifierAndSkip("durative-action")
|| tokenizer.testIdentifierAndSkip("derived"))
{
tokenizer.seek(sectionIdentifierPosition);
const auto sectionIdentifier = tokenizer.getIdentifier();
m_context.logger.log(output::Priority::Warning, tokenizer, "section type “" + sectionIdentifier + "” currently unsupported");
tokenizer.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer, "unknown domain section “" + sectionIdentifier + "");
}
// Skip section for now and parse it later
skipSection(tokenizer);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parse()
{
auto &tokenizer = m_context.tokenizer;
if (m_requirementsPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_requirementsPosition);
parseRequirementSection();
}
if (m_typesPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_typesPosition);
parseTypeSection();
}
if (m_constantsPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_constantsPosition);
parseConstantSection();
}
if (m_predicatesPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_predicatesPosition);
parsePredicateSection();
}
for (size_t i = 0; i < m_actionPositions.size(); i++)
if (m_actionPositions[i] != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_actionPositions[i]);
parseActionSection();
}
computeDerivedRequirements();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::setName(std::string name)
{
m_name = name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Domain::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Requirements &Domain::requirements() const
{
return m_requirements;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::PrimitiveTypes &Domain::types()
{
return m_types;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::PrimitiveTypes &Domain::types() const
{
return m_types;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::Constants &Domain::constants()
{
return m_constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Constants &Domain::constants() const
{
return m_constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::PredicateDeclarations &Domain::predicates()
{
return m_predicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::PredicateDeclarations &Domain::predicates() const
{
return m_predicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::vector<std::unique_ptr<Action>> &Domain::actions()
{
return m_actions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<std::unique_ptr<Action>> &Domain::actions() const
{
return m_actions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::DerivedPredicates &Domain::derivedPredicates()
{
return m_derivedPredicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::DerivedPredicates &Domain::derivedPredicates() const
{
return m_derivedPredicates;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseRequirementSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("requirements");
while (tokenizer.currentCharacter() != ')')
{
tokenizer.expect<std::string>(":");
m_requirements.emplace_back(Requirement::parse(m_context));
tokenizer.skipWhiteSpace();
}
// TODO: do this check only once the problem is parsed
// If no requirements are specified, assume STRIPS
if (m_requirements.empty())
m_requirements.emplace_back(Requirement::Type::STRIPS);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Domain::hasRequirement(Requirement::Type requirementType) const
{
const auto match = std::find_if(m_requirements.cbegin(), m_requirements.cend(),
[&](const auto &requirement)
{
return requirement.type() == requirementType;
});
return match != m_requirements.cend();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::checkRequirement(Requirement::Type requirementType)
{
if (hasRequirement(requirementType))
return;
m_context.logger.log(output::Priority::Warning, m_context.tokenizer, "requirement “" + Requirement(requirementType).toPDDL() + "” used but never declared");
m_requirements.push_back(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::computeDerivedRequirements()
{
const auto addRequirementUnique =
[&](const auto requirement)
{
if (hasRequirement(requirement))
return;
m_requirements.push_back(Requirement(requirement));
};
if (hasRequirement(Requirement::Type::ADL))
{
addRequirementUnique(Requirement::Type::STRIPS);
addRequirementUnique(Requirement::Type::Typing);
addRequirementUnique(Requirement::Type::NegativePreconditions);
addRequirementUnique(Requirement::Type::DisjunctivePreconditions);
addRequirementUnique(Requirement::Type::Equality);
addRequirementUnique(Requirement::Type::QuantifiedPreconditions);
addRequirementUnique(Requirement::Type::ConditionalEffects);
}
if (hasRequirement(Requirement::Type::QuantifiedPreconditions))
{
addRequirementUnique(Requirement::Type::ExistentialPreconditions);
addRequirementUnique(Requirement::Type::UniversalPreconditions);
}
if (hasRequirement(Requirement::Type::Fluents))
{
addRequirementUnique(Requirement::Type::NumericFluents);
addRequirementUnique(Requirement::Type::ObjectFluents);
}
if (hasRequirement(Requirement::Type::TimedInitialLiterals))
addRequirementUnique(Requirement::Type::DurativeActions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseTypeSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("types");
checkRequirement(Requirement::Type::Typing);
tokenizer.skipWhiteSpace();
// Store types and their parent types
while (tokenizer.currentCharacter() != ')')
{
if (tokenizer.currentCharacter() == '(')
throw tokenize::TokenizerException(tokenizer, "only primitive types are allowed in type section");
expressions::PrimitiveType::parseTypedDeclaration(m_context, *this);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseConstantSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("constants");
// Store constants
expressions::Constant::parseTypedDeclarations(m_context, *this);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parsePredicateSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("predicates");
tokenizer.skipWhiteSpace();
// Store predicates and their arguments
while (tokenizer.currentCharacter() != ')')
{
expressions::PredicateDeclaration::parse(m_context, *this);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseActionSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("action");
Action::parseDeclaration(m_context, *this);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::checkConsistency()
{
// Verify that constants are unique
// Verify that all primitive types are unique
// Check for case-sensitivity issues
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::normalize()
{
std::for_each(m_predicates.begin(), m_predicates.end(),
[](auto &predicate)
{
predicate->normalizeParameterNames();
});
std::for_each(m_actions.begin(), m_actions.end(),
[&](auto &action)
{
action->normalize(m_derivedPredicates);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,336 +0,0 @@
#include <plasp/pddl/Expression.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Exists.h>
#include <plasp/pddl/expressions/ForAll.h>
#include <plasp/pddl/expressions/Imply.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Or.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/expressions/Unsupported.h>
#include <plasp/pddl/expressions/When.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Expression
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::copy()
{
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::normalized()
{
return reduced()->simplified()->existentiallyQuantified()->simplified();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::reduced()
{
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::existentiallyQuantified()
{
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::simplified()
{
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::decomposed(expressions::DerivedPredicates &)
{
throw output::TranslatorException("expression cannot be decomposed (not normalized)");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Expression::negated()
{
if (is<expressions::Not>())
return as<expressions::Not>().argument();
auto notExpression = expressions::NotPointer(new expressions::Not);
notExpression->setArgument(this);
return notExpression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// 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);
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePreconditionExpression(Context &context,
ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parsePreconditionExpression))
|| (expression = expressions::ForAll::parse(context, expressionContext, parsePreconditionExpression)))
{
return expression;
}
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("preference"))
{
// TODO: refactor
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(position);
return parseExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseExpression(Context &context, ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Or::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Exists::parse(context, expressionContext, parseExpression))
|| (expression = expressions::ForAll::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Not::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Imply::parse(context, expressionContext, parseExpression))
|| (expression = expressions::Predicate::parse(context, expressionContext)))
{
return expression;
}
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("-")
|| tokenizer.testIdentifierAndSkip("=")
|| tokenizer.testIdentifierAndSkip("*")
|| tokenizer.testIdentifierAndSkip("+")
|| tokenizer.testIdentifierAndSkip("-")
|| tokenizer.testIdentifierAndSkip("/")
|| tokenizer.testIdentifierAndSkip(">")
|| tokenizer.testIdentifierAndSkip("<")
|| tokenizer.testIdentifierAndSkip("=")
|| tokenizer.testIdentifierAndSkip(">=")
|| tokenizer.testIdentifierAndSkip("<="))
{
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectExpression(Context &context, ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parseEffectExpression))
|| (expression = expressions::ForAll::parse(context, expressionContext, parseEffectExpression))
|| (expression = expressions::When::parse(context, expressionContext, parseExpression, parseConditionalEffectExpression)))
{
return expression;
}
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("when"))
{
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(position);
return parseEffectBodyExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseEffectBodyExpression(Context &context, ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
ExpressionPointer expression;
if ((expression = expressions::Not::parse(context, expressionContext, parsePredicate))
|| (expression = expressions::Predicate::parse(context, expressionContext)))
{
return expression;
}
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("=")
|| tokenizer.testIdentifierAndSkip("assign")
|| tokenizer.testIdentifierAndSkip("scale-up")
|| tokenizer.testIdentifierAndSkip("scale-down")
|| tokenizer.testIdentifierAndSkip("increase")
|| tokenizer.testIdentifierAndSkip("decrease"))
{
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseConditionalEffectExpression(Context &context, ExpressionContext &expressionContext)
{
ExpressionPointer expression;
if ((expression = expressions::And::parse(context, expressionContext, parseEffectBodyExpression)))
return expression;
return parseEffectBodyExpression(context, expressionContext);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parsePredicate(Context &context, ExpressionContext &expressionContext)
{
ExpressionPointer expression;
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
throw tokenize::TokenizerException(context.tokenizer, "expected predicate");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseLiteral(Context &context, ExpressionContext &expressionContext)
{
ExpressionPointer expression;
if ((expression = parseAtomicFormula(context, expressionContext))
|| (expression = expressions::Not::parse(context, expressionContext, parseAtomicFormula)))
{
return expression;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer parseAtomicFormula(Context &context, ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
ExpressionPointer expression;
if ((expression = expressions::Predicate::parse(context, expressionContext)))
return expression;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("("))
return nullptr;
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("="))
{
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(position);
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,54 +0,0 @@
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/Problem.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ExpressionContext
//
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionContext::ExpressionContext(Domain &domain)
: domain(domain),
problem(nullptr)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionContext::ExpressionContext(Domain &domain, Problem *problem)
: domain(domain),
problem{problem}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool ExpressionContext::hasRequirement(Requirement::Type requirementType) const
{
if (problem != nullptr)
return problem->hasRequirement(requirementType);
return domain.hasRequirement(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void ExpressionContext::checkRequirement(Requirement::Type requirementType) const
{
if (problem != nullptr)
problem->checkRequirement(requirementType);
else
domain.checkRequirement(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,90 +0,0 @@
#include <plasp/pddl/InitialState.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/At.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/expressions/Unsupported.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// InitialState
//
////////////////////////////////////////////////////////////////////////////////////////////////////
std::unique_ptr<InitialState> InitialState::parseDeclaration(Context &context,
ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
auto initialState = std::make_unique<InitialState>(InitialState());
const auto parseInitialStateElement =
[&]() -> ExpressionPointer
{
ExpressionPointer expression;
// TODO: do not allow negative initial state literals
if ((expression = parseLiteral(context, expressionContext))
|| (expression = expressions::At::parse(context, expressionContext, parseLiteral)))
{
return expression;
}
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
const auto expressionIdentifierPosition = tokenizer.position();
if (tokenizer.testIdentifierAndSkip("="))
{
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
return expressions::Unsupported::parse(context);
}
tokenizer.seek(expressionIdentifierPosition);
const auto expressionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer, "expression type “" + expressionIdentifier + "” unknown or not allowed in this context");
};
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
ExpressionPointer expression;
if ((expression = parseInitialStateElement()))
initialState->m_facts.emplace_back(std::move(expression));
tokenizer.skipWhiteSpace();
}
return initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expressions &InitialState::facts() const
{
return m_facts;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,408 +0,0 @@
#include <plasp/pddl/Problem.h>
#include <algorithm>
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/IO.h>
#include <plasp/pddl/expressions/Constant.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Problem::Problem(Context &context, Domain &domain)
: m_context(context),
m_domain(domain),
m_domainPosition{tokenize::InvalidStreamPosition},
m_requirementsPosition{tokenize::InvalidStreamPosition},
m_objectsPosition{tokenize::InvalidStreamPosition},
m_initialStatePosition{tokenize::InvalidStreamPosition},
m_goalPosition{tokenize::InvalidStreamPosition}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::findSections()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("define");
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>("problem");
m_name = tokenizer.getIdentifier();
tokenizer.expect<std::string>(")");
const auto setSectionPosition =
[&](const std::string &sectionName, auto &sectionPosition, const auto value, bool unique = false)
{
if (unique && sectionPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(value);
throw tokenize::TokenizerException(tokenizer, "only one “:" + sectionName + "” section allowed");
}
sectionPosition = value;
};
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
const auto position = tokenizer.position();
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
const auto sectionIdentifierPosition = tokenizer.position();
// TODO: check order of the sections
if (tokenizer.testIdentifierAndSkip("domain"))
setSectionPosition("domain", m_domainPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("requirements"))
setSectionPosition("requirements", m_requirementsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("objects"))
setSectionPosition("objects", m_objectsPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("init"))
setSectionPosition("init", m_initialStatePosition, position, true);
else if (tokenizer.testIdentifierAndSkip("goal"))
setSectionPosition("goal", m_goalPosition, position, true);
else if (tokenizer.testIdentifierAndSkip("constraints")
|| tokenizer.testIdentifierAndSkip("metric")
|| tokenizer.testIdentifierAndSkip("length"))
{
tokenizer.seek(sectionIdentifierPosition);
const auto sectionIdentifier = tokenizer.getIdentifier();
m_context.logger.log(output::Priority::Warning, tokenizer, "section type “" + sectionIdentifier + "” currently unsupported");
tokenizer.seek(sectionIdentifierPosition);
}
else
{
const auto sectionIdentifier = tokenizer.getIdentifier();
tokenizer.seek(position);
throw tokenize::TokenizerException(tokenizer, "unknown problem section “" + sectionIdentifier + "");
}
// Skip section for now and parse it later
skipSection(tokenizer);
tokenizer.skipWhiteSpace();
}
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parse()
{
auto &tokenizer = m_context.tokenizer;
if (m_domainPosition == tokenize::InvalidStreamPosition)
throw ConsistencyException("problem description does not specify the corresponding domain");
tokenizer.seek(m_domainPosition);
parseDomainSection();
if (m_requirementsPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_requirementsPosition);
parseRequirementSection();
}
if (m_objectsPosition != tokenize::InvalidStreamPosition)
{
tokenizer.seek(m_objectsPosition);
parseObjectSection();
}
if (m_initialStatePosition == tokenize::InvalidStreamPosition)
throw ConsistencyException("problem description does not specify an initial state");
tokenizer.seek(m_initialStatePosition);
parseInitialStateSection();
if (m_goalPosition == tokenize::InvalidStreamPosition)
throw ConsistencyException("problem description does not specify a goal");
tokenizer.seek(m_goalPosition);
parseGoalSection();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Domain &Problem::domain()
{
return m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Domain &Problem::domain() const
{
return m_domain;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Problem::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Requirements &Problem::requirements() const
{
return m_requirements;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::Constants &Problem::objects()
{
return m_objects;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const expressions::Constants &Problem::objects() const
{
return m_objects;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseDomainSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("domain");
tokenizer.skipWhiteSpace();
const auto domainName = tokenizer.getIdentifier();
if (m_domain.name() != domainName)
throw tokenize::TokenizerException(tokenizer, "domains do not match (“" + m_domain.name() + "” and “" + domainName + "”)");
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseRequirementSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("requirements");
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
tokenizer.expect<std::string>(":");
m_requirements.emplace_back(Requirement::parse(m_context));
tokenizer.skipWhiteSpace();
}
// TODO: do this check only once the domain is parsed
// If no requirements are specified, assume STRIPS
if (m_requirements.empty())
m_requirements.emplace_back(Requirement::Type::STRIPS);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Problem::hasRequirement(Requirement::Type requirementType) const
{
const auto match = std::find_if(m_requirements.cbegin(), m_requirements.cend(),
[&](const auto &requirement)
{
return requirement.type() == requirementType;
});
if (match != m_requirements.cend())
return true;
return m_domain.hasRequirement(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::checkRequirement(Requirement::Type requirementType)
{
if (hasRequirement(requirementType))
return;
m_context.logger.log(output::Priority::Warning, m_context.tokenizer, "requirement “" + Requirement(requirementType).toPDDL() + "” used but never declared");
m_requirements.push_back(requirementType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::computeDerivedRequirements()
{
const auto addRequirementUnique =
[&](const auto requirement)
{
if (hasRequirement(requirement))
return;
m_requirements.push_back(Requirement(requirement));
};
if (hasRequirement(Requirement::Type::ADL))
{
addRequirementUnique(Requirement::Type::STRIPS);
addRequirementUnique(Requirement::Type::Typing);
addRequirementUnique(Requirement::Type::NegativePreconditions);
addRequirementUnique(Requirement::Type::DisjunctivePreconditions);
addRequirementUnique(Requirement::Type::Equality);
addRequirementUnique(Requirement::Type::QuantifiedPreconditions);
addRequirementUnique(Requirement::Type::ConditionalEffects);
}
if (hasRequirement(Requirement::Type::QuantifiedPreconditions))
{
addRequirementUnique(Requirement::Type::ExistentialPreconditions);
addRequirementUnique(Requirement::Type::UniversalPreconditions);
}
if (hasRequirement(Requirement::Type::Fluents))
{
addRequirementUnique(Requirement::Type::NumericFluents);
addRequirementUnique(Requirement::Type::ObjectFluents);
}
if (hasRequirement(Requirement::Type::TimedInitialLiterals))
addRequirementUnique(Requirement::Type::DurativeActions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseObjectSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("objects");
tokenizer.skipWhiteSpace();
// Store constants
expressions::Constant::parseTypedDeclarations(m_context, *this);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseInitialStateSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("init");
ExpressionContext expressionContext(m_domain, this);
m_initialState = InitialState::parseDeclaration(m_context, expressionContext);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseGoalSection()
{
auto &tokenizer = m_context.tokenizer;
tokenizer.expect<std::string>("(");
tokenizer.expect<std::string>(":");
tokenizer.expect<std::string>("goal");
ExpressionContext expressionContext(m_domain, this);
m_goal = parsePreconditionExpression(m_context, expressionContext);
tokenizer.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
InitialState &Problem::initialState()
{
BOOST_ASSERT(m_initialState);
return *m_initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const InitialState &Problem::initialState() const
{
BOOST_ASSERT(m_initialState);
return *m_initialState;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expression &Problem::goal() const
{
BOOST_ASSERT(m_goal);
return *m_goal;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::checkConsistency()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::normalize()
{
BOOST_ASSERT(m_goal);
// TODO: normalize objects and initial state
m_goal = m_goal->normalized();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,134 +0,0 @@
#include <plasp/pddl/Requirement.h>
#include <boost/assert.hpp>
#include <boost/assign.hpp>
#include <boost/bimap.hpp>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirement
//
////////////////////////////////////////////////////////////////////////////////////////////////////
using RequirementTypeNames = boost::bimap<Requirement::Type, std::string>;
////////////////////////////////////////////////////////////////////////////////////////////////////
const RequirementTypeNames requirementTypesToPDDL = boost::assign::list_of<RequirementTypeNames::relation>
(Requirement::Type::STRIPS, "strips")
(Requirement::Type::Typing, "typing")
(Requirement::Type::NegativePreconditions, "negative-preconditions")
(Requirement::Type::DisjunctivePreconditions, "disjunctive-preconditions")
(Requirement::Type::Equality, "equality")
(Requirement::Type::ExistentialPreconditions, "existential-preconditions")
(Requirement::Type::UniversalPreconditions, "universal-preconditions")
(Requirement::Type::QuantifiedPreconditions, "quantified-preconditions")
(Requirement::Type::ConditionalEffects, "conditional-effects")
(Requirement::Type::Fluents, "fluents")
(Requirement::Type::NumericFluents, "numeric-fluents")
(Requirement::Type::ObjectFluents, "object-fluents")
(Requirement::Type::ADL, "adl")
(Requirement::Type::DurativeActions, "durative-actions")
(Requirement::Type::DurationInequalities, "duration-inequalities")
(Requirement::Type::ContinuousEffects, "continuous-effects")
(Requirement::Type::DerivedPredicates, "derived-predicates")
(Requirement::Type::TimedInitialLiterals, "timed-initial-literals")
(Requirement::Type::Preferences, "preferences")
(Requirement::Type::Constraints, "constraints")
(Requirement::Type::ActionCosts, "action-costs")
(Requirement::Type::GoalUtilities, "goal-utilities");
////////////////////////////////////////////////////////////////////////////////////////////////////
const RequirementTypeNames requirementTypesToASP = boost::assign::list_of<RequirementTypeNames::relation>
(Requirement::Type::STRIPS, "strips")
(Requirement::Type::Typing, "typing")
(Requirement::Type::NegativePreconditions, "negativePreconditions")
(Requirement::Type::DisjunctivePreconditions, "disjunctivePreconditions")
(Requirement::Type::Equality, "equality")
(Requirement::Type::ExistentialPreconditions, "existentialPreconditions")
(Requirement::Type::UniversalPreconditions, "universalPreconditions")
(Requirement::Type::QuantifiedPreconditions, "quantifiedPreconditions")
(Requirement::Type::ConditionalEffects, "conditionalEffects")
(Requirement::Type::Fluents, "fluents")
(Requirement::Type::NumericFluents, "numericFluents")
(Requirement::Type::ObjectFluents, "objectFluents")
(Requirement::Type::ADL, "adl")
(Requirement::Type::DurativeActions, "durativeActions")
(Requirement::Type::DurationInequalities, "durationInequalities")
(Requirement::Type::ContinuousEffects, "continuousEffects")
(Requirement::Type::DerivedPredicates, "derivedPredicates")
(Requirement::Type::TimedInitialLiterals, "timedInitialLiterals")
(Requirement::Type::Preferences, "preferences")
(Requirement::Type::Constraints, "constraints")
(Requirement::Type::ActionCosts, "actionCosts")
(Requirement::Type::GoalUtilities, "goalUtilities");
////////////////////////////////////////////////////////////////////////////////////////////////////
Requirement::Requirement(Requirement::Type type)
: m_type{type}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Requirement Requirement::parse(Context &context)
{
auto &tokenizer = context.tokenizer;
const auto requirementName = tokenizer.getIdentifier();
const auto match = requirementTypesToPDDL.right.find(requirementName);
if (match == requirementTypesToPDDL.right.end())
throw tokenize::TokenizerException(tokenizer, "unknown PDDL requirement “" + requirementName + "");
const auto requirementType = match->second;
if (requirementType == Requirement::Type::GoalUtilities)
context.logger.log(output::Priority::Warning, tokenizer, "requirement “goal-utilities” is not part of the PDDL 3.1 specification");
return Requirement(match->second);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Requirement::Type Requirement::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::string Requirement::toPDDL() const
{
const auto match = requirementTypesToPDDL.left.find(m_type);
BOOST_ASSERT(match != requirementTypesToPDDL.left.end());
return match->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
std::string Requirement::toASP() const
{
const auto match = requirementTypesToASP.left.find(m_type);
BOOST_ASSERT(match != requirementTypesToASP.left.end());
return match->second;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -2,11 +2,13 @@
#include <boost/assert.hpp>
#include <pddlparse/AST.h>
#include <plasp/output/Formatting.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/translation/Effect.h>
#include <plasp/pddl/translation/Goal.h>
#include <plasp/pddl/translation/Precondition.h>
#include <plasp/pddl/translation/Predicate.h>
#include <plasp/pddl/translation/Primitives.h>
@ -23,11 +25,10 @@ namespace pddl
//
////////////////////////////////////////////////////////////////////////////////////////////////////
TranslatorASP::TranslatorASP(Description &description, output::ColorStream &outputStream)
: m_description(description),
TranslatorASP::TranslatorASP(const ::pddl::ast::Description &description, output::ColorStream &outputStream)
: m_description{description},
m_outputStream(outputStream)
{
m_description.normalize();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -36,7 +37,7 @@ void TranslatorASP::translate() const
{
translateDomain();
if (m_description.containsProblem())
if (m_description.problem)
{
m_outputStream << std::endl;
translateProblem();
@ -49,35 +50,28 @@ void TranslatorASP::translateDomain() const
{
m_outputStream << output::Heading1("domain");
const auto &domain = m_description.domain();
const auto &domain = m_description.domain;
// Types
m_outputStream << std::endl;
translateTypes();
// Constants
if (!domain.constants().empty())
if (!domain->constants.empty())
{
m_outputStream << std::endl;
translateConstants("constants", domain.constants());
translateConstants("constants", domain->constants);
}
// Predicates
if (!domain.predicates().empty())
if (!domain->predicates.empty())
{
m_outputStream << std::endl;
translatePredicates();
}
// Derived predicates
if (!domain.derivedPredicates().empty())
{
m_outputStream << std::endl;
translateDerivedPredicates();
}
// Actions
if (!domain.actions().empty())
if (!domain->actions.empty())
{
m_outputStream << std::endl;
translateActions();
@ -92,7 +86,7 @@ void TranslatorASP::translateTypes() const
m_outputStream << std::endl;
const auto &types = m_description.domain().types();
const auto &types = m_description.domain->types;
if (types.empty())
{
@ -108,18 +102,18 @@ void TranslatorASP::translateTypes() const
m_outputStream
<< output::Function("type") << "("
<< output::Keyword("type") << "("
<< output::String(type->name().c_str())
<< *type
<< "))." << std::endl;
const auto &parentTypes = type->parentTypes();
const auto &parentTypes = type->parentTypes;
std::for_each(parentTypes.cbegin(), parentTypes.cend(),
[&](const auto &parentType)
{
m_outputStream
<< output::Function("inherits") << "(" << output::Keyword("type")
<< "(" << output::String(type->name().c_str()) << "), " << output::Keyword("type")
<< "(" << output::String(parentType->name().c_str()) << "))." << std::endl;
<< "(" << *type << "), " << output::Keyword("type")
<< "(" << *parentType << "))." << std::endl;
});
}
@ -143,17 +137,17 @@ void TranslatorASP::translatePredicates() const
{
m_outputStream << output::Heading2("variables");
const auto &predicates = m_description.domain().predicates();
const auto &predicates = m_description.domain->predicates;
for (const auto &predicate : predicates)
{
m_outputStream << std::endl << output::Function("variable") << "(";
translation::printPredicateName(m_outputStream, *predicate);
translatePredicateDeclaration(m_outputStream, *predicate);
m_outputStream << ")";
translation::translateVariablesForRuleBody(m_outputStream, predicate->parameters());
translateVariablesForRuleBody(m_outputStream, predicate->parameters);
m_outputStream << ".";
}
@ -173,160 +167,47 @@ void TranslatorASP::translatePredicates() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateDerivedPredicates() const
{
m_outputStream << output::Heading2("derived predicates");
const auto &derivedPredicates = m_description.domain().derivedPredicates();
for (const auto &derivedPredicate : derivedPredicates)
{
const auto printObjectName =
[&](auto &outputStream)
{
translation::printDerivedPredicateName(outputStream, *derivedPredicate);
};
m_outputStream << std::endl << output::Function("derivedVariable") << "(";
printObjectName(m_outputStream);
m_outputStream << ")";
translation::translateVariablesForRuleBody(m_outputStream, derivedPredicate->parameters());
m_outputStream << ".";
translation::translatePreconditionDisjunction(m_outputStream, "derivedVariable", printObjectName, 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("derivedVariable") << "(" << output::Keyword("derivedVariable") << "(" << output::Variable("X") << ")), "
<< output::Function("boolean") << "(" << output::Variable("B") << ")."
<< std::endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateActions() const
{
m_outputStream << output::Heading2("actions");
const auto &actions = m_description.domain().actions();
const auto printActionName =
[&](const auto &action)
{
m_outputStream << output::Keyword("action") << "(";
if (action.parameters().empty())
{
m_outputStream << output::String(action.name().c_str()) << ")";
return;
}
m_outputStream << "(" << output::String(action.name().c_str());
translation::translateVariablesForRuleHead(m_outputStream, action.parameters());
m_outputStream << "))";
};
const auto &actions = m_description.domain->actions;
for (const auto &action : actions)
{
const auto translateExpression =
[&](const auto &ruleHead, const auto &literal, bool enumerateEffects = false)
const auto printActionName =
[&]()
{
m_outputStream << std::endl << output::Function(ruleHead) << "(";
m_outputStream << output::Keyword("action") << "(";
printActionName(*action);
if (action->parameters.empty())
{
m_outputStream << *action << ")";
return;
}
// TODO: implement conditional effects
if (enumerateEffects)
m_outputStream << ", " << output::Keyword("effect") << "(" << output::Reserved("unconditional") << ")";
m_outputStream << ", ";
translation::translateLiteral(m_outputStream, literal);
m_outputStream << ") :- " << output::Function("action") << "(";
printActionName(*action);
m_outputStream << ").";
m_outputStream << "(" << *action;
translateVariablesForRuleHead(m_outputStream, action->parameters);
m_outputStream << "))";
};
m_outputStream << std::endl;
// Name
m_outputStream << output::Function("action") << "(";
printActionName(*action);
printActionName();
m_outputStream << ")";
translation::translateVariablesForRuleBody(m_outputStream, action->parameters());
translateVariablesForRuleBody(m_outputStream, action->parameters);
m_outputStream << ".";
// Precondition
if (action->precondition())
{
const auto &precondition = *action->precondition();
if (action->precondition)
translatePrecondition(m_outputStream, action->precondition.value(), "action", printActionName);
switch (precondition.expressionType())
{
case Expression::Type::And:
{
const auto &andExpression = precondition.as<expressions::And>();
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
[&](const auto argument)
{
translateExpression("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()) + ")");
}
}
// Effect
if (action->effect())
{
const auto &effect = *action->effect();
if (effect.is<expressions::Predicate>() || effect.is<expressions::Not>())
{
translateExpression("postcondition", effect, true);
}
// Assuming a conjunction
else
{
if (effect.expressionType() != Expression::Type::And)
throw output::TranslatorException("only “and” expressions and (negated) predicates supported as action effects currently");
const auto &andExpression = effect.as<expressions::And>();
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
[&](const auto argument)
{
translateExpression("postcondition", *argument, true);
});
}
}
if (action->effect)
translateEffect(m_outputStream, action->effect.value(), "action", printActionName);
m_outputStream << std::endl;
}
@ -334,7 +215,7 @@ void TranslatorASP::translateActions() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateConstants(const std::string &heading, const expressions::Constants &constants) const
void TranslatorASP::translateConstants(const std::string &heading, const ::pddl::ast::ConstantDeclarations &constants) const
{
m_outputStream << output::Heading2(heading.c_str());
@ -343,21 +224,26 @@ void TranslatorASP::translateConstants(const std::string &heading, const express
m_outputStream << std::endl
<< output::Function("constant") << "("
<< output::Keyword("constant") << "("
<< output::String(constant->name().c_str())
<< *constant
<< "))." << std::endl;
const auto type = constant->type();
const auto &type = constant->type;
if (type != nullptr)
if (type)
{
if (!type.value().is<::pddl::ast::PrimitiveTypePointer>())
throw output::TranslatorException("only primitive types supported currently");
const auto &primitveType = type.value().get<::pddl::ast::PrimitiveTypePointer>();
m_outputStream << output::Function("has") << "("
<< output::Keyword("constant") << "(" << output::String(constant->name().c_str()) << "), "
<< output::Keyword("type") << "(" << output::String(type->name().c_str()) << "))." << std::endl;
<< output::Keyword("constant") << "(" << *constant << "), "
<< output::Keyword("type") << "(" << *primitveType << "))." << std::endl;
}
else
{
m_outputStream << output::Function("has") << "("
<< output::Keyword("constant") << "(" << output::String(constant->name().c_str()) << "), "
<< output::Keyword("constant") << "(" << *constant << "), "
<< output::Keyword("type") << "(" << output::String("object") << "))." << std::endl;
}
}
@ -367,17 +253,17 @@ void TranslatorASP::translateConstants(const std::string &heading, const express
void TranslatorASP::translateProblem() const
{
BOOST_ASSERT(m_description.containsProblem());
assert(m_description.problem);
m_outputStream << output::Heading1("problem");
const auto &problem = m_description.problem();
const auto &problem = m_description.problem.value();
// Objects
if (!problem.objects().empty())
if (!problem->objects.empty())
{
m_outputStream << std::endl;
translateConstants("objects", problem.objects());
translateConstants("objects", problem->objects);
}
// Initial State
@ -385,42 +271,45 @@ void TranslatorASP::translateProblem() const
translateInitialState();
// Goal
m_outputStream << std::endl;
translateGoal();
if (problem->goal)
{
m_outputStream << std::endl;
translateGoal();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void TranslatorASP::translateInitialState() const
{
BOOST_ASSERT(m_description.containsProblem());
assert(m_description.problem);
m_outputStream << output::Heading2("initial state");
const auto &initialStateFacts = m_description.problem().initialState().facts();
const auto &facts = m_description.problem.value()->initialState.facts;
for (const auto &fact : initialStateFacts)
for (const auto &fact : facts)
{
m_outputStream << std::endl << output::Function("initialState") << "(";
// Translate single predicate
if (fact->is<expressions::Predicate>())
if (fact.is<::pddl::ast::AtomicFormula>() && fact.get<::pddl::ast::AtomicFormula>().is<::pddl::ast::PredicatePointer>())
{
const auto &predicate = fact->as<expressions::Predicate>();
const auto &predicate = fact.get<::pddl::ast::AtomicFormula>().get<::pddl::ast::PredicatePointer>();
m_outputStream << output::Keyword("variable") << "(";
translation::translatePredicate(m_outputStream, predicate);
m_outputStream << "), " << output::Keyword("value") << "(";
translation::translatePredicate(m_outputStream, predicate);
m_outputStream << ", " << output::Boolean("true") << ")";
translatePredicateToVariable(m_outputStream, *predicate, true);
}
// Assuming that "not" expression may only contain a predicate
else if (fact->is<expressions::Not>())
else if (fact.is<::pddl::ast::NotPointer<::pddl::ast::Fact>>())
{
const auto &notExpression = fact->as<expressions::Not>();
const auto &notExpression = fact.get<::pddl::ast::NotPointer<::pddl::ast::Fact>>();
if (notExpression.argument()->expressionType() != Expression::Type::Predicate)
if (!notExpression->argument.is<::pddl::ast::AtomicFormula>() || !notExpression->argument.get<::pddl::ast::AtomicFormula>().is<::pddl::ast::PredicatePointer>())
throw output::TranslatorException("only negations of simple predicates supported in initial state currently");
const auto &predicate = notExpression->argument.get<::pddl::ast::AtomicFormula>().get<::pddl::ast::PredicatePointer>();
translatePredicateToVariable(m_outputStream, *predicate, false);
}
else
throw output::TranslatorException("only predicates and their negations supported in initial state currently");
@ -445,36 +334,14 @@ void TranslatorASP::translateInitialState() const
void TranslatorASP::translateGoal() const
{
BOOST_ASSERT(m_description.containsProblem());
assert(m_description.problem);
assert(m_description.problem.value()->goal);
m_outputStream << output::Heading2("goal");
const auto &goal = m_description.problem().goal();
if (goal.is<expressions::Predicate>() || goal.is<expressions::Not>())
{
m_outputStream << std::endl << output::Function("goal") << "(";
translation::translateLiteral(m_outputStream, goal);
m_outputStream << ").";
}
else if (goal.is<expressions::And>())
{
const auto &andExpression = goal.as<expressions::And>();
std::for_each(andExpression.arguments().cbegin(), andExpression.arguments().cend(),
[&](const auto argument)
{
m_outputStream << std::endl << output::Function("goal") << "(";
translation::translateLiteral(m_outputStream, *argument);
m_outputStream << ").";
});
}
else
throw output::TranslatorException("only single predicates, their negations, and conjunctions are currently supported in the goal");
const auto &goal = m_description.problem.value()->goal.value();
// TODO: refactor
::plasp::pddl::translateGoal(m_outputStream, goal);
m_outputStream << std::endl;
}

View File

@ -1,62 +0,0 @@
#include <plasp/pddl/VariableStack.h>
#include <plasp/pddl/Context.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// VariableStack
//
////////////////////////////////////////////////////////////////////////////////////////////////////
void VariableStack::push(expressions::Variables *variables)
{
m_variableStack.push_back(variables);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void VariableStack::pop()
{
m_variableStack.pop_back();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
expressions::VariablePointer VariableStack::parseAndFind(plasp::pddl::Context &context)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
tokenizer.expect<std::string>("?");
const auto variableName = tokenizer.getIdentifier();
for (auto i = m_variableStack.crbegin(); i != m_variableStack.crend(); i++)
{
const auto *variables = *i;
BOOST_ASSERT(variables);
const auto match = std::find_if(variables->crbegin(), variables->crend(),
[&](const auto &variable)
{
return variable->name() == variableName;
});
if (match != variables->crend())
return match->get();
}
throw tokenize::TokenizerException(tokenizer, "variable “" + variableName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -1,49 +0,0 @@
#include <plasp/pddl/expressions/And.h>
#include <algorithm>
#include <iostream>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/expressions/Or.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// And
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string And::Identifier = "and";
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer And::decomposed(DerivedPredicates &derivedPredicates)
{
BOOST_ASSERT(!m_arguments.empty());
derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size()));
auto derivedPredicate = derivedPredicates.back();
for (auto &argument : m_arguments)
argument = argument->decomposed(derivedPredicates);
std::vector<Expressions> preconditions;
preconditions.emplace_back(std::move(m_arguments));
// Move this expressions arguments to the derived predicate
derivedPredicate->setPreconditions(std::move(preconditions));
return derivedPredicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,99 +0,0 @@
#include <plasp/pddl/expressions/At.h>
#include <plasp/output/TranslatorException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// At
//
////////////////////////////////////////////////////////////////////////////////////////////////////
At::At()
: m_argument{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer At::copy()
{
auto result = new At;
result->m_argument = m_argument->copy();
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void At::setArgument(ExpressionPointer argument)
{
m_argument = argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer At::argument() const
{
return m_argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer At::reduced()
{
throw output::TranslatorException("reducing “at” predicates currently not supported");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer At::existentiallyQuantified()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->existentiallyQuantified();
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer At::simplified()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->simplified();
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void At::collectParameters(std::set<VariablePointer> &parameters)
{
m_argument->collectParameters(parameters);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void At::print(std::ostream &ostream) const
{
ostream << "(at " << m_timePoint << " ";
m_argument->print(ostream);
ostream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,253 +0,0 @@
#include <plasp/pddl/expressions/Constant.h>
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant::Constant()
: m_isDirty{false},
m_type{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ConstantPointer Constant::parseDeclaration(Context &context)
{
context.tokenizer.skipWhiteSpace();
auto constant = ConstantPointer(new Constant);
constant->m_name = context.tokenizer.getIdentifier();
BOOST_ASSERT(constant->m_name != "-");
// Flag constant for potentially upcoming type declaration
constant->setDirty();
return constant;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Domain &domain)
{
parseTypedDeclaration(context, domain, domain.constants());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Problem &problem)
{
parseTypedDeclaration(context, problem.domain(), problem.objects());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclaration(Context &context, Domain &domain, Constants &constants)
{
// Parse and store constant
constants.emplace_back(parseDeclaration(context));
context.tokenizer.skipWhiteSpace();
// Check for typing information
if (!context.tokenizer.testAndSkip<char>('-'))
return;
// If existing, parse and store parent type
auto type = PrimitiveType::parseAndFind(context, domain);
// Assign parent type to all types that were previously flagged
std::for_each(constants.begin(), constants.end(),
[&](auto &constant)
{
if (!constant->isDirty())
return;
constant->setType(type);
constant->setDirty(false);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclarations(Context &context, Domain &domain)
{
auto &tokenizer = context.tokenizer;
while (tokenizer.currentCharacter() != ')')
{
parseTypedDeclaration(context, domain);
tokenizer.skipWhiteSpace();
}
if (domain.constants().empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (domain.constants().back()->type() != nullptr);
// If types are given, check that typing is a requirement
if (typingUsed)
domain.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (domain.hasRequirement(Requirement::Type::Typing))
throw tokenize::TokenizerException(tokenizer, "constant has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::parseTypedDeclarations(Context &context, Problem &problem)
{
auto &tokenizer = context.tokenizer;
while (tokenizer.currentCharacter() != ')')
{
parseTypedDeclaration(context, problem);
tokenizer.skipWhiteSpace();
}
if (problem.objects().empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (problem.objects().back()->type() != nullptr);
// If types are given, check that typing is a requirement
if (typingUsed)
problem.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (problem.hasRequirement(Requirement::Type::Typing))
throw tokenize::TokenizerException(tokenizer, "constant has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ConstantPointer Constant::parseAndFind(Context &context, const Domain &domain)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
const auto constantName = tokenizer.getIdentifier();
auto constant = parseAndFind(constantName, domain.constants());
if (constant != nullptr)
return constant;
throw tokenize::TokenizerException(tokenizer, "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ConstantPointer Constant::parseAndFind(Context &context, const Problem &problem)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
const auto constantName = tokenizer.getIdentifier();
auto constant = parseAndFind(constantName, problem.domain().constants());
if (constant)
return constant;
constant = parseAndFind(constantName, problem.objects());
if (constant)
return constant;
throw tokenize::TokenizerException(tokenizer, "constant “" + constantName + "” used but never declared");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ConstantPointer Constant::parseAndFind(const std::string &constantName, const Constants &constants)
{
const auto match = std::find_if(constants.cbegin(), constants.cend(),
[&](const auto &constant)
{
return constant->name() == constantName;
});
const auto constantExists = (match != constants.cend());
if (!constantExists)
return nullptr;
return match->get();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Constant::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Constant::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setType(PrimitiveTypePointer type)
{
m_type = type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveTypePointer Constant::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::print(std::ostream &ostream) const
{
ostream << "(" << m_name << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,133 +0,0 @@
#include <plasp/pddl/expressions/DerivedPredicate.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// DerivedPredicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
DerivedPredicate::DerivedPredicate(size_t id)
: m_id{id}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
size_t DerivedPredicate::id() const
{
return m_id;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DerivedPredicate::setPreconditions(std::vector<Expressions> &&preconditions)
{
m_preconditions = std::move(preconditions);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<Expressions> &DerivedPredicate::preconditions() const
{
return m_preconditions;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DerivedPredicate::collectParameters()
{
for (const auto &conjunction : m_preconditions)
for (const auto &precondition : conjunction)
precondition->collectParameters(m_parameters);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::set<VariablePointer> &DerivedPredicate::parameters() const
{
return m_parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void DerivedPredicate::collectParameters(std::set<VariablePointer> &parameters)
{
for (auto &conjunction : m_preconditions)
for (auto &precondition : conjunction)
{
BOOST_ASSERT(precondition.get() != this);
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 " << m_id << " ";
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 << "))";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,34 +0,0 @@
#include <plasp/pddl/expressions/Dummy.h>
#include <plasp/pddl/IO.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Dummy
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Dummy::Dummy(std::string name)
: m_name{name}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Dummy::print(std::ostream &ostream) const
{
ostream << "(" << m_name << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,22 +0,0 @@
#include <plasp/pddl/expressions/Either.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Either
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Either::Identifier = "either";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,25 +0,0 @@
#include <plasp/pddl/expressions/Exists.h>
#include <algorithm>
#include <iostream>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Exists
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Exists::Identifier = "exists";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,42 +0,0 @@
#include <plasp/pddl/expressions/ForAll.h>
#include <algorithm>
#include <iostream>
#include <plasp/pddl/expressions/Exists.h>
#include <plasp/pddl/expressions/Not.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// ForAll
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string ForAll::Identifier = "forall";
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer ForAll::existentiallyQuantified()
{
auto existsExpression = ExistsPointer(new Exists());
auto notExpression = NotPointer(new Not());
notExpression->setArgument(m_argument->existentiallyQuantified());
existsExpression->setArgument(notExpression);
existsExpression->variables() = std::move(m_variables);
return existsExpression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,46 +0,0 @@
#include <plasp/pddl/expressions/Imply.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Or.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Imply
//
////////////////////////////////////////////////////////////////////////////////////////////////////
// TODO: make static character string literal
const std::string Imply::Identifier = "imply";
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Imply::reduced()
{
BOOST_ASSERT(m_arguments[0]);
BOOST_ASSERT(m_arguments[1]);
m_arguments[0] = m_arguments[0]->reduced();
m_arguments[1] = m_arguments[1]->reduced();
auto notArgument0 = NotPointer(new Not);
notArgument0->setArgument(m_arguments[0]);
auto orExpression = OrPointer(new Or);
orExpression->addArgument(notArgument0);
orExpression->addArgument(m_arguments[1]);
return orExpression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,134 +0,0 @@
#include <plasp/pddl/expressions/Not.h>
#include <plasp/output/TranslatorException.h>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/DerivedPredicate.h>
#include <plasp/pddl/expressions/Exists.h>
#include <plasp/pddl/expressions/ForAll.h>
#include <plasp/pddl/expressions/Or.h>
#include <plasp/pddl/expressions/Predicate.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Not
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Not::Not()
: m_argument{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Not::copy()
{
auto result = new Not;
result->m_argument = m_argument->copy();
return result;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Not::setArgument(ExpressionPointer argument)
{
m_argument = argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Not::argument() const
{
return m_argument;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Not::reduced()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->reduced();
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Not::existentiallyQuantified()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->existentiallyQuantified();
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Not::simplified()
{
BOOST_ASSERT(m_argument);
m_argument = m_argument->simplified();
if (!m_argument->is<Not>())
return this;
// Remove double negations
const auto &notExpression = m_argument->as<Not>();
return notExpression.argument();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Not::collectParameters(std::set<VariablePointer> &parameters)
{
m_argument->collectParameters(parameters);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Not::decomposed(DerivedPredicates &derivedPredicates)
{
m_argument = m_argument->decomposed(derivedPredicates);
// Predicates and derived predicates can be directly negated
if (m_argument->is<Predicate>() || m_argument->is<DerivedPredicate>())
return this;
derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size()));
auto derivedPredicate = derivedPredicates.back();
// Move this expressions arguments to the derived predicate
derivedPredicate->setPreconditions({{this}});
return derivedPredicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Not::print(std::ostream &ostream) const
{
ostream << "(not ";
m_argument->print(ostream);
ostream << ")";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,61 +0,0 @@
#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
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Or
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string Or::Identifier = "or";
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Or::decomposed(DerivedPredicates &derivedPredicates)
{
BOOST_ASSERT(!m_arguments.empty());
derivedPredicates.emplace_back(new DerivedPredicate(derivedPredicates.size()));
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->is<And>())
{
conjunction = std::move(argument->as<And>().arguments());
for (auto &argument : conjunction)
argument = argument->decomposed(derivedPredicates);
}
else
conjunction.emplace_back(argument->decomposed(derivedPredicates));
// Move this expressions arguments to the derived predicate
preconditions.emplace_back(std::move(conjunction));
}
derivedPredicate->setPreconditions(std::move(preconditions));
return derivedPredicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,199 +0,0 @@
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/Problem.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Predicate
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Predicate::Predicate()
: m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(Context &context, ExpressionContext &expressionContext)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("("))
{
tokenizer.seek(position);
return nullptr;
}
const auto predicateName = tokenizer.getIdentifier();
const auto &predicates = expressionContext.domain.predicates();
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
tokenizer.seek(position);
return nullptr;
}
auto predicate = PredicatePointer(new Predicate);
predicate->m_name = predicateName;
tokenizer.skipWhiteSpace();
// Parse arguments
while (tokenizer.currentCharacter() != ')')
{
// Parse variables
if (tokenizer.currentCharacter() == '?')
{
const auto variable = expressionContext.variables.parseAndFind(context);
predicate->m_arguments.emplace_back(variable);
}
// Parse constants
else
{
const auto constant = (expressionContext.problem == nullptr)
? Constant::parseAndFind(context, expressionContext.domain)
: Constant::parseAndFind(context, *expressionContext.problem);
predicate->m_arguments.emplace_back(constant);
}
tokenizer.skipWhiteSpace();
}
// TODO: check that signature matches one of the declared ones
tokenizer.expect<std::string>(")");
return predicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicatePointer Predicate::parse(Context &context, const Problem &problem)
{
auto &tokenizer = context.tokenizer;
const auto position = tokenizer.position();
if (!tokenizer.testAndSkip<std::string>("("))
{
tokenizer.seek(position);
return nullptr;
}
const auto predicateName = tokenizer.getIdentifier();
const auto &predicates = problem.domain().predicates();
const auto matchingPredicate = std::find_if(predicates.cbegin(), predicates.cend(),
[&](const auto &predicate)
{
return predicate->name() == predicateName;
});
if (matchingPredicate == predicates.cend())
{
tokenizer.seek(position);
return nullptr;
}
auto predicate = PredicatePointer(new Predicate);
predicate->m_name = predicateName;
tokenizer.skipWhiteSpace();
while (tokenizer.currentCharacter() != ')')
{
if (tokenizer.currentCharacter() == '?')
throw tokenize::TokenizerException(tokenizer, "variables not allowed in this context");
// Parse objects and constants
const auto constant = Constant::parseAndFind(context, problem);
predicate->m_arguments.emplace_back(constant);
}
// TODO: check that signature matches one of the declared ones
tokenizer.expect<std::string>(")");
return predicate;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Predicate::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Predicate::decomposed(DerivedPredicates &)
{
// Predicates cannot be further decomposed
return this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::collectParameters(std::set<VariablePointer> &parameters)
{
for (const auto &argument : m_arguments)
argument->collectParameters(parameters);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Predicate::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Expressions &Predicate::arguments() const
{
return m_arguments;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Predicate::print(std::ostream &ostream) const
{
// TODO: implement correctly
ostream << "(<predicate>)";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,103 +0,0 @@
#include <plasp/pddl/expressions/PredicateDeclaration.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/Constant.h>
#include <plasp/pddl/expressions/Variable.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PredicateDeclaration
//
////////////////////////////////////////////////////////////////////////////////////////////////////
PredicateDeclaration::PredicateDeclaration()
: m_isDeclared{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::parse(Context &context, Domain &domain)
{
auto &tokenizer = context.tokenizer;
tokenizer.expect<std::string>("(");
auto predicate = PredicateDeclarationPointer(new PredicateDeclaration);
predicate->m_name = tokenizer.getIdentifier();
// Flag predicate as correctly declared in the types section
predicate->setDeclared();
tokenizer.skipWhiteSpace();
ExpressionContext expressionContext(domain);
expressionContext.variables.push(&predicate->m_parameters);
// Parse parameters
Variable::parseTypedDeclarations(context, expressionContext, predicate->m_parameters);
tokenizer.expect<std::string>(")");
domain.predicates().emplace_back(std::move(predicate));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool PredicateDeclaration::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &PredicateDeclaration::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Variables &PredicateDeclaration::parameters() const
{
return m_parameters;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::normalizeParameterNames()
{
for (size_t i = 0; i < m_parameters.size(); i++)
m_parameters[i]->setName("X" + std::to_string(i));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PredicateDeclaration::print(std::ostream &ostream) const
{
// TODO: implement correctly
ostream << "(<predicate declaration>)";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,184 +0,0 @@
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// PrimitiveType
//
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType::PrimitiveType()
: m_isDirty{true}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveType::PrimitiveType(std::string name)
: m_isDirty{true},
m_name{name}
{
BOOST_ASSERT(!m_name.empty());
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::parseDeclaration(Context &context, Domain &domain)
{
auto &types = domain.types();
context.tokenizer.skipWhiteSpace();
const auto typeName = context.tokenizer.getIdentifier();
const auto match = std::find_if(types.cbegin(), types.cend(),
[&](const auto &primitiveType)
{
return primitiveType->name() == typeName;
});
// Return existing primitive type
if (match != types.cend())
{
auto *type = match->get();
type->setDirty();
return;
}
types.emplace_back(PrimitiveTypePointer(new PrimitiveType(typeName)));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::parseTypedDeclaration(Context &context, Domain &domain)
{
auto &types = domain.types();
// Parse and store type
parseDeclaration(context, domain);
context.tokenizer.skipWhiteSpace();
// Check for type inheritance
if (!context.tokenizer.testAndSkip<char>('-'))
return;
domain.checkRequirement(Requirement::Type::Typing);
// If existing, parse and store parent type
auto parentType = parseAndFind(context, domain);
parentType->setDirty(false);
// Assign parent type to all types that were previously flagged
std::for_each(types.begin(), types.end(),
[&](auto &childType)
{
if (!childType->isDirty())
return;
childType->m_parentTypes.push_back(parentType);
childType->setDirty(false);
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveTypePointer PrimitiveType::parseAndFind(Context &context, Domain &domain)
{
auto &tokenizer = context.tokenizer;
auto &types = domain.types();
tokenizer.skipWhiteSpace();
const auto typeName = tokenizer.getIdentifier();
if (typeName.empty())
throw tokenize::TokenizerException(tokenizer, "no type supplied");
const auto match = std::find_if(types.cbegin(), types.cend(),
[&](const auto &primitiveType)
{
return primitiveType->name() == typeName;
});
if (match == types.cend())
{
// Only "object" is allowed as an implicit type
if (typeName == "object" || typeName == "objects")
{
context.logger.log(output::Priority::Warning, tokenizer, "primitive type “" + typeName + "” should be declared");
types.emplace_back(PrimitiveTypePointer(new PrimitiveType(typeName)));
}
else
throw tokenize::TokenizerException(tokenizer, "type “" + typeName + "” used but never declared");
return types.back().get();
}
auto *type = match->get();
type->setDirty();
return type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool PrimitiveType::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &PrimitiveType::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const PrimitiveTypes &PrimitiveType::parentTypes() const
{
return m_parentTypes;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::print(std::ostream &ostream) const
{
// TODO: implement correctly
ostream << "(<primitive type" << m_name << ">)";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,30 +0,0 @@
#include <plasp/pddl/expressions/Type.h>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Type
//
////////////////////////////////////////////////////////////////////////////////////////////////////
PrimitiveTypePointer parseExistingPrimitiveType(Context &context,
ExpressionContext &expressionContext)
{
return PrimitiveType::parseAndFind(context, expressionContext.domain);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,54 +0,0 @@
#include <plasp/pddl/expressions/Unsupported.h>
#include <plasp/pddl/IO.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Unsupported
//
////////////////////////////////////////////////////////////////////////////////////////////////////
UnsupportedPointer Unsupported::parse(Context &context)
{
auto &tokenizer = context.tokenizer;
auto expression = UnsupportedPointer(new Unsupported);
tokenizer.expect<std::string>("(");
expression->m_type = tokenizer.getIdentifier();
context.logger.log(output::Priority::Warning, tokenizer, "expression type “" + expression->m_type + "” currently unsupported in this context");
skipSection(tokenizer);
return expression;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Unsupported::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Unsupported::print(std::ostream &ostream) const
{
// TODO: implement correctly
ostream << "(<unsupported expression “" << m_type << "”>)";
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,210 +0,0 @@
#include <plasp/pddl/expressions/Variable.h>
#include <algorithm>
#include <boost/assert.hpp>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/ExpressionContext.h>
#include <plasp/pddl/expressions/Either.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
#include <plasp/pddl/expressions/Type.h>
#include <tokenize/TokenizerException.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Variable
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Variable::Variable()
: m_isDirty{false}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Variable::Variable(std::string name)
: m_isDirty{false},
m_name{name}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseDeclaration(Context &context, Variables &parameters)
{
auto &tokenizer = context.tokenizer;
tokenizer.skipWhiteSpace();
tokenizer.expect<std::string>("?");
auto variable = VariablePointer(new Variable);
variable->m_name = tokenizer.getIdentifier();
// Check if variable of that name already exists in the current scope
const auto match = std::find_if(parameters.cbegin(), parameters.cend(),
[&](const auto &parameter)
{
return parameter->name() == variable->m_name;
});
if (match != parameters.cend())
throw tokenize::TokenizerException(tokenizer, "variable “" + variable->m_name + "” already declared in this scope");
// Flag variable for potentially upcoming type declaration
variable->setDirty();
parameters.emplace_back(variable);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseTypedDeclaration(Context &context, ExpressionContext &expressionContext,
Variables &variables)
{
auto &tokenizer = context.tokenizer;
// Parse and store variable itself
parseDeclaration(context, variables);
auto variable = variables.back();
tokenizer.skipWhiteSpace();
// Check if the variable has a type declaration
if (!tokenizer.testAndSkip<char>('-'))
return;
const auto setType =
[&](ExpressionPointer type)
{
// Set the argument type for all previously flagged arguments
for (auto &variable : variables)
{
if (!variable->isDirty())
return;
variable->setType(type);
variable->setDirty(false);
}
};
tokenizer.skipWhiteSpace();
// Parse argument if it has "either" type (always begins with opening parenthesis)
variable->m_type = Either::parse(context, expressionContext, parseExistingPrimitiveType);
// Else, try parsing it as a primitive type
if (!variable->m_type)
variable->m_type = PrimitiveType::parseAndFind(context, expressionContext.domain);
setType(variable->m_type);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::parseTypedDeclarations(Context &context, ExpressionContext &expressionContext,
Variables &variables)
{
auto &tokenizer = context.tokenizer;
while (tokenizer.currentCharacter() != ')')
{
parseTypedDeclaration(context, expressionContext, variables);
tokenizer.skipWhiteSpace();
}
if (variables.empty())
return;
// Check correct use of typing requirement
const auto typingUsed = (variables.back()->type() != nullptr);
// If types are given, check that typing is a requirement
if (typingUsed)
expressionContext.checkRequirement(Requirement::Type::Typing);
// If no types are given, check that typing is not a requirement
else if (expressionContext.hasRequirement(Requirement::Type::Typing))
throw tokenize::TokenizerException(tokenizer, "variable has undeclared type");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setName(std::string name)
{
m_name = name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Variable::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setType(ExpressionPointer type)
{
m_type = type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
ExpressionPointer Variable::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Variable::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::collectParameters(std::set<VariablePointer> &parameters)
{
parameters.emplace(this);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Variable::print(std::ostream &ostream) const
{
ostream << "?" << m_name;
if (m_type)
{
ostream << " - ";
m_type->print(ostream);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -1,22 +0,0 @@
#include <plasp/pddl/expressions/When.h>
namespace plasp
{
namespace pddl
{
namespace expressions
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// When
//
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string When::Identifier = "when";
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
}

View File

@ -7,6 +7,8 @@ set(includes
${PROJECT_SOURCE_DIR}/include
${PROJECT_SOURCE_DIR}/lib/catch/single_include
${PROJECT_SOURCE_DIR}/lib/tokenize/include
${PROJECT_SOURCE_DIR}/lib/variant/include
${PROJECT_SOURCE_DIR}/lib/pddlparse/include
)
set(libraries

View File

@ -1,19 +1,8 @@
#include <catch.hpp>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Dummy.h>
#include <plasp/pddl/expressions/Exists.h>
#include <plasp/pddl/expressions/ForAll.h>
#include <plasp/pddl/expressions/Imply.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Or.h>
#include <plasp/pddl/expressions/Variable.h>
using namespace plasp::pddl;
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL normalization] PDDL expressions are correctly reduced", "[PDDL normalization]")
/*TEST_CASE("[PDDL normalization] PDDL expressions are correctly reduced", "[PDDL normalization]")
{
auto n1 = expressions::NotPointer(new expressions::Not);
auto n2 = expressions::NotPointer(new expressions::Not);
@ -205,4 +194,4 @@ TEST_CASE("[PDDL normalization] “for all” expressions are correctly replaced
f1->normalized()->print(output);
CHECK(output.str() == "(exists (?x ?y) (not (exists (?z ?u ?v ?w) (not (a)))))");
}
}*/

View File

@ -1,532 +0,0 @@
#include <catch.hpp>
#include <fstream>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <plasp/pddl/ConsistencyException.h>
#include <plasp/pddl/Description.h>
#include <plasp/pddl/expressions/And.h>
#include <plasp/pddl/expressions/Either.h>
#include <plasp/pddl/expressions/Not.h>
#include <plasp/pddl/expressions/Predicate.h>
#include <plasp/pddl/expressions/PrimitiveType.h>
using namespace plasp::pddl;
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] The Blocks World domain is parsed correctly", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
const auto description = Description::fromFile("data/blocksworld-domain.pddl", context);
REQUIRE_NOTHROW(description.domain());
const auto &domain = description.domain();
// Name
CHECK(domain.name() == "blocks");
// Requirements
REQUIRE(domain.requirements().size() == 2u);
CHECK(domain.requirements()[0].type() == Requirement::Type::STRIPS);
CHECK(domain.requirements()[1].type() == Requirement::Type::Typing);
// Types
REQUIRE(domain.types().size() == 1u);
const auto &block = *domain.types()[0];
CHECK(block.name() == "block");
REQUIRE(block.parentTypes().size() == 0u);
// Predicates
REQUIRE(domain.predicates().size() == 5u);
const auto &on = *domain.predicates()[0];
CHECK(on.name() == "on");
REQUIRE(on.parameters().size() == 2u);
CHECK(on.parameters()[0]->name() == "x");
const auto &onArgument0Type = on.parameters()[0]->type()->as<expressions::PrimitiveType>();
CHECK(&onArgument0Type == &block);
CHECK(on.parameters()[1]->name() == "y");
const auto &onArgument1Type = on.parameters()[1]->type()->as<expressions::PrimitiveType>();
CHECK(&onArgument1Type == &block);
const auto &handempty = *domain.predicates()[3];
CHECK(handempty.name() == "handempty");
CHECK(handempty.parameters().empty());
// Actions
REQUIRE(domain.actions().size() == 4u);
const auto &pickUp = *domain.actions()[0];
CHECK(pickUp.name() == "pick-up");
REQUIRE(pickUp.parameters().size() == 1u);
CHECK(pickUp.parameters()[0]->name() == "x");
CHECK(pickUp.parameters()[0]->type() == &block);
const auto &pickUpPre = pickUp.precondition()->as<expressions::And>();
REQUIRE(pickUpPre.arguments().size() == 3u);
const auto &pickUpPre0 = pickUpPre.arguments()[0]->as<expressions::Predicate>();
CHECK(pickUpPre0.name() == "clear");
REQUIRE(pickUpPre0.arguments().size() == 1u);
const auto &pickUpPre00 = pickUpPre0.arguments()[0]->as<expressions::Variable>();
CHECK(pickUpPre00.name() == "x");
CHECK(pickUpPre00.type() == &block);
CHECK(&pickUpPre00 == pickUp.parameters()[0].get());
const auto &pickUpPre2 = pickUpPre.arguments()[2]->as<expressions::Predicate>();
CHECK(pickUpPre2.name() == "handempty");
CHECK(pickUpPre2.arguments().empty());
const auto &pickUpEff = pickUp.effect()->as<expressions::And>();
REQUIRE(pickUpEff.arguments().size() == 4u);
const auto &pickUpEff0 = pickUpEff.arguments()[0]->as<expressions::Not>();
const auto &pickUpEff00 = pickUpEff0.argument()->as<expressions::Predicate>();
CHECK(pickUpEff00.name() == "ontable");
REQUIRE(pickUpEff00.arguments().size() == 1u);
const auto &pickUpEff000 = pickUpEff00.arguments()[0]->as<expressions::Variable>();
CHECK(pickUpEff000.name() == "x");
CHECK(pickUpEff000.type() == &block);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] A Blocks World problem is parsed correctly", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
const auto description = Description::fromFiles({"data/blocksworld-domain.pddl", "data/blocksworld-problem.pddl"}, context);
REQUIRE_NOTHROW(description.problem());
const auto &problem = description.problem();
// Name
CHECK(problem.name() == "blocks-4-0");
CHECK(problem.domain().name() == "blocks");
// Requirements
// TODO: compute domain vs. problem requirements correctly and check them
// Objects
REQUIRE(problem.objects().size() == 4u);
CHECK(problem.objects()[0]->name() == "d");
REQUIRE(problem.objects()[0]->type() != nullptr);
CHECK(problem.objects()[0]->type()->name() == "block");
CHECK(problem.objects()[3]->name() == "c");
REQUIRE(problem.objects()[3]->type() != nullptr);
CHECK(problem.objects()[3]->type()->name() == "block");
// Initial State
const auto &facts = problem.initialState().facts();
REQUIRE(facts.size() == 9u);
const auto &fact0 = facts[0].get()->as<expressions::Predicate>();
CHECK(fact0.name() == "clear");
REQUIRE(fact0.arguments().size() == 1u);
const auto &fact00 = fact0.arguments()[0]->as<expressions::Constant>();
CHECK(fact00.name() == "c");
REQUIRE(fact00.type() != nullptr);
CHECK(fact00.type()->name() == "block");
const auto &fact8 = facts[8].get()->as<expressions::Predicate>();
CHECK(fact8.name() == "handempty");
REQUIRE(fact8.arguments().size() == 0u);
// Goal
const auto &goal = problem.goal().as<expressions::And>();
REQUIRE(goal.arguments().size() == 3u);
const auto &goal0 = goal.arguments()[0]->as<expressions::Predicate>();
CHECK(goal0.name() == "on");
REQUIRE(goal0.arguments().size() == 2u);
const auto &goal00 = goal0.arguments()[0]->as<expressions::Constant>();
CHECK(goal00.name() == "d");
const auto &goal01 = goal0.arguments()[1]->as<expressions::Constant>();
CHECK(goal01.name() == "c");
const auto &goal2 = goal.arguments()[2]->as<expressions::Predicate>();
CHECK(goal2.name() == "on");
REQUIRE(goal2.arguments().size() == 2u);
const auto &goal20 = goal2.arguments()[0]->as<expressions::Constant>();
CHECK(goal20.name() == "b");
const auto &goal21 = goal2.arguments()[1]->as<expressions::Constant>();
CHECK(goal21.name() == "a");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] The Storage domain is parsed correctly", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
const auto description = plasp::pddl::Description::fromFile("data/storage-domain.pddl", context);
REQUIRE_NOTHROW(description.domain());
const auto &domain = description.domain();
// Name
CHECK(domain.name() == "storage-propositional");
// Requirements
REQUIRE(domain.requirements().size() == 1u);
CHECK(domain.requirements()[0].type() == Requirement::Type::Typing);
// Types
REQUIRE(domain.types().size() == 10u);
const auto &hoist = *domain.types()[0];
const auto &surface = *domain.types()[1];
const auto &area = *domain.types()[3];
const auto &object = *domain.types()[4];
const auto &storearea = *domain.types()[7];
const auto &crate = *domain.types()[9];
const auto &hoistParents = hoist.parentTypes();
REQUIRE(hoistParents.size() == 1u);
CHECK(std::find(hoistParents.cbegin(), hoistParents.cend(), &object) != hoistParents.cend());
const auto &areaParents = area.parentTypes();
REQUIRE(areaParents.size() == 2u);
CHECK(std::find(areaParents.cbegin(), areaParents.cend(), &object) != areaParents.cend());
CHECK(std::find(areaParents.cbegin(), areaParents.cend(), &surface) != areaParents.cend());
// Predicates
REQUIRE(domain.predicates().size() == 8u);
const auto &on = *domain.predicates()[5];
CHECK(on.name() == "on");
REQUIRE(on.parameters().size() == 2u);
CHECK(on.parameters()[0]->name() == "c");
const auto &onArgument0Type = on.parameters()[0]->type()->as<expressions::PrimitiveType>();
CHECK(&onArgument0Type == &crate);
CHECK(on.parameters()[1]->name() == "s");
const auto &onArgument1Type = on.parameters()[1]->type()->as<expressions::PrimitiveType>();
CHECK(&onArgument1Type == &storearea);
const auto &in = *domain.predicates()[1];
CHECK(in.name() == "in");
REQUIRE(in.parameters().size() == 2u);
CHECK(in.parameters()[0]->name() == "x");
const auto &inArgument0Type = in.parameters()[0]->type()->as<expressions::Either>();
REQUIRE(inArgument0Type.arguments().size() == 2u);
const auto &inArgument0Type0 = inArgument0Type.arguments()[0]->as<expressions::PrimitiveType>();
CHECK(&inArgument0Type0 == &storearea);
const auto &inArgument0Type1 = inArgument0Type.arguments()[1]->as<expressions::PrimitiveType>();
CHECK(&inArgument0Type1 == &crate);
// Actions
REQUIRE(domain.actions().size() == 5u);
const auto &drop = *domain.actions()[1];
CHECK(drop.name() == "drop");
REQUIRE(drop.parameters().size() == 5u);
CHECK(drop.parameters()[3]->name() == "a2");
CHECK(drop.parameters()[3]->type() == &area);
const auto &dropPre = drop.precondition()->as<expressions::And>();
REQUIRE(dropPre.arguments().size() == 5u);
const auto &dropPre2 = dropPre.arguments()[2]->as<expressions::Predicate>();
CHECK(dropPre2.name() == "lifting");
REQUIRE(dropPre2.arguments().size() == 2u);
const auto &dropPre21 = dropPre2.arguments()[1]->as<expressions::Variable>();
CHECK(dropPre21.name() == "c");
CHECK(dropPre21.type() == &crate);
const auto &dropEff = drop.effect()->as<expressions::And>();
REQUIRE(dropEff.arguments().size() == 5u);
const auto &dropEff2 = dropEff.arguments()[2]->as<expressions::Not>();
const auto &dropEff20 = dropEff2.argument()->as<expressions::Predicate>();
CHECK(dropEff20.name() == "clear");
REQUIRE(dropEff20.arguments().size() == 1u);
const auto &dropEff200 = dropEff20.arguments()[0]->as<expressions::Variable>();
CHECK(dropEff200.name() == "a1");
CHECK(dropEff200.type() == &storearea);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] A Storage problem is parsed correctly", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
const auto description = Description::fromFiles({"data/storage-domain.pddl", "data/storage-problem.pddl"}, context);
REQUIRE_NOTHROW(description.problem());
const auto &problem = description.problem();
// Name
CHECK(problem.name() == "storage-1");
CHECK(problem.domain().name() == "storage-propositional");
// Requirements
// TODO: compute domain vs. problem requirements correctly and check them
// Objects
REQUIRE(problem.objects().size() == 7u);
CHECK(problem.objects()[0]->name() == "depot0-1-1");
REQUIRE(problem.objects()[0]->type() != nullptr);
CHECK(problem.objects()[0]->type()->name() == "storearea");
CHECK(problem.objects()[6]->name() == "loadarea");
REQUIRE(problem.objects()[6]->type() != nullptr);
CHECK(problem.objects()[6]->type()->name() == "transitarea");
// Initial State
const auto &facts = problem.initialState().facts();
REQUIRE(facts.size() == 10u);
const auto &fact0 = facts[0].get()->as<expressions::Predicate>();
CHECK(fact0.name() == "in");
REQUIRE(fact0.arguments().size() == 2u);
const auto &fact01 = fact0.arguments()[1]->as<expressions::Constant>();
CHECK(fact01.name() == "depot0");
REQUIRE(fact01.type() != nullptr);
CHECK(fact01.type()->name() == "depot");
const auto &fact9 = facts[9].get()->as<expressions::Predicate>();
CHECK(fact9.name() == "available");
REQUIRE(fact9.arguments().size() == 1u);
const auto &fact90 = fact9.arguments()[0]->as<expressions::Constant>();
CHECK(fact90.name() == "hoist0");
REQUIRE(fact90.type() != nullptr);
CHECK(fact90.type()->name() == "hoist");
// Goal
const auto &goal = problem.goal().as<expressions::And>();
REQUIRE(goal.arguments().size() == 1u);
const auto &goal0 = goal.arguments()[0]->as<expressions::Predicate>();
CHECK(goal0.name() == "in");
REQUIRE(goal0.arguments().size() == 2u);
const auto &goal00 = goal0.arguments()[0]->as<expressions::Constant>();
CHECK(goal00.name() == "crate0");
const auto &goal01 = goal0.arguments()[1]->as<expressions::Constant>();
CHECK(goal01.name() == "depot0");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] Constants are parsed correctly", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
const auto description = Description::fromFile("data/woodworking-domain.pddl", context);
REQUIRE_NOTHROW(description.domain());
const auto &domain = description.domain();
// Name
CHECK(domain.name() == "woodworking");
// Types
const auto &acolour = *domain.types()[0];
const auto &surface = *domain.types()[4];
const auto &treatmentstatus = *domain.types()[5];
// Constants
REQUIRE(domain.constants().size() == 8u);
CHECK(domain.constants()[0]->type() == &surface);
CHECK(domain.constants()[2]->type() == &surface);
CHECK(domain.constants()[3]->type() == &treatmentstatus);
CHECK(domain.constants()[6]->type() == &treatmentstatus);
CHECK(domain.constants()[7]->type() == &acolour);
// TODO: add test with constants in predicates
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] White spaces are ignored", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
CHECK_NOTHROW(Description::fromFile("data/test-cases/white-space.pddl", context));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] Missing or unmatching domain descriptions are detected", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
SECTION("")
{
CHECK_THROWS_AS(Description::fromFile("data/blocksworld-problem.pddl", context), ConsistencyException);
}
SECTION("")
{
CHECK_THROWS_AS(Description::fromFiles({"data/blocksworld-problem.pddl", "data/storage-domain.pddl"}, context), tokenize::TokenizerException);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] Common PDDL syntax errors are detected", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
SECTION("")
{
CHECK_NOTHROW(Description::fromFile("data/pddl-syntax/domain-valid.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-expressions-1.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-expressions-2.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-expressions-3.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-expression-name-1.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-expression-name-2.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-expression-name-3.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-1.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-2.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-3.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-4.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-5.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-6.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-7.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-parentheses-8.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-1.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-2.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-3.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-4.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-5.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-6.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-section-name-7.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-types-1.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-types-2.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-types-3.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-types-4.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-variables-1.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-variables-2.pddl", context));
}
SECTION("")
{
CHECK_THROWS(Description::fromFile("data/pddl-syntax/domain-variables-3.pddl", context));
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL parser] Former issues are fixed", "[PDDL parser]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
SECTION("white space issues with constants and parsing unsupported sections")
{
CHECK_NOTHROW(Description::fromFile("data/issues/issue-1.pddl", context));
}
SECTION("white space issues with empty n-ary predicates")
{
CHECK_NOTHROW(Description::fromFile("data/issues/issue-2.pddl", context));
}
SECTION("comments are correctly ignored")
{
CHECK_NOTHROW(Description::fromFile("data/issues/issue-3.pddl", context));
}
}

View File

@ -3,31 +3,37 @@
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/null.hpp>
#include <plasp/pddl/Description.h>
#include <pddlparse/AST.h>
#include <pddlparse/Parse.h>
#include <plasp/output/Logger.h>
#include <plasp/pddl/TranslatorASP.h>
using namespace plasp::pddl;
boost::iostreams::stream<boost::iostreams::null_sink> nullStream((boost::iostreams::null_sink()));
const pddl::Context::WarningCallback ignoreWarnings = [](const auto &, const auto &){};
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_CASE("[PDDL translation] Former issues are fixed", "[PDDL translation]")
{
plasp::output::Logger logger;
Context context(Tokenizer(), logger);
// TODO: refactor
plasp::output::Logger logger(nullStream, nullStream);
pddl::Tokenizer tokenizer;
pddl::Context context(std::move(tokenizer), ignoreWarnings);
SECTION("translating domains without typing information works")
{
auto description = Description::fromFile("data/issues/issue-4.pddl", context);
const auto translator = TranslatorASP(description, description.context().logger.outputStream());
context.tokenizer.read("data/issues/issue-4.pddl");
auto description = pddl::parseDescription(context);
const auto translator = plasp::pddl::TranslatorASP(std::move(description), logger.outputStream());
CHECK_NOTHROW(translator.translate());
}
SECTION("translating the simple blocks world domain works")
{
auto description = Description::fromFile("data/issues/issue-5.pddl", context);
const auto translator = TranslatorASP(description, description.context().logger.outputStream());
context.tokenizer.read("data/issues/issue-5.pddl");
auto description = pddl::parseDescription(context);
const auto translator = plasp::pddl::TranslatorASP(std::move(description), logger.outputStream());
CHECK_NOTHROW(translator.translate());
}
}