Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseMdpInstantiationModelChecker.cpp
Go to the documentation of this file.
2
13#include "storm/utility/graph.h"
15
16namespace storm {
17namespace modelchecker {
18
19template<typename SparseModelType, typename ConstantType>
21 bool produceScheduler)
22 : SparseInstantiationModelChecker<SparseModelType, ConstantType>(parametricModel), modelInstantiator(parametricModel), produceScheduler(produceScheduler) {
23 // Intentionally left empty
24}
25
26template<typename SparseModelType, typename ConstantType>
29 STORM_LOG_THROW(this->currentCheckTask, storm::exceptions::InvalidStateException, "Checking has been invoked but no property has been specified before.");
30
31 auto const& instantiatedModel = modelInstantiator.instantiate(valuation);
32 if (instantiatedModel.isExact()) {
33 STORM_LOG_THROW(instantiatedModel.getTransitionMatrix().isProbabilistic(storm::utility::zero<ConstantType>()),
34 storm::exceptions::InvalidArgumentException, "Instantiation point is invalid as the transition matrix becomes non-stochastic.");
35 } else {
36 auto const& generalSettings = storm::settings::getModule<storm::settings::modules::GeneralSettings>();
37 STORM_LOG_THROW(instantiatedModel.getTransitionMatrix().isProbabilistic(storm::utility::convertNumber<ConstantType>(generalSettings.getPrecision())),
38 storm::exceptions::InvalidArgumentException, "Instantiation point is invalid as the transition matrix becomes non-stochastic.");
39 }
40
42
43 // Check if there are some optimizations implemented for the specified property
44 if (this->currentCheckTask->getFormula().isInFragment(storm::logic::reachability())) {
45 return checkReachabilityProbabilityFormula(env, modelChecker, instantiatedModel);
46 } else if (this->currentCheckTask->getFormula().isInFragment(storm::logic::propositional()
51 return checkReachabilityRewardFormula(env, modelChecker, instantiatedModel);
52 } else if (this->currentCheckTask->getFormula().isInFragment(storm::logic::propositional()
59 return checkBoundedUntilFormula(env, modelChecker);
60 } else {
61 return modelChecker.check(env, *this->currentCheckTask);
62 }
63}
64
65template<typename SparseModelType, typename ConstantType>
68 storm::models::sparse::Mdp<ConstantType> const& instantiatedModel) {
69 if (produceScheduler) {
70 this->currentCheckTask->setProduceSchedulers(true);
71 }
72
73 if (!this->currentCheckTask->getHint().isExplicitModelCheckerHint()) {
74 this->currentCheckTask->setHint(std::make_shared<ExplicitModelCheckerHint<ConstantType>>());
75 }
76 ExplicitModelCheckerHint<ConstantType>& hint = this->currentCheckTask->getHint().template asExplicitModelCheckerHint<ConstantType>();
77
78 if (this->getInstantiationsAreGraphPreserving() && !hint.hasMaybeStates()) {
79 // Perform purely qualitative analysis once
80 std::vector<ConstantType> qualitativeResult;
81 if (this->currentCheckTask->getFormula().asOperatorFormula().hasQuantitativeResult()) {
82 auto newCheckTask = *this->currentCheckTask;
83 newCheckTask.setQualitative(true);
84 newCheckTask.setOnlyInitialStatesRelevant(false);
85 newCheckTask.setProduceSchedulers(false);
86 qualitativeResult = modelChecker.check(env, newCheckTask)->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector();
87 } else {
88 auto newCheckTask = this->currentCheckTask->substituteFormula(this->currentCheckTask->getFormula().asOperatorFormula().getSubformula());
89 newCheckTask.setQualitative(true);
90 newCheckTask.setOnlyInitialStatesRelevant(false);
91 newCheckTask.setProduceSchedulers(false);
92 qualitativeResult =
93 modelChecker.computeProbabilities(env, newCheckTask)->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector();
94 }
95 storm::storage::BitVector maybeStates = storm::utility::vector::filter<ConstantType>(qualitativeResult, [](ConstantType const& value) -> bool {
96 return !(storm::utility::isZero<ConstantType>(value) || storm::utility::isOne<ConstantType>(value));
97 });
98 hint.setMaybeStates(std::move(maybeStates));
99 hint.setResultHint(std::move(qualitativeResult));
100 hint.setComputeOnlyMaybeStates(true);
101
102 // Check if there can be end components within the maybestates
103 if (storm::solver::minimize(this->currentCheckTask->getOptimizationDirection()) ||
104 storm::utility::graph::performProb1A(instantiatedModel.getTransitionMatrix(), instantiatedModel.getTransitionMatrix().getRowGroupIndices(),
105 instantiatedModel.getBackwardTransitions(), hint.getMaybeStates(), ~hint.getMaybeStates())
106 .full()) {
108 }
109 }
110
111 std::unique_ptr<CheckResult> result;
112 // Check the formula and store the result as a hint for the next call.
113 // For qualitative properties, we still want a quantitative result hint. Hence we perform the check on the subformula
114 if (this->currentCheckTask->getFormula().asOperatorFormula().hasQuantitativeResult()) {
115 result = modelChecker.check(env, *this->currentCheckTask);
116 hint.setResultHint(result->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector());
117 if (produceScheduler) {
118 storm::storage::Scheduler<ConstantType> const& scheduler = result->template asExplicitQuantitativeCheckResult<ConstantType>().getScheduler();
119 hint.setSchedulerHint(dynamic_cast<storm::storage::Scheduler<ConstantType> const&>(scheduler));
120 }
121 } else {
122 auto newCheckTask = this->currentCheckTask->substituteFormula(this->currentCheckTask->getFormula().asOperatorFormula().getSubformula())
123 .setOnlyInitialStatesRelevant(false);
124 std::unique_ptr<storm::modelchecker::CheckResult> quantitativeResult = modelChecker.computeProbabilities(env, newCheckTask);
125 result = quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().compareAgainstBound(
126 this->currentCheckTask->getFormula().asOperatorFormula().getComparisonType(),
127 this->currentCheckTask->getFormula().asOperatorFormula().template getThresholdAs<ConstantType>());
128 hint.setResultHint(std::move(quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector()));
129 if (produceScheduler) {
130 storm::storage::Scheduler<ConstantType>& scheduler = quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().getScheduler();
131 hint.setSchedulerHint(std::move(dynamic_cast<storm::storage::Scheduler<ConstantType>&>(scheduler)));
132 }
133 }
134
135 return result;
136}
137
138template<typename SparseModelType, typename ConstantType>
141 storm::models::sparse::Mdp<ConstantType> const& instantiatedModel) {
142 this->currentCheckTask->setProduceSchedulers(true);
143
144 if (!this->currentCheckTask->getHint().isExplicitModelCheckerHint()) {
145 this->currentCheckTask->setHint(std::make_shared<ExplicitModelCheckerHint<ConstantType>>());
146 }
147 ExplicitModelCheckerHint<ConstantType>& hint = this->currentCheckTask->getHint().template asExplicitModelCheckerHint<ConstantType>();
148
149 if (this->getInstantiationsAreGraphPreserving() && !hint.hasMaybeStates()) {
150 // Perform purely qualitative analysis once
151 std::vector<ConstantType> qualitativeResult;
152 if (this->currentCheckTask->getFormula().asOperatorFormula().hasQuantitativeResult()) {
153 auto newCheckTask = *this->currentCheckTask;
154 newCheckTask.setQualitative(true);
155 newCheckTask.setOnlyInitialStatesRelevant(false);
156 newCheckTask.setProduceSchedulers(false);
157 qualitativeResult = modelChecker.check(env, newCheckTask)->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector();
158 } else {
159 auto newCheckTask = this->currentCheckTask->substituteFormula(this->currentCheckTask->getFormula().asOperatorFormula().getSubformula());
160 newCheckTask.setQualitative(true);
161 newCheckTask.setOnlyInitialStatesRelevant(false);
162 newCheckTask.setProduceSchedulers(false);
163 qualitativeResult = modelChecker.computeRewards(env, newCheckTask)->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector();
164 }
165 storm::storage::BitVector maybeStates = storm::utility::vector::filter<ConstantType>(qualitativeResult, [](ConstantType const& value) -> bool {
166 return !(storm::utility::isZero<ConstantType>(value) || storm::utility::isInfinity<ConstantType>(value));
167 });
168 hint.setMaybeStates(std::move(maybeStates));
169 hint.setResultHint(std::move(qualitativeResult));
170 hint.setComputeOnlyMaybeStates(true);
171
172 // Check if there can be end components within the maybestates
173 if (storm::solver::maximize(this->currentCheckTask->getOptimizationDirection()) ||
174 storm::utility::graph::performProb1A(instantiatedModel.getTransitionMatrix(), instantiatedModel.getTransitionMatrix().getRowGroupIndices(),
175 instantiatedModel.getBackwardTransitions(), hint.getMaybeStates(), ~hint.getMaybeStates())
176 .full()) {
178 }
179 }
180
181 std::unique_ptr<CheckResult> result;
182 // Check the formula and store the result as a hint for the next call.
183 // For qualitative properties, we still want a quantitative result hint. Hence we perform the check on the subformula
184 if (this->currentCheckTask->getFormula().asOperatorFormula().hasQuantitativeResult()) {
185 result = modelChecker.check(env, *this->currentCheckTask);
186 storm::storage::Scheduler<ConstantType> const& scheduler = result->template asExplicitQuantitativeCheckResult<ConstantType>().getScheduler();
187 hint.setResultHint(result->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector());
188 hint.setSchedulerHint(dynamic_cast<storm::storage::Scheduler<ConstantType> const&>(scheduler));
189 } else {
190 auto newCheckTask = this->currentCheckTask->substituteFormula(this->currentCheckTask->getFormula().asOperatorFormula().getSubformula())
191 .setOnlyInitialStatesRelevant(false);
192 std::unique_ptr<storm::modelchecker::CheckResult> quantitativeResult = modelChecker.computeRewards(env, newCheckTask);
193 result = quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().compareAgainstBound(
194 this->currentCheckTask->getFormula().asOperatorFormula().getComparisonType(),
195 this->currentCheckTask->getFormula().asOperatorFormula().template getThresholdAs<ConstantType>());
196 storm::storage::Scheduler<ConstantType>& scheduler = quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().getScheduler();
197 hint.setResultHint(std::move(quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector()));
198 hint.setSchedulerHint(std::move(dynamic_cast<storm::storage::Scheduler<ConstantType>&>(scheduler)));
199 }
200
201 return result;
202}
203
204template<typename SparseModelType, typename ConstantType>
207 if (!this->currentCheckTask->getHint().isExplicitModelCheckerHint()) {
208 this->currentCheckTask->setHint(std::make_shared<ExplicitModelCheckerHint<ConstantType>>());
209 }
210 std::unique_ptr<CheckResult> result;
211 ExplicitModelCheckerHint<ConstantType>& hint = this->currentCheckTask->getHint().template asExplicitModelCheckerHint<ConstantType>();
212
213 if (this->getInstantiationsAreGraphPreserving() && !hint.hasMaybeStates()) {
214 // We extract the maybestates from the quantitative result
215 // For qualitative properties, we still need a quantitative result. Hence we perform the check on the subformula
216 if (this->currentCheckTask->getFormula().asOperatorFormula().hasQuantitativeResult()) {
217 result = modelChecker.check(env, *this->currentCheckTask);
218 hint.setResultHint(result->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector());
219 } else {
220 auto newCheckTask = this->currentCheckTask->substituteFormula(this->currentCheckTask->getFormula().asOperatorFormula().getSubformula())
221 .setOnlyInitialStatesRelevant(false);
222 std::unique_ptr<CheckResult> quantitativeResult = modelChecker.computeProbabilities(env, newCheckTask);
223 result = quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().compareAgainstBound(
224 this->currentCheckTask->getFormula().asOperatorFormula().getComparisonType(),
225 this->currentCheckTask->getFormula().asOperatorFormula().template getThresholdAs<ConstantType>());
226 hint.setResultHint(std::move(quantitativeResult->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector()));
227 }
229 // We need to exclude the target states from the maybe states.
230 // Note that we can not consider the states with probability one since a state might reach a target state with prob 1 within >0 steps
231 std::unique_ptr<CheckResult> subFormulaResult =
232 modelChecker.check(env, this->currentCheckTask->getFormula().asOperatorFormula().getSubformula().asBoundedUntilFormula().getRightSubformula());
233 maybeStates = maybeStates & ~(subFormulaResult->asExplicitQualitativeCheckResult().getTruthValuesVector());
234 hint.setMaybeStates(std::move(maybeStates));
235 hint.setComputeOnlyMaybeStates(true);
236 } else {
237 result = modelChecker.check(env, *this->currentCheckTask);
238 }
239 return result;
240}
241
242template<typename SparseModelType, typename ConstantType>
245 // TODO note that this is quite an expensive routine currently.
246 auto const& instantiatedModel = modelInstantiator.instantiate(valuation);
247 if (instantiatedModel.isExact()) {
248 return instantiatedModel.getTransitionMatrix().isProbabilistic(storm::utility::zero<ConstantType>());
249 } else {
250 auto const& generalSettings = storm::settings::getModule<storm::settings::modules::GeneralSettings>();
251 return instantiatedModel.getTransitionMatrix().isProbabilistic(storm::utility::convertNumber<ConstantType>(generalSettings.getPrecision()));
252 }
253}
254
257
258} // namespace modelchecker
259} // namespace storm
FragmentSpecification & setStepBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setOperatorAtTopLevelRequired(bool newValue)
FragmentSpecification & setTimeBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setReachabilityRewardFormulasAllowed(bool newValue)
FragmentSpecification & setRewardOperatorsAllowed(bool newValue)
FragmentSpecification & setBoundedUntilFormulasAllowed(bool newValue)
FragmentSpecification & setNestedOperatorsAllowed(bool newValue)
FragmentSpecification & setProbabilityOperatorsAllowed(bool newValue)
virtual std::unique_ptr< CheckResult > check(Environment const &env, CheckTask< storm::logic::Formula, SolutionType > const &checkTask)
Checks the provided formula.
This class contains information that might accelerate the model checking process.
void setSchedulerHint(boost::optional< storage::Scheduler< ValueType > > const &schedulerHint)
void setResultHint(boost::optional< std::vector< ValueType > > const &resultHint)
storm::storage::BitVector const & getMaybeStates() const
void setMaybeStates(storm::storage::BitVector const &maybeStates)
std::vector< ValueType > const & getResultHint() const
Class to efficiently check a formula on a parametric model with different parameter instantiations.
Class to efficiently check a formula on a parametric model with different parameter instantiations.
std::unique_ptr< CheckResult > checkReachabilityProbabilityFormula(Environment const &env, storm::modelchecker::SparseMdpPrctlModelChecker< storm::models::sparse::Mdp< ConstantType > > &modelChecker, storm::models::sparse::Mdp< ConstantType > const &instantiatedModel)
virtual std::unique_ptr< CheckResult > check(Environment const &env, storm::utility::parametric::Valuation< typename SparseModelType::ValueType > const &valuation) override
std::unique_ptr< CheckResult > checkBoundedUntilFormula(Environment const &env, storm::modelchecker::SparseMdpPrctlModelChecker< storm::models::sparse::Mdp< ConstantType > > &modelChecker)
virtual bool isWellDefined(storm::utility::parametric::Valuation< typename SparseModelType::ValueType > const &valuation) override
Checks if the given valuation is valid for the current model.
std::unique_ptr< CheckResult > checkReachabilityRewardFormula(Environment const &env, storm::modelchecker::SparseMdpPrctlModelChecker< storm::models::sparse::Mdp< ConstantType > > &modelChecker, storm::models::sparse::Mdp< ConstantType > const &instantiatedModel)
SparseMdpInstantiationModelChecker(SparseModelType const &parametricModel, bool produceScheduler=true)
This class represents a (discrete-time) Markov decision process.
Definition Mdp.h:13
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:197
storm::storage::SparseMatrix< ValueType > getBackwardTransitions() const
Retrieves the backward transition relation of the model, i.e.
Definition Model.cpp:157
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
This class defines which action is chosen in a particular state of a non-deterministic model.
Definition Scheduler.h:18
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
FragmentSpecification propositional()
FragmentSpecification reachability()
bool constexpr maximize(OptimizationDirection d)
bool constexpr minimize(OptimizationDirection d)
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
Definition graph.cpp:987
std::map< typename VariableType< FunctionType >::type, typename CoefficientType< FunctionType >::type > Valuation
Definition parametric.h:43
storm::storage::BitVector filterGreaterZero(std::vector< T > const &values)
Retrieves a bit vector containing all the indices for which the value at this position is greater tha...
Definition vector.h:512