From 21237ecac778e2053a8fdabd889a95351dc570d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Sun, 22 May 2016 14:35:53 +0200 Subject: [PATCH] Made Operator a proper class. --- include/plasp/sas/Operator.h | 26 ++++--- src/plasp/sas/Description.cpp | 81 ++++------------------ src/plasp/sas/Operator.cpp | 116 ++++++++++++++++++++++++++++++++ src/plasp/sas/TranslatorASP.cpp | 16 +++-- tests/TestSASParser.cpp | 44 ++++++------ 5 files changed, 179 insertions(+), 104 deletions(-) create mode 100644 src/plasp/sas/Operator.cpp diff --git a/include/plasp/sas/Operator.h b/include/plasp/sas/Operator.h index 35186e3..a47361b 100644 --- a/include/plasp/sas/Operator.h +++ b/include/plasp/sas/Operator.h @@ -20,20 +20,30 @@ namespace sas // //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Operator; +class Operator; using Operators = std::vector; //////////////////////////////////////////////////////////////////////////////////////////////////// -struct Operator +class Operator { - using Condition = AssignedVariable; - using Conditions = AssignedVariables; + public: + static Operator fromSAS(std::istream &istream, const Variables &variables); - Predicate predicate; - Conditions preconditions; - Effects effects; - size_t costs; + using Condition = AssignedVariable; + using Conditions = AssignedVariables; + + public: + const Predicate &predicate() const; + const Conditions &preconditions() const; + const Effects &effects() const; + size_t costs() const; + + private: + Predicate m_predicate; + Conditions m_preconditions; + Effects m_effects; + size_t m_costs; }; //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/plasp/sas/Description.cpp b/src/plasp/sas/Description.cpp index accafda..25bf85f 100644 --- a/src/plasp/sas/Description.cpp +++ b/src/plasp/sas/Description.cpp @@ -183,10 +183,13 @@ void Description::print(std::ostream &ostream) const std::for_each(m_operators.cbegin(), m_operators.cend(), [&](const auto &operator_) { - ostream << "\t" << operator_.predicate << ":" << std::endl; - ostream << "\t\tpreconditions: " << operator_.preconditions.size() << std::endl; + ostream << "\t" << operator_.predicate() << ":" << std::endl; - std::for_each(operator_.preconditions.cbegin(), operator_.preconditions.cend(), + const auto &preconditions = operator_.preconditions(); + + ostream << "\t\tpreconditions: " << preconditions.size() << std::endl; + + std::for_each(preconditions.cbegin(), preconditions.cend(), [&](const auto &precondition) { std::cout << "\t\t\t" << precondition.variable().name() << " = "; @@ -194,9 +197,11 @@ void Description::print(std::ostream &ostream) const ostream << std::endl; }); - ostream << "\t\teffects: " << operator_.effects.size() << std::endl; + const auto &effects = operator_.effects(); - std::for_each(operator_.effects.cbegin(), operator_.effects.cend(), + ostream << "\t\teffects: " << effects.size() << std::endl; + + std::for_each(effects.cbegin(), effects.cend(), [&](const auto &effect) { ostream << "\t\t\teffect:" << std::endl; @@ -216,7 +221,7 @@ void Description::print(std::ostream &ostream) const ostream << std::endl; }); - ostream << "\t\tcosts: " << operator_.costs << std::endl; + ostream << "\t\tcosts: " << operator_.costs() << std::endl; }); // Axiom section @@ -310,70 +315,10 @@ void Description::parseGoalSection(std::istream &istream) void Description::parseOperatorSection(std::istream &istream) { const auto numberOfOperators = utils::parse(istream); - m_operators.resize(numberOfOperators); + m_operators.reserve(numberOfOperators); for (size_t i = 0; i < numberOfOperators; i++) - { - utils::parseExpected(istream, "begin_operator"); - - auto &operator_ = m_operators[i]; - - try - { - istream.ignore(std::numeric_limits::max(), '\n'); - - // TODO: Inefficient, reimplement in one pass - std::string line; - std::getline(istream, line); - - std::stringstream lineStream(line); - - operator_.predicate.name = utils::parse(lineStream); - - while (lineStream.peek() == ' ') - lineStream.ignore(1); - - for (std::string argument; std::getline(lineStream, argument, ' ');) - operator_.predicate.arguments.push_back(std::move(argument)); - } - catch (const std::exception &e) - { - throw utils::ParserException("Could not parse operator predicate"); - } - - const auto numberOfPrevailConditions = utils::parse(istream); - operator_.preconditions.reserve(numberOfPrevailConditions); - - for (size_t j = 0; j < numberOfPrevailConditions; j++) - operator_.preconditions.emplace_back(AssignedVariable::fromSAS(istream, m_variables)); - - const auto numberOfEffects = utils::parse(istream); - operator_.effects.reserve(numberOfEffects); - - for (size_t j = 0; j < numberOfEffects; j++) - { - Effect::Conditions conditions; - - const auto numberOfEffectConditions = utils::parse(istream); - conditions.reserve(numberOfEffectConditions); - - for (size_t k = 0; k < numberOfEffectConditions; k++) - conditions.emplace_back(AssignedVariable::fromSAS(istream, m_variables)); - - const auto variableTransition = VariableTransition::fromSAS(istream, m_variables); - - if (&variableTransition.valueBefore() != &Value::Any) - operator_.preconditions.emplace_back(AssignedVariable(variableTransition.variable(), variableTransition.valueBefore())); - - const Effect::Condition postcondition = {variableTransition.variable(), variableTransition.valueAfter()}; - const Effect effect = {std::move(conditions), std::move(postcondition)}; - operator_.effects.push_back(std::move(effect)); - } - - operator_.costs = utils::parse(istream); - - utils::parseExpected(istream, "end_operator"); - } + m_operators.emplace_back(Operator::fromSAS(istream, m_variables)); } //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/plasp/sas/Operator.cpp b/src/plasp/sas/Operator.cpp new file mode 100644 index 0000000..f93faef --- /dev/null +++ b/src/plasp/sas/Operator.cpp @@ -0,0 +1,116 @@ +#include + +#include +#include + +#include +#include + +namespace plasp +{ +namespace sas +{ + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Operator +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +Operator Operator::fromSAS(std::istream &istream, const Variables &variables) +{ + Operator operator_; + + utils::parseExpected(istream, "begin_operator"); + + try + { + istream.ignore(std::numeric_limits::max(), '\n'); + + // TODO: Inefficient, reimplement in one pass + std::string line; + std::getline(istream, line); + + std::stringstream lineStream(line); + + operator_.m_predicate.name = utils::parse(lineStream); + + while (lineStream.peek() == ' ') + lineStream.ignore(1); + + for (std::string argument; std::getline(lineStream, argument, ' ');) + operator_.m_predicate.arguments.push_back(std::move(argument)); + } + catch (const std::exception &e) + { + throw utils::ParserException("Could not parse operator predicate"); + } + + const auto numberOfPrevailConditions = utils::parse(istream); + operator_.m_preconditions.reserve(numberOfPrevailConditions); + + for (size_t j = 0; j < numberOfPrevailConditions; j++) + operator_.m_preconditions.emplace_back(AssignedVariable::fromSAS(istream, variables)); + + const auto numberOfEffects = utils::parse(istream); + operator_.m_effects.reserve(numberOfEffects); + + for (size_t j = 0; j < numberOfEffects; j++) + { + Effect::Conditions conditions; + + const auto numberOfEffectConditions = utils::parse(istream); + conditions.reserve(numberOfEffectConditions); + + for (size_t k = 0; k < numberOfEffectConditions; k++) + conditions.emplace_back(AssignedVariable::fromSAS(istream, variables)); + + const auto variableTransition = VariableTransition::fromSAS(istream, variables); + + if (&variableTransition.valueBefore() != &Value::Any) + operator_.m_preconditions.emplace_back(AssignedVariable(variableTransition.variable(), variableTransition.valueBefore())); + + const Effect::Condition postcondition = {variableTransition.variable(), variableTransition.valueAfter()}; + const Effect effect = {std::move(conditions), std::move(postcondition)}; + operator_.m_effects.push_back(std::move(effect)); + } + + operator_.m_costs = utils::parse(istream); + + utils::parseExpected(istream, "end_operator"); + + return operator_; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const Predicate &Operator::predicate() const +{ + return m_predicate; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const Operator::Conditions &Operator::preconditions() const +{ + return m_preconditions; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +const Effects &Operator::effects() const +{ + return m_effects; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +size_t Operator::costs() const +{ + return m_costs; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// + +} +} diff --git a/src/plasp/sas/TranslatorASP.cpp b/src/plasp/sas/TranslatorASP.cpp index 2d29e4d..339ca6c 100644 --- a/src/plasp/sas/TranslatorASP.cpp +++ b/src/plasp/sas/TranslatorASP.cpp @@ -36,7 +36,7 @@ void TranslatorASP::checkSupport() const std::for_each(operators.cbegin(), operators.cend(), [&](const auto &operator_) { - std::for_each(operator_.effects.cbegin(), operator_.effects.cend(), + std::for_each(operator_.effects().cbegin(), operator_.effects().cend(), [&](const auto &effect) { if (!effect.conditions.empty()) @@ -123,21 +123,25 @@ void TranslatorASP::translate(std::ostream &ostream) const std::for_each(operators.cbegin(), operators.cend(), [&](const auto &operator_) { - ostream << "action(" << operator_.predicate << ")." << std::endl; + ostream << "action(" << operator_.predicate() << ")." << std::endl; - std::for_each(operator_.preconditions.cbegin(), operator_.preconditions.cend(), + const auto &preconditions = operator_.preconditions(); + + std::for_each(preconditions.cbegin(), preconditions.cend(), [&](const auto &precondition) { - ostream << "precondition(" << operator_.predicate + ostream << "precondition(" << operator_.predicate() << ", " << precondition.value().name() << ", " << (precondition.value().sign() == Value::Sign::Positive ? "true" : "false") << ")." << std::endl; }); - std::for_each(operator_.effects.cbegin(), operator_.effects.cend(), + const auto &effects = operator_.effects(); + + std::for_each(effects.cbegin(), effects.cend(), [&](const auto &effect) { - ostream << "postcondition(" << operator_.predicate + ostream << "postcondition(" << operator_.predicate() << ", " << effect.postcondition.value().name() << ", " << (effect.postcondition.value().sign() == Value::Sign::Positive ? "true" : "false") << ")." << std::endl; diff --git a/tests/TestSASParser.cpp b/tests/TestSASParser.cpp index c8bdd1c..d7df800 100644 --- a/tests/TestSASParser.cpp +++ b/tests/TestSASParser.cpp @@ -67,28 +67,28 @@ TEST_F(SASParserTests, ParseValidSASFile) ASSERT_EQ(&description.goal().facts()[1].value(), &description.variables()[7].values()[0]); ASSERT_EQ(description.operators().size(), 34); - ASSERT_EQ(description.operators()[0].predicate.name, "activate-trans"); - ASSERT_EQ(description.operators()[0].predicate.arguments.size(), 5); - ASSERT_EQ(description.operators()[0].predicate.arguments[0], "philosopher-0"); - ASSERT_EQ(description.operators()[0].predicate.arguments[4], "state-3"); - ASSERT_EQ(description.operators()[0].preconditions.size(), 3); - ASSERT_EQ(&description.operators()[0].preconditions[0].value(), &description.variables()[4].values()[4]); - ASSERT_EQ(&description.operators()[0].preconditions[1].value(), &description.variables()[16].values()[1]); - ASSERT_EQ(&description.operators()[0].preconditions[2].value(), &description.variables()[0].values()[8]); - ASSERT_EQ(description.operators()[0].effects.size(), 1); - ASSERT_EQ(description.operators()[0].effects[0].conditions.size(), 0); - ASSERT_EQ(&description.operators()[0].effects[0].postcondition.value(), &description.variables()[0].values()[0]); - ASSERT_EQ(description.operators()[33].predicate.name, "queue-write"); - ASSERT_EQ(description.operators()[33].predicate.arguments.size(), 4); - ASSERT_EQ(description.operators()[33].predicate.arguments[0], "philosopher-1"); - ASSERT_EQ(description.operators()[33].predicate.arguments[3], "fork"); - ASSERT_EQ(description.operators()[33].preconditions.size(), 2); - ASSERT_EQ(&description.operators()[33].preconditions[0].value(), &description.variables()[1].values()[3]); - ASSERT_EQ(&description.operators()[33].preconditions[1].value(), &description.variables()[2].values()[2]); - ASSERT_EQ(description.operators()[33].effects.size(), 3); - ASSERT_EQ(description.operators()[33].effects[0].conditions.size(), 0); - ASSERT_EQ(&description.operators()[33].effects[0].postcondition.value(), &description.variables()[1].values()[7]); - ASSERT_EQ(&description.operators()[33].effects[2].postcondition.value(), &description.variables()[35].values()[0]); + ASSERT_EQ(description.operators()[0].predicate().name, "activate-trans"); + ASSERT_EQ(description.operators()[0].predicate().arguments.size(), 5); + ASSERT_EQ(description.operators()[0].predicate().arguments[0], "philosopher-0"); + ASSERT_EQ(description.operators()[0].predicate().arguments[4], "state-3"); + ASSERT_EQ(description.operators()[0].preconditions().size(), 3); + ASSERT_EQ(&description.operators()[0].preconditions()[0].value(), &description.variables()[4].values()[4]); + ASSERT_EQ(&description.operators()[0].preconditions()[1].value(), &description.variables()[16].values()[1]); + ASSERT_EQ(&description.operators()[0].preconditions()[2].value(), &description.variables()[0].values()[8]); + ASSERT_EQ(description.operators()[0].effects().size(), 1); + ASSERT_EQ(description.operators()[0].effects()[0].conditions.size(), 0); + ASSERT_EQ(&description.operators()[0].effects()[0].postcondition.value(), &description.variables()[0].values()[0]); + ASSERT_EQ(description.operators()[33].predicate().name, "queue-write"); + ASSERT_EQ(description.operators()[33].predicate().arguments.size(), 4); + ASSERT_EQ(description.operators()[33].predicate().arguments[0], "philosopher-1"); + ASSERT_EQ(description.operators()[33].predicate().arguments[3], "fork"); + ASSERT_EQ(description.operators()[33].preconditions().size(), 2); + ASSERT_EQ(&description.operators()[33].preconditions()[0].value(), &description.variables()[1].values()[3]); + ASSERT_EQ(&description.operators()[33].preconditions()[1].value(), &description.variables()[2].values()[2]); + ASSERT_EQ(description.operators()[33].effects().size(), 3); + ASSERT_EQ(description.operators()[33].effects()[0].conditions.size(), 0); + ASSERT_EQ(&description.operators()[33].effects()[0].postcondition.value(), &description.variables()[1].values()[7]); + ASSERT_EQ(&description.operators()[33].effects()[2].postcondition.value(), &description.variables()[35].values()[0]); ASSERT_EQ(description.axiomRules().size(), 33); ASSERT_EQ(description.axiomRules()[0].conditions.size(), 4);