You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

496 lines
25 KiB

1 year ago
  1. #include "PrismModulesPrinter.h"
  2. #include <map>
  3. #include <string>
  4. namespace prism {
  5. PrismModulesPrinter::PrismModulesPrinter(const ModelType &modelType, const size_t &numberOfPlayer)
  6. : modelType(modelType), numberOfPlayer(numberOfPlayer) {
  7. }
  8. std::ostream& PrismModulesPrinter::printModel(std::ostream &os, const ModelType &modelType) {
  9. switch(modelType) {
  10. case(ModelType::MDP):
  11. os << "mdp";
  12. break;
  13. case(ModelType::SMG):
  14. os << "smg";
  15. break;
  16. }
  17. os << "\n\n";
  18. return os;
  19. }
  20. std::ostream& PrismModulesPrinter::printBackgroundLabels(std::ostream &os, const AgentName &agentName, const std::pair<Color, cells> &backgroundTiles) {
  21. if(backgroundTiles.second.size() == 0) return os;
  22. bool first = true;
  23. std::string color = getColor(backgroundTiles.first);
  24. color.at(0) = std::toupper(color.at(0));
  25. os << "label " << agentName << "On" << color << " = ";
  26. for(auto const& cell : backgroundTiles.second) {
  27. if(first) first = false; else os << " | ";
  28. os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")";
  29. }
  30. os << ";\n";
  31. return os;
  32. }
  33. std::ostream& PrismModulesPrinter::printRestrictionFormula(std::ostream& os, const AgentName &agentName, const std::string &direction, const cells &cells) {
  34. bool first = true;
  35. os << "formula " << agentName << "CannotMove" << direction << " = " ;
  36. for(auto const& cell : cells) {
  37. if(first) first = false;
  38. else os << " | ";
  39. os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")";
  40. }
  41. os << ";\n";
  42. return os;
  43. }
  44. std::ostream& PrismModulesPrinter::printIsOnSlipperyFormula(std::ostream& os, const AgentName &agentName, const std::vector<std::reference_wrapper<cells>>& slipperyCollection) {
  45. if(std::find_if(slipperyCollection.cbegin(), slipperyCollection.cend(), [=](const std::reference_wrapper<cells>& c) { return !c.get().empty(); }) == slipperyCollection.cend()) {
  46. os << "formula " << agentName << "IsOnSlippery = false;\n";
  47. return os;
  48. }
  49. bool first = true;
  50. os << "formula " << agentName << "IsOnSlippery = ";
  51. for (const auto& slippery: slipperyCollection) {
  52. for(const auto& cell : slippery.get()) {
  53. if(first) first = false; else os << " | ";
  54. os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")";
  55. }
  56. }
  57. os << ";\n";
  58. return os;
  59. }
  60. std::ostream& PrismModulesPrinter::printIsInLavaFormula(std::ostream& os, const AgentName &agentName, const cells &lava) {
  61. if(lava.size() == 0) {
  62. os << "formula " << agentName << "IsInLava = false;\n";
  63. return os;
  64. }
  65. bool first = true;
  66. os << "formula " << agentName << "IsInLava = ";
  67. for(auto const& cell : lava) {
  68. if(first) first = false; else os << " | ";
  69. os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")";
  70. }
  71. os << ";\n";
  72. os << "formula " << agentName << "IsInLavaAndNotDone = " << agentName << "IsInLava & !" << agentName << "Done;\n";
  73. os << "label \"" << agentName << "IsInLavaAndNotDone\" = " << agentName << "IsInLava & !" << agentName << "Done;\n";
  74. return os;
  75. }
  76. std::ostream& PrismModulesPrinter::printFormulas(std::ostream& os,
  77. const AgentName &agentName,
  78. const cells &restrictionNorth,
  79. const cells &restrictionEast,
  80. const cells &restrictionSouth,
  81. const cells &restrictionWest,
  82. const std::vector<std::reference_wrapper<cells>> &slipperyCollection,
  83. const cells &lava) {
  84. printRestrictionFormula(os, agentName, "North", restrictionNorth);
  85. printRestrictionFormula(os, agentName, "East ", restrictionEast);
  86. printRestrictionFormula(os, agentName, "South", restrictionSouth);
  87. printRestrictionFormula(os, agentName, "West ", restrictionWest);
  88. printIsOnSlipperyFormula(os, agentName, slipperyCollection);
  89. printIsInLavaFormula(os, agentName, lava);
  90. os << "\n";
  91. return os;
  92. }
  93. std::ostream& PrismModulesPrinter::printGoalLabel(std::ostream& os, const AgentName &agentName, const cells &goals) {
  94. if(goals.size() == 0) {
  95. os << "formula " << agentName << "IsInGoal = false;\n";
  96. return os;
  97. }
  98. bool first = true;
  99. os << "formula " << agentName << "IsInGoal = ";
  100. for(auto const& cell : goals) {
  101. if(first) first = false; else os << " | ";
  102. os << "(x" << agentName << "=" << cell.column << "&y" << agentName << "=" << cell.row << ")";
  103. }
  104. os << ";\n";
  105. os << "formula " << agentName << "IsInGoalAndNotDone = " << agentName << "IsInGoal & !" << agentName << "Done;\n";
  106. os << "label \"" << agentName << "IsInGoalAndNotDone\" = " << agentName << "IsInGoal & !" << agentName << "Done;\n";
  107. return os;
  108. }
  109. std::ostream& PrismModulesPrinter::printCrashLabel(std::ostream &os, const std::vector<AgentName> agentNames) {
  110. os << "label crash = ";
  111. bool first = true;
  112. for(auto const& agentName : agentNames) {
  113. if(agentName == "Agent") continue;
  114. if(first) first = false; else os << " | ";
  115. os << "(xAgent=x" << agentName << ")&(yAgent=y" << agentName << ")";
  116. }
  117. os << ";\n\n";
  118. return os;
  119. }
  120. std::ostream& PrismModulesPrinter::printAvoidanceLabel(std::ostream &os, const std::vector<AgentName> agentNames, const int &distance) {
  121. os << "label avoidance = ";
  122. bool first = true;
  123. for(auto const& agentName : agentNames) {
  124. if(agentName == "Agent") continue;
  125. if(first) first = false; else os << " | ";
  126. os << "max(xAgent-x" << agentName << ",x" << agentName << "-xAgent)+";
  127. os << "max(yAgent-y" << agentName << ",y" << agentName << "-yAgent) ";
  128. }
  129. os << ";\n\n";
  130. return os;
  131. }
  132. std::ostream& PrismModulesPrinter::printKeysLabels(std::ostream& os, const AgentName &agentName, const cells &keys) {
  133. if(keys.size() == 0) return os;
  134. for(auto const& key : keys) {
  135. std::string keyColor = key.getColor();
  136. os << "label picked_up_" << keyColor << "_key = has_" << keyColor << "_key = true;\n";
  137. }
  138. os << "\n";
  139. return os;
  140. }
  141. std::ostream& PrismModulesPrinter::printBooleansForKeys(std::ostream &os, const cells &keys) {
  142. for(auto const& key : keys) {
  143. os << "\thas_"<< key.getColor() << "_key : bool init false;\n";
  144. }
  145. os << "\n";
  146. return os;
  147. }
  148. std::ostream& PrismModulesPrinter::printActionsForKeys(std::ostream &os, cells keys) {
  149. for(auto const& key : keys) {
  150. std::string keyColor = key.getColor();
  151. os << "\t[pickup_" << keyColor << "_key] \n";
  152. os << "\t\tview=0 & x=" << key.row << " & y=" << key.column - 1 << " |\n";
  153. os << "\t\tview=1 & x=" << key.row - 1 << " & y=" << key.column << " |\n";
  154. os << "\t\tview=2 & x=" << key.row << " & y=" << key.column + 1 << " |\n";
  155. os << "\t\tview=3 & x=" << key.row + 1 << " & y=" << key.column << " -> (has_" << keyColor << "_key'=true);\n";
  156. }
  157. os << "\n";
  158. return os;
  159. }
  160. std::ostream& PrismModulesPrinter::printModule(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const coordinates &boundaries, const coordinates& initialPosition, const cells &keys, const bool agentWithView, const std::vector<float> &probabilities) {
  161. os << "module " << agentName << "\n";
  162. os << "\tx" << agentName << " : [1.." << boundaries.first << "] init " << initialPosition.second << ";\n";
  163. os << "\ty" << agentName << " : [1.." << boundaries.second << "] init " << initialPosition.first << ";\n";
  164. printBooleansForKeys(os, keys);
  165. os << "\t" << agentName << "Done : bool init false;\n";
  166. if(agentWithView) {
  167. os << "\tview" << agentName << " : [0..3] init 0;\n";
  168. os << "\n";
  169. os << "\t[" << agentName << "_turn_right] " << moveGuard(agentIndex) << " !" << agentName << "IsInGoal & !" << agentName << "IsInLava & !" << agentName << "IsOnSlippery -> (view" << agentName << "'=mod(view" << agentName << " + 1, 4)) " << moveUpdate(agentIndex) << ";\n";
  170. os << "\t[" << agentName << "_turn_left] " << moveGuard(agentIndex) << " !" << agentName << "IsInGoal & !" << agentName << "IsInLava & !" << agentName << "IsOnSlippery & view" << agentName << ">0 -> (view" << agentName << "'=view" << agentName << " - 1) " << moveUpdate(agentIndex) << ";\n";
  171. os << "\t[" << agentName << "_turn_left] " << moveGuard(agentIndex) << " !" << agentName << "IsInGoal & !" << agentName << "IsInLava & !" << agentName << "IsOnSlippery & view" << agentName << "=0 -> (view" << agentName << "'=3) " << moveUpdate(agentIndex) << ";\n";
  172. } else {
  173. os << "\t[" << agentName << "_turns] " << moveGuard(agentIndex) << " true -> (x" << agentName << "'=x" << agentName << ")" << moveUpdate(agentIndex) << ";\n";
  174. }
  175. printActionsForKeys(os, keys);
  176. os << "\n";
  177. printMovementActions(os, agentName, agentIndex, agentWithView);
  178. for(auto const& probability : probabilities) {
  179. printMovementActions(os, agentName, agentIndex, agentWithView, probability);
  180. }
  181. printDoneActions(os, agentName, agentIndex);
  182. os << "\n";
  183. return os;
  184. }
  185. std::ostream& PrismModulesPrinter::printMovementActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex, const bool agentWithView, const float &probability) {
  186. if(probability >= 1) {
  187. os << "\t[" << agentName << "_move_north]" << moveGuard(agentIndex) << viewVariable(agentName, 3, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal & !" << agentName << "CannotMoveNorth -> (y" << agentName << "'=y" << agentName << "-1)" << moveUpdate(agentIndex) << ";\n";
  188. os << "\t[" << agentName << "_move_east] " << moveGuard(agentIndex) << viewVariable(agentName, 0, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal & !" << agentName << "CannotMoveEast -> (x" << agentName << "'=x" << agentName << "+1)" << moveUpdate(agentIndex) << ";\n";
  189. os << "\t[" << agentName << "_move_south]" << moveGuard(agentIndex) << viewVariable(agentName, 1, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal & !" << agentName << "CannotMoveSouth -> (y" << agentName << "'=y" << agentName << "+1)" << moveUpdate(agentIndex) << ";\n";
  190. os << "\t[" << agentName << "_move_west] " << moveGuard(agentIndex) << viewVariable(agentName, 2, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava &!" << agentName << "IsInGoal & !" << agentName << "CannotMoveWest -> (x" << agentName << "'=x" << agentName << "-1)" << moveUpdate(agentIndex) << ";\n";
  191. } else {
  192. std::string probabilityString = std::to_string(probability);
  193. std::string percentageString = std::to_string((int)(100 * probability));
  194. std::string complementProbabilityString = std::to_string(1 - probability);
  195. os << "\t[" << agentName << "_move_north_" << percentageString << "] ";
  196. os << moveGuard(agentIndex) << viewVariable(agentName, 3, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveNorth -> ";
  197. os << probabilityString << ": (y" << agentName << "'=y" << agentName << "-1)" << moveUpdate(agentIndex) << " + ";
  198. os << complementProbabilityString << ": (y" << agentName << "'=y" << agentName << ") " << moveUpdate(agentIndex) << ";\n";
  199. os << "\t[" << agentName << "_move_east_" << percentageString << "] ";
  200. os << moveGuard(agentIndex) << viewVariable(agentName, 0, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveEast -> ";
  201. os << probabilityString << ": (x" << agentName << "'=x" << agentName << "+1)" << moveUpdate(agentIndex) << " + ";
  202. os << complementProbabilityString << ": (x" << agentName << "'=x" << agentName << ") " << moveUpdate(agentIndex) << ";\n";
  203. os << "\t[" << agentName << "_move_south_" << percentageString << "] ";
  204. os << moveGuard(agentIndex) << viewVariable(agentName, 1, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveSouth -> ";
  205. os << probabilityString << ": (y" << agentName << "'=y" << agentName << "+1)" << moveUpdate(agentIndex) << " + ";
  206. os << complementProbabilityString << ": (y" << agentName << "'=y" << agentName << ") " << moveUpdate(agentIndex) << ";\n";
  207. os << "\t[" << agentName << "_move_west_" << percentageString << "] ";
  208. os << moveGuard(agentIndex) << viewVariable(agentName, 2, agentWithView) << " !" << agentName << "IsOnSlippery & !" << agentName << "IsInLava & !" << agentName << "CannotMoveWest -> ";
  209. os << probabilityString << ": (x" << agentName << "'=x" << agentName << "-1)" << moveUpdate(agentIndex) << " + ";
  210. os << complementProbabilityString << ": (x" << agentName << "'=x" << agentName << ") " << moveUpdate(agentIndex) << ";\n";
  211. }
  212. return os;
  213. }
  214. std::ostream& PrismModulesPrinter::printDoneActions(std::ostream &os, const AgentName &agentName, const size_t &agentIndex) {
  215. os << "\t[" << agentName << "_done]" << moveGuard(agentIndex) << agentName << "IsInGoal | " << agentName << "IsInLava -> (" << agentName << "Done'=true);\n";
  216. return os;
  217. }
  218. 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) {
  219. constexpr std::size_t PROB_PIECES = 9, ALL_POSS_DIRECTIONS = 9;
  220. std::array<std::string, ALL_POSS_DIRECTIONS> positionTransition = {
  221. /* north */ "(y" + agentName + "'=y" + agentName + "-1)",
  222. /* north east */ "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "-1)",
  223. /* east */ "(x" + agentName + "'=x" + agentName + "+1)",
  224. /* east south */ "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "+1)",
  225. /* south */ "(y" + agentName + "'=y" + agentName + "+1)",
  226. /* south west */ "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "+1)",
  227. /* west */ "(x" + agentName + "'=x" + agentName + "-1)",
  228. /* north west */ "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "-1)",
  229. /* own position */ "(x" + agentName + "'=x" + agentName + ") & (y" + agentName + "'=y" + agentName + ")"
  230. };
  231. // view transition appdx in form (guard, update part)
  232. // IMPORTANT: No mod() usage for turn left due to bug in mod() function for decrement
  233. std::array<std::pair<std::string, std::string>, 3> viewTransition = {
  234. /* turn to right */ std::make_pair("", " & (view" + agentName + "'=mod(view" + agentName + " + 1, 4))"),
  235. /* turn to left */ std::make_pair(" & view" + agentName + ">0", " & (view" + agentName + "'=view" + agentName + " - 1)"),
  236. /* turn to left */ std::make_pair(" & view" + agentName + "=0", " & (view" + agentName + "'=3)")
  237. };
  238. // direction specifics
  239. std::string actionName;
  240. std::size_t remainPosIndex = 8;
  241. std::array<std::size_t, ALL_POSS_DIRECTIONS> prob_piece_dir; // { n, ne, w, se, s, sw, w, nw, CURRENT POS }
  242. switch (orientation)
  243. {
  244. case SlipperyType::North:
  245. actionName = "\t[" + agentName + "turn_at_slip_north]";
  246. prob_piece_dir = { 0, 0, 0, 1, 1, 1, 0, 0, 0 /* <- R */ };
  247. break;
  248. case SlipperyType::South:
  249. actionName = "\t[" + agentName + "turn_at_slip_south]";
  250. prob_piece_dir = { 1, 1, 0, 0, 0, 0, 0, 1, 0 /* <- R */ };
  251. break;
  252. case SlipperyType::East:
  253. actionName = "\t[" + agentName + "turn_at_slip_east]";
  254. prob_piece_dir = { 0, 0, 0, 0, 0, 1, 1, 1, 0 /* <- R */ };
  255. break;
  256. case SlipperyType::West:
  257. actionName = "\t[" + agentName + "turn_at_slip_west]";
  258. prob_piece_dir = { 0, 1, 1, 1, 0, 0, 0, 0, 0 /* <- R */ };
  259. break;
  260. }
  261. slipperyActions.insert(actionName);
  262. // override probability to 0 if corresp. direction is blocked
  263. for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS - 1; i++) {
  264. if (!neighborhood.at(i))
  265. prob_piece_dir.at(i) = 0;
  266. }
  267. // determine residual probability (R) by replacing 0 with (1 - overall sum)
  268. prob_piece_dir.at(remainPosIndex) = PROB_PIECES - std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0);
  269. // <DEBUG_AREA>
  270. {
  271. assert(prob_piece_dir.at(remainPosIndex) <= 9 && prob_piece_dir.at(remainPosIndex) >= 6 && "Value not in Range!");
  272. assert(std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0) == PROB_PIECES && "Does not sum up to 1!");
  273. }
  274. // </DEBUG_AREA>
  275. // generic output (for every view transition)
  276. for (std::size_t v = 0; v < viewTransition.size(); v++) {
  277. os << actionName << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first << viewTransition.at(v).first;
  278. for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) {
  279. os << (i == 0 ? " -> " : " + ") << prob_piece_dir.at(i) << "/" << PROB_PIECES << " : " << positionTransition.at(i) << viewTransition.at(v).second << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n");
  280. }
  281. }
  282. return os;
  283. }
  284. 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) {
  285. constexpr std::size_t PROB_PIECES = 9, ALL_POSS_DIRECTIONS = 8;
  286. std::array<std::string, ALL_POSS_DIRECTIONS> positionTransition = {
  287. /* north */ "(y" + agentName + "'=y" + agentName + "-1)",
  288. /* north east */ "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "-1)",
  289. /* east */ "(x" + agentName + "'=x" + agentName + "+1)",
  290. /* east south */ "(x" + agentName + "'=x" + agentName + "+1) & (y" + agentName + "'=y" + agentName + "+1)",
  291. /* south */ "(y" + agentName + "'=y" + agentName + "+1)",
  292. /* south west */ "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "+1)",
  293. /* west */ "(x" + agentName + "'=x" + agentName + "-1)",
  294. /* north west */ "(x" + agentName + "'=x" + agentName + "-1) & (y" + agentName + "'=y" + agentName + "-1)"
  295. };
  296. // direction specifics
  297. std::size_t straightPosIndex;
  298. std::string actionName, specialTransition; // if straight ahead is blocked
  299. std::array<std::size_t, ALL_POSS_DIRECTIONS> prob_piece_dir; // { n, ne, w, se, s, sw, w, nw }
  300. switch (orientation)
  301. {
  302. case SlipperyType::North:
  303. actionName = "\t[" + agentName + "move_on_slip_north]";
  304. prob_piece_dir = { 0, 0, 1, 2, 0 /* <- R */, 2, 1, 0 };
  305. straightPosIndex = 4;
  306. specialTransition = "(y" + agentName + "'=y" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "+1)");
  307. break;
  308. case SlipperyType::South:
  309. actionName = "\t[" + agentName + "move_on_slip_south]";
  310. prob_piece_dir = { 0 /* <- R */, 2, 1, 0, 0, 0, 1, 2 };
  311. straightPosIndex = 0; // always north
  312. specialTransition = "(y" + agentName + "'=y" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "-1)");
  313. break;
  314. case SlipperyType::East:
  315. actionName = "\t[" + agentName + "move_on_slip_east]";
  316. prob_piece_dir = { 1, 0, 0, 0, 1, 2, 0 /* <- R */, 2 };
  317. straightPosIndex = 6;
  318. specialTransition = "(x" + agentName + "'=x" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "-1)");
  319. break;
  320. case SlipperyType::West:
  321. actionName = "\t[" + agentName + "move_on_slip_west]";
  322. prob_piece_dir = { 1, 2, 0 /* <- R */, 2, 1, 0, 0, 0 };
  323. straightPosIndex = 2;
  324. specialTransition = "(x" + agentName + "'=x" + agentName + (!neighborhood.at(straightPosIndex) ? ")" : "+1)");
  325. break;
  326. }
  327. slipperyActions.insert(actionName);
  328. // override probability to 0 if corresp. direction is blocked
  329. for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) {
  330. if (!neighborhood.at(i))
  331. prob_piece_dir.at(i) = 0;
  332. }
  333. // determine residual probability (R) by replacing 0 with (1 - overall sum)
  334. prob_piece_dir.at(straightPosIndex) = PROB_PIECES - std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0);
  335. // <DEBUG_AREA>
  336. {
  337. assert(prob_piece_dir.at(straightPosIndex) <= 9 && prob_piece_dir.at(straightPosIndex) >= 3 && "Value not in Range!");
  338. assert(std::accumulate(prob_piece_dir.begin(), prob_piece_dir.end(), 0) == PROB_PIECES && "Does not sum up to 1!");
  339. assert(orientation != SlipperyType::North || (prob_piece_dir.at(7) == 0 && prob_piece_dir.at(0) == 0 && prob_piece_dir.at(1) == 0 && "Slippery up should be impossible!"));
  340. assert(orientation != SlipperyType::South || (prob_piece_dir.at(3) == 0 && prob_piece_dir.at(4) == 0 && prob_piece_dir.at(5) == 0 && "Slippery down should be impossible!"));
  341. assert(orientation != SlipperyType::East || (prob_piece_dir.at(1) == 0 && prob_piece_dir.at(2) == 0 && prob_piece_dir.at(3) == 0 && "Slippery right should be impossible!"));
  342. assert(orientation != SlipperyType::West || (prob_piece_dir.at(5) == 0 && prob_piece_dir.at(6) == 0 && prob_piece_dir.at(7) == 0 && "Slippery left should be impossible!"));
  343. }
  344. // </DEBUG_AREA>
  345. // special case: straight forward is blocked (then remain in same position)
  346. positionTransition.at(straightPosIndex) = specialTransition;
  347. // generic output (for every view and every possible view direction)
  348. os << actionName << moveGuard(agentIndex) << " x" << agentName << "=" << c.second << " & y" << agentName << "=" << c.first;
  349. for (std::size_t i = 0; i < ALL_POSS_DIRECTIONS; i++) {
  350. os << (i == 0 ? " -> " : " + ") << prob_piece_dir.at(i) << "/" << PROB_PIECES << " : " << positionTransition.at(i) << moveUpdate(agentIndex) << (i == ALL_POSS_DIRECTIONS - 1 ? ";\n" : "\n");
  351. }
  352. return os;
  353. }
  354. std::ostream& PrismModulesPrinter::printEndmodule(std::ostream &os) {
  355. os << "endmodule\n";
  356. os << "\n";
  357. return os;
  358. }
  359. std::ostream& PrismModulesPrinter::printPlayerStruct(std::ostream &os, const AgentName &agentName, const bool agentWithView, const std::vector<float> &probabilities, const std::set<std::string> &slipperyActions) {
  360. os << "player " << agentName << "\n\t";
  361. bool first = true;
  362. std::list<std::string> allActions = { "_move_north", "_move_east", "_move_south", "_move_west" };
  363. std::list<std::string> movementActions = allActions;
  364. for(auto const& probability : probabilities) {
  365. std::string percentageString = std::to_string((int)(100 * probability));
  366. for(auto const& movement : movementActions) {
  367. allActions.push_back(movement + "_" + percentageString);
  368. }
  369. }
  370. if(agentWithView) {
  371. allActions.push_back("_turn_left");
  372. allActions.push_back("_turn_right");
  373. } else {
  374. allActions.push_back("_turns");
  375. }
  376. for(auto const& action : allActions) {
  377. if(first) first = false; else os << ", ";
  378. os << "[" << agentName << action << "]";
  379. }
  380. for(auto const& action : slipperyActions) {
  381. os << ", " << action;
  382. }
  383. os << "\nendplayer\n";
  384. return os;
  385. }
  386. std::ostream& PrismModulesPrinter::printGlobalMoveVariable(std::ostream &os, const size_t &numberOfPlayer) {
  387. os << "\nglobal move : [0.." << std::to_string(numberOfPlayer - 1) << "] init 0;\n\n";
  388. return os;
  389. }
  390. std::ostream& PrismModulesPrinter::printRewards(std::ostream &os, const std::map<coordinates, float> &stateRewards, const cells &lava, const cells &goals) {
  391. os << "rewards \"NoBFS\"\n";
  392. os << "\tAgentIsInGoalAndNotDone: 100;\n";
  393. os << "\tAgentIsInLavaAndNotDone: -100;\n";
  394. os << "endrewards\n";
  395. os << "rewards \"WithBFS\"\n";
  396. os << "\tAgentIsInGoalAndNotDone: 100;\n";
  397. os << "\tAgentIsInLavaAndNotDone: -100;\n";
  398. for(auto const [coordinates, reward] : stateRewards) {
  399. os << "\txAgent=" << coordinates.first << "&yAgent=" << coordinates.second << " : " << reward << ";\n";
  400. }
  401. os << "endrewards\n";
  402. return os;
  403. }
  404. std::string PrismModulesPrinter::moveGuard(const size_t &agentIndex) {
  405. return isGame() ? " move=" + std::to_string(agentIndex) + " & " : " ";
  406. }
  407. std::string PrismModulesPrinter::moveUpdate(const size_t &agentIndex) {
  408. return isGame() ?
  409. (agentIndex == numberOfPlayer - 1) ?
  410. " & (move'=0) " :
  411. " & (move'=" + std::to_string(agentIndex + 1) + ") " :
  412. "";
  413. }
  414. std::string PrismModulesPrinter::viewVariable(const AgentName &agentName, const size_t &agentDirection, const bool agentWithView) {
  415. return agentWithView ? " view" + agentName + "=" + std::to_string(agentDirection) + " & " : " ";
  416. }
  417. bool PrismModulesPrinter::isGame() const {
  418. return modelType == ModelType::SMG;
  419. }
  420. }