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.

264 lines
18 KiB

  1. #include "gtest/gtest.h"
  2. #include "storm-config.h"
  3. #ifdef STORM_HAVE_CARL
  4. #include "src/adapters/CarlAdapter.h"
  5. #include<carl/numbers/numbers.h>
  6. #include<carl/core/VariablePool.h>
  7. #include "src/settings/SettingsManager.h"
  8. #include "src/settings/modules/GeneralSettings.h"
  9. #include "utility/storm.h"
  10. #include "utility/ModelInstantiator.h"
  11. #include "src/models/sparse/Model.h"
  12. #include "src/models/sparse/Dtmc.h"
  13. #include "src/models/sparse/Mdp.h"
  14. TEST(ModelInstantiatorTest, BrpProb) {
  15. carl::VariablePool::getInstance().clear();
  16. std::string programFile = STORM_CPP_TESTS_BASE_PATH "/functional/utility/brp16_2.pm";
  17. std::string formulaAsString = "P=? [F s=5 ]";
  18. std::string constantsAsString = ""; //e.g. pL=0.9,TOACK=0.5
  19. // Program and formula
  20. storm::prism::Program program = storm::parseProgram(programFile);
  21. program.checkValidity();
  22. std::vector<std::shared_ptr<storm::logic::Formula>> formulas = storm::parseFormulasForProgram(formulaAsString, program);
  23. ASSERT_TRUE(formulas.size()==1);
  24. // Parametric model
  25. typename storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options options = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options(*formulas[0]);
  26. options.addConstantDefinitionsFromString(program, constantsAsString);
  27. options.preserveFormula(*formulas[0]);
  28. std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>(program, options).translate()->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
  29. storm::utility::ModelInstantiator<storm::models::sparse::Dtmc<storm::RationalFunction>, storm::models::sparse::Dtmc<double>> modelInstantiator(*dtmc);
  30. EXPECT_FALSE(dtmc->hasRewardModel());
  31. {
  32. std::map<storm::Variable, storm::RationalNumber> valuation;
  33. storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL");
  34. ASSERT_NE(pL, carl::Variable::NO_VARIABLE);
  35. storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK");
  36. ASSERT_NE(pK, carl::Variable::NO_VARIABLE);
  37. valuation.insert(std::make_pair(pL,carl::rationalize<storm::RationalNumber>(0.8)));
  38. valuation.insert(std::make_pair(pK,carl::rationalize<storm::RationalNumber>(0.9)));
  39. storm::models::sparse::Dtmc<double> const& instantiated(modelInstantiator.instantiate(valuation));
  40. ASSERT_EQ(dtmc->getTransitionMatrix().getRowGroupIndices(), instantiated.getTransitionMatrix().getRowGroupIndices());
  41. for(std::size_t rowGroup = 0; rowGroup < dtmc->getTransitionMatrix().getRowGroupCount(); ++rowGroup){
  42. for(std::size_t row = dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup]; row < dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup+1]; ++row){
  43. auto instantiatedEntry = instantiated.getTransitionMatrix().getRow(row).begin();
  44. for(auto const& paramEntry : dtmc->getTransitionMatrix().getRow(row)){
  45. EXPECT_EQ(paramEntry.getColumn(), instantiatedEntry->getColumn());
  46. double evaluatedValue = carl::toDouble(paramEntry.getValue().evaluate(valuation));
  47. EXPECT_EQ(evaluatedValue, instantiatedEntry->getValue());
  48. ++instantiatedEntry;
  49. }
  50. EXPECT_EQ(instantiated.getTransitionMatrix().getRow(row).end(),instantiatedEntry);
  51. }
  52. }
  53. EXPECT_EQ(dtmc->getStateLabeling(), instantiated.getStateLabeling());
  54. EXPECT_EQ(dtmc->getOptionalChoiceLabeling(), instantiated.getOptionalChoiceLabeling());
  55. storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> modelchecker(instantiated);
  56. std::unique_ptr<storm::modelchecker::CheckResult> chkResult = modelchecker.check(*formulas[0]);
  57. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeChkResult = chkResult->asExplicitQuantitativeCheckResult<double>();
  58. EXPECT_NEAR(0.2989278941, quantitativeChkResult[*instantiated.getInitialStates().begin()], storm::settings::generalSettings().getPrecision());
  59. }
  60. {
  61. std::map<storm::Variable, storm::RationalNumber> valuation;
  62. storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL");
  63. ASSERT_NE(pL, carl::Variable::NO_VARIABLE);
  64. storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK");
  65. ASSERT_NE(pK, carl::Variable::NO_VARIABLE);
  66. valuation.insert(std::make_pair(pL,carl::rationalize<storm::RationalNumber>(1.0)));
  67. valuation.insert(std::make_pair(pK,carl::rationalize<storm::RationalNumber>(1.0)));
  68. storm::models::sparse::Dtmc<double> const& instantiated(modelInstantiator.instantiate(valuation));
  69. ASSERT_EQ(dtmc->getTransitionMatrix().getRowGroupIndices(), instantiated.getTransitionMatrix().getRowGroupIndices());
  70. for(std::size_t rowGroup = 0; rowGroup < dtmc->getTransitionMatrix().getRowGroupCount(); ++rowGroup){
  71. for(std::size_t row = dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup]; row < dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup+1]; ++row){
  72. auto instantiatedEntry = instantiated.getTransitionMatrix().getRow(row).begin();
  73. for(auto const& paramEntry : dtmc->getTransitionMatrix().getRow(row)){
  74. EXPECT_EQ(paramEntry.getColumn(), instantiatedEntry->getColumn());
  75. double evaluatedValue = carl::toDouble(paramEntry.getValue().evaluate(valuation));
  76. EXPECT_EQ(evaluatedValue, instantiatedEntry->getValue());
  77. ++instantiatedEntry;
  78. }
  79. EXPECT_EQ(instantiated.getTransitionMatrix().getRow(row).end(),instantiatedEntry);
  80. }
  81. }
  82. EXPECT_EQ(dtmc->getStateLabeling(), instantiated.getStateLabeling());
  83. EXPECT_EQ(dtmc->getOptionalChoiceLabeling(), instantiated.getOptionalChoiceLabeling());
  84. storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> modelchecker(instantiated);
  85. std::unique_ptr<storm::modelchecker::CheckResult> chkResult = modelchecker.check(*formulas[0]);
  86. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeChkResult = chkResult->asExplicitQuantitativeCheckResult<double>();
  87. EXPECT_EQ(0.0 , quantitativeChkResult[*instantiated.getInitialStates().begin()]);
  88. }
  89. {
  90. std::map<storm::Variable, storm::RationalNumber> valuation;
  91. storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL");
  92. ASSERT_NE(pL, carl::Variable::NO_VARIABLE);
  93. storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK");
  94. ASSERT_NE(pK, carl::Variable::NO_VARIABLE);
  95. valuation.insert(std::make_pair(pL,carl::rationalize<storm::RationalNumber>(1.0)));
  96. valuation.insert(std::make_pair(pK,carl::rationalize<storm::RationalNumber>(0.9)));
  97. storm::models::sparse::Dtmc<double> const& instantiated(modelInstantiator.instantiate(valuation));
  98. ASSERT_EQ(dtmc->getTransitionMatrix().getRowGroupIndices(), instantiated.getTransitionMatrix().getRowGroupIndices());
  99. for(std::size_t rowGroup = 0; rowGroup < dtmc->getTransitionMatrix().getRowGroupCount(); ++rowGroup){
  100. for(std::size_t row = dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup]; row < dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup+1]; ++row){
  101. auto instantiatedEntry = instantiated.getTransitionMatrix().getRow(row).begin();
  102. for(auto const& paramEntry : dtmc->getTransitionMatrix().getRow(row)){
  103. EXPECT_EQ(paramEntry.getColumn(), instantiatedEntry->getColumn());
  104. double evaluatedValue = carl::toDouble(paramEntry.getValue().evaluate(valuation));
  105. EXPECT_EQ(evaluatedValue, instantiatedEntry->getValue());
  106. ++instantiatedEntry;
  107. }
  108. EXPECT_EQ(instantiated.getTransitionMatrix().getRow(row).end(),instantiatedEntry);
  109. }
  110. }
  111. EXPECT_EQ(dtmc->getStateLabeling(), instantiated.getStateLabeling());
  112. EXPECT_EQ(dtmc->getOptionalChoiceLabeling(), instantiated.getOptionalChoiceLabeling());
  113. storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> modelchecker(instantiated);
  114. std::unique_ptr<storm::modelchecker::CheckResult> chkResult = modelchecker.check(*formulas[0]);
  115. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeChkResult = chkResult->asExplicitQuantitativeCheckResult<double>();
  116. EXPECT_NEAR(0.01588055832, quantitativeChkResult[*instantiated.getInitialStates().begin()], storm::settings::generalSettings().getPrecision());
  117. }
  118. }
  119. TEST(ModelInstantiatorTest, Brp_Rew) {
  120. carl::VariablePool::getInstance().clear();
  121. std::string programFile = STORM_CPP_TESTS_BASE_PATH "/functional/utility/brp16_2.pm";
  122. std::string formulaAsString = "R=? [F ((s=5) | (s=0&srep=3)) ]";
  123. std::string constantsAsString = ""; //e.g. pL=0.9,TOACK=0.5
  124. // Program and formula
  125. storm::prism::Program program = storm::parseProgram(programFile);
  126. program.checkValidity();
  127. std::vector<std::shared_ptr<storm::logic::Formula>> formulas = storm::parseFormulasForProgram(formulaAsString, program);
  128. ASSERT_TRUE(formulas.size()==1);
  129. // Parametric model
  130. typename storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options options = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options(*formulas[0]);
  131. options.addConstantDefinitionsFromString(program, constantsAsString);
  132. options.preserveFormula(*formulas[0]);
  133. std::shared_ptr<storm::models::sparse::Dtmc<storm::RationalFunction>> dtmc = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>(program, options).translate()->as<storm::models::sparse::Dtmc<storm::RationalFunction>>();
  134. storm::utility::ModelInstantiator<storm::models::sparse::Dtmc<storm::RationalFunction>, storm::models::sparse::Dtmc<double>> modelInstantiator(*dtmc);
  135. {
  136. std::map<storm::Variable, storm::RationalNumber> valuation;
  137. storm::Variable const& pL = carl::VariablePool::getInstance().findVariableWithName("pL");
  138. ASSERT_NE(pL, carl::Variable::NO_VARIABLE);
  139. storm::Variable const& pK = carl::VariablePool::getInstance().findVariableWithName("pK");
  140. ASSERT_NE(pK, carl::Variable::NO_VARIABLE);
  141. storm::Variable const& TOMsg = carl::VariablePool::getInstance().findVariableWithName("TOMsg");
  142. ASSERT_NE(pK, carl::Variable::NO_VARIABLE);
  143. storm::Variable const& TOAck = carl::VariablePool::getInstance().findVariableWithName("TOAck");
  144. ASSERT_NE(pK, carl::Variable::NO_VARIABLE);
  145. valuation.insert(std::make_pair(pL,carl::rationalize<storm::RationalNumber>(0.9)));
  146. valuation.insert(std::make_pair(pK,carl::rationalize<storm::RationalNumber>(0.3)));
  147. valuation.insert(std::make_pair(TOMsg,carl::rationalize<storm::RationalNumber>(0.3)));
  148. valuation.insert(std::make_pair(TOAck,carl::rationalize<storm::RationalNumber>(0.5)));
  149. storm::models::sparse::Dtmc<double> const& instantiated(modelInstantiator.instantiate(valuation));
  150. ASSERT_EQ(dtmc->getTransitionMatrix().getRowGroupIndices(), instantiated.getTransitionMatrix().getRowGroupIndices());
  151. for(std::size_t rowGroup = 0; rowGroup < dtmc->getTransitionMatrix().getRowGroupCount(); ++rowGroup){
  152. for(std::size_t row = dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup]; row < dtmc->getTransitionMatrix().getRowGroupIndices()[rowGroup+1]; ++row){
  153. auto instantiatedEntry = instantiated.getTransitionMatrix().getRow(row).begin();
  154. for(auto const& paramEntry : dtmc->getTransitionMatrix().getRow(row)){
  155. EXPECT_EQ(paramEntry.getColumn(), instantiatedEntry->getColumn());
  156. double evaluatedValue = carl::toDouble(paramEntry.getValue().evaluate(valuation));
  157. EXPECT_EQ(evaluatedValue, instantiatedEntry->getValue());
  158. ++instantiatedEntry;
  159. }
  160. EXPECT_EQ(instantiated.getTransitionMatrix().getRow(row).end(),instantiatedEntry);
  161. }
  162. }
  163. ASSERT_TRUE(instantiated.hasUniqueRewardModel());
  164. EXPECT_FALSE(instantiated.getUniqueRewardModel()->second.hasStateRewards());
  165. EXPECT_FALSE(instantiated.getUniqueRewardModel()->second.hasTransitionRewards());
  166. EXPECT_TRUE(instantiated.getUniqueRewardModel()->second.hasStateActionRewards());
  167. ASSERT_TRUE(dtmc->getUniqueRewardModel()->second.hasStateActionRewards());
  168. std::size_t stateActionEntries = dtmc->getUniqueRewardModel()->second.getStateActionRewardVector().size();
  169. ASSERT_EQ(stateActionEntries, instantiated.getUniqueRewardModel()->second.getStateActionRewardVector().size());
  170. for(std::size_t i =0; i<stateActionEntries; ++i){
  171. double evaluatedValue = carl::toDouble(dtmc->getUniqueRewardModel()->second.getStateActionRewardVector()[i].evaluate(valuation));
  172. EXPECT_EQ(evaluatedValue, instantiated.getUniqueRewardModel()->second.getStateActionRewardVector()[i]);
  173. }
  174. EXPECT_EQ(dtmc->getStateLabeling(), instantiated.getStateLabeling());
  175. EXPECT_EQ(dtmc->getOptionalChoiceLabeling(), instantiated.getOptionalChoiceLabeling());
  176. storm::modelchecker::SparseDtmcPrctlModelChecker<storm::models::sparse::Dtmc<double>> modelchecker(instantiated);
  177. std::unique_ptr<storm::modelchecker::CheckResult> chkResult = modelchecker.check(*formulas[0]);
  178. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeChkResult = chkResult->asExplicitQuantitativeCheckResult<double>();
  179. EXPECT_NEAR(1.308324495, quantitativeChkResult[*instantiated.getInitialStates().begin()], storm::settings::generalSettings().getPrecision());
  180. }
  181. }
  182. TEST(ModelInstantiatorTest, Consensus) {
  183. carl::VariablePool::getInstance().clear();
  184. std::string programFile = STORM_CPP_TESTS_BASE_PATH "/functional/utility/coin2_2.pm";
  185. std::string formulaAsString = "Pmin=? [F \"finished\"&\"all_coins_equal_1\" ]";
  186. std::string constantsAsString = ""; //e.g. pL=0.9,TOACK=0.5
  187. // Program and formula
  188. storm::prism::Program program = storm::parseProgram(programFile);
  189. program.checkValidity();
  190. std::vector<std::shared_ptr<storm::logic::Formula>> formulas = storm::parseFormulasForProgram(formulaAsString, program);
  191. ASSERT_TRUE(formulas.size()==1);
  192. // Parametric model
  193. typename storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options options = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>::Options(*formulas[0]);
  194. options.addConstantDefinitionsFromString(program, constantsAsString);
  195. options.preserveFormula(*formulas[0]);
  196. std::shared_ptr<storm::models::sparse::Mdp<storm::RationalFunction>> mdp = storm::builder::ExplicitPrismModelBuilder<storm::RationalFunction>(program, options).translate()->as<storm::models::sparse::Mdp<storm::RationalFunction>>();
  197. storm::utility::ModelInstantiator<storm::models::sparse::Mdp<storm::RationalFunction>, storm::models::sparse::Mdp<double>> modelInstantiator(*mdp);
  198. std::map<storm::Variable, storm::RationalNumber> valuation;
  199. storm::Variable const& p1 = carl::VariablePool::getInstance().findVariableWithName("p1");
  200. ASSERT_NE(p1, carl::Variable::NO_VARIABLE);
  201. storm::Variable const& p2 = carl::VariablePool::getInstance().findVariableWithName("p2");
  202. ASSERT_NE(p2, carl::Variable::NO_VARIABLE);
  203. valuation.insert(std::make_pair(p1,carl::rationalize<storm::RationalNumber>(0.51)));
  204. valuation.insert(std::make_pair(p2,carl::rationalize<storm::RationalNumber>(0.49)));
  205. storm::models::sparse::Mdp<double> const& instantiated(modelInstantiator.instantiate(valuation));
  206. ASSERT_EQ(mdp->getTransitionMatrix().getRowGroupIndices(), instantiated.getTransitionMatrix().getRowGroupIndices());
  207. for(std::size_t rowGroup = 0; rowGroup < mdp->getTransitionMatrix().getRowGroupCount(); ++rowGroup){
  208. for(std::size_t row = mdp->getTransitionMatrix().getRowGroupIndices()[rowGroup]; row < mdp->getTransitionMatrix().getRowGroupIndices()[rowGroup+1]; ++row){
  209. auto instantiatedEntry = instantiated.getTransitionMatrix().getRow(row).begin();
  210. for(auto const& paramEntry : mdp->getTransitionMatrix().getRow(row)){
  211. EXPECT_EQ(paramEntry.getColumn(), instantiatedEntry->getColumn());
  212. double evaluatedValue = carl::toDouble(paramEntry.getValue().evaluate(valuation));
  213. EXPECT_EQ(evaluatedValue, instantiatedEntry->getValue());
  214. ++instantiatedEntry;
  215. }
  216. EXPECT_EQ(instantiated.getTransitionMatrix().getRow(row).end(),instantiatedEntry);
  217. }
  218. }
  219. EXPECT_EQ(mdp->getStateLabeling(), instantiated.getStateLabeling());
  220. EXPECT_EQ(mdp->getOptionalChoiceLabeling(), instantiated.getOptionalChoiceLabeling());
  221. storm::modelchecker::SparseMdpPrctlModelChecker<storm::models::sparse::Mdp<double>> modelchecker(instantiated);
  222. std::unique_ptr<storm::modelchecker::CheckResult> chkResult = modelchecker.check(*formulas[0]);
  223. storm::modelchecker::ExplicitQuantitativeCheckResult<double>& quantitativeChkResult = chkResult->asExplicitQuantitativeCheckResult<double>();
  224. EXPECT_NEAR(0.3526577219, quantitativeChkResult[*instantiated.getInitialStates().begin()], storm::settings::generalSettings().getPrecision());
  225. }
  226. #endif