From 56e569890e33f948b430bea4de1d81a83c01173f Mon Sep 17 00:00:00 2001 From: Thomas Knoll Date: Wed, 30 Aug 2023 12:04:34 +0200 Subject: [PATCH] added basic config parser added unlocked door handling --- main.cpp | 27 +++++++++++++- util/ConfigGrammar.h | 72 ++++++++++++++++++++++++++++++++++++ util/Grid.cpp | 11 ++++++ util/Grid.h | 2 + util/PrismModulesPrinter.cpp | 10 +++-- 5 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 util/ConfigGrammar.h diff --git a/main.cpp b/main.cpp index 58de07f..aa6b336 100644 --- a/main.cpp +++ b/main.cpp @@ -1,6 +1,7 @@ #include "util/OptionParser.h" #include "util/MinigridGrammar.h" #include "util/Grid.h" +#include "util/ConfigGrammar.h" #include #include @@ -54,6 +55,9 @@ int main(int argc, char* argv[]) { auto enforceOneWays = optionParser.add("f", "force-oneways", "Enforce encoding of oneways. This entails that slippery tiles do not allow turning and have prob 1 to shift the agent by one and makes turning impossible if in a one tile wide section of the grid."); + auto configFilename = optionParser.add, popl::Attribute::optional>("c", "config-file", "Filename of the predicate configuration file."); + + try { optionParser.parse(argc, argv); @@ -100,7 +104,7 @@ int main(int argc, char* argv[]) { std::fstream file {outputFilename->value(0), file.trunc | file.out}; std::fstream infile {inputFilename->value(0), infile.in}; - std::string line, content, background, rewards; + std::string line, content, background, rewards, config; std::cout << "\n"; bool parsingBackground = false; bool parsingStateRewards = false; @@ -126,6 +130,14 @@ int main(int argc, char* argv[]) { std::cout << "\n"; + if (configFilename->is_set()) { + std::fstream configFile {configFilename->value(0), configFile.in}; + while (std::getline(configFile, line) && !line.empty()) { + std::cout << "Configuration :\t" << line << "\n"; + config += line + "\n"; + } + } + pos_iterator_t contentFirst(content.begin()); pos_iterator_t contentIter = contentFirst; pos_iterator_t contentLast(content.end()); @@ -134,15 +146,28 @@ int main(int argc, char* argv[]) { pos_iterator_t backgroundIter = backgroundFirst; pos_iterator_t backgroundLast(background.end()); MinigridParser backgroundParser(backgroundFirst); + pos_iterator_t configFirst(config.begin()); + pos_iterator_t configIter = configFirst; + pos_iterator_t configLast(config.end()); + ConfigParser configParser(configFirst); cells contentCells; cells backgroundCells; + std::vector configurations; std::map stateRewards; try { bool ok = phrase_parse(contentIter, contentLast, contentParser, qi::space, contentCells); // TODO if(background is not empty) { ok &= phrase_parse(backgroundIter, backgroundLast, backgroundParser, qi::space, backgroundCells); // TODO } + if (configFilename->is_set()) { + ok &= phrase_parse(configIter, configLast, configParser, qi::space, configurations); + } + + std::cout << "Found " << configurations.size() << "configs" << std::endl; + for (auto& config : configurations) { + std::cout << config << std::endl; + } boost::escaped_list_separator seps('\\', ';', '\n'); Tokenizer csvParser(rewards, seps); diff --git a/util/ConfigGrammar.h b/util/ConfigGrammar.h new file mode 100644 index 0000000..597df96 --- /dev/null +++ b/util/ConfigGrammar.h @@ -0,0 +1,72 @@ +#pragma once + +#include "cell.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace qi = boost::spirit::qi; +namespace phoenix = boost::phoenix; + +typedef std::vector expressions; + +struct Configuration +{ + expressions expressions_; + std::string derivation_; + + Configuration() = default; + Configuration(expressions expressions, std::string derivation) : expressions_(expressions), derivation_(derivation) {} + ~Configuration() = default; + Configuration(const Configuration&) = default; + + friend std::ostream& operator << (std::ostream& os, const Configuration& config) { + os << "Configuration" << std::endl; + + for (auto& expression : config.expressions_) { + os << "Expression=" << expression << std::endl; + } + + return os << "Derviation=" << config.derivation_; + } +}; + + +BOOST_FUSION_ADAPT_STRUCT( + Configuration, + (expressions, expressions_) + (std::string, derivation_) +) + + +template + struct ConfigParser : qi::grammar> +{ + ConfigParser(It first) : ConfigParser::base_type(config_) + { + using namespace qi; + + expression_ = +char_("a-zA-Z_0-9"); + expressions_ = (expression_ % ','); + row_ = (expressions_ > ';' > expression_); + config_ = (row_ % "\n"); + + BOOST_SPIRIT_DEBUG_NODE(expression_); + BOOST_SPIRIT_DEBUG_NODE(expressions_); + BOOST_SPIRIT_DEBUG_NODE(config_); + } + + private: + + qi::rule expressions_; + qi::rule expression_; + qi::rule row_; + qi::rule> config_; +}; \ No newline at end of file diff --git a/util/Grid.cpp b/util/Grid.cpp index d13c2b5..3036503 100644 --- a/util/Grid.cpp +++ b/util/Grid.cpp @@ -31,6 +31,9 @@ Grid::Grid(cells gridCells, cells background, const GridOptions &gridOptions, co std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(lockedDoors), [](cell c) { return c.type == Type::LockedDoor; }); + std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(unlockedDoors), [](cell c) { + return c.type == Type::Door; + }); std::copy_if(gridCells.begin(), gridCells.end(), std::back_inserter(goals), [](cell c) { return c.type == Type::Goal; }); @@ -105,6 +108,13 @@ bool Grid::isLockedDoor(coordinates p) { }) != lockedDoors.end(); } +bool Grid::isUnlockedDoor(coordinates p) { + return std::find_if(unlockedDoors.begin(), unlockedDoors.end(), + [p](cell cell) { + return cell.row == p.first && cell.column == p.second; + }) != unlockedDoors.end(); +} + bool Grid::isKey(coordinates p) { return std::find_if(keys.begin(), keys.end(), [p](cell cell) { @@ -132,6 +142,7 @@ void Grid::printToPrism(std::ostream& os, const prism::ModelType& modelType) { walkable.insert(walkable.end(), lava.begin(), lava.end()); walkable.insert(walkable.end(), keys.begin(), keys.end()); walkable.insert(walkable.end(), lockedDoors.begin(), lockedDoors.end()); + walkable.insert(walkable.end(), unlockedDoors.begin(), unlockedDoors.end()); for(auto const& c : walkable) { if(isBlocked(c.getNorth())) northRestriction.push_back(c); diff --git a/util/Grid.h b/util/Grid.h index 84c2eb2..a17fb42 100644 --- a/util/Grid.h +++ b/util/Grid.h @@ -25,6 +25,7 @@ class Grid { bool isBlocked(coordinates p); bool isWall(coordinates p); bool isLockedDoor(coordinates p); + bool isUnlockedDoor(coordinates p); bool isKey(coordinates p); bool isBox(coordinates p); void printToPrism(std::ostream &os, const prism::ModelType& modelType); @@ -51,6 +52,7 @@ class Grid { cells slipperySouth; cells slipperyWest; cells lockedDoors; + cells unlockedDoors; cells boxes; cells lava; diff --git a/util/PrismModulesPrinter.cpp b/util/PrismModulesPrinter.cpp index 0b15af2..12c0c4e 100644 --- a/util/PrismModulesPrinter.cpp +++ b/util/PrismModulesPrinter.cpp @@ -608,10 +608,12 @@ namespace prism { os << "endrewards\n"; } - os << "rewards \"SafetyNoBFSAndGoal\"\n"; - if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone: 100;\n"; - if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; - os << "endrewards\n"; + if (!goals.empty() || !lava.empty()) { + os << "rewards \"SafetyNoBFSAndGoal\"\n"; + if(goals.size() != 0) os << "\tAgentIsInGoalAndNotDone: 100;\n"; + if(lava.size() != 0) os << "\tAgentIsInLavaAndNotDone: -100;\n"; + os << "endrewards\n"; + } os << "rewards \"Time\"\n"; os << "\t!AgentIsInGoal : -1;\n";