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.

200 lines
7.3 KiB

2 months ago
  1. #include "util/OptionParser.h"
  2. #include "util/MinigridGrammar.h"
  3. #include "util/Grid.h"
  4. #include "util/ConfigYaml.h"
  5. #include <iostream>
  6. #include <fstream>
  7. #include <filesystem>
  8. #include <sstream>
  9. std::vector<std::string> parseCommaSeparatedString(std::string const& str) {
  10. std::vector<std::string> result;
  11. std::stringstream stream(str);
  12. while(stream.good()) {
  13. std::string substr;
  14. getline(stream, substr, ',');
  15. substr.at(0) = std::toupper(substr.at(0));
  16. result.push_back(substr);
  17. }
  18. return result;
  19. }
  20. struct printer {
  21. typedef boost::spirit::utf8_string string;
  22. void element(string const& tag, string const& value, int depth) const {
  23. for (int i = 0; i < (depth*4); ++i) std::cout << ' ';
  24. std::cout << "tag: " << tag;
  25. if (value != "") std::cout << ", value: " << value;
  26. std::cout << std::endl;
  27. }
  28. };
  29. void print_info(boost::spirit::info const& what) {
  30. using boost::spirit::basic_info_walker;
  31. printer pr;
  32. basic_info_walker<printer> walker(pr, what.tag, 0);
  33. boost::apply_visitor(walker, what.value);
  34. }
  35. void setProbability(const std::string& gridProperties, const std::vector<Property> configProperties, const std::string& identifier, float& prop) {
  36. auto start_pos = gridProperties.find(identifier);
  37. std::string seperator = ";";
  38. if (start_pos != std::string::npos) {
  39. auto end_pos = gridProperties.find('\n', start_pos);
  40. auto value = gridProperties.substr(start_pos + identifier.length() + seperator.size(), end_pos - start_pos - identifier.length());
  41. prop = std::stod(value);
  42. }
  43. auto yaml_config_prop = std::find_if(configProperties.begin(), configProperties.end(), [&identifier](const Property& obj) -> bool {return obj.property == identifier;} );
  44. if (yaml_config_prop != configProperties.end()) {
  45. prop = (*yaml_config_prop).value_;
  46. }
  47. }
  48. int main(int argc, char* argv[]) {
  49. popl::OptionParser optionParser("Allowed options");
  50. auto helpOption = optionParser.add<popl::Switch>("h", "help", "Print this help message.");
  51. auto inputFilename = optionParser.add<popl::Value<std::string>>("i", "input-file", "Filename of the input file.");
  52. auto outputFilename = optionParser.add<popl::Value<std::string>>("o", "output-file", "Filename for the output file.");
  53. auto configFilename = optionParser.add<popl::Value<std::string>, popl::Attribute::optional>("c", "config-file", "Filename of the predicate configuration file.");
  54. try {
  55. optionParser.parse(argc, argv);
  56. if(helpOption->count() > 0) {
  57. std::cout << optionParser << std::endl;
  58. return EXIT_SUCCESS;
  59. }
  60. } catch (const popl::invalid_option &e) {
  61. return io::printPoplException(e);
  62. } catch (const std::exception &e) {
  63. std::cerr << "Exception: " << e.what() << "\n";
  64. return EXIT_FAILURE;
  65. }
  66. std::fstream file {outputFilename->value(0), file.trunc | file.out};
  67. std::fstream infile {inputFilename->value(0), infile.in};
  68. std::string line, content, background, rewards, properties;
  69. std::cout << "\n";
  70. bool parsingBackground = false;
  71. bool parsingStateRewards = false;
  72. bool parsingEnvironmentProperties = false;
  73. while (std::getline(infile, line) && !line.empty()) {
  74. if(line.at(0) == '-' && line.at(line.size() - 1) == '-' && parsingBackground) {
  75. parsingStateRewards = true;
  76. parsingBackground = false;
  77. continue;
  78. } else if (line.at(0) == '-' && line.at(line.size() - 1 ) == '-' && parsingStateRewards) {
  79. parsingStateRewards = false;
  80. parsingEnvironmentProperties = true;
  81. continue;
  82. } else if(line.at(0) == '-' && line.at(line.size() - 1) == '-') {
  83. parsingBackground = true;
  84. continue;
  85. }
  86. if(!parsingBackground && !parsingStateRewards && !parsingEnvironmentProperties) {
  87. content += line + "\n";
  88. } else if (parsingBackground) {
  89. background += line + "\n";
  90. } else if(parsingStateRewards) {
  91. rewards += line + "\n";
  92. } else if (parsingEnvironmentProperties) {
  93. properties += line + "\n";
  94. }
  95. }
  96. std::cout << "\n";
  97. pos_iterator_t contentFirst(content.begin());
  98. pos_iterator_t contentIter = contentFirst;
  99. pos_iterator_t contentLast(content.end());
  100. MinigridParser<pos_iterator_t> contentParser(contentFirst);
  101. pos_iterator_t backgroundFirst(background.begin());
  102. pos_iterator_t backgroundIter = backgroundFirst;
  103. pos_iterator_t backgroundLast(background.end());
  104. MinigridParser<pos_iterator_t> backgroundParser(backgroundFirst);
  105. cells contentCells;
  106. cells backgroundCells;
  107. std::vector<Configuration> configurations;
  108. std::vector<Property> parsed_properties;
  109. std::map<coordinates, float> stateRewards;
  110. float faultyProbability = 0.0;
  111. float probIntended = 1.0;
  112. float probTurnIntended = 1.0;
  113. try {
  114. bool ok = phrase_parse(contentIter, contentLast, contentParser, qi::space, contentCells);
  115. // TODO if(background is not empty) {
  116. ok &= phrase_parse(backgroundIter, backgroundLast, backgroundParser, qi::space, backgroundCells);
  117. // TODO }
  118. if (configFilename->is_set()) {
  119. YamlConfigParser parser(configFilename->value(0));
  120. auto parseResult = parser.parseConfiguration();
  121. configurations = parseResult.configurations_;
  122. parsed_properties = parseResult.properties_;
  123. }
  124. boost::escaped_list_separator<char> seps('\\', ';', '\n');
  125. Tokenizer csvParser(rewards, seps);
  126. for(auto iter = csvParser.begin(); iter != csvParser.end(); ++iter) {
  127. int x = std::stoi(*iter);
  128. int y = std::stoi(*(++iter));
  129. float reward = std::stof(*(++iter));
  130. stateRewards[std::make_pair(x,y)] = reward;
  131. }
  132. if (!properties.empty()) {
  133. auto faultProbabilityIdentifier = std::string("FaultProbability");
  134. auto probForwardIntendedIdentifier = std::string("ProbForwardIntended");
  135. auto probTurnIntendedIdentifier = std::string("ProbTurnIntended");
  136. setProbability(properties, parsed_properties, faultProbabilityIdentifier, faultyProbability);
  137. setProbability(properties, parsed_properties, probForwardIntendedIdentifier, probIntended);
  138. setProbability(properties, parsed_properties, probTurnIntendedIdentifier, probTurnIntended);
  139. }
  140. if(ok) {
  141. Grid grid(contentCells, backgroundCells, stateRewards, probIntended, faultyProbability);
  142. auto modelTypeIter = std::find_if(parsed_properties.begin(), parsed_properties.end(), [](const Property& obj) -> bool {return obj.property == "modeltype";});
  143. prism::ModelType modelType = prism::ModelType::MDP;;
  144. if (modelTypeIter != parsed_properties.end()) {
  145. if ((*modelTypeIter).value_str_ == "smg") {
  146. modelType = prism::ModelType::SMG;
  147. } else {
  148. modelType = prism::ModelType::MDP;
  149. }
  150. grid.setModelType(modelType);
  151. }
  152. //grid.printToPrism(std::cout, configurations);
  153. std::stringstream ss;
  154. grid.printToPrism(ss, configurations);
  155. std::string str = ss.str();
  156. grid.applyOverwrites(str, configurations);
  157. file << str;
  158. }
  159. } catch(qi::expectation_failure<pos_iterator_t> const& e) {
  160. std::cout << "expected: "; print_info(e.what_);
  161. std::cout << "got: \"" << std::string(e.first, e.last) << '"' << std::endl;
  162. std::cout << "Expectation failure: " << e.what() << " at '" << std::string(e.first,e.last) << "'\n";
  163. } catch(const std::exception& e) {
  164. std::cerr << "Exception '" << typeid(e).name() << "' caught:" << e.what() << std::endl;
  165. std::cerr << "\t" << e.what() << std::endl;
  166. std::exit(EXIT_FAILURE);
  167. }
  168. return 0;
  169. }