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.

171 lines
6.8 KiB

  1. #include "util/OptionParser.h"
  2. #include "util/MinigridGrammar.h"
  3. #include "util/Grid.h"
  4. #include <iostream>
  5. #include <fstream>
  6. #include <filesystem>
  7. #include <sstream>
  8. std::vector<std::string> parseCommaSeparatedString(std::string const& str) {
  9. std::vector<std::string> result;
  10. std::stringstream stream(str);
  11. while(stream.good()) {
  12. std::string substr;
  13. getline(stream, substr, ',');
  14. substr.at(0) = std::toupper(substr.at(0));
  15. result.push_back(substr);
  16. }
  17. return result;
  18. }
  19. struct printer {
  20. typedef boost::spirit::utf8_string string;
  21. void element(string const& tag, string const& value, int depth) const {
  22. for (int i = 0; i < (depth*4); ++i) std::cout << ' ';
  23. std::cout << "tag: " << tag;
  24. if (value != "") std::cout << ", value: " << value;
  25. std::cout << std::endl;
  26. }
  27. };
  28. void print_info(boost::spirit::info const& what) {
  29. using boost::spirit::basic_info_walker;
  30. printer pr;
  31. basic_info_walker<printer> walker(pr, what.tag, 0);
  32. boost::apply_visitor(walker, what.value);
  33. }
  34. int main(int argc, char* argv[]) {
  35. popl::OptionParser optionParser("Allowed options");
  36. auto helpOption = optionParser.add<popl::Switch>("h", "help", "Print this help message.");
  37. auto inputFilename = optionParser.add<popl::Value<std::string>>("i", "input-file", "Filename of the input file.");
  38. auto outputFilename = optionParser.add<popl::Value<std::string>>("o", "output-file", "Filename for the output file.");
  39. auto agentsToBeConsidered = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("a", "agents", "Which parsed agents should be considered in the output. WIP.");
  40. auto viewForAgents = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("v", "view", "Agents for which the 'view'('direction') variable should be included. WIP.");
  41. auto probabilisticBehaviourAgents = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("p", "prob-beh", "Agents for which we want to include probabilistic actions");
  42. auto probabilities = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("q", "probs", "The probabilities for which probabilistic actions should be added. WIP");
  43. auto enforceOneWays = optionParser.add<popl::Switch>("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.");
  44. try {
  45. optionParser.parse(argc, argv);
  46. if(helpOption->count() > 0) {
  47. std::cout << optionParser << std::endl;
  48. return EXIT_SUCCESS;
  49. }
  50. } catch (const popl::invalid_option &e) {
  51. return io::printPoplException(e);
  52. } catch (const std::exception &e) {
  53. std::cerr << "Exception: " << e.what() << "\n";
  54. return EXIT_FAILURE;
  55. }
  56. GridOptions gridOptions = { {}, {} };
  57. if(agentsToBeConsidered->is_set()) {
  58. gridOptions.agentsToBeConsidered = parseCommaSeparatedString(agentsToBeConsidered->value(0));
  59. }
  60. if(viewForAgents->is_set()) {
  61. gridOptions.agentsWithView = parseCommaSeparatedString(viewForAgents->value(0));
  62. }
  63. if(enforceOneWays->is_set()) {
  64. gridOptions.enforceOneWays = true;
  65. }
  66. if(probabilisticBehaviourAgents->is_set()) {
  67. gridOptions.agentsWithProbabilisticBehaviour = parseCommaSeparatedString(probabilisticBehaviourAgents->value(0));
  68. for(auto const& a : gridOptions.agentsWithProbabilisticBehaviour) {
  69. std::cout << a << std::endl;
  70. }
  71. if(probabilities->is_set()) {
  72. std::vector<std::string> parsedStrings = parseCommaSeparatedString(probabilities->value(0));
  73. std::transform(parsedStrings.begin(), parsedStrings.end(), std::back_inserter(gridOptions.probabilitiesForActions), [](const std::string& string) {
  74. return std::stof(string);
  75. });
  76. for(auto const& a : gridOptions.probabilitiesForActions) {
  77. std::cout << a << std::endl;
  78. }
  79. } else {
  80. throw std::logic_error{ "When adding agents with probabilistic behaviour, you also need to specify a list of probabilities via --probs." };
  81. }
  82. }
  83. std::fstream file {outputFilename->value(0), file.trunc | file.out};
  84. std::fstream infile {inputFilename->value(0), infile.in};
  85. std::string line, content, background, rewards;
  86. std::cout << "\n";
  87. bool parsingBackground = false;
  88. bool parsingStateRewards = false;
  89. while (std::getline(infile, line) && !line.empty()) {
  90. if(line.at(0) == '-' && line.at(line.size() - 1) == '-' && parsingBackground) {
  91. parsingStateRewards = true;
  92. parsingBackground = false;
  93. continue;
  94. } else if(line.at(0) == '-' && line.at(line.size() - 1) == '-') {
  95. parsingBackground = true;
  96. continue;
  97. }
  98. if(!parsingBackground && !parsingStateRewards) {
  99. std::cout << "Reading :\t" << line << "\n";
  100. content += line + "\n";
  101. } else if (parsingBackground) {
  102. std::cout << "Background:\t" << line << "\n";
  103. background += line + "\n";
  104. } else if(parsingStateRewards) {
  105. rewards += line + "\n";
  106. }
  107. }
  108. std::cout << "\n";
  109. pos_iterator_t contentFirst(content.begin());
  110. pos_iterator_t contentIter = contentFirst;
  111. pos_iterator_t contentLast(content.end());
  112. MinigridParser<pos_iterator_t> contentParser(contentFirst);
  113. pos_iterator_t backgroundFirst(background.begin());
  114. pos_iterator_t backgroundIter = backgroundFirst;
  115. pos_iterator_t backgroundLast(background.end());
  116. MinigridParser<pos_iterator_t> backgroundParser(backgroundFirst);
  117. cells contentCells;
  118. cells backgroundCells;
  119. std::map<coordinates, float> stateRewards;
  120. try {
  121. bool ok = phrase_parse(contentIter, contentLast, contentParser, qi::space, contentCells);
  122. // TODO if(background is not empty) {
  123. ok &= phrase_parse(backgroundIter, backgroundLast, backgroundParser, qi::space, backgroundCells);
  124. // TODO }
  125. boost::escaped_list_separator<char> seps('\\', ';', '\n');
  126. Tokenizer csvParser(rewards, seps);
  127. for(auto iter = csvParser.begin(); iter != csvParser.end(); ++iter) {
  128. int x = std::stoi(*iter);
  129. int y = std::stoi(*(++iter));
  130. float reward = std::stof(*(++iter));
  131. stateRewards[std::make_pair(x,y)] = reward;
  132. }
  133. if(ok) {
  134. Grid grid(contentCells, backgroundCells, gridOptions, stateRewards);
  135. //grid.printToPrism(std::cout, prism::ModelType::MDP);
  136. grid.printToPrism(file, prism::ModelType::MDP);
  137. }
  138. } catch(qi::expectation_failure<pos_iterator_t> const& e) {
  139. std::cout << "expected: "; print_info(e.what_);
  140. std::cout << "got: \"" << std::string(e.first, e.last) << '"' << std::endl;
  141. std::cout << "Expectation failure: " << e.what() << " at '" << std::string(e.first,e.last) << "'\n";
  142. } catch(const std::exception& e) {
  143. std::cerr << "Exception '" << typeid(e).name() << "' caught:" << std::endl;
  144. std::cerr << "\t" << e.what() << std::endl;
  145. std::exit(EXIT_FAILURE);
  146. }
  147. return 0;
  148. }