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.

236 lines
16 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #include "src/logic/Formulas.h"
  4. #include "src/utility/solver.h"
  5. #include "src/modelchecker/prctl/SymbolicMdpPrctlModelChecker.h"
  6. #include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
  7. #include "src/modelchecker/results/SymbolicQuantitativeCheckResult.h"
  8. #include "src/parser/FormulaParser.h"
  9. #include "src/parser/PrismParser.h"
  10. #include "src/builder/DdPrismModelBuilder.h"
  11. #include "src/models/symbolic/Dtmc.h"
  12. #include "src/models/symbolic/StandardRewardModel.h"
  13. #include "src/settings/SettingsManager.h"
  14. #include "src/settings/modules/NativeEquationSolverSettings.h"
  15. #include "src/settings/modules/GeneralSettings.h"
  16. TEST(SymbolicMdpPrctlModelCheckerTest, AsynchronousLeader_Cudd) {
  17. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/performance/builder/leader5.nm");
  18. // A parser that we use for conveniently constructing the formulas.
  19. storm::parser::FormulaParser formulaParser;
  20. // Build the die model with its reward model.
  21. #ifdef WINDOWS
  22. storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options;
  23. #else
  24. typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options;
  25. #endif
  26. options.buildAllRewardModels = false;
  27. options.rewardModelsToBuild.insert("rounds");
  28. std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>().translateProgram(program, options);
  29. EXPECT_EQ(27299ul, model->getNumberOfStates());
  30. EXPECT_EQ(74365ul, model->getNumberOfTransitions());
  31. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  32. std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>();
  33. storm::modelchecker::SymbolicMdpPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*mdp, std::unique_ptr<storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>>(new storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>()));
  34. std::shared_ptr<const storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]");
  35. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
  36. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates()));
  37. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD, double>();
  38. EXPECT_NEAR(1, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  39. EXPECT_NEAR(1, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  40. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]");
  41. result = checker.check(*formula);
  42. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates()));
  43. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD, double>();
  44. EXPECT_NEAR(0, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  45. EXPECT_NEAR(0, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  46. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]");
  47. result = checker.check(*formula);
  48. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates()));
  49. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult5 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD, double>();
  50. EXPECT_NEAR(5.0348834996352601, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  51. EXPECT_NEAR(5.0348834996352601, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  52. }
  53. TEST(SymbolicMdpPrctlModelCheckerTest, AsynchronousLeader_Sylvan) {
  54. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/performance/builder/leader5.nm");
  55. // A parser that we use for conveniently constructing the formulas.
  56. storm::parser::FormulaParser formulaParser;
  57. // Build the die model with its reward model.
  58. #ifdef WINDOWS
  59. storm::builder::DdPrismModelBuilder<storm::dd::DdType::Sylvan>::Options options;
  60. #else
  61. typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::Sylvan>::Options options;
  62. #endif
  63. options.buildAllRewardModels = false;
  64. options.rewardModelsToBuild.insert("rounds");
  65. std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::Sylvan>> model = storm::builder::DdPrismModelBuilder<storm::dd::DdType::Sylvan>().translateProgram(program, options);
  66. EXPECT_EQ(27299ul, model->getNumberOfStates());
  67. EXPECT_EQ(74365ul, model->getNumberOfTransitions());
  68. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  69. std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan>>();
  70. storm::modelchecker::SymbolicMdpPrctlModelChecker<storm::dd::DdType::Sylvan, double> checker(*mdp, std::unique_ptr<storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::Sylvan, double>>(new storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::Sylvan, double>()));
  71. std::shared_ptr<const storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F \"elected\"]");
  72. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
  73. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::Sylvan>(model->getReachableStates(), model->getInitialStates()));
  74. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan, double>();
  75. EXPECT_NEAR(1, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  76. EXPECT_NEAR(1, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  77. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [F<=25 \"elected\"]");
  78. result = checker.check(*formula);
  79. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::Sylvan>(model->getReachableStates(), model->getInitialStates()));
  80. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan, double>();
  81. EXPECT_NEAR(0, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  82. EXPECT_NEAR(0, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  83. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [F \"elected\"]");
  84. result = checker.check(*formula);
  85. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::Sylvan>(model->getReachableStates(), model->getInitialStates()));
  86. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan>& quantitativeResult5 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan, double>();
  87. EXPECT_NEAR(5.034920501133386, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  88. EXPECT_NEAR(5.034920501133386, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  89. }
  90. TEST(SymbolicMdpPrctlModelCheckerTest, CSMA_Cudd) {
  91. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/performance/builder/csma3_2.nm");
  92. // A parser that we use for conveniently constructing the formulas.
  93. storm::parser::FormulaParser formulaParser(program);
  94. // Build the die model with its reward model.
  95. #ifdef WINDOWS
  96. storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options;
  97. #else
  98. typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD>::Options options;
  99. #endif
  100. options.buildAllRewardModels = false;
  101. options.rewardModelsToBuild.insert("time");
  102. storm::builder::DdPrismModelBuilder<storm::dd::DdType::CUDD> builder;
  103. std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::CUDD>> model = builder.translateProgram(program, options);
  104. storm::prism::Program translatedProgram = builder.getTranslatedProgram();
  105. EXPECT_EQ(36850ul, model->getNumberOfStates());
  106. EXPECT_EQ(55862ul, model->getNumberOfTransitions());
  107. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  108. std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::CUDD>>();
  109. storm::modelchecker::SymbolicMdpPrctlModelChecker<storm::dd::DdType::CUDD, double> checker(*mdp, std::unique_ptr<storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>>(new storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::CUDD, double>()));
  110. std::shared_ptr<const storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [ !\"collision_max_backoff\" U \"all_delivered\" ]");
  111. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
  112. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates()));
  113. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD, double>();
  114. EXPECT_NEAR(0.4349662650631545, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  115. EXPECT_NEAR(0.4349662650631545, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  116. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [ F (min_backoff_after_success < 4) ]");
  117. formula = formula->substitute(translatedProgram.getConstantsSubstitution());
  118. result = checker.check(*formula);
  119. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates()));
  120. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD, double>();
  121. EXPECT_NEAR(1, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  122. EXPECT_NEAR(1, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  123. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [ F \"all_delivered\" ]");
  124. result = checker.check(*formula);
  125. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::CUDD>(model->getReachableStates(), model->getInitialStates()));
  126. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD>& quantitativeResult5 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::CUDD, double>();
  127. EXPECT_NEAR(93.624085091252454, quantitativeResult5.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  128. EXPECT_NEAR(93.624085091252454, quantitativeResult5.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  129. }
  130. TEST(SymbolicMdpPrctlModelCheckerTest, CSMA_Sylvan) {
  131. storm::prism::Program program = storm::parser::PrismParser::parse(STORM_CPP_TESTS_BASE_PATH "/performance/builder/csma3_2.nm");
  132. // A parser that we use for conveniently constructing the formulas.
  133. storm::parser::FormulaParser formulaParser(program);
  134. // Build the die model with its reward model.
  135. #ifdef WINDOWS
  136. storm::builder::DdPrismModelBuilder<storm::dd::DdType::Sylvan>::Options options;
  137. #else
  138. typename storm::builder::DdPrismModelBuilder<storm::dd::DdType::Sylvan>::Options options;
  139. #endif
  140. options.buildAllRewardModels = false;
  141. options.rewardModelsToBuild.insert("time");
  142. storm::builder::DdPrismModelBuilder<storm::dd::DdType::Sylvan> builder;
  143. std::shared_ptr<storm::models::symbolic::Model<storm::dd::DdType::Sylvan>> model = builder.translateProgram(program, options);
  144. storm::prism::Program translatedProgram = builder.getTranslatedProgram();
  145. EXPECT_EQ(36850ul, model->getNumberOfStates());
  146. EXPECT_EQ(55862ul, model->getNumberOfTransitions());
  147. ASSERT_EQ(model->getType(), storm::models::ModelType::Mdp);
  148. std::shared_ptr<storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan>> mdp = model->as<storm::models::symbolic::Mdp<storm::dd::DdType::Sylvan>>();
  149. storm::modelchecker::SymbolicMdpPrctlModelChecker<storm::dd::DdType::Sylvan, double> checker(*mdp, std::unique_ptr<storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::Sylvan, double>>(new storm::utility::solver::SymbolicMinMaxLinearEquationSolverFactory<storm::dd::DdType::Sylvan, double>()));
  150. std::shared_ptr<const storm::logic::Formula> formula = formulaParser.parseSingleFormulaFromString("Pmin=? [ !\"collision_max_backoff\" U \"all_delivered\" ]");
  151. std::unique_ptr<storm::modelchecker::CheckResult> result = checker.check(*formula);
  152. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::Sylvan>(model->getReachableStates(), model->getInitialStates()));
  153. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan>& quantitativeResult1 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan, double>();
  154. EXPECT_NEAR(0.4349666248753522, quantitativeResult1.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  155. EXPECT_NEAR(0.4349666248753522, quantitativeResult1.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  156. formula = formulaParser.parseSingleFormulaFromString("Pmin=? [ F (min_backoff_after_success < 4) ]");
  157. formula = formula->substitute(translatedProgram.getConstantsSubstitution());
  158. result = checker.check(*formula);
  159. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::Sylvan>(model->getReachableStates(), model->getInitialStates()));
  160. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan>& quantitativeResult3 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan, double>();
  161. EXPECT_NEAR(1, quantitativeResult3.getMin(), storm::settings::nativeEquationSolverSettings().getPrecision());
  162. EXPECT_NEAR(1, quantitativeResult3.getMax(), storm::settings::nativeEquationSolverSettings().getPrecision());
  163. formula = formulaParser.parseSingleFormulaFromString("Rmin=? [ F \"all_delivered\" ]");
  164. result = checker.check(*formula);
  165. result->filter(storm::modelchecker::SymbolicQualitativeCheckResult<storm::dd::DdType::Sylvan>(model->getReachableStates(), model->getInitialStates()));
  166. storm::modelchecker::SymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan>& quantitativeResult5 = result->asSymbolicQuantitativeCheckResult<storm::dd::DdType::Sylvan, double>();
  167. // FIXME: not optimal precision.
  168. EXPECT_NEAR(93.624117712294478, quantitativeResult5.getMin(), 100 * storm::settings::nativeEquationSolverSettings().getPrecision());
  169. EXPECT_NEAR(93.624117712294478, quantitativeResult5.getMax(), 100 * storm::settings::nativeEquationSolverSettings().getPrecision());
  170. }