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.

275 lines
16 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #include "src/parser/FormulaParser.h"
  4. #include "src/logic/Formulas.h"
  5. #include "src/solver/StandardMinMaxLinearEquationSolver.h"
  6. #include "src/models/sparse/StandardRewardModel.h"
  7. #include "src/modelchecker/prctl/SparseMdpPrctlModelChecker.h"
  8. #include "src/modelchecker/results/ExplicitQuantitativeCheckResult.h"
  9. #include "src/settings/SettingsManager.h"
  10. #include "src/settings/modules/GeneralSettings.h"
  11. #include "src/settings/modules/GmmxxEquationSolverSettings.h"
  12. #include "src/settings/modules/NativeEquationSolverSettings.h"
  13. #include "src/parser/AutoParser.h"
  14. #include "src/parser/PrismParser.h"
  15. #include "src/builder/ExplicitModelBuilder.h"
  16. TEST(GmmxxMdpPrctlModelCheckerTest, Dice) {
  17. std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.tra", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.lab", "", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.trans.rew");
  18. // A parser that we use for conveniently constructing the formulas.
  19. storm::parser::FormulaParser formulaParser;
  20. ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp);
  21. std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
  22. ASSERT_EQ(mdp->getNumberOfStates(), 169ull);
  23. ASSERT_EQ(mdp->getNumberOfTransitions(), 436ull);
  24. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::make_unique<storm::solver::GmmxxMinMaxLinearEquationSolverFactory<double>>());
  25. std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"two\"]");
  26. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
  27. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
  28. EXPECT_NEAR(0.0277777612209320068, quantitativeResult1[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  29. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"two\"]");
  30. result = checker.check(*formula);
  31. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
  32. EXPECT_NEAR(0.0277777612209320068, quantitativeResult2[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  33. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"three\"]");
  34. result = checker.check(*formula);
  35. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
  36. EXPECT_NEAR(0.0555555224418640136, quantitativeResult3[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  37. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"three\"]");
  38. result = checker.check(*formula);
  39. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
  40. EXPECT_NEAR(0.0555555224418640136, quantitativeResult4[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  41. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"four\"]");
  42. result = checker.check(*formula);
  43. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
  44. EXPECT_NEAR(0.083333283662796020508, quantitativeResult5[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  45. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"four\"]");
  46. result = checker.check(*formula);
  47. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
  48. EXPECT_NEAR(0.083333283662796020508, quantitativeResult6[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  49. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
  50. result = checker.check(*formula);
  51. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult7 = result->asExplicitQuantitativeCheckResult<double>();
  52. EXPECT_NEAR(7.333329499, quantitativeResult7[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  53. formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
  54. result = checker.check(*formula);
  55. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult8 = result->asExplicitQuantitativeCheckResult<double>();
  56. EXPECT_NEAR(7.333329499, quantitativeResult8[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  57. abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.tra", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.lab", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.state.rew", "");
  58. ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp);
  59. std::shared_ptr<storm::models::sparse::Mdp<double>> stateRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
  60. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateRewardModelChecker(*mdp, std::make_unique<storm::solver::GmmxxMinMaxLinearEquationSolverFactory<double>>());
  61. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
  62. result = stateRewardModelChecker.check(*formula);
  63. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult9 = result->asExplicitQuantitativeCheckResult<double>();
  64. EXPECT_NEAR(7.333329499, quantitativeResult9[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  65. formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
  66. result = stateRewardModelChecker.check(*formula);
  67. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult10 = result->asExplicitQuantitativeCheckResult<double>();
  68. EXPECT_NEAR(7.333329499, quantitativeResult10[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  69. abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.tra", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.lab", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.state.rew", STORM_CPP_BASE_PATH "/examples/mdp/two_dice/two_dice.flip.trans.rew");
  70. ASSERT_EQ(abstractModel->getType(), storm::models::ModelType::Mdp);
  71. std::shared_ptr<storm::models::sparse::Mdp<double>> stateAndTransitionRewardMdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
  72. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> stateAndTransitionRewardModelChecker(*stateAndTransitionRewardMdp, std::make_unique<storm::solver::GmmxxMinMaxLinearEquationSolverFactory<double>>());
  73. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"done\"]");
  74. result = stateAndTransitionRewardModelChecker.check(*formula);
  75. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult11 = result->asExplicitQuantitativeCheckResult<double>();
  76. EXPECT_NEAR(14.666658998, quantitativeResult11[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  77. formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"done\"]");
  78. result = stateAndTransitionRewardModelChecker.check(*formula);
  79. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult12 = result->asExplicitQuantitativeCheckResult<double>();
  80. EXPECT_NEAR(14.666658998, quantitativeResult12[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  81. }
  82. TEST(GmmxxMdpPrctlModelCheckerTest, AsynchronousLeader) {
  83. std::shared_ptr<storm::models::sparse::Model<double>> abstractModel = storm::parser::AutoParser<>::parseModel(STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader4.tra", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader4.lab", "", STORM_CPP_BASE_PATH "/examples/mdp/asynchronous_leader/leader4.trans.rew");
  84. // A parser that we use for conveniently constructing the formulas.
  85. storm::parser::FormulaParser formulaParser;
  86. ASSERT_EQ(storm::models::ModelType::Mdp, abstractModel->getType());
  87. std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = abstractModel->as<storm::models::sparse::Mdp<double>>();
  88. ASSERT_EQ(3172ull, mdp->getNumberOfStates());
  89. ASSERT_EQ(7144ull, mdp->getNumberOfTransitions());
  90. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::make_unique<storm::solver::GmmxxMinMaxLinearEquationSolverFactory<double>>());
  91. std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]");
  92. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
  93. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult1 = result->asExplicitQuantitativeCheckResult<double>();
  94. EXPECT_NEAR(1, quantitativeResult1[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  95. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"elected\"]");
  96. result = checker.check(*formula);
  97. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult2 = result->asExplicitQuantitativeCheckResult<double>();
  98. EXPECT_NEAR(1, quantitativeResult2[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  99. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]");
  100. result = checker.check(*formula);
  101. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult3 = result->asExplicitQuantitativeCheckResult<double>();
  102. EXPECT_NEAR(0.0625, quantitativeResult3[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  103. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F<=25 \"elected\"]");
  104. result = checker.check(*formula);
  105. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult4 = result->asExplicitQuantitativeCheckResult<double>();
  106. EXPECT_NEAR(0.0625, quantitativeResult4[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  107. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]");
  108. result = checker.check(*formula);
  109. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult5 = result->asExplicitQuantitativeCheckResult<double>();
  110. EXPECT_NEAR(4.285689611, quantitativeResult5[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  111. formula = formulaParser.parseSingleFormulaFromString("Rmax=? [F \"elected\"]");
  112. result = checker.check(*formula);
  113. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeResult6 = result->asExplicitQuantitativeCheckResult<double>();
  114. EXPECT_NEAR(4.285689611, quantitativeResult6[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  115. }
  116. TEST(GmmxxMdpPrctlModelCheckerTest, SchedulerGeneration) {
  117. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/scheduler_generation.nm");
  118. // A parser that we use for conveniently constructing the formulas.
  119. storm::parser::FormulaParser formulaParser;
  120. storm::generator::NextStateGeneratorOptions options;
  121. options.setBuildAllLabels();
  122. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitModelBuilder<double>(program, options).build();
  123. EXPECT_EQ(4ul, model->getNumberOfStates());
  124. EXPECT_EQ(11ul, model->getNumberOfTransitions());
  125. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  126. std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = model->as<storm::models::sparse::Mdp<double>>();
  127. EXPECT_EQ(7ul, mdp->getNumberOfChoices());
  128. auto solverFactory = std::make_unique<storm::solver::GmmxxMinMaxLinearEquationSolverFactory<double>>();
  129. solverFactory->getSettings().setSolutionMethod(storm::solver::StandardMinMaxLinearEquationSolverSettings<double>::SolutionMethod::PolicyIteration);
  130. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::move(solverFactory));
  131. std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"target\"]");
  132. storm::modelchecker::CheckTask<storm::logic::Formula> checkTask(*formula);
  133. checkTask.setProduceSchedulers(true);
  134. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(checkTask);
  135. ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
  136. ASSERT_TRUE(result->asExplicitQuantitativeCheckResult<double>().hasScheduler());
  137. storm::storage::Scheduler const& scheduler = result->asExplicitQuantitativeCheckResult<double>().getScheduler();
  138. EXPECT_EQ(0, scheduler.getChoice(0));
  139. EXPECT_EQ(1, scheduler.getChoice(1));
  140. EXPECT_EQ(0, scheduler.getChoice(2));
  141. EXPECT_EQ(0, scheduler.getChoice(3));
  142. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"target\"]");
  143. checkTask = storm::modelchecker::CheckTask<storm::logic::Formula>(*formula);
  144. checkTask.setProduceSchedulers(true);
  145. result = checker.check(checkTask);
  146. ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
  147. ASSERT_TRUE(result->asExplicitQuantitativeCheckResult<double>().hasScheduler());
  148. storm::storage::Scheduler const& scheduler2 = result->asExplicitQuantitativeCheckResult<double>().getScheduler();
  149. EXPECT_EQ(1, scheduler2.getChoice(0));
  150. EXPECT_EQ(2, scheduler2.getChoice(1));
  151. EXPECT_EQ(0, scheduler2.getChoice(2));
  152. EXPECT_EQ(0, scheduler2.getChoice(3));
  153. }
  154. TEST(GmmxxMdpPrctlModelCheckerTest, TinyRewards) {
  155. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/functional/modelchecker/tiny_rewards.nm");
  156. // A parser that we use for conveniently constructing the formulas.
  157. storm::parser::FormulaParser formulaParser;
  158. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitModelBuilder<double>(program, storm::generator::NextStateGeneratorOptions(true, true)).build();
  159. EXPECT_EQ(3ul, model->getNumberOfStates());
  160. EXPECT_EQ(4ul, model->getNumberOfTransitions());
  161. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  162. std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = model->as<storm::models::sparse::Mdp<double>>();
  163. EXPECT_EQ(4ul, mdp->getNumberOfChoices());
  164. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::make_unique<storm::solver::GmmxxMinMaxLinearEquationSolverFactory<double>>());
  165. std::shared_ptr<storm::logic::Formula const> formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"target\"]");
  166. storm::modelchecker::CheckTask<storm::logic::Formula> checkTask(*formula);
  167. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(checkTask);
  168. ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
  169. EXPECT_NEAR(1,result->asExplicitQuantitativeCheckResult<double>().getValueVector()[0], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  170. EXPECT_NEAR(1,result->asExplicitQuantitativeCheckResult<double>().getValueVector()[1], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  171. EXPECT_NEAR(0,result->asExplicitQuantitativeCheckResult<double>().getValueVector()[2], storm::settings::getModule<storm::settings::modules::NativeEquationSolverSettings>().getPrecision());
  172. }