From d26ff2df77ba8729edee8bb9154b3e230a335fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Mon, 30 May 2016 15:44:13 +0200 Subject: [PATCH] Implemented computation of derived requirements. --- include/plasp/pddl/Description.h | 1 + include/plasp/pddl/Domain.h | 1 + include/plasp/pddl/Requirement.h | 1 + src/plasp/pddl/Description.cpp | 9 +++++ src/plasp/pddl/Domain.cpp | 60 ++++++++++++++++++++++++++++++++ src/plasp/pddl/Requirement.cpp | 2 ++ tests/TestPDDLParser.cpp | 57 ++++++++++++++++++++++++++++++ tests/TestSASParser.cpp | 8 ----- 8 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 tests/TestPDDLParser.cpp diff --git a/include/plasp/pddl/Description.h b/include/plasp/pddl/Description.h index a699d98..d066740 100644 --- a/include/plasp/pddl/Description.h +++ b/include/plasp/pddl/Description.h @@ -24,6 +24,7 @@ class Description static Description fromFile(const boost::filesystem::path &path); public: + const Domain &domain() const; private: Description() = default; diff --git a/include/plasp/pddl/Domain.h b/include/plasp/pddl/Domain.h index 6659d2b..1c059cb 100644 --- a/include/plasp/pddl/Domain.h +++ b/include/plasp/pddl/Domain.h @@ -30,6 +30,7 @@ class Domain void parseSection(utils::Parser &parser); void parseRequirementsSection(utils::Parser &parser); + void computeDerivedRequirements(); std::string m_name; Requirement::Types m_requirements; diff --git a/include/plasp/pddl/Requirement.h b/include/plasp/pddl/Requirement.h index 4b16ad7..730e211 100644 --- a/include/plasp/pddl/Requirement.h +++ b/include/plasp/pddl/Requirement.h @@ -30,6 +30,7 @@ struct Requirement ConditionalEffects, Fluents, NumericFluents, + ObjectFluents, ADL, DurativeActions, DurationInequalities, diff --git a/src/plasp/pddl/Description.cpp b/src/plasp/pddl/Description.cpp index 99b52b0..303ca88 100644 --- a/src/plasp/pddl/Description.cpp +++ b/src/plasp/pddl/Description.cpp @@ -51,6 +51,15 @@ Description Description::fromFile(const boost::filesystem::path &path) //////////////////////////////////////////////////////////////////////////////////////////////////// +const Domain &Description::domain() const +{ + BOOST_ASSERT(m_domain); + + return *m_domain; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + void Description::parseContent(utils::Parser &parser) { std::cout << "Parsing file content" << std::endl; diff --git a/src/plasp/pddl/Domain.cpp b/src/plasp/pddl/Domain.cpp index 2ce294e..d002a35 100644 --- a/src/plasp/pddl/Domain.cpp +++ b/src/plasp/pddl/Domain.cpp @@ -1,6 +1,9 @@ #include +#include + #include +#include namespace plasp { @@ -33,6 +36,8 @@ Domain Domain::fromPDDL(utils::Parser &parser) domain.parseSection(parser); } + domain.computeDerivedRequirements(); + return domain; } @@ -115,10 +120,65 @@ void Domain::parseRequirementsSection(utils::Parser &parser) m_requirements.emplace_back(Requirement::fromPDDL(parser)); } + if (m_requirements.empty()) + throw utils::ParserException(parser.row(), parser.column(), "Requirements section does not contain any requirements"); + parser.expect(")"); } //////////////////////////////////////////////////////////////////////////////////////////////////// +void Domain::computeDerivedRequirements() +{ + const auto hasRequirement = + [&](const auto requirement) + { + const auto match = std::find(m_requirements.cbegin(), m_requirements.cend(), requirement); + + return match != m_requirements.cend(); + }; + + const auto addRequirementUnique = + [&](const auto requirement) + { + if (hasRequirement(requirement)) + return; + + m_requirements.push_back(requirement); + }; + + // If no requirements are specified, assume STRIPS + if (m_requirements.empty()) + addRequirementUnique(Requirement::Type::STRIPS); + + 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); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + } } diff --git a/src/plasp/pddl/Requirement.cpp b/src/plasp/pddl/Requirement.cpp index 3b1b574..c7b2ad3 100644 --- a/src/plasp/pddl/Requirement.cpp +++ b/src/plasp/pddl/Requirement.cpp @@ -34,6 +34,7 @@ const RequirementTypeNames requirementTypesToPDDL = boost::assign::list_of + +#include +#include +#include +#include + +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +class PDDLParserTests : public ::testing::Test +{ + protected: + PDDLParserTests() + : m_blocksworldDomainFile(readFile("data/blocksworld-domain.pddl")) + { + } + + static std::stringstream readFile(const std::string &path) + { + std::ifstream fileStream(path, std::ios::in); + + std::stringstream outputStream; + + if (!fileStream.is_open()) + throw std::runtime_error("Could not open file \"" + path + "\""); + + outputStream << fileStream.rdbuf(); + + return outputStream; + } + + std::stringstream m_blocksworldDomainFile; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +TEST_F(PDDLParserTests, ParseValidPDDLFile) +{ + try + { + const auto description = plasp::pddl::Description::fromStream(m_blocksworldDomainFile); + + ASSERT_NO_THROW(description.domain()); + + const auto &domain = description.domain(); + + ASSERT_EQ(domain.requirements().size(), 2u); + ASSERT_EQ(domain.requirements()[0], plasp::pddl::Requirement::Type::STRIPS); + ASSERT_EQ(domain.requirements()[1], plasp::pddl::Requirement::Type::Typing); + } + catch (const std::exception &e) + { + FAIL() << e.what(); + } +} diff --git a/tests/TestSASParser.cpp b/tests/TestSASParser.cpp index 72a3df7..0d8705c 100644 --- a/tests/TestSASParser.cpp +++ b/tests/TestSASParser.cpp @@ -175,11 +175,3 @@ TEST_F(SASParserTests, ParseRequirements) FAIL() << e.what(); } } - -//////////////////////////////////////////////////////////////////////////////////////////////////// - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -}