Started implementation of PDDL problem parser.

This commit is contained in:
Patrick Lühne 2016-06-04 17:53:42 +02:00
parent ee597c805e
commit e481732fae
4 changed files with 259 additions and 3 deletions

View File

@ -4,6 +4,7 @@
#include <boost/filesystem/path.hpp>
#include <plasp/pddl/Domain.h>
#include <plasp/pddl/Problem.h>
#include <plasp/utils/Parser.h>
namespace plasp
@ -36,7 +37,7 @@ class Description
Context m_context;
std::unique_ptr<Domain> m_domain;
//std::unique_ptr<Problem> m_problem;
std::unique_ptr<Problem> m_problem;
};
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -0,0 +1,50 @@
#ifndef __PLASP__PDDL__PROBLEM_H
#define __PLASP__PDDL__PROBLEM_H
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Expression.h>
#include <plasp/pddl/Requirement.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Problem
{
public:
static Problem fromPDDL(Context &context);
public:
const std::string &name() const;
const Requirements &requirements() const;
private:
Problem(Context &context);
void parseSection();
void parseRequirementSection();
bool hasRequirement(Requirement::Type requirementType) const;
void computeDerivedRequirements();
void checkConsistency();
Context &m_context;
std::string m_name;
Requirements m_requirements;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -89,8 +89,8 @@ void Description::parseSection()
if (sectionIdentifier == "domain")
m_domain = std::make_unique<Domain>(Domain::fromPDDL(m_context));
//else if (sectionIdentifier == "problem")
// m_problem = std::make_unique<Problem>(Problem::fromPDDL(parser));
else if (sectionIdentifier == "problem")
m_problem = std::make_unique<Problem>(Problem::fromPDDL(m_context));
else
throw utils::ParserException(m_context.parser, "Unknown PDDL section \"" + sectionIdentifier + "\"");
}

205
src/plasp/pddl/Problem.cpp Normal file
View File

@ -0,0 +1,205 @@
#include <plasp/pddl/Problem.h>
#include <algorithm>
#include <plasp/pddl/Identifier.h>
#include <plasp/utils/IO.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Problem
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Problem::Problem(Context &context)
: m_context(context)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Problem Problem::fromPDDL(Context &context)
{
Problem problem(context);
problem.m_name = context.parser.parseIdentifier(isIdentifier);
std::cout << "Parsing problem " << problem.m_name << std::endl;
context.parser.expect<std::string>(")");
while (true)
{
context.parser.skipWhiteSpace();
if (context.parser.currentCharacter() == ')')
break;
problem.parseSection();
}
problem.computeDerivedRequirements();
problem.checkConsistency();
return problem;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Problem::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const Requirements &Problem::requirements() const
{
return m_requirements;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseSection()
{
m_context.parser.expect<std::string>("(");
m_context.parser.expect<std::string>(":");
const auto sectionIdentifier = utils::toLowerCase(m_context.parser.parseIdentifier(isIdentifier));
const auto skipSection =
[&]()
{
std::cout << "Skipping section " << sectionIdentifier << std::endl;
size_t openParentheses = 1;
while (true)
{
const auto character = m_context.parser.currentCharacter();
m_context.parser.advance();
if (character == '(')
openParentheses++;
else if (character == ')')
{
openParentheses--;
if (openParentheses == 0)
return;
}
}
};
// TODO: check order of the sections
if (sectionIdentifier == "domain")
skipSection();
else if (sectionIdentifier == "requirements")
parseRequirementSection();
else if (sectionIdentifier == "objects")
skipSection();
else if (sectionIdentifier == "init")
skipSection();
else if (sectionIdentifier == "goal")
skipSection();
else if (sectionIdentifier == "constraints")
skipSection();
else if (sectionIdentifier == "metric")
skipSection();
else if (sectionIdentifier == "length")
skipSection();
else
throw utils::ParserException(m_context.parser, "Unknown problem section \"" + sectionIdentifier + "\"");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Problem::parseRequirementSection()
{
m_context.parser.skipWhiteSpace();
while (m_context.parser.currentCharacter() != ')')
{
m_context.parser.expect<std::string>(":");
m_requirements.emplace_back(Requirement::parse(m_context));
m_context.parser.skipWhiteSpace();
}
// If no requirements are specified, assume STRIPS
if (m_requirements.empty())
m_requirements.emplace_back(Requirement::Type::STRIPS);
m_context.parser.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;
});
return match != m_requirements.cend();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
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::checkConsistency()
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}