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.

176 lines
16 KiB

  1. #include "storm/modelchecker/csl/SparseCtmcCslModelChecker.h"
  2. #include "storm/modelchecker/csl/helper/SparseCtmcCslHelper.h"
  3. #include "storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h"
  4. #include "storm/models/sparse/StandardRewardModel.h"
  5. #include "storm/utility/macros.h"
  6. #include "storm/utility/vector.h"
  7. #include "storm/utility/graph.h"
  8. #include "storm/utility/solver.h"
  9. #include "storm/utility/FilteredRewardModel.h"
  10. #include "storm/modelchecker/results/ExplicitQualitativeCheckResult.h"
  11. #include "storm/modelchecker/results/ExplicitQuantitativeCheckResult.h"
  12. #include "storm/logic/FragmentSpecification.h"
  13. #include "storm/adapters/RationalFunctionAdapter.h"
  14. #include "storm/exceptions/InvalidStateException.h"
  15. #include "storm/exceptions/InvalidPropertyException.h"
  16. #include "storm/exceptions/NotImplementedException.h"
  17. namespace storm {
  18. namespace modelchecker {
  19. template <typename SparseCtmcModelType>
  20. SparseCtmcCslModelChecker<SparseCtmcModelType>::SparseCtmcCslModelChecker(SparseCtmcModelType const& model) : SparsePropositionalModelChecker<SparseCtmcModelType>(model) {
  21. // Intentionally left empty.
  22. }
  23. template <typename ModelType>
  24. bool SparseCtmcCslModelChecker<ModelType>::canHandleStatic(CheckTask<storm::logic::Formula, ValueType> const& checkTask) {
  25. auto fragment = storm::logic::csrl().setGloballyFormulasAllowed(false).setLongRunAverageRewardFormulasAllowed(true).setLongRunAverageProbabilitiesAllowed(true).setTimeAllowed(true).setTimeOperatorsAllowed(true).setTotalRewardFormulasAllowed(true).setRewardAccumulationAllowed(true);
  26. if (!storm::NumberTraits<ValueType>::SupportsExponential) {
  27. fragment.setBoundedUntilFormulasAllowed(false).setCumulativeRewardFormulasAllowed(false).setInstantaneousFormulasAllowed(false);
  28. }
  29. return checkTask.getFormula().isInFragment(fragment);
  30. }
  31. template <typename SparseCtmcModelType>
  32. bool SparseCtmcCslModelChecker<SparseCtmcModelType>::canHandle(CheckTask<storm::logic::Formula, ValueType> const& checkTask) const {
  33. return canHandleStatic(checkTask);
  34. }
  35. template <typename SparseCtmcModelType>
  36. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeBoundedUntilProbabilities(Environment const& env, CheckTask<storm::logic::BoundedUntilFormula, ValueType> const& checkTask) {
  37. storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula();
  38. std::unique_ptr<CheckResult> leftResultPointer = this->check(env, pathFormula.getLeftSubformula());
  39. std::unique_ptr<CheckResult> rightResultPointer = this->check(env, pathFormula.getRightSubformula());
  40. ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult();;
  41. ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult();
  42. STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported.");
  43. double lowerBound = 0;
  44. double upperBound = 0;
  45. if (pathFormula.hasLowerBound()) {
  46. lowerBound = pathFormula.getLowerBound<double>();
  47. }
  48. if (pathFormula.hasUpperBound()) {
  49. upperBound = pathFormula.getNonStrictUpperBound<double>();
  50. } else {
  51. upperBound = storm::utility::infinity<double>();
  52. }
  53. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeBoundedUntilProbabilities(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), checkTask.isQualitativeSet(), lowerBound, upperBound);
  54. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  55. }
  56. template <typename SparseCtmcModelType>
  57. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeNextProbabilities(Environment const& env, CheckTask<storm::logic::NextFormula, ValueType> const& checkTask) {
  58. storm::logic::NextFormula const& pathFormula = checkTask.getFormula();
  59. std::unique_ptr<CheckResult> subResultPointer = this->check(env, pathFormula.getSubformula());
  60. ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult();
  61. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeNextProbabilities(env, this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector());
  62. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  63. }
  64. template <typename SparseCtmcModelType>
  65. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeUntilProbabilities(Environment const& env, CheckTask<storm::logic::UntilFormula, ValueType> const& checkTask) {
  66. storm::logic::UntilFormula const& pathFormula = checkTask.getFormula();
  67. std::unique_ptr<CheckResult> leftResultPointer = this->check(env, pathFormula.getLeftSubformula());
  68. std::unique_ptr<CheckResult> rightResultPointer = this->check(env, pathFormula.getRightSubformula());
  69. ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult();
  70. ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult();
  71. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeUntilProbabilities(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), checkTask.isQualitativeSet());
  72. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  73. }
  74. template <typename SparseCtmcModelType>
  75. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeInstantaneousRewards(Environment const& env, storm::logic::RewardMeasureType, CheckTask<storm::logic::InstantaneousRewardFormula, ValueType> const& checkTask) {
  76. storm::logic::InstantaneousRewardFormula const& rewardPathFormula = checkTask.getFormula();
  77. STORM_LOG_THROW(!rewardPathFormula.isStepBounded(), storm::exceptions::NotImplementedException, "Currently step-bounded properties on CTMCs are not supported.");
  78. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeInstantaneousRewards(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), checkTask.isRewardModelSet() ? this->getModel().getRewardModel(checkTask.getRewardModel()) : this->getModel().getRewardModel(""), rewardPathFormula.getBound<double>());
  79. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  80. }
  81. template <typename SparseCtmcModelType>
  82. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeCumulativeRewards(Environment const& env, storm::logic::RewardMeasureType, CheckTask<storm::logic::CumulativeRewardFormula, ValueType> const& checkTask) {
  83. storm::logic::CumulativeRewardFormula const& rewardPathFormula = checkTask.getFormula();
  84. STORM_LOG_THROW(rewardPathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded and reward-bounded properties on CTMCs are not supported.");
  85. auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask);
  86. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeCumulativeRewards(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getExitRateVector(), rewardModel.get(), rewardPathFormula.getNonStrictBound<double>());
  87. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  88. }
  89. template <typename SparseCtmcModelType>
  90. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeReachabilityRewards(Environment const& env, storm::logic::RewardMeasureType, CheckTask<storm::logic::EventuallyFormula, ValueType> const& checkTask) {
  91. storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula();
  92. std::unique_ptr<CheckResult> subResultPointer = this->check(env, eventuallyFormula.getSubformula());
  93. ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult();
  94. auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask);
  95. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityRewards(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), rewardModel.get(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet());
  96. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  97. }
  98. template<typename SparseCtmcModelType>
  99. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeTotalRewards(Environment const& env, storm::logic::RewardMeasureType, CheckTask<storm::logic::TotalRewardFormula, ValueType> const& checkTask) {
  100. auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask);
  101. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeTotalRewards(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), rewardModel.get(), checkTask.isQualitativeSet());
  102. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  103. }
  104. template <typename SparseCtmcModelType>
  105. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeLongRunAverageProbabilities(Environment const& env, CheckTask<storm::logic::StateFormula, ValueType> const& checkTask) {
  106. storm::logic::StateFormula const& stateFormula = checkTask.getFormula();
  107. std::unique_ptr<CheckResult> subResultPointer = this->check(env, stateFormula);
  108. ExplicitQualitativeCheckResult const& subResult = subResultPointer->asExplicitQualitativeCheckResult();
  109. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageProbabilities(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), subResult.getTruthValuesVector(), &this->getModel().getExitRateVector());
  110. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  111. }
  112. template <typename SparseCtmcModelType>
  113. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeLongRunAverageRewards(Environment const& env, storm::logic::RewardMeasureType rewardMeasureType, CheckTask<storm::logic::LongRunAverageRewardFormula, ValueType> const& checkTask) {
  114. auto rewardModel = storm::utility::createFilteredRewardModel(this->getModel(), checkTask);
  115. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeLongRunAverageRewards(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), rewardModel.get(), &this->getModel().getExitRateVector());
  116. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  117. }
  118. template <typename SparseCtmcModelType>
  119. std::unique_ptr<CheckResult> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeReachabilityTimes(Environment const& env, storm::logic::RewardMeasureType, CheckTask<storm::logic::EventuallyFormula, ValueType> const& checkTask) {
  120. storm::logic::EventuallyFormula const& eventuallyFormula = checkTask.getFormula();
  121. std::unique_ptr<CheckResult> subResultPointer = this->check(env, eventuallyFormula.getSubformula());
  122. ExplicitQualitativeCheckResult& subResult = subResultPointer->asExplicitQualitativeCheckResult();
  123. std::vector<ValueType> numericResult = storm::modelchecker::helper::SparseCtmcCslHelper::computeReachabilityTimes(env, storm::solver::SolveGoal<ValueType>(this->getModel(), checkTask), this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getExitRateVector(), subResult.getTruthValuesVector(), checkTask.isQualitativeSet());
  124. return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(std::move(numericResult)));
  125. }
  126. template <typename SparseCtmcModelType>
  127. std::vector<typename SparseCtmcModelType::ValueType> SparseCtmcCslModelChecker<SparseCtmcModelType>::computeAllTransientProbabilities(Environment const& env, CheckTask<storm::logic::BoundedUntilFormula, ValueType> const& checkTask) {
  128. storm::logic::BoundedUntilFormula const& pathFormula = checkTask.getFormula();
  129. STORM_LOG_THROW(pathFormula.getTimeBoundReference().isTimeBound(), storm::exceptions::NotImplementedException, "Currently step-bounded or reward-bounded properties on CTMCs are not supported.");
  130. STORM_LOG_THROW(pathFormula.hasUpperBound(), storm::exceptions::NotImplementedException, "Computation needs upper limit for time bound.");
  131. double upperBound = pathFormula.getNonStrictUpperBound<double>();
  132. std::unique_ptr<CheckResult> leftResultPointer = this->check(env, pathFormula.getLeftSubformula());
  133. std::unique_ptr<CheckResult> rightResultPointer = this->check(env, pathFormula.getRightSubformula());
  134. ExplicitQualitativeCheckResult const& leftResult = leftResultPointer->asExplicitQualitativeCheckResult();;
  135. ExplicitQualitativeCheckResult const& rightResult = rightResultPointer->asExplicitQualitativeCheckResult();
  136. std::vector<ValueType> result = storm::modelchecker::helper::SparseCtmcCslHelper::computeAllTransientProbabilities(env, this->getModel().getTransitionMatrix(), this->getModel().getInitialStates(), leftResult.getTruthValuesVector(), rightResult.getTruthValuesVector(), this->getModel().getExitRateVector(), upperBound);
  137. return result;
  138. }
  139. // Explicitly instantiate the model checker.
  140. template class SparseCtmcCslModelChecker<storm::models::sparse::Ctmc<double>>;
  141. #ifdef STORM_HAVE_CARL
  142. template class SparseCtmcCslModelChecker<storm::models::sparse::Ctmc<storm::RationalNumber>>;
  143. template class SparseCtmcCslModelChecker<storm::models::sparse::Ctmc<storm::RationalFunction>>;
  144. #endif
  145. } // namespace modelchecker
  146. } // namespace storm