Implemented parsing of PDDL constants.

This commit is contained in:
Patrick Lühne 2016-06-01 16:47:34 +02:00
parent 3c97ced486
commit 25cf7c8ae8
9 changed files with 509 additions and 6 deletions

View File

@ -0,0 +1,60 @@
#ifndef __PLASP__PDDL__CONSTANT_H
#define __PLASP__PDDL__CONSTANT_H
#include <string>
#include <vector>
#include <plasp/pddl/Type.h>
#include <plasp/utils/Parser.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
class Context;
////////////////////////////////////////////////////////////////////////////////////////////////////
class Constant
{
public:
static Constant &parse(utils::Parser &parser, Context &context);
static Constant &parseDeclaration(utils::Parser &parser, Context &context);
public:
const std::string &name() const;
const PrimitiveType *type() const;
bool isDeclared() const;
private:
Constant(std::string name);
void setDirty(bool isDirty = true);
bool isDirty() const;
void setDeclared();
void setType(const PrimitiveType *parentType);
bool m_isDirty;
bool m_isDeclared;
std::string m_name;
const PrimitiveType *m_type;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}
#endif

View File

@ -5,6 +5,7 @@
#include <unordered_map>
#include <vector>
#include <plasp/pddl/Constant.h>
#include <plasp/pddl/Predicate.h>
#include <plasp/pddl/Type.h>
@ -27,6 +28,9 @@ class Context
std::vector<std::unique_ptr<EitherType>> eitherTypes;
std::vector<std::unique_ptr<Constant>> constants;
std::unordered_map<std::string, Constant *> constantsHashMap;
std::vector<std::unique_ptr<Predicate>> predicates;
std::unordered_map<PredicateHashMapKey, Predicate *> predicatesHashMap;
};

View File

@ -29,6 +29,7 @@ class Domain
const std::string &name() const;
const Requirements &requirements() const;
const std::vector<std::unique_ptr<PrimitiveType>> &types() const;
const std::vector<std::unique_ptr<Constant>> &constants() const;
const std::vector<std::unique_ptr<Predicate>> &predicates() const;
private:
@ -42,6 +43,8 @@ class Domain
void parseTypeSection(utils::Parser &parser);
void parseConstantSection(utils::Parser &parser);
void parsePredicateSection(utils::Parser &parser);
void checkConsistency();

View File

@ -41,7 +41,7 @@ class PrimitiveType
void setDeclared();
void addParentType(const PrimitiveType &parentType);
void addParentType(const PrimitiveType *parentType);
bool m_isDirty;
bool m_isDeclared;

146
src/plasp/pddl/Constant.cpp Normal file
View File

