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.

258 lines
16 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #include "src/settings/SettingMemento.h"
  4. #include "src/parser/PrismParser.h"
  5. #include "src/parser/FormulaParser.h"
  6. #include "src/logic/Formulas.h"
  7. #include "src/builder/ExplicitPrismModelBuilder.h"
  8. #include "src/utility/solver.h"
  9. #include "src/modelchecker/csl/SparseCtmcCslModelChecker.h"
  10. #include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h"
  11. #include "src/settings/SettingsManager.h"
  12. #include "src/settings/modules/GeneralSettings.h"
  13. #include "src/settings/modules/NativeEquationSolverSettings.h"
  14. TEST(SparseCtmcCslModelCheckerTest, Cluster) {
  15. // Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
  16. std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true);
  17. // Parse the model description.
  18. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/cluster2.sm");
  19. storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer());
  20. std::shared_ptr<storm::logic::Formula> formula(nullptr);
  21. // Build the model.
  22. #ifdef WINDOWS
  23. storm::builder::ExplicitPrismModelBuilder<double>::Options options;
  24. #else
  25. typename storm::builder::ExplicitPrismModelBuilder<double>::Options options;
  26. #endif
  27. options.buildRewards = true;
  28. options.rewardModelName = "num_repairs";
  29. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program, options);
  30. ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType());
  31. std::shared_ptr<storm::models::sparse::Ctmc<double>> ctmc = model->as<storm::models::sparse::Ctmc<double>>();
  32. uint_fast64_t initialState = *ctmc->getInitialStates().begin();
  33. // Create model checker.
  34. storm::modelchecker::SparseCtmcCslModelChecker<double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>()));
  35. // Start checking properties.
  36. formula = formulaParser.parseFromString("P=? [ F<=100 !\"minimum\"]");
  37. std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula);
  38. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  39. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult1 = checkResult->asExplicitQuantitativeCheckResult<double>();
  40. EXPECT_NEAR(5.5461254704419085E-5, quantitativeCheckResult1[initialState], storm::settings::generalSettings().getPrecision());
  41. formula = formulaParser.parseFromString("P=? [ F[100,100] !\"minimum\"]");
  42. checkResult = modelchecker.check(*formula);
  43. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  44. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult2 = checkResult->asExplicitQuantitativeCheckResult<double>();
  45. EXPECT_NEAR(2.3397873548343415E-6, quantitativeCheckResult2[initialState], storm::settings::generalSettings().getPrecision());
  46. formula = formulaParser.parseFromString("P=? [ F[100,2000] !\"minimum\"]");
  47. checkResult = modelchecker.check(*formula);
  48. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  49. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult3 = checkResult->asExplicitQuantitativeCheckResult<double>();
  50. EXPECT_NEAR(0.001105335651670241, quantitativeCheckResult3[initialState], storm::settings::generalSettings().getPrecision());
  51. formula = formulaParser.parseFromString("P=? [ \"minimum\" U<=10 \"premium\"]");
  52. checkResult = modelchecker.check(*formula);
  53. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  54. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult4 = checkResult->asExplicitQuantitativeCheckResult<double>();
  55. EXPECT_NEAR(1, quantitativeCheckResult4[initialState], storm::settings::generalSettings().getPrecision());
  56. formula = formulaParser.parseFromString("P=? [ !\"minimum\" U[1,inf] \"minimum\"]");
  57. checkResult = modelchecker.check(*formula);
  58. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  59. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult5 = checkResult->asExplicitQuantitativeCheckResult<double>();
  60. EXPECT_NEAR(0, quantitativeCheckResult5[initialState], storm::settings::generalSettings().getPrecision());
  61. formula = formulaParser.parseFromString("P=? [ \"minimum\" U[1,inf] !\"minimum\"]");
  62. checkResult = modelchecker.check(*formula);
  63. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  64. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult6 = checkResult->asExplicitQuantitativeCheckResult<double>();
  65. EXPECT_NEAR(0.9999999033633374, quantitativeCheckResult6[initialState], storm::settings::generalSettings().getPrecision());
  66. formula = formulaParser.parseFromString("R=? [C<=100]");
  67. checkResult = modelchecker.check(*formula);
  68. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  69. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult7 = checkResult->asExplicitQuantitativeCheckResult<double>();
  70. EXPECT_NEAR(0.8602815057967503, quantitativeCheckResult7[initialState], storm::settings::generalSettings().getPrecision());
  71. }
  72. TEST(SparseCtmcCslModelCheckerTest, Embedded) {
  73. // Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
  74. std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true);
  75. // Parse the model description.
  76. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/embedded2.sm");
  77. storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer());
  78. std::shared_ptr<storm::logic::Formula> formula(nullptr);
  79. // Build the model.
  80. #ifdef WINDOWS
  81. storm::builder::ExplicitPrismModelBuilder<double>::Options options;
  82. #else
  83. typename storm::builder::ExplicitPrismModelBuilder<double>::Options options;
  84. #endif
  85. options.buildRewards = true;
  86. options.rewardModelName = "up";
  87. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program, options);
  88. ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType());
  89. std::shared_ptr<storm::models::sparse::Ctmc<double>> ctmc = model->as<storm::models::sparse::Ctmc<double>>();
  90. uint_fast64_t initialState = *ctmc->getInitialStates().begin();
  91. // Create model checker.
  92. storm::modelchecker::SparseCtmcCslModelChecker<double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>()));
  93. // Start checking properties.
  94. formula = formulaParser.parseFromString("P=? [ F<=10000 \"down\"]");
  95. std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula);
  96. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  97. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult1 = checkResult->asExplicitQuantitativeCheckResult<double>();
  98. EXPECT_NEAR(0.0019216435246119591, quantitativeCheckResult1[initialState], storm::settings::generalSettings().getPrecision());
  99. formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_actuators\"]");
  100. checkResult = modelchecker.check(*formula);
  101. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  102. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult2 = checkResult->asExplicitQuantitativeCheckResult<double>();
  103. EXPECT_NEAR(3.7079151806696567E-6, quantitativeCheckResult2[initialState], storm::settings::generalSettings().getPrecision());
  104. formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_io\"]");
  105. checkResult = modelchecker.check(*formula);
  106. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  107. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult3 = checkResult->asExplicitQuantitativeCheckResult<double>();
  108. EXPECT_NEAR(0.001556839327673734, quantitativeCheckResult3[initialState], storm::settings::generalSettings().getPrecision());
  109. formula = formulaParser.parseFromString("P=? [ !\"down\" U<=10000 \"fail_sensors\"]");
  110. checkResult = modelchecker.check(*formula);
  111. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  112. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult4 = checkResult->asExplicitQuantitativeCheckResult<double>();
  113. EXPECT_NEAR(4.429620626755424E-5, quantitativeCheckResult4[initialState], storm::settings::generalSettings().getPrecision());
  114. formula = formulaParser.parseFromString("R=? [C<=10000]");
  115. checkResult = modelchecker.check(*formula);
  116. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  117. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult5 = checkResult->asExplicitQuantitativeCheckResult<double>();
  118. EXPECT_NEAR(2.7745274082080154, quantitativeCheckResult5[initialState], storm::settings::generalSettings().getPrecision());
  119. }
  120. TEST(SparseCtmcCslModelCheckerTest, Polling) {
  121. // Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
  122. std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true);
  123. // Parse the model description.
  124. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/polling2.sm");
  125. storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer());
  126. std::shared_ptr<storm::logic::Formula> formula(nullptr);
  127. // Build the model.
  128. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program);
  129. ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType());
  130. std::shared_ptr<storm::models::sparse::Ctmc<double>> ctmc = model->as<storm::models::sparse::Ctmc<double>>();
  131. uint_fast64_t initialState = *ctmc->getInitialStates().begin();
  132. // Create model checker.
  133. storm::modelchecker::SparseCtmcCslModelChecker<double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>()));
  134. // Start checking properties.
  135. formula = formulaParser.parseFromString("P=?[ F<=10 \"target\"]");
  136. std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula);
  137. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  138. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult1 = checkResult->asExplicitQuantitativeCheckResult<double>();
  139. EXPECT_NEAR(1, quantitativeCheckResult1[initialState], storm::settings::generalSettings().getPrecision());
  140. }
  141. TEST(SparseCtmcCslModelCheckerTest, Fms) {
  142. // Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
  143. std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true);
  144. // No properties to check at this point.
  145. }
  146. TEST(SparseCtmcCslModelCheckerTest, Tandem) {
  147. // Set the PRISM compatibility mode temporarily. It is set to its old value once the returned object is destructed.
  148. std::unique_ptr<storm::settings::SettingMemento> enablePrismCompatibility = storm::settings::mutableGeneralSettings().overridePrismCompatibilityMode(true);
  149. // Parse the model description.
  150. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/builder/tandem5.sm");
  151. storm::parser::FormulaParser formulaParser(program.getManager().getSharedPointer());
  152. std::shared_ptr<storm::logic::Formula> formula(nullptr);
  153. // Build the model with the customers reward structure.
  154. #ifdef WINDOWS
  155. storm::builder::ExplicitPrismModelBuilder<double>::Options options;
  156. #else
  157. typename storm::builder::ExplicitPrismModelBuilder<double>::Options options;
  158. #endif
  159. options.buildRewards = true;
  160. options.rewardModelName = "customers";
  161. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitPrismModelBuilder<double>::translateProgram(program, options);
  162. ASSERT_EQ(storm::models::ModelType::Ctmc, model->getType());
  163. std::shared_ptr<storm::models::sparse::Ctmc<double>> ctmc = model->as<storm::models::sparse::Ctmc<double>>();
  164. uint_fast64_t initialState = *ctmc->getInitialStates().begin();
  165. // Create model checker.
  166. storm::modelchecker::SparseCtmcCslModelChecker<double> modelchecker(*ctmc, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<double>>(new storm::utility::solver::NativeLinearEquationSolverFactory<double>()));
  167. // Start checking properties.
  168. formula = formulaParser.parseFromString("P=? [ F<=10 \"network_full\" ]");
  169. std::unique_ptr<storm::modelchecker::CheckResult> checkResult = modelchecker.check(*formula);
  170. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  171. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult1 = checkResult->asExplicitQuantitativeCheckResult<double>();
  172. EXPECT_NEAR(0.015446370562428037, quantitativeCheckResult1[initialState], storm::settings::generalSettings().getPrecision());
  173. formula = formulaParser.parseFromString("P=? [ F<=10 \"first_queue_full\" ]");
  174. checkResult = modelchecker.check(*formula);
  175. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  176. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult2 = checkResult->asExplicitQuantitativeCheckResult<double>();
  177. EXPECT_NEAR(0.999999837225515, quantitativeCheckResult2[initialState], storm::settings::generalSettings().getPrecision());
  178. formula = formulaParser.parseFromString("P=? [\"second_queue_full\" U<=1 !\"second_queue_full\"]");
  179. checkResult = modelchecker.check(*formula);
  180. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  181. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult3 = checkResult->asExplicitQuantitativeCheckResult<double>();
  182. EXPECT_NEAR(1, quantitativeCheckResult3[initialState], storm::settings::generalSettings().getPrecision());
  183. formula = formulaParser.parseFromString("R=? [I=10]");
  184. checkResult = modelchecker.check(*formula);
  185. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  186. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult4 = checkResult->asExplicitQuantitativeCheckResult<double>();
  187. EXPECT_NEAR(5.679243850315877, quantitativeCheckResult4[initialState], storm::settings::generalSettings().getPrecision());
  188. formula = formulaParser.parseFromString("R=? [C<=10]");
  189. checkResult = modelchecker.check(*formula);
  190. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  191. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult5 = checkResult->asExplicitQuantitativeCheckResult<double>();
  192. EXPECT_NEAR(55.44792186036232, quantitativeCheckResult5[initialState], storm::settings::generalSettings().getPrecision());
  193. formula = formulaParser.parseFromString("R=? [F \"first_queue_full\"&\"second_queue_full\"]");
  194. checkResult = modelchecker.check(*formula);
  195. ASSERT_TRUE(checkResult->isExplicitQuantitativeCheckResult());
  196. storm::modelchecker::ExplicitQuantitativeCheckResult<double> quantitativeCheckResult6 = checkResult->asExplicitQuantitativeCheckResult<double>();
  197. EXPECT_NEAR(262.78584491454814, quantitativeCheckResult6[initialState], storm::settings::generalSettings().getPrecision());
  198. }