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.

271 lines
12 KiB

  1. /*
  2. * NondeterministicSparseTransitionParserTest.cpp
  3. *
  4. * Created on: Feb 26, 2014
  5. * Author: Manuel Sascha Weiand
  6. */
  7. #include "gtest/gtest.h"
  8. #include "storm-config.h"
  9. #include "src/parser/NondeterministicSparseTransitionParser.h"
  10. #include "src/storage/SparseMatrix.h"
  11. #include "src/settings/SettingMemento.h"
  12. #include "src/settings/SettingsManager.h"
  13. #include "src/settings/modules/MarkovChainSettings.h"
  14. #include "src/exceptions/FileIoException.h"
  15. #include "src/exceptions/WrongFormatException.h"
  16. #include "src/exceptions/InvalidArgumentException.h"
  17. TEST(NondeterministicSparseTransitionParserTest, NonExistingFile) {
  18. // No matter what happens, please do NOT create a file with the name "nonExistingFile.not"!
  19. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not"), storm::exceptions::FileIoException);
  20. storm::storage::SparseMatrix<double> nullInformation;
  21. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/nonExistingFile.not", nullInformation), storm::exceptions::FileIoException);
  22. }
  23. TEST(NondeterministicSparseTransitionParserTest, BasicTransitionsParsing) {
  24. // Parse a nondeterministic transitions file and test the result.
  25. storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
  26. // Test the row mapping, i.e. at which row which state starts.
  27. ASSERT_EQ(6ul, result.getRowGroupCount());
  28. ASSERT_EQ(7ul, result.getRowGroupIndices().size());
  29. ASSERT_EQ(0ul, result.getRowGroupIndices()[0]);
  30. ASSERT_EQ(4ul, result.getRowGroupIndices()[1]);
  31. ASSERT_EQ(5ul, result.getRowGroupIndices()[2]);
  32. ASSERT_EQ(7ul, result.getRowGroupIndices()[3]);
  33. ASSERT_EQ(8ul, result.getRowGroupIndices()[4]);
  34. ASSERT_EQ(9ul, result.getRowGroupIndices()[5]);
  35. ASSERT_EQ(11ul, result.getRowGroupIndices()[6]);
  36. // Test the transition matrix.
  37. ASSERT_EQ(6ul, result.getColumnCount());
  38. ASSERT_EQ(11ul, result.getRowCount());
  39. ASSERT_EQ(22ul, result.getEntryCount());
  40. // Test every entry of the matrix.
  41. storm::storage::SparseMatrix<double>::const_iterator cIter = result.begin(0);
  42. ASSERT_EQ(0ul, cIter->getColumn());
  43. ASSERT_EQ(0.9, cIter->getValue());
  44. cIter++;
  45. ASSERT_EQ(1ul, cIter->getColumn());
  46. ASSERT_EQ(0.1, cIter->getValue());
  47. cIter++;
  48. ASSERT_EQ(1ul, cIter->getColumn());
  49. ASSERT_EQ(0.2, cIter->getValue());
  50. cIter++;
  51. ASSERT_EQ(2ul, cIter->getColumn());
  52. ASSERT_EQ(0.2, cIter->getValue());
  53. cIter++;
  54. ASSERT_EQ(3ul, cIter->getColumn());
  55. ASSERT_EQ(0.2, cIter->getValue());
  56. cIter++;
  57. ASSERT_EQ(4ul, cIter->getColumn());
  58. ASSERT_EQ(0.2, cIter->getValue());
  59. cIter++;
  60. ASSERT_EQ(5ul, cIter->getColumn());
  61. ASSERT_EQ(0.2, cIter->getValue());
  62. cIter++;
  63. ASSERT_EQ(5ul, cIter->getColumn());
  64. ASSERT_EQ(1, cIter->getValue());
  65. cIter++;
  66. ASSERT_EQ(0ul, cIter->getColumn());
  67. ASSERT_EQ(0.1, cIter->getValue());
  68. cIter++;
  69. ASSERT_EQ(4ul, cIter->getColumn());
  70. ASSERT_EQ(0.9, cIter->getValue());
  71. cIter++;
  72. ASSERT_EQ(2ul, cIter->getColumn());
  73. ASSERT_EQ(1, cIter->getValue());
  74. cIter++;
  75. ASSERT_EQ(2ul, cIter->getColumn());
  76. ASSERT_EQ(0.5, cIter->getValue());
  77. cIter++;
  78. ASSERT_EQ(3ul, cIter->getColumn());
  79. ASSERT_EQ(0.5, cIter->getValue());
  80. cIter++;
  81. ASSERT_EQ(2ul, cIter->getColumn());
  82. ASSERT_EQ(1, cIter->getValue());
  83. cIter++;
  84. ASSERT_EQ(2ul, cIter->getColumn());
  85. ASSERT_EQ(0.001, cIter->getValue());
  86. cIter++;
  87. ASSERT_EQ(3ul, cIter->getColumn());
  88. ASSERT_EQ(0.999, cIter->getValue());
  89. cIter++;
  90. ASSERT_EQ(1ul, cIter->getColumn());
  91. ASSERT_EQ(0.7, cIter->getValue());
  92. cIter++;
  93. ASSERT_EQ(4ul, cIter->getColumn());
  94. ASSERT_EQ(0.3, cIter->getValue());
  95. cIter++;
  96. ASSERT_EQ(1ul, cIter->getColumn());
  97. ASSERT_EQ(0.2, cIter->getValue());
  98. cIter++;
  99. ASSERT_EQ(4ul, cIter->getColumn());
  100. ASSERT_EQ(0.2, cIter->getValue());
  101. cIter++;
  102. ASSERT_EQ(5ul, cIter->getColumn());
  103. ASSERT_EQ(0.6, cIter->getValue());
  104. cIter++;
  105. ASSERT_EQ(5ul, cIter->getColumn());
  106. ASSERT_EQ(1, cIter->getValue());
  107. }
  108. TEST(NondeterministicSparseTransitionParserTest, BasicTransitionsRewardsParsing) {
  109. // Parse a nondeterministic transitions file and test the result.
  110. storm::storage::SparseMatrix<double> modelInformation(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
  111. storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew", modelInformation));
  112. // Test the transition matrix.
  113. ASSERT_EQ(6ul, result.getColumnCount());
  114. ASSERT_EQ(11ul, result.getRowCount());
  115. ASSERT_EQ(17ul, result.getEntryCount());
  116. // Test every entry of the matrix.
  117. storm::storage::SparseMatrix<double>::const_iterator cIter = result.begin(0);
  118. ASSERT_EQ(0ul, cIter->getColumn());
  119. ASSERT_EQ(1, cIter->getValue());
  120. cIter++;
  121. ASSERT_EQ(1ul, cIter->getColumn());
  122. ASSERT_EQ(30, cIter->getValue());
  123. cIter++;
  124. ASSERT_EQ(1ul, cIter->getColumn());
  125. ASSERT_EQ(15.2, cIter->getValue());
  126. cIter++;
  127. ASSERT_EQ(2ul, cIter->getColumn());
  128. ASSERT_EQ(75, cIter->getValue());
  129. cIter++;
  130. ASSERT_EQ(5ul, cIter->getColumn());
  131. ASSERT_EQ(2.45, cIter->getValue());
  132. cIter++;
  133. ASSERT_EQ(5ul, cIter->getColumn());
  134. ASSERT_EQ(1, cIter->getValue());
  135. cIter++;
  136. ASSERT_EQ(0ul, cIter->getColumn());
  137. ASSERT_EQ(0.114, cIter->getValue());
  138. cIter++;
  139. ASSERT_EQ(4ul, cIter->getColumn());
  140. ASSERT_EQ(90, cIter->getValue());
  141. cIter++;
  142. ASSERT_EQ(2ul, cIter->getColumn());
  143. ASSERT_EQ(1, cIter->getValue());
  144. cIter++;
  145. ASSERT_EQ(2ul, cIter->getColumn());
  146. ASSERT_EQ(55, cIter->getValue());
  147. cIter++;
  148. ASSERT_EQ(3ul, cIter->getColumn());
  149. ASSERT_EQ(87, cIter->getValue());
  150. cIter++;
  151. ASSERT_EQ(2ul, cIter->getColumn());
  152. ASSERT_EQ(13, cIter->getValue());
  153. cIter++;
  154. ASSERT_EQ(3ul, cIter->getColumn());
  155. ASSERT_EQ(999, cIter->getValue());
  156. cIter++;
  157. ASSERT_EQ(1ul, cIter->getColumn());
  158. ASSERT_EQ(0.7, cIter->getValue());
  159. cIter++;
  160. ASSERT_EQ(4ul, cIter->getColumn());
  161. ASSERT_EQ(0.3, cIter->getValue());
  162. cIter++;
  163. ASSERT_EQ(1ul, cIter->getColumn());
  164. ASSERT_EQ(0.1, cIter->getValue());
  165. cIter++;
  166. ASSERT_EQ(5ul, cIter->getColumn());
  167. ASSERT_EQ(6, cIter->getValue());
  168. }
  169. TEST(NondeterministicSparseTransitionParserTest, Whitespaces) {
  170. // Test the resilience of the parser against whitespaces.
  171. // Do so by comparing the hashes of the transition matices and the rowMapping vectors element by element.
  172. storm::storage::SparseMatrix<double> correctResult(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra"));
  173. storm::storage::SparseMatrix<double> whitespaceResult = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_whitespaces.tra");
  174. ASSERT_EQ(correctResult.hash(), whitespaceResult.hash());
  175. ASSERT_EQ(correctResult.getRowGroupIndices().size(), whitespaceResult.getRowGroupIndices().size());
  176. for(uint_fast64_t i = 0; i < correctResult.getRowGroupIndices().size(); i++) {
  177. ASSERT_EQ(correctResult.getRowGroupIndices()[i], whitespaceResult.getRowGroupIndices()[i]);
  178. }
  179. // Do the same (minus the unused rowMapping) for the corresponding transition rewards file (with and without whitespaces)
  180. uint_fast64_t correctHash = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_general.trans.rew", correctResult).hash();
  181. ASSERT_EQ(correctHash, storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_whitespaces.trans.rew", whitespaceResult).hash());
  182. }
  183. TEST(NondeterministicSparseTransitionParserTest, MixedTransitionOrder) {
  184. // Since the MatrixBuilder needs sequential input of new elements reordering of transitions or states should throw an exception.
  185. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_mixedStateOrder.tra"), storm::exceptions::InvalidArgumentException);
  186. storm::storage::SparseMatrix<double> modelInformation = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra");
  187. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_mixedStateOrder.trans.rew", modelInformation), storm::exceptions::InvalidArgumentException);
  188. }
  189. TEST(NondeterministicSparseTransitionParserTest, FixDeadlocks) {
  190. // Set the fixDeadlocks flag temporarily. It is set to its old value once the deadlockOption object is destructed.
  191. std::unique_ptr<storm::settings::SettingMemento> fixDeadlocks = storm::settings::mutableMarkovChainSettings().overrideDontFixDeadlocksSet(false);
  192. // Parse a transitions file with the fixDeadlocks Flag set and test if it works.
  193. storm::storage::SparseMatrix<double> result(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_deadlock.tra"));
  194. ASSERT_EQ(8ul, result.getRowGroupIndices().size());
  195. ASSERT_EQ(9ul, result.getRowGroupIndices()[5]);
  196. ASSERT_EQ(10ul, result.getRowGroupIndices()[6]);
  197. ASSERT_EQ(12ul, result.getRowGroupIndices()[7]);
  198. ASSERT_EQ(7ul, result.getColumnCount());
  199. ASSERT_EQ(12ul, result.getRowCount());
  200. ASSERT_EQ(23ul, result.getEntryCount());
  201. storm::storage::SparseMatrix<double>::const_iterator cIter = result.begin(8);
  202. ASSERT_EQ(1ul, cIter->getColumn());
  203. ASSERT_EQ(0.7, cIter->getValue());
  204. cIter++;
  205. ASSERT_EQ(4ul, cIter->getColumn());
  206. ASSERT_EQ(0.3, cIter->getValue());
  207. cIter++;
  208. ASSERT_EQ(5ul, cIter->getColumn());
  209. ASSERT_EQ(1, cIter->getValue());
  210. cIter++;
  211. ASSERT_EQ(1ul, cIter->getColumn());
  212. ASSERT_EQ(0.2, cIter->getValue());
  213. cIter++;
  214. ASSERT_EQ(4ul, cIter->getColumn());
  215. ASSERT_EQ(0.2, cIter->getValue());
  216. cIter++;
  217. ASSERT_EQ(5ul, cIter->getColumn());
  218. ASSERT_EQ(0.6, cIter->getValue());
  219. cIter++;
  220. ASSERT_EQ(5ul, cIter->getColumn());
  221. ASSERT_EQ(1, cIter->getValue());
  222. }
  223. TEST(NondeterministicSparseTransitionParserTest, DontFixDeadlocks) {
  224. // Try to parse a transitions file containing a deadlock state with the fixDeadlocksFlag unset. This should throw an exception.
  225. std::unique_ptr<storm::settings::SettingMemento> dontFixDeadlocks = storm::settings::mutableMarkovChainSettings().overrideDontFixDeadlocksSet(true);
  226. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_deadlock.tra"), storm::exceptions::WrongFormatException);
  227. }
  228. TEST(NondeterministicSparseTransitionParserTest, DoubledLines) {
  229. // There is a redundant line in the transition file. As the transition already exists this should throw an exception.
  230. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_doubledLines.tra"), storm::exceptions::InvalidArgumentException);
  231. }
  232. TEST(NondeterministicSparseTransitionParserTest, RewardForNonExistentTransition) {
  233. // First parse a transition file. Then parse a transition reward file for the resulting transition matrix.
  234. storm::storage::SparseMatrix<double> transitionResult = storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitions(STORM_CPP_TESTS_BASE_PATH "/functional/parser/tra_files/mdp_general.tra");
  235. // There is a reward for a transition that does not exist in the transition matrix.
  236. ASSERT_THROW(storm::parser::NondeterministicSparseTransitionParser<>::parseNondeterministicTransitionRewards(STORM_CPP_TESTS_BASE_PATH "/functional/parser/rew_files/mdp_rewardForNonExTrans.trans.rew", transitionResult), storm::exceptions::WrongFormatException);
  237. }