diff --git a/include/plasp/pddl/Context.h b/include/plasp/pddl/Context.h index 5a3cd52..95c3529 100644 --- a/include/plasp/pddl/Context.h +++ b/include/plasp/pddl/Context.h @@ -1,6 +1,10 @@ #ifndef __PLASP__PDDL__CONTEXT_H #define __PLASP__PDDL__CONTEXT_H +#include +#include +#include + #include #include @@ -18,8 +22,13 @@ namespace pddl class Context { public: - TypeHashMap types; - PredicateHashMap predicates; + std::vector> primitiveTypes; + std::unordered_map primitiveTypesHashMap; + + std::vector> eitherTypes; + + std::vector> predicates; + std::unordered_map predicatesHashMap; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/plasp/pddl/Domain.h b/include/plasp/pddl/Domain.h index 61f6519..914284b 100644 --- a/include/plasp/pddl/Domain.h +++ b/include/plasp/pddl/Domain.h @@ -28,8 +28,8 @@ class Domain public: const std::string &name() const; const Requirements &requirements() const; - const TypeHashMap &types() const; - const PredicateHashMap &predicates() const; + const std::vector> &types() const; + const std::vector> &predicates() const; private: Domain(Context &context); @@ -40,7 +40,7 @@ class Domain bool hasRequirement(Requirement::Type requirementType) const; void computeDerivedRequirements(); - void parseTypingSection(utils::Parser &parser); + void parseTypeSection(utils::Parser &parser); void parsePredicateSection(utils::Parser &parser); diff --git a/include/plasp/pddl/EitherType.h b/include/plasp/pddl/EitherType.h new file mode 100644 index 0000000..6118607 --- /dev/null +++ b/include/plasp/pddl/EitherType.h @@ -0,0 +1,43 @@ +#ifndef __PLASP__PDDL__EITHER_TYPE_H +#define __PLASP__PDDL__EITHER_TYPE_H + +#include + +#include +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// EitherType +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class Context; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class EitherType +{ + public: + static EitherType &parse(utils::Parser &parser, Context &context); + + public: + const std::vector &allowedTypes() const; + + private: + EitherType() = default; + + std::vector m_allowedTypes; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} + +#endif diff --git a/include/plasp/pddl/Predicate.h b/include/plasp/pddl/Predicate.h index 17daa79..d1bd27d 100644 --- a/include/plasp/pddl/Predicate.h +++ b/include/plasp/pddl/Predicate.h @@ -1,7 +1,6 @@ #ifndef __PLASP__PDDL__PREDICATE_H #define __PLASP__PDDL__PREDICATE_H -#include #include #include @@ -33,9 +32,6 @@ struct PredicateHashMapKey } }; -class Predicate; -using PredicateHashMap = std::unordered_map; - //////////////////////////////////////////////////////////////////////////////////////////////////// class Predicate diff --git a/include/plasp/pddl/PrimitiveType.h b/include/plasp/pddl/PrimitiveType.h index 59fdc30..0f33657 100644 --- a/include/plasp/pddl/PrimitiveType.h +++ b/include/plasp/pddl/PrimitiveType.h @@ -1,5 +1,5 @@ -#ifndef __PLASP__PDDL__TYPE_PRIMITIVE_H -#define __PLASP__PDDL__TYPE_PRIMITIVE_H +#ifndef __PLASP__PDDL__PRIMITIVE_TYPE_H +#define __PLASP__PDDL__PRIMITIVE_TYPE_H #include #include @@ -13,7 +13,7 @@ namespace pddl //////////////////////////////////////////////////////////////////////////////////////////////////// // -// TypePrimitive +// PrimitiveType // //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -21,34 +21,34 @@ class Context; //////////////////////////////////////////////////////////////////////////////////////////////////// -class TypePrimitive +class PrimitiveType { public: - static TypePrimitive &parse(utils::Parser &parser, Context &context); - static TypePrimitive &parseDeclaration(utils::Parser &parser, Context &context); + static PrimitiveType &parse(utils::Parser &parser, Context &context); + static PrimitiveType &parseDeclaration(utils::Parser &parser, Context &context); public: const std::string &name() const; - const std::vector &parentTypes() const; + const std::vector &parentTypes() const; bool isDeclared() const; private: - TypePrimitive(std::string name); + PrimitiveType(std::string name); void setDirty(bool isDirty = true); bool isDirty() const; void setDeclared(); - void addParentType(const TypePrimitive &parentType); + void addParentType(const PrimitiveType &parentType); bool m_isDirty; bool m_isDeclared; std::string m_name; - std::vector m_parentTypes; + std::vector m_parentTypes; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/plasp/pddl/Type.h b/include/plasp/pddl/Type.h index f6f6756..ddda7b9 100644 --- a/include/plasp/pddl/Type.h +++ b/include/plasp/pddl/Type.h @@ -1,11 +1,10 @@ #ifndef __PLASP__PDDL__TYPE_H #define __PLASP__PDDL__TYPE_H -#include - #include -#include +#include +#include namespace plasp { @@ -18,8 +17,7 @@ namespace pddl // //////////////////////////////////////////////////////////////////////////////////////////////////// -using Type = boost::variant; -using TypeHashMap = std::unordered_map; +using TypePtr = boost::variant; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/include/plasp/pddl/Variable.h b/include/plasp/pddl/Variable.h index c820d51..6ea62a3 100644 --- a/include/plasp/pddl/Variable.h +++ b/include/plasp/pddl/Variable.h @@ -31,12 +31,12 @@ class Variable public: const std::string &name() const; - const Type &type() const; + TypePtr type() const; void setDirty(bool isDirty = true); bool isDirty() const; - void setType(const Type &type); + void setType(TypePtr type); private: Variable(std::string name); @@ -45,7 +45,7 @@ class Variable std::string m_name; - const Type *m_type; + TypePtr m_type; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/plasp/pddl/Domain.cpp b/src/plasp/pddl/Domain.cpp index 611a613..c2ea837 100644 --- a/src/plasp/pddl/Domain.cpp +++ b/src/plasp/pddl/Domain.cpp @@ -67,14 +67,14 @@ const Requirements &Domain::requirements() const //////////////////////////////////////////////////////////////////////////////////////////////////// -const TypeHashMap &Domain::types() const +const std::vector> &Domain::types() const { - return m_context.types; + return m_context.primitiveTypes; } //////////////////////////////////////////////////////////////////////////////////////////////////// -const PredicateHashMap &Domain::predicates() const +const std::vector> &Domain::predicates() const { return m_context.predicates; } @@ -114,7 +114,7 @@ void Domain::parseSection(utils::Parser &parser) if (sectionIdentifier == "requirements") parseRequirementsSection(parser); else if (sectionIdentifier == "types") - parseTypingSection(parser); + parseTypeSection(parser); else if (sectionIdentifier == "constants") skipSection(); else if (sectionIdentifier == "predicates") @@ -208,14 +208,17 @@ void Domain::computeDerivedRequirements() //////////////////////////////////////////////////////////////////////////////////////////////////// -void Domain::parseTypingSection(utils::Parser &parser) +void Domain::parseTypeSection(utils::Parser &parser) { parser.skipWhiteSpace(); // Store types and their parent types while (parser.currentCharacter() != ')') { - TypePrimitive::parseDeclaration(parser, m_context); + if (parser.currentCharacter() == '(') + throw utils::ParserException(parser.row(), parser.column(), "Only primitive types are allowed in type section"); + + PrimitiveType::parseDeclaration(parser, m_context); parser.skipWhiteSpace(); } @@ -245,7 +248,7 @@ void Domain::parsePredicateSection(utils::Parser &parser) void Domain::checkConsistency() { // Verify that typing requirement is correctly declared if used - if (!m_context.types.empty() && !hasRequirement(Requirement::Type::Typing)) + if (!m_context.primitiveTypes.empty() && !hasRequirement(Requirement::Type::Typing)) { throw ConsistencyException("Domain contains typing information but does not declare typing requirement"); @@ -253,25 +256,19 @@ void Domain::checkConsistency() } // Verify that all used types have been declared - std::for_each(m_context.types.cbegin(), m_context.types.cend(), + std::for_each(m_context.primitiveTypes.cbegin(), m_context.primitiveTypes.cend(), [&](const auto &type) { - // TODO: refactor without typeinfo - if (type.second.type() != boost::typeindex::type_id()) - return; - - const auto &typePrimitive = boost::get(type.second); - - if (!typePrimitive.isDeclared()) - throw ConsistencyException("Type \"" + typePrimitive.name() + "\" used but never declared"); + if (!type->isDeclared()) + throw ConsistencyException("Type \"" + type->name() + "\" used but never declared"); }); // Verify that all used predicates have been declared std::for_each(m_context.predicates.cbegin(), m_context.predicates.cend(), [&](const auto &predicate) { - if (!predicate.second.isDeclared()) - throw ConsistencyException("Predicate \"" + predicate.second.name() + "\" used but never declared"); + if (!predicate->isDeclared()) + throw ConsistencyException("Predicate \"" + predicate->name() + "\" used but never declared"); }); // Verify that all variables have types diff --git a/src/plasp/pddl/EitherType.cpp b/src/plasp/pddl/EitherType.cpp new file mode 100644 index 0000000..42d2d34 --- /dev/null +++ b/src/plasp/pddl/EitherType.cpp @@ -0,0 +1,52 @@ +#include + +#include + +#include +#include + +namespace plasp +{ +namespace pddl +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// EitherType +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +EitherType &EitherType::parse(utils::Parser &parser, Context &context) +{ + parser.skipWhiteSpace(); + + auto eitherType = std::make_unique(EitherType()); + + parser.expect("(either"); + parser.skipWhiteSpace(); + + while (parser.currentCharacter() != ')') + { + eitherType->m_allowedTypes.push_back(&PrimitiveType::parse(parser, context)); + + parser.skipWhiteSpace(); + } + + context.eitherTypes.emplace_back(std::move(eitherType)); + + parser.expect(")"); + + return *context.eitherTypes.back(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const std::vector &EitherType::allowedTypes() const +{ + return m_allowedTypes; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/src/plasp/pddl/Predicate.cpp b/src/plasp/pddl/Predicate.cpp index 7372fc6..507a10b 100644 --- a/src/plasp/pddl/Predicate.cpp +++ b/src/plasp/pddl/Predicate.cpp @@ -30,17 +30,17 @@ Predicate &Predicate::parseDeclaration(utils::Parser &parser, Context &context) const auto predicateName = parser.parseIdentifier(isIdentifier); - Predicate predicate(predicateName); + auto predicate = std::make_unique(Predicate(predicateName)); // Flag predicate as correctly declared in the types section - predicate.setDeclared(); + predicate->setDeclared(); parser.skipWhiteSpace(); // Parse arguments while (parser.currentCharacter() != ')') { - predicate.m_arguments.emplace_back(Variable::parse(parser, context)); + predicate->m_arguments.emplace_back(Variable::parse(parser, context)); parser.skipWhiteSpace(); @@ -48,11 +48,22 @@ Predicate &Predicate::parseDeclaration(utils::Parser &parser, Context &context) if (!parser.advanceIf('-')) continue; + auto parseType = + [&]() -> TypePtr + { + parser.skipWhiteSpace(); + + if (parser.currentCharacter() == '(') + return TypePtr(&EitherType::parse(parser, context)); + + return TypePtr(&PrimitiveType::parse(parser, context)); + }; + // Parse argument type - const auto &type = TypePrimitive::parse(parser, context); + const auto type = parseType(); // Set the argument type for all previously flagged arguments - std::for_each(predicate.m_arguments.begin(), predicate.m_arguments.end(), + std::for_each(predicate->m_arguments.begin(), predicate->m_arguments.end(), [&](auto &argument) { if (!argument.isDirty()) @@ -67,14 +78,16 @@ Predicate &Predicate::parseDeclaration(utils::Parser &parser, Context &context) parser.expect(")"); - const auto predicateArity = predicate.m_arguments.size(); + const auto predicateArity = predicate->m_arguments.size(); const PredicateHashMapKey key = {predicateName, predicateArity}; - const auto insertionResult = context.predicates.emplace(std::make_pair(key, std::move(predicate))); + // Store new predicate + context.predicates.emplace_back(std::move(predicate)); - std::cout << "Emplaced " << insertionResult.first->second.name() << std::endl; + // Add a pointer to the predicate to the hash map + context.predicatesHashMap.emplace(std::make_pair(key, context.predicates.back().get())); - return insertionResult.first->second; + return *context.predicates.back(); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/plasp/pddl/PrimitiveType.h b/src/plasp/pddl/PrimitiveType.cpp similarity index 65% rename from src/plasp/pddl/PrimitiveType.h rename to src/plasp/pddl/PrimitiveType.cpp index 9f25166..f922d3a 100644 --- a/src/plasp/pddl/PrimitiveType.h +++ b/src/plasp/pddl/PrimitiveType.cpp @@ -1,4 +1,4 @@ -#include +#include #include @@ -12,11 +12,11 @@ namespace pddl //////////////////////////////////////////////////////////////////////////////////////////////////// // -// TypePrimitive +// PrimitiveType // //////////////////////////////////////////////////////////////////////////////////////////////////// -TypePrimitive::TypePrimitive(std::string name) +PrimitiveType::PrimitiveType(std::string name) : m_isDirty{false}, m_isDeclared{false}, m_name(name) @@ -25,37 +25,41 @@ TypePrimitive::TypePrimitive(std::string name) //////////////////////////////////////////////////////////////////////////////////////////////////// -TypePrimitive &TypePrimitive::parse(utils::Parser &parser, Context &context) +PrimitiveType &PrimitiveType::parse(utils::Parser &parser, Context &context) { parser.skipWhiteSpace(); const auto typeName = parser.parseIdentifier(isIdentifier); - const auto match = context.types.find(typeName); - const auto typeExists = (match != context.types.cend()); + const auto match = context.primitiveTypesHashMap.find(typeName); + const auto typeExists = (match != context.primitiveTypesHashMap.cend()); + // Return existing primitive types if (typeExists) { - auto &type = match->second; - auto &primitiveType = boost::get(type); + auto &type = *match->second; - primitiveType.setDirty(); + type.setDirty(); - return primitiveType; + return type; } - const auto insertionResult = context.types.emplace(std::make_pair(typeName, TypePrimitive(typeName))); - auto &type = insertionResult.first->second; - auto &primitiveType = boost::get(type); + // Store new primitive type + context.primitiveTypes.emplace_back(std::make_unique(PrimitiveType(typeName))); + + auto &type = *context.primitiveTypes.back(); + + // Add a pointer to the primitive type to the hash map + context.primitiveTypesHashMap.emplace(std::make_pair(typeName, &type)); // Flag type for potentially upcoming parent type declaration - primitiveType.setDirty(); + type.setDirty(); - return primitiveType; + return type; } //////////////////////////////////////////////////////////////////////////////////////////////////// -TypePrimitive &TypePrimitive::parseDeclaration(utils::Parser &parser, Context &context) +PrimitiveType &PrimitiveType::parseDeclaration(utils::Parser &parser, Context &context) { // Parse and store type auto &type = parse(parser, context); @@ -79,16 +83,14 @@ TypePrimitive &TypePrimitive::parseDeclaration(utils::Parser &parser, Context &c parentType.setDeclared(); // Assign parent type to all types that were previously flagged - std::for_each(context.types.begin(), context.types.end(), + std::for_each(context.primitiveTypes.begin(), context.primitiveTypes.end(), [&](auto &childType) { - auto &childTypePrimitive = boost::get(childType.second); - - if (!childTypePrimitive.isDirty()) + if (!childType->isDirty()) return; - childTypePrimitive.addParentType(parentType); - childTypePrimitive.setDirty(false); + childType->addParentType(parentType); + childType->setDirty(false); }); return type; @@ -96,49 +98,49 @@ TypePrimitive &TypePrimitive::parseDeclaration(utils::Parser &parser, Context &c //////////////////////////////////////////////////////////////////////////////////////////////////// -void TypePrimitive::setDirty(bool isDirty) +void PrimitiveType::setDirty(bool isDirty) { m_isDirty = isDirty; } //////////////////////////////////////////////////////////////////////////////////////////////////// -bool TypePrimitive::isDirty() const +bool PrimitiveType::isDirty() const { return m_isDirty; } //////////////////////////////////////////////////////////////////////////////////////////////////// -void TypePrimitive::setDeclared() +void PrimitiveType::setDeclared() { m_isDeclared = true; } //////////////////////////////////////////////////////////////////////////////////////////////////// -bool TypePrimitive::isDeclared() const +bool PrimitiveType::isDeclared() const { return m_isDeclared; } //////////////////////////////////////////////////////////////////////////////////////////////////// -const std::string &TypePrimitive::name() const +const std::string &PrimitiveType::name() const { return m_name; } //////////////////////////////////////////////////////////////////////////////////////////////////// -void TypePrimitive::addParentType(const TypePrimitive &parentType) +void PrimitiveType::addParentType(const PrimitiveType &parentType) { m_parentTypes.emplace_back(&parentType); } //////////////////////////////////////////////////////////////////////////////////////////////////// -const std::vector &TypePrimitive::parentTypes() const +const std::vector &PrimitiveType::parentTypes() const { return m_parentTypes; } diff --git a/src/plasp/pddl/Variable.cpp b/src/plasp/pddl/Variable.cpp index af566df..d916b06 100644 --- a/src/plasp/pddl/Variable.cpp +++ b/src/plasp/pddl/Variable.cpp @@ -61,18 +61,16 @@ const std::string &Variable::name() const //////////////////////////////////////////////////////////////////////////////////////////////////// -void Variable::setType(const Type &type) +void Variable::setType(TypePtr type) { - m_type = &type; + m_type = type; } //////////////////////////////////////////////////////////////////////////////////////////////////// -const Type &Variable::type() const +TypePtr Variable::type() const { - BOOST_ASSERT(m_type != nullptr); - - return *m_type; + return m_type; } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/tests/TestPDDLParser.cpp b/tests/TestPDDLParser.cpp index 554719b..8d6ced2 100644 --- a/tests/TestPDDLParser.cpp +++ b/tests/TestPDDLParser.cpp @@ -48,22 +48,40 @@ TEST_F(PDDLParserTests, ParseBlocksWorldDomain) const auto &domain = description.domain(); + // Name ASSERT_EQ(domain.name(), "BLOCKS"); + // Requirements ASSERT_EQ(domain.requirements().size(), 2u); ASSERT_EQ(domain.requirements()[0].type(), plasp::pddl::Requirement::Type::STRIPS); ASSERT_EQ(domain.requirements()[1].type(), plasp::pddl::Requirement::Type::Typing); + // Types ASSERT_EQ(domain.types().size(), 1u); - const auto block = boost::get(domain.types().find("block")->second); + const auto &block = *domain.types()[0]; ASSERT_EQ(block.name(), "block"); ASSERT_EQ(block.parentTypes().size(), 0u); + // Predicates ASSERT_EQ(domain.predicates().size(), 5u); - const auto on = domain.predicates().find({"on", 2}); + const auto &on = *domain.predicates()[0]; + + ASSERT_EQ(on.name(), "on"); + ASSERT_EQ(on.arguments().size(), 2u); + ASSERT_EQ(on.arguments()[0].name(), "x"); + const auto onArgument0Type = boost::get(on.arguments()[0].type()); + ASSERT_EQ(onArgument0Type, &block); + ASSERT_EQ(on.arguments()[1].name(), "y"); + const auto onArgument1Type = boost::get(on.arguments()[1].type()); + ASSERT_EQ(onArgument1Type, &block); + + const auto &handempty = *domain.predicates()[3]; + + ASSERT_EQ(handempty.name(), "handempty"); + ASSERT_TRUE(handempty.arguments().empty()); } catch (const std::exception &e) { @@ -83,16 +101,22 @@ TEST_F(PDDLParserTests, ParseStorageDomain) const auto &domain = description.domain(); + // Name ASSERT_EQ(domain.name(), "Storage-Propositional"); + // Requirements ASSERT_EQ(domain.requirements().size(), 1u); ASSERT_EQ(domain.requirements()[0].type(), plasp::pddl::Requirement::Type::Typing); - const auto area = boost::get(domain.types().find("area")->second); - const auto hoist = boost::get(domain.types().find("hoist")->second); - const auto object = boost::get(domain.types().find("object")->second); - const auto storearea = boost::get(domain.types().find("storearea")->second); - const auto surface = boost::get(domain.types().find("surface")->second); + // Types + ASSERT_EQ(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(); ASSERT_EQ(hoistParents.size(), 1u); @@ -102,6 +126,29 @@ TEST_F(PDDLParserTests, ParseStorageDomain) ASSERT_EQ(areaParents.size(), 2u); ASSERT_TRUE(std::find(areaParents.cbegin(), areaParents.cend(), &object) != areaParents.cend()); ASSERT_TRUE(std::find(areaParents.cbegin(), areaParents.cend(), &surface) != areaParents.cend()); + + // Predicates + ASSERT_EQ(domain.predicates().size(), 8u); + + const auto &on = *domain.predicates()[5]; + + ASSERT_EQ(on.name(), "on"); + ASSERT_EQ(on.arguments().size(), 2u); + ASSERT_EQ(on.arguments()[0].name(), "c"); + const auto onArgument0Type = boost::get(on.arguments()[0].type()); + ASSERT_EQ(onArgument0Type, &crate); + ASSERT_EQ(on.arguments()[1].name(), "s"); + const auto onArgument1Type = boost::get(on.arguments()[1].type()); + ASSERT_EQ(onArgument1Type, &storearea); + + const auto &in = *domain.predicates()[1]; + ASSERT_EQ(in.name(), "in"); + ASSERT_EQ(in.arguments().size(), 2u); + ASSERT_EQ(in.arguments()[0].name(), "x"); + const auto inArgument0Type = boost::get(in.arguments()[0].type()); + ASSERT_EQ(inArgument0Type->allowedTypes().size(), 2u); + ASSERT_EQ(inArgument0Type->allowedTypes()[0], &storearea); + ASSERT_EQ(inArgument0Type->allowedTypes()[1], &crate); } catch (const std::exception &e) { diff --git a/tests/data/storage-domain.pddl b/tests/data/storage-domain.pddl index c001130..911b159 100644 --- a/tests/data/storage-domain.pddl +++ b/tests/data/storage-domain.pddl @@ -1,32 +1,32 @@ (define (domain Storage-Propositional) (:requirements :typing) (:types hoist surface place area - object - container depot - place - storearea transitarea - area - area crate - surface) + container depot - place + storearea transitarea - area + area crate - surface) (:predicates (clear ?s - storearea) - (in ?x - (either storearea crate) ?p - place) - (available ?h - hoist) - (lifting ?h - hoist ?c - crate) - (at ?h - hoist ?a - area) - (on ?c - crate ?s - storearea) - (connected ?a1 ?a2 - area) + (in ?x - (either storearea crate) ?p - place) + (available ?h - hoist) + (lifting ?h - hoist ?c - crate) + (at ?h - hoist ?a - area) + (on ?c - crate ?s - storearea) + (connected ?a1 ?a2 - area) (compatible ?c1 ?c2 - crate)) (:action lift :parameters (?h - hoist ?c - crate ?a1 - storearea ?a2 - area ?p - place) :precondition (and (connected ?a1 ?a2) (at ?h ?a2) (available ?h) - (on ?c ?a1) (in ?a1 ?p)) + (on ?c ?a1) (in ?a1 ?p)) :effect (and (not (on ?c ?a1)) (clear ?a1) - (not (available ?h)) (lifting ?h ?c) (not (in ?c ?p)))) - + (not (available ?h)) (lifting ?h ?c) (not (in ?c ?p)))) + (:action drop :parameters (?h - hoist ?c - crate ?a1 - storearea ?a2 - area ?p - place) :precondition (and (connected ?a1 ?a2) (at ?h ?a2) (lifting ?h ?c) - (clear ?a1) (in ?a1 ?p)) + (clear ?a1) (in ?a1 ?p)) :effect (and (not (lifting ?h ?c)) (available ?h) - (not (clear ?a1)) (on ?c ?a1) (in ?c ?p))) + (not (clear ?a1)) (on ?c ?a1) (in ?c ?p))) (:action move :parameters (?h - hoist ?from ?to - storearea)