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.

242 lines
14 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/utility/solver.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/ExplicitPrismModelBuilder.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::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
  25. std::shared_ptr<const storm::logic::Formula> 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::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::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::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::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::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::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::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::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::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
  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::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::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::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
  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::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::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::unique_ptr<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(new storm::utility::solver::MinMaxLinearEquationSolverFactory<double>(storm::solver::EquationSolverTypeSelection::Gmmxx)));
  91. std::shared_ptr<const storm::logic::Formula> 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::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::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::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::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::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::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. std::shared_ptr<storm::models::sparse::Model<double>> model = storm::builder::ExplicitPrismModelBuilder<double>().translateProgram(program);
  121. EXPECT_EQ(4ul, model->getNumberOfStates());
  122. EXPECT_EQ(11ul, model->getNumberOfTransitions());
  123. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  124. std::shared_ptr<storm::models::sparse::Mdp<double>> mdp = model->as<storm::models::sparse::Mdp<double>>();
  125. EXPECT_EQ(7ul, mdp->getNumberOfChoices());
  126. auto solverFactory = std::make_unique<storm::utility::solver::MinMaxLinearEquationSolverFactory<double>>(storm::solver::EquationSolverTypeSelection::Gmmxx);
  127. solverFactory->setPreferredTechnique(storm::solver::MinMaxTechniqueSelection::PolicyIteration);
  128. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> checker(*mdp, std::move(solverFactory));
  129. std::shared_ptr<const storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"target\"]");
  130. storm::modelchecker::CheckTask<storm::logic::Formula> checkTask(*formula);
  131. checkTask.setProduceSchedulers(true);
  132. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(checkTask);
  133. ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
  134. ASSERT_TRUE(result->asExplicitQuantitativeCheckResult<double>().hasScheduler());
  135. storm::storage::Scheduler const& scheduler = result->asExplicitQuantitativeCheckResult<double>().getScheduler();
  136. EXPECT_EQ(0, scheduler.getChoice(0));
  137. EXPECT_EQ(1, scheduler.getChoice(1));
  138. EXPECT_EQ(0, scheduler.getChoice(2));
  139. EXPECT_EQ(0, scheduler.getChoice(3));
  140. formula = formulaParser.parseSingleFormulaFromString("Pmax=? [F \"target\"]");
  141. checkTask = storm::modelchecker::CheckTask<storm::logic::Formula>(*formula);
  142. checkTask.setProduceSchedulers(true);
  143. result = checker.check(checkTask);
  144. ASSERT_TRUE(result->isExplicitQuantitativeCheckResult());
  145. ASSERT_TRUE(result->asExplicitQuantitativeCheckResult<double>().hasScheduler());
  146. storm::storage::Scheduler const& scheduler2 = result->asExplicitQuantitativeCheckResult<double>().getScheduler();
  147. EXPECT_EQ(1, scheduler2.getChoice(0));
  148. EXPECT_EQ(2, scheduler2.getChoice(1));
  149. EXPECT_EQ(0, scheduler2.getChoice(2));
  150. EXPECT_EQ(0, scheduler2.getChoice(3));
  151. }