From 7cdbff0970101f7df25a958e795bb3115f387abc Mon Sep 17 00:00:00 2001 From: Thomas Knoll <thomas.knoll@student.tugraz.at> Date: Thu, 30 Nov 2023 10:13:16 +0100 Subject: [PATCH] added const to config + const prop handling --- util/ConfigYaml.cpp | 51 ++++++++++++++++++++++++++++++++++-- util/ConfigYaml.h | 21 ++++++++++++++- util/Grid.cpp | 39 ++++++++++++++++----------- util/PrismModulesPrinter.cpp | 43 ++++++++++++++++++++++-------- util/PrismModulesPrinter.h | 6 ++--- 5 files changed, 127 insertions(+), 33 deletions(-) diff --git a/util/ConfigYaml.cpp b/util/ConfigYaml.cpp index 063face..07c2b8e 100644 --- a/util/ConfigYaml.cpp +++ b/util/ConfigYaml.cpp @@ -16,6 +16,11 @@ std::ostream& operator << (std::ostream& os, const Action& action) { return os; } +std::ostream& operator << (std::ostream& os, const Constant& constant) { + os << "const " << constant.type_ << " " << constant.constant_ << " = " << constant.value_; + return os; +} + std::ostream& operator << (std::ostream& os, const Module& module) { os << "Module: " << module.module_ << std::endl; for (auto& action : module.actions_) { @@ -48,6 +53,14 @@ std::string Action::createExpression() const { return "\t" + action_ + "\t" + guard_ + "-> " + update_+ Configuration::configuration_identifier_; } +std::string Constant::createExpression() const { + if (overwrite_) { + return "const " + type_ + " " + constant_ + " = " + value_ + Configuration::overwrite_identifier_; + } + + return "const " + type_ + " " + constant_ + " = " + value_ + Configuration::configuration_identifier_; +} + YAML::Node YAML::convert<Module>::encode(const Module& rhs) { YAML::Node node; @@ -145,6 +158,33 @@ bool YAML::convert<Formula>::decode(const YAML::Node& node, Formula& rhs) { return true; } +YAML::Node YAML::convert<Constant>::encode(const Constant& rhs) { + YAML::Node node; + + node.push_back(rhs.constant_); + node.push_back(rhs.value_); + node.push_back(rhs.type_); + node.push_back(rhs.overwrite_); + + return node; +} + +bool YAML::convert<Constant>::decode(const YAML::Node& node, Constant& rhs) { + if (!node.IsDefined() || !node.Type() == NodeType::Map || !node["constant"] || !node["type"] || !node["value"]) { + return false; + } + + rhs.constant_ = node["constant"].as<std::string>(); + rhs.type_ = node["type"].as<std::string>(); + rhs.value_ = node["value"].as<std::string>(); + + if(node["overwrite"]) { + rhs.overwrite_ = node["overwrite"].as<bool>(); + } + + return true; +} + const std::string Configuration::configuration_identifier_ { "; // created through configuration"}; const std::string Configuration::overwrite_identifier_{"; // Overwritten through configuration"}; @@ -156,6 +196,7 @@ const std::string Configuration::overwrite_identifier_{"; // Overwritten through std::vector<Label> labels; std::vector<Formula> formulas; std::vector<Module> modules; + std::vector<Constant> constants; if (config["labels"]) { labels = config["labels"].as<std::vector<Label>>(); @@ -166,6 +207,10 @@ const std::string Configuration::overwrite_identifier_{"; // Overwritten through if (config["modules"]) { modules = config["modules"].as<std::vector<Module>>(); } + + if (config["constants"]) { + constants = config["constants"].as<std::vector<Constant>>(); + } for (auto& label : labels) { configuration.push_back({label.createExpression(), label.label_ , ConfigType::Label, label.overwrite_}); @@ -178,8 +223,10 @@ const std::string Configuration::overwrite_identifier_{"; // Overwritten through configuration.push_back({action.createExpression(), action.action_, ConfigType::Module, action.overwrite_, module.module_, action.index_}); } } - - + for (auto& constant : constants) { + // std::cout << constant.constant_ << std::endl; + configuration.push_back({constant.createExpression(), "const " + constant.type_ + " " + constant.constant_, ConfigType::Constant, constant.overwrite_}); + } } catch(const std::exception& e) { std::cout << "Exception '" << typeid(e).name() << "' caught:" << std::endl; diff --git a/util/ConfigYaml.h b/util/ConfigYaml.h index 9eed26f..6b4e93a 100644 --- a/util/ConfigYaml.h +++ b/util/ConfigYaml.h @@ -9,7 +9,8 @@ enum class ConfigType : char { Label = 'L', Formula = 'F', - Module = 'M' + Module = 'M', + Constant = 'C' }; struct Configuration @@ -42,7 +43,19 @@ struct Configuration } }; +struct Constant { + private: + + public: + std::string constant_; + std::string type_; + std::string value_; + bool overwrite_{false}; + + std::string createExpression() const; + friend std::ostream& operator <<(std::ostream &os, const Constant& constant); +}; struct Label { private: @@ -118,6 +131,12 @@ struct YAML::convert<Formula> { static bool decode(const YAML::Node& node, Formula& rhs); }; +template<> +struct YAML::convert<Constant> { + static YAML::Node encode(const Constant& rhs); + static bool decode(const YAML::Node& node, Constant& rhs); +}; + struct YamlConfigParser { public: diff --git a/util/Grid.cpp b/util/Grid.cpp index f5bc5d6..569fd76 100644 --- a/util/Grid.cpp +++ b/util/Grid.cpp @@ -166,6 +166,9 @@ void Grid::applyOverwrites(std::string& str, std::vector<Configuration>& configu auto iter = boost::find_nth(str, config.identifier_, config.index_); start_pos = std::distance(str.begin(), iter.begin()); } + else if (config.type_ == ConfigType::Constant) { + start_pos = str.find(config.identifier_); + } size_t end_pos = str.find(';', start_pos) + 1; @@ -240,6 +243,13 @@ void Grid::printToPrism(std::ostream& os, std::vector<Configuration>& configurat printer.printGoalLabel(os, agentNameAndPosition->first, goals); printer.printKeysLabels(os, agentNameAndPosition->first, keys); } + std::vector<std::string> constants {"const double prop_zero = 0/9;", + "const double prop_adj = 1/9;", + "const double prop_slippery_move_forward = 3/9;", + "const double prop_slippery_turn = 6/9;", + "const double prop_neighbour = 2/9;", + "const double total_prop = 9;"}; + printer.printConstants(os, constants); std::vector<AgentName> agentNames; std::transform(agentNameAndPositionMap.begin(), @@ -262,25 +272,22 @@ void Grid::printToPrism(std::ostream& os, std::vector<Configuration>& configurat std::set<std::string> slipperyActions; // TODO AGENT POSITION INITIALIZATIN if(agentWithProbabilisticBehaviour) printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView, gridOptions.probabilitiesForActions); else printer.printModule(os, agentName, agentIndex, maxBoundaries, agentNameAndPosition->second, keys, backgroundTiles, agentWithView); - if (!slipperyNorth.empty()) { - auto c = slipperyNorth.at(0); - printer.printSlipperyMove(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North); - if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North); + for(auto const& c : slipperyNorth) { + printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North); + if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::North); + } - if (!slipperyEast.empty()) { - auto c = slipperyEast.at(0); - printer.printSlipperyMove(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East); - if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East); + for(auto const& c : slipperyEast) { + printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East); + if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::East); } - if (!slipperySouth.empty()) { - auto c = slipperySouth.at(0); - printer.printSlipperyMove(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South); - if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South); + for(auto const& c : slipperySouth) { + printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South); + if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::South); } - if (!slipperyWest.empty()) { - auto c = slipperyWest.at(0); - printer.printSlipperyMove(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West); - if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West); + for(auto const& c : slipperyWest) { + printer.printSlipperyMove(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West); + if(!gridOptions.enforceOneWays) printer.printSlipperyTurn(os, agentName, agentIndex, c.getCoordinates(), slipperyActions, getWalkableDirOf8Neighborhood(c), prism::PrismModulesPrinter::SlipperyType::West); } printer.printEndmodule(os); diff --git a/util/PrismModulesPrinter.cpp b/util/PrismModulesPrinter.cpp index 09b30d6..09f93b3 100644 --- a/util/PrismModulesPrinter.cpp +++ b/util/PrismModulesPrinter.cpp @@ -361,6 +361,16 @@ namespace prism { return os; } + std::ostream& PrismModulesPrinter::printConstants(std::ostream &os, const std::vector<std::string> &constants) { + + for (auto& constant : constants) { + os << constant << std::endl; + } + + return os; + } + + std::ostream& PrismModulesPrinter::printAvoidanceLabel(std::ostream &os, const std::vector<AgentName> agentNames, const int &distance) { os << "label avoidance = "; bool first = true; @@ -681,7 +691,7 @@ namespace prism { return os; } - std::ostream& PrismModulesPrinter::printSlipperyTurn(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation) { + std::ostream& PrismModulesPrinter::printSlipperyTurn(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation) { constexpr std::size_t PROB_PIECES = 9, ALL_POSS_DIRECTIONS = 9; std::array<std::string, ALL_POSS_DIRECTIONS> positionTransition = { @@ -712,6 +722,7 @@ namespace prism { std::string positionGuard; std::size_t remainPosIndex = 8; std::array<std::size_t, ALL_POSS_DIRECTIONS> prob_piece_dir; // { n, ne, w, se, s, sw, w, nw, CURRENT POS } + std::array<std::string, ALL_POSS_DIRECTIONS> prob_piece_dir_constants; switch (orientation) { @@ -719,24 +730,28 @@ namespace prism { actionName = "\t[" + agentName + "turn_at_slip_north"; positionGuard = "\t" + agentName + "IsOnSlipperyNorth"; prob_piece_dir = { 0, 0, 0, 1, 1, 1, 0, 0, 0 /* <- R */ }; + prob_piece_dir_constants = { "prop_zero", "prop_zero", "prop_zero", "prop_adj", "prop_adj" /* <- R */, "prop_adj", "prop_zero", "prop_zero","prop_zero" }; break; case SlipperyType::South: actionName = "\t[" + agentName + "turn_at_slip_south"; positionGuard = "\t" + agentName + "IsOnSlipperySouth"; prob_piece_dir = { 1, 1, 0, 0, 0, 0, 0, 1, 0 /* <- R */ }; + prob_piece_dir_constants = { "prop_adj", "prop_adj", "prop_zero", "prop_zero", "prop_zero", "prop_zero", "prop_zero", "prop_adj", "prop_zero" }; break; case SlipperyType::East: actionName = "\t[" + agentName + "turn_at_slip_east"; positionGuard = "\t" + agentName + "IsOnSlipperyEast"; prob_piece_dir = { 0, 0, 0, 0, 0, 1, 1, 1, 0 /* <- R */ }; + prob_piece_dir_constants = { "prop_zero", "prop_zero", "prop_zero", "prop_zero", "prop_zero", "prop_adj", "prop_adj", "prop_adj", "prop_zero" }; break; case SlipperyType::West: actionName = "\t[" + agentName + "turn_at_slip_west"; positionGuard = "\t" + agentName + "IsOnSlipperyWest"; prob_piece_dir = { 0, 1, 1, 1, 0, 0, 0, 0, 0 /* <- R */ }; + prob_piece_dir_constants = { "prop_zero", "prop_adj", "prop_adj", "prop_adj", "prop_zero", "prop_zero", "prop_zero", "prop_zero", "prop_zero" }; break; } @@ -753,7 +768,7 @@ namespace prism { // determine residual probability (R) by replacing 0 with (1 - overall sum) prob_piece_dir.at(remainPosIndex) = PROB_PIECES - std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0); - + prob_piece_dir_constants.at(remainPosIndex) = "prop_slippery_turn"; // <DEBUG_AREA> { assert(prob_piece_dir.at(remainPosIndex) <= 9 && prob_piece_dir.at(remainPosIndex) >= 6 && "Value not in Range!"); @@ -763,18 +778,17 @@ namespace prism { // generic output (for every view transition) for (std::size_t v = 0; v < viewTransition.size(); v++) { - os << actionName << std::get<2>(viewTransition.at(v)) << moveGuard(agentIndex) << positionGuard << std::get<0>(viewTransition.at(v)); - - // os << actionName << std::get<2>(viewTransition.at(v)) << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first << std::get<0>(viewTransition.at(v)); + os << actionName << std::get<2>(viewTransition.at(v)) << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first << std::get<0>(viewTransition.at(v)); for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) { - os << (i == 0 ? " -> " : " + ") << prob_piece_dir.at(i) << "/" << PROB_PIECES << " : " << positionTransition.at(i) << std::get<1>(viewTransition.at(v)) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); + // os << (i == 0 ? " -> " : " + ") << prob_piece_dir_constants.at(i) << "/" << "total_prob" << " : " << positionTransition.at(i) << std::get<1>(viewTransition.at(v)) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); + os << (i == 0 ? " -> " : " + ") << prob_piece_dir_constants.at(i) << " : " << positionTransition.at(i) << std::get<1>(viewTransition.at(v)) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); } } return os; } - std::ostream& PrismModulesPrinter::printSlipperyMove(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation) { + std::ostream& PrismModulesPrinter::printSlipperyMove(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation) { constexpr std::size_t PROB_PIECES = 9, ALL_POSS_DIRECTIONS = 8; std::array<std::string, ALL_POSS_DIRECTIONS> positionTransition = { @@ -794,13 +808,15 @@ namespace prism { std::string actionName, specialTransition; // if straight ahead is blocked std::string positionGuard; std::array<std::size_t, ALL_POSS_DIRECTIONS> prob_piece_dir; // { n, ne, w, se, s, sw, w, nw } - + std::array<std::string, ALL_POSS_DIRECTIONS> prob_piece_dir_constants; + switch (orientation) { case SlipperyType::North: actionName = "\t[" + agentName + "move_on_slip_north]"; positionGuard = "\t" + agentName + "IsOnSlipperyNorth"; prob_piece_dir = { 0, 0, 1, 2, 0 /* <- R */, 2, 1, 0 }; + prob_piece_dir_constants = { "prop_zero", "prop_zero", "prop_adj", "prop_neighbour", "prop_zero" /* <- R */, "prop_neighbour", "prop_adj", "prop_zero" }; straightPosIndex = 4; specialTransition = "(y" + agentName + "'=y" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "+1)"); break; @@ -809,6 +825,7 @@ namespace prism { actionName = "\t[" + agentName + "move_on_slip_south]"; positionGuard = "\t" + agentName + "IsOnSlipperySouth"; prob_piece_dir = { 0 /* <- R */, 2, 1, 0, 0, 0, 1, 2 }; + prob_piece_dir_constants = { "prop_zero" /* <- R */, "prop_neighbour", "prop_adj", "prop_zero", "prop_zero", "prop_zero", "prop_adj", "prop_neighbour" }; straightPosIndex = 0; // always north specialTransition = "(y" + agentName + "'=y" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "-1)"); break; @@ -817,6 +834,7 @@ namespace prism { actionName = "\t[" + agentName + "move_on_slip_east]"; positionGuard = "\t" + agentName + "IsOnSlipperyEast"; prob_piece_dir = { 1, 0, 0, 0, 1, 2, 0 /* <- R */, 2 }; + prob_piece_dir_constants = { "prop_adj", "prop_zero", "prop_zero", "prop_zero", "prop_adj", "prop_neighbour", "prop_zero" /* <- R */, "prop_neighbour" }; straightPosIndex = 6; specialTransition = "(x" + agentName + "'=x" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "-1)"); break; @@ -825,6 +843,7 @@ namespace prism { actionName = "\t[" + agentName + "move_on_slip_west]"; positionGuard = "\t" + agentName + "IsOnSlipperyWest"; prob_piece_dir = { 1, 2, 0 /* <- R */, 2, 1, 0, 0, 0 }; + prob_piece_dir_constants = {"prop_adj", "prop_neighbour", "prop_zero" /* <- R */, "prop_neighbour", "prop_adj", "prop_zero","prop_zero", "prop_zero" }; straightPosIndex = 2; specialTransition = "(x" + agentName + "'=x" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "+1)"); break; @@ -842,9 +861,10 @@ namespace prism { // determine residual probability (R) by replacing 0 with (1 - overall sum) if(enforceOneWays) { prob_piece_dir = {0,0,0,0,0,0,0,0}; + prob_piece_dir_constants = {"zero","zero","zero","zero","zero","zero","zero","zero"}; } prob_piece_dir.at(straightPosIndex) = PROB_PIECES - std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0); - + prob_piece_dir_constants.at(straightPosIndex) = "prop_slippery_move_forward"; // <DEBUG_AREA> { assert(prob_piece_dir.at(straightPosIndex) <= 9 && prob_piece_dir.at(straightPosIndex) >= 3 && "Value not in Range!"); @@ -862,10 +882,11 @@ namespace prism { // generic output (for every view and every possible view direction) - os << actionName << moveGuard(agentIndex) << positionGuard << " & " << agentName << "SlipperyMoveForwardAllowed "; + os << actionName << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first << " & " << agentName << "SlipperyMoveForwardAllowed "; for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) { - os << (i == 0 ? " -> " : " + ") << prob_piece_dir.at(i) << "/" << PROB_PIECES << " : " << positionTransition.at(i) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); + os << (i == 0 ? " -> " : " + ") << prob_piece_dir_constants.at(i) << " : " << positionTransition.at(i) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); + // os << (i == 0 ? " -> " : " + ") << prob_piece_dir_constants.at(i) << "/" << "total_prob" << " : " << positionTransition.at(i) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n"); } return os; diff --git a/util/PrismModulesPrinter.h b/util/PrismModulesPrinter.h index 7d31b45..005ebf0 100644 --- a/util/PrismModulesPrinter.h +++ b/util/PrismModulesPrinter.h @@ -46,7 +46,7 @@ namespace prism { std::ostream& printDoorModule(std::ostream &os, const cell &door, const coordinates &boundaries, AgentName agentName); std::ostream& printDoorActions(std::ostream &os, const cell &door ,const std::string &doorIdentifier, AgentName agentName); - + std::ostream& printConstants(std::ostream &os, const std::vector<std::string> &constants); /* * Representation for Slippery Tile. * -) North: Slips from North to South @@ -62,7 +62,7 @@ namespace prism { * @param neighborhood: Information of wall-blocks in 8-neighborhood { n, nw, e, se, s, sw, w, nw }. If entry is false, then corresponding neighboorhood position is a wall. * @param orientation: Information of slippery type (either north, south, east, west). */ - std::ostream& printSlipperyMove(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation); + std::ostream& printSlipperyMove(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation); /* * Prints Slippery on turn action. @@ -70,7 +70,7 @@ namespace prism { * @param neighborhood: Information of wall-blocks in 8-neighborhood { n, nw, e, se, s, sw, w, nw }. If entry is false, then corresponding neighboorhood position is a wall. * @param orientation: Information of slippery type (either north, south, east, west). */ - std::ostream& printSlipperyTurn(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation); + std::ostream& printSlipperyTurn(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &c, std::set<std::string> &slipperyActions, const std::array<bool, 8>& neighborhood, SlipperyType orientation); std::ostream& printModel(std::ostream &os, const ModelType &modelType); std::ostream& printBooleansForKeys(std::ostream &os, const AgentName &agentName, const cells &keys);