@ -0,0 +1,146 @@
#include <plasp/pddl/Constant.h>
#include <algorithm>
#include <plasp/pddl/Context.h>
#include <plasp/pddl/Identifier.h>
namespace plasp
{
namespace pddl
{
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constant
//
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant::Constant(std::string name)
: m_isDirty{false},
m_isDeclared{false},
m_name(name),
m_type{nullptr}
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant &Constant::parse(utils::Parser &parser, Context &context)
{
parser.skipWhiteSpace();
const auto constantName = parser.parseIdentifier(isIdentifier);
const auto match = context.constantsHashMap.find(constantName);
const auto constantExists = (match != context.constantsHashMap.cend());
// Return existing primitive types
if (constantExists)
{
auto &constant = *match->second;
constant.setDirty();
return constant;
}
// Store new primitive type
context.constants.emplace_back(std::make_unique<Constant>(Constant(constantName)));
auto &constant = *context.constants.back();
// Add a pointer to the primitive type to the hash map
context.constantsHashMap.emplace(std::make_pair(constantName, &constant));
// Flag type for potentially upcoming parent type declaration
constant.setDirty();
return constant;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
Constant &Constant::parseDeclaration(utils::Parser &parser, Context &context)
{
// Parse and store constant
auto &constant = parse(parser, context);
// Flag constant as correctly declared in the types section
constant.setDeclared();
parser.skipWhiteSpace();
// Check for typing information
if (!parser.advanceIf('-'))
return constant;
// If existing, parse and store parent type
auto &type = PrimitiveType::parse(parser, context);
// Assign parent type to all types that were previously flagged
std::for_each(context.constants.begin(), context.constants.end(),
[&](auto &constant)
{
if (!constant->isDirty())
return;
constant->setType(&type);
constant->setDirty(false);
});
return constant;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setDirty(bool isDirty)
{
m_isDirty = isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Constant::isDirty() const
{
return m_isDirty;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setDeclared()
{
m_isDeclared = true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
bool Constant::isDeclared() const
{
return m_isDeclared;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::string &Constant::name() const
{
return m_name;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Constant::setType(const PrimitiveType *type)
{
m_type = type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const PrimitiveType *Constant::type() const
{
return m_type;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
}
}

View File

@ -74,6 +74,13 @@ const std::vector<std::unique_ptr<PrimitiveType>> &Domain::types() const
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<std::unique_ptr<Constant>> &Domain::constants() const
{
return m_context.constants;
}
////////////////////////////////////////////////////////////////////////////////////////////////////
const std::vector<std::unique_ptr<Predicate>> &Domain::predicates() const
{
return m_context.predicates;
@ -116,7 +123,7 @@ void Domain::parseSection(utils::Parser &parser)
else if (sectionIdentifier == "types")
parseTypeSection(parser);
else if (sectionIdentifier == "constants")
skipSection();
parseConstantSection(parser);
else if (sectionIdentifier == "predicates")
parsePredicateSection(parser);
else if (sectionIdentifier == "functions")
@ -125,6 +132,10 @@ void Domain::parseSection(utils::Parser &parser)
skipSection();
else if (sectionIdentifier == "action")
skipSection();
else if (sectionIdentifier == "durative-action")
skipSection();
else if (sectionIdentifier == "derived")
skipSection();
}
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -228,6 +239,23 @@ void Domain::parseTypeSection(utils::Parser &parser)
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parseConstantSection(utils::Parser &parser)
{
parser.skipWhiteSpace();
// Store constants
while (parser.currentCharacter() != ')')
{
Constant::parseDeclaration(parser, m_context);
parser.skipWhiteSpace();
}
parser.expect<std::string>(")");
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void Domain::parsePredicateSection(utils::Parser &parser)
{
parser.skipWhiteSpace();
@ -263,6 +291,17 @@ void Domain::checkConsistency()
throw ConsistencyException("Type \"" + type->name() + "\" used but never declared");
});
// Verify that all used constants have been declared
std::for_each(m_context.constants.cbegin(), m_context.constants.cend(),
[&](const auto &constant)
{
if (!constant->isDeclared())
throw ConsistencyException("Constant \"" + constant->name() + "\" used but never declared");
if (constant->type() == nullptr)
throw ConsistencyException("Constant \"" + constant->name() + "\" has an undeclared type");
});
// Verify that all used predicates have been declared
std::for_each(m_context.predicates.cbegin(), m_context.predicates.cend(),
[&](const auto &predicate)

View File

@ -89,7 +89,7 @@ PrimitiveType &PrimitiveType::parseDeclaration(utils::Parser &parser, Context &c
if (!childType->isDirty())
return;
childType->addParentType(parentType);
childType->addParentType(&parentType);
childType->setDirty(false);
});
@ -133,9 +133,9 @@ const std::string &PrimitiveType::name() const
////////////////////////////////////////////////////////////////////////////////////////////////////
void PrimitiveType::addParentType(const PrimitiveType &parentType)
void PrimitiveType::addParentType(const PrimitiveType *parentType)
{
m_parentTypes.emplace_back(&parentType);
m_parentTypes.push_back(parentType);
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -14,7 +14,8 @@ class PDDLParserTests : public ::testing::Test
protected:
PDDLParserTests()
: m_blocksworldDomainFile(readFile("data/blocksworld-domain.pddl")),
m_storageDomainFile(readFile("data/storage-domain.pddl"))
m_storageDomainFile(readFile("data/storage-domain.pddl")),
m_woodworkingDomainFile(readFile("data/woodworking-domain.pddl"))
{
}
@ -34,6 +35,7 @@ class PDDLParserTests : public ::testing::Test
std::stringstream m_blocksworldDomainFile;
std::stringstream m_storageDomainFile;
std::stringstream m_woodworkingDomainFile;
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@ -155,3 +157,37 @@ TEST_F(PDDLParserTests, ParseStorageDomain)
FAIL() << e.what();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
TEST_F(PDDLParserTests, ParseConstants)
{
try
{
const auto description = plasp::pddl::Description::fromStream(m_woodworkingDomainFile);
ASSERT_NO_THROW(description.domain());
const auto &domain = description.domain();
// Name
ASSERT_EQ(domain.name(), "woodworking");
// Types
const auto &acolour = *domain.types()[0];
const auto &surface = *domain.types()[4];
const auto &treatmentstatus = *domain.types()[5];
// Constants
ASSERT_EQ(domain.constants().size(), 8u);
ASSERT_EQ(domain.constants()[0]->type(), &surface);
ASSERT_EQ(domain.constants()[2]->type(), &surface);
ASSERT_EQ(domain.constants()[3]->type(), &treatmentstatus);
ASSERT_EQ(domain.constants()[6]->type(), &treatmentstatus);
ASSERT_EQ(domain.constants()[7]->type(), &acolour);
}
catch (const std::exception &e)
{
FAIL() << e.what();
}
}

View File

@ -0,0 +1,215 @@
(define (domain woodworking)
(:requirements :typing :durative-actions :numeric-fluents)
(:types
acolour awood woodobj machine
surface treatmentstatus - object
highspeed-saw glazer grinder immersion-varnisher
planer saw spray-varnisher - machine
board part - woodobj)
(:constants
verysmooth smooth rough - surface
varnished glazed untreated colourfragments - treatmentstatus
natural - acolour)
(:predicates
(idle ?machine - machine)
(unused ?obj - part)
(available ?obj - woodobj)
(surface-condition ?obj - woodobj ?surface - surface)
(treatment ?obj - part ?treatment - treatmentstatus)
(colour ?obj - part ?colour - acolour)
(wood ?obj - woodobj ?wood - awood)
(in-highspeed-saw ?b - board ?m - highspeed-saw)
(empty ?m - highspeed-saw)
(has-colour ?machine - machine ?colour - acolour)
(grind-treatment-change ?old ?new - treatmentstatus)
(is-smooth ?surface - surface))
(:functions
(board-size ?board - board)
(goal-size ?obj - part))
(:durative-action do-immersion-varnish
:parameters (?x - part ?m - immersion-varnisher
?newcolour - acolour ?surface - surface)
:duration (= ?duration 10)
:condition (and
(at start (idle ?m))
(at start (available ?x))
(at start (surface-condition ?x ?surface))
(at start (is-smooth ?surface))
(at start (has-colour ?m ?newcolour))
(at start (treatment ?x untreated)))
:effect (and
(at start (not (idle ?m)))
(at start (not (available ?x)))
(at start (not (treatment ?x untreated)))
(at start (not (colour ?x natural)))
(at end (idle ?m))
(at end (available ?x))
(at end (treatment ?x varnished))
(at end (colour ?x ?newcolour))))
(:durative-action do-spray-varnish
:parameters (?x - part ?m - spray-varnisher
?newcolour - acolour ?surface - surface)
:duration (= ?duration (goal-size ?x))
:condition (and
(at start (idle ?m))
(at start (available ?x))
(at start (surface-condition ?x ?surface))
(at start (is-smooth ?surface))
(at start (has-colour ?m ?newcolour))
(at start (treatment ?x untreated)))
:effect (and
(at start (not (idle ?m)))
(at start (not (available ?x)))
(at start (not (treatment ?x untreated)))
(at start (not (colour ?x natural)))
(at end (idle ?m))
(at end (available ?x))
(at end (treatment ?x varnished))
(at end (colour ?x ?newcolour))))
(:durative-action do-glaze
:parameters (?x - part ?m - glazer
?newcolour - acolour)
:duration (= ?duration (+ (goal-size ?x) 5))
:condition (and
(at start (idle ?m))
(at start (available ?x))
(at start (has-colour ?m ?newcolour))
(at start (treatment ?x untreated)))
:effect (and
(at start (not (idle ?m)))
(at start (not (available ?x)))
(at start (not (treatment ?x untreated)))
(at start (not (colour ?x natural)))
(at end (idle ?m))
(at end (available ?x))
(at end (treatment ?x glazed))
(at end (colour ?x ?newcolour))))
(:durative-action do-grind
:parameters (?x - part ?m - grinder ?oldsurface - surface
?oldcolour - acolour
?oldtreatment ?newtreatment - treatmentstatus)
:duration (= ?duration (* 3 (goal-size ?x)))
:condition (and
(at start (idle ?m))
(at start (available ?x))
(at start (surface-condition ?x ?oldsurface))
(at start (is-smooth ?oldsurface))
(at start (colour ?x ?oldcolour))
(at start (treatment ?x ?oldtreatment))
(at start (grind-treatment-change ?oldtreatment ?newtreatment)))
:effect (and
(at start (not (idle ?m)))
(at start (not (available ?x)))
(at start (not (surface-condition ?x ?oldsurface)))
(at start (not (treatment ?x ?oldtreatment)))
(at start (not (colour ?x ?oldcolour)))
(at end (idle ?m))
(at end (available ?x))
(at end (surface-condition ?x verysmooth))
(at end (treatment ?x ?newtreatment))
(at end (colour ?x natural))))
(:durative-action do-plane
:parameters (?x - part ?m - planer ?oldsurface - surface
?oldcolour - acolour ?oldtreatment - treatmentstatus)
:duration (= ?duration (* 2 (goal-size ?x)))
:condition (and
(at start (idle ?m))
(at start (available ?x))
(at start (surface-condition ?x ?oldsurface))
(at start (treatment ?x ?oldtreatment))
(at start (colour ?x ?oldcolour)))
:effect (and
(at start (not (idle ?m)))
(at start (not (available ?x)))
(at start (not (surface-condition ?x ?oldsurface)))
(at start (not (treatment ?x ?oldtreatment)))
(at start (not (colour ?x ?oldcolour)))
(at end (idle ?m))
(at end (available ?x))
(at end (surface-condition ?x smooth))
(at end (treatment ?x untreated))
(at end (colour ?x natural))))
(:durative-action load-highspeed-saw
:parameters (?b - board ?m - highspeed-saw)
:duration (= ?duration 30)
:condition (and
(at start (idle ?m))
(at start (empty ?m))
(at start (available ?b)))
:effect (and
(at start (not (idle ?m)))
(at start (not (available ?b)))
(at start (not (empty ?m)))
(at end (idle ?m))
(at end (in-highspeed-saw ?b ?m))))
(:durative-action unload-highspeed-saw
:parameters (?b - board ?m - highspeed-saw)
:duration (= ?duration 10)
:condition (and
(at start (idle ?m))
(at start (in-highspeed-saw ?b ?m)))
:effect (and
(at start (not (idle ?m)))
(at end (available ?b))
(at end (not (in-highspeed-saw ?b ?m)))
(at end (empty ?m))
(at end (idle ?m))))
(:durative-action cut-board
:parameters (?b - board ?p - part ?m - highspeed-saw ?w - awood
?surface - surface)
:duration (= ?duration 10)
:condition (and
(at start (idle ?m))
(at start (unused ?p))
(at start (in-highspeed-saw ?b ?m))
(at start (wood ?b ?w))
(at start (surface-condition ?b ?surface))
(at start (>= (board-size ?b) (goal-size ?p))))
:effect (and
(at start (not (idle ?m)))
(at start (not (unused ?p)))
(at start (decrease (board-size ?b) (goal-size ?p)))
(at end (idle ?m))
(at end (available ?p))
(at end (wood ?p ?w))
(at end (surface-condition ?p ?surface))
(at end (colour ?p natural))
(at end (treatment ?p untreated))))
(:durative-action do-saw
:parameters (?b - board ?p - part ?m - saw ?w - awood
?surface - surface)
:duration (= ?duration 30)
:condition (and
(at start (idle ?m))
(at start (unused ?p))
(at start (available ?b))
(at start (wood ?b ?w))
(at start (surface-condition ?b ?surface))
(at start (>= (board-size ?b) (goal-size ?p))))
:effect (and
(at start (not (idle ?m)))
(at start (not (unused ?p)))
(at start (not (available ?b)))
(at end (decrease (board-size ?b) (goal-size ?p)))
(at end (idle ?m))
(at end (available ?p))
(at end (available ?b))
(at end (wood ?p ?w))
(at end (surface-condition ?p ?surface))
(at end (colour ?p natural))
(at end (treatment ?p untreated))))
)