Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseDtmcParameterLiftingModelChecker.cpp
Go to the documentation of this file.
2
3#include <memory>
4#include <vector>
5
33#include "storm/utility/graph.h"
37
38namespace storm {
39namespace modelchecker {
40
41template<typename SparseModelType, typename ConstantType, bool Robust>
43 : SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>(std::make_unique<GeneralSolverFactoryType<ConstantType, Robust>>()) {
44 // Intentionally left empty
45}
46
47template<typename SparseModelType, typename ConstantType, bool Robust>
49 std::unique_ptr<SolverFactoryType<ConstantType, Robust>>&& solverFactory)
50 : solverFactory(std::move(solverFactory)), solvingRequiresUpperRewardBounds(false) {
51 // Intentionally left empty
52}
53
54template<typename SparseModelType, typename ConstantType, bool Robust>
56 std::shared_ptr<storm::models::ModelBase> parametricModel, CheckTask<storm::logic::Formula, ParametricType> const& checkTask) const {
57 bool result = parametricModel->isOfType(storm::models::ModelType::Dtmc);
58 result &= parametricModel->isSparseModel();
59 result &= parametricModel->supportsParameters();
60 auto dtmc = parametricModel->template as<SparseModelType>();
61 result &= static_cast<bool>(dtmc);
62 result &= checkTask.getFormula().isInFragment(storm::logic::reachability()
63 .setRewardOperatorsAllowed(true)
64 .setReachabilityRewardFormulasAllowed(true)
65 .setBoundedUntilFormulasAllowed(true)
66 .setCumulativeRewardFormulasAllowed(true)
67 .setStepBoundedCumulativeRewardFormulasAllowed(true)
68 .setTimeBoundedCumulativeRewardFormulasAllowed(true)
69 .setTimeBoundedUntilFormulasAllowed(true)
70 .setStepBoundedUntilFormulasAllowed(true)
71 .setTimeBoundedUntilFormulasAllowed(true));
72 return result;
73}
74
75template<typename SparseModelType, typename ConstantType, bool Robust>
77 Environment const& env, std::shared_ptr<storm::models::ModelBase> parametricModel, CheckTask<storm::logic::Formula, ParametricType> const& checkTask,
78 std::optional<RegionSplitEstimateKind> generateRegionSplitEstimates, std::shared_ptr<MonotonicityBackend<ParametricType>> monotonicityBackend,
79 bool allowModelSimplifications, storm::pars::analysis::GraphPreservationStatus graphPreservationStatus) {
80 STORM_LOG_THROW(this->canHandle(parametricModel, checkTask), storm::exceptions::NotSupportedException,
81 "Combination of model " << parametricModel->getType() << " and formula '" << checkTask.getFormula() << "' is not supported.");
82 this->specifySplitEstimates(generateRegionSplitEstimates, checkTask);
84 this->graphPreservationStatus = graphPreservationStatus;
85 auto dtmc = parametricModel->template as<SparseModelType>();
86 if (isOrderBasedMonotonicityBackend()) {
87 STORM_LOG_WARN_COND(!(allowModelSimplifications),
88 "Allowing model simplification when using order-based monotonicity is not useful, as for order-based monotonicity checking model "
89 "simplification is done as preprocessing"); // TODO: Find out where this preprocessing for monotonicity is done
90 getOrderBasedMonotonicityBackend().initializeMonotonicityChecker(dtmc->getTransitionMatrix());
91 }
92
93 reset();
94
95 if (allowModelSimplifications && storm::pars::analysis::isGraphPreserving(graphPreservationStatus)) {
97 simplifier.setPreserveParametricTransitions(true);
98 STORM_LOG_THROW(simplifier.simplify(checkTask.getFormula()), storm::exceptions::UnexpectedException, "Simplifying the model was not successfull.");
99 this->parametricModel = simplifier.getSimplifiedModel();
100 this->specifyFormula(env, checkTask.substituteFormula(*simplifier.getSimplifiedFormula()));
101 } else {
102 this->parametricModel = dtmc;
103 this->specifyFormula(env, checkTask);
104 }
105 if constexpr (!Robust) {
106 if (isOrderBasedMonotonicityBackend()) {
107 getOrderBasedMonotonicityBackend().registerParameterLifterReference(*parameterLifter);
108 getOrderBasedMonotonicityBackend().registerPLABoundFunction(
110 // sets known value bounds within the region
112 });
113 }
114 }
115 std::shared_ptr<storm::logic::Formula> formulaWithoutBounds = this->currentCheckTask->getFormula().clone();
116 formulaWithoutBounds->asOperatorFormula().removeBound();
117 this->currentFormulaNoBound = formulaWithoutBounds->asSharedPointer();
118 this->currentCheckTaskNoBound = std::make_unique<storm::modelchecker::CheckTask<storm::logic::Formula, ParametricType>>(*this->currentFormulaNoBound);
120 this->derivativeChecker =
121 std::make_unique<storm::derivative::SparseDerivativeInstantiationModelChecker<ParametricType, ConstantType>>(*this->parametricModel);
122 this->derivativeChecker->specifyFormula(env, *this->currentCheckTaskNoBound);
123 }
124}
125
126template<typename SparseModelType, typename ConstantType, bool Robust>
129 STORM_LOG_ERROR_COND(!Robust, "Bounded until formulas not implemented for Robust PLA");
130 // get the step bound
131 STORM_LOG_THROW(!checkTask.getFormula().hasLowerBound(), storm::exceptions::NotSupportedException, "Lower step bounds are not supported.");
132 STORM_LOG_THROW(checkTask.getFormula().hasUpperBound(), storm::exceptions::NotSupportedException, "Expected a bounded until formula with an upper bound.");
133 STORM_LOG_THROW(checkTask.getFormula().getTimeBoundReference().isStepBound(), storm::exceptions::NotSupportedException,
134 "Expected a bounded until formula with step bounds.");
135 stepBound = checkTask.getFormula().getUpperBound().evaluateAsInt();
136 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
137 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
138 if (checkTask.getFormula().isUpperBoundStrict()) {
139 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException, "Expected a strict upper step bound that is greater than zero.");
140 --(*stepBound);
141 }
142 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
143 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
144
145 // get the results for the subformulas
147 STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) &&
148 propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()),
149 storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported.");
150 storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())
151 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
152 .getTruthValuesVector());
153 storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())
154 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
155 .getTruthValuesVector());
156
157 // get the maybeStates
158 maybeStates = storm::utility::graph::performProbGreater0(this->parametricModel->getBackwardTransitions(), phiStates, psiStates, true, *stepBound);
159 maybeStates &= ~psiStates;
160
161 // set the result for all non-maybe states
162 resultsForNonMaybeStates = std::vector<ExtendedConstantType>(this->parametricModel->getNumberOfStates(), storm::utility::zero<ConstantType>());
164
165 // if there are maybestates, create the parameterLifter
166 if (Robust || !maybeStates.empty()) {
167 // Create the vector of one-step probabilities to go to target states.
168 std::vector<ParametricType> b = this->parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
169 storm::storage::BitVector(this->parametricModel->getTransitionMatrix().getRowCount(), true), psiStates);
170 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
171 this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, false, isOrderBasedMonotonicityBackend());
172 }
173
174 // We know some bounds for the results so set them
175 lowerResultBound = storm::utility::zero<ConstantType>();
176 upperResultBound = storm::utility::one<ConstantType>();
177 // No requirements for bounded formulas
178 solverFactory->setRequirementsChecked(true);
179
180 if (isOrderBasedMonotonicityBackend()) {
181 auto [prob0, prob1] = storm::utility::graph::performProb01(this->parametricModel->getBackwardTransitions(), phiStates, psiStates);
182 getOrderBasedMonotonicityBackend().initializeOrderExtender(prob1, prob0, this->parametricModel->getTransitionMatrix());
183 }
184}
185
186template<typename SparseModelType, typename ConstantType, bool Robust>
189 // get the results for the subformulas
191 STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getLeftSubformula()) &&
192 propositionalChecker.canHandle(checkTask.getFormula().getRightSubformula()),
193 storm::exceptions::NotSupportedException, "Parameter lifting with non-propositional subformulas is not supported.");
194 storm::storage::BitVector phiStates = std::move(propositionalChecker.check(checkTask.getFormula().getLeftSubformula())
195 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
196 .getTruthValuesVector());
197 storm::storage::BitVector psiStates = std::move(propositionalChecker.check(checkTask.getFormula().getRightSubformula())
198 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
199 .getTruthValuesVector());
200
201 // get the maybeStates
202 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
203 storm::utility::graph::performProb01(this->parametricModel->getBackwardTransitions(), phiStates, psiStates);
204 maybeStates = ~(statesWithProbability01.first | statesWithProbability01.second);
205
206 // set the result for all non-maybe states
207 resultsForNonMaybeStates = std::vector<ExtendedConstantType>(this->parametricModel->getNumberOfStates(), storm::utility::zero<ConstantType>());
208 storm::utility::vector::setVectorValues(resultsForNonMaybeStates, statesWithProbability01.second, storm::utility::one<ConstantType>());
209
210 // if there are maybestates, create the parameterLifter
211 if (Robust || !maybeStates.empty()) {
212 if constexpr (Robust) {
213 // Create the vector of one-step probabilities to go to target states.
214 // Robust PLA doesn't support eliminating states because it gets complicated with the polynomials you know
215 std::vector<ParametricType> target(this->parametricModel->getNumberOfStates(), storm::utility::zero<ParametricType>());
216 storm::storage::BitVector allTrue(maybeStates.size(), true);
217
218 if (!storm::pars::analysis::isGraphPreserving(this->graphPreservationStatus)) {
220 maybeStates = ~statesWithProbability01.first & ~psiStates;
221 } else {
222 storm::utility::vector::setVectorValues(target, statesWithProbability01.second, storm::utility::one<ParametricType>());
223 }
224
225 // With Robust PLA, we cannot drop the non-maybe states out of the matrix for technical reasons
226 auto rowFilter = this->parametricModel->getTransitionMatrix().getRowFilter(maybeStates);
227 auto filteredMatrix = this->parametricModel->getTransitionMatrix().filterEntries(rowFilter);
228
229 maybeStates = allTrue;
230
231 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
232 filteredMatrix, target, allTrue, allTrue, isValueDeltaRegionSplitEstimates(), isOrderBasedMonotonicityBackend());
233 } else {
234 // Create the vector of one-step probabilities to go to target states.
235 std::vector<ParametricType> b = this->parametricModel->getTransitionMatrix().getConstrainedRowSumVector(
236 storm::storage::BitVector(this->parametricModel->getTransitionMatrix().getRowCount(), true), statesWithProbability01.second);
237 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
238 this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, isValueDeltaRegionSplitEstimates(),
239 isOrderBasedMonotonicityBackend());
240 }
241 }
242
243 // We know some bounds for the results so set them
244 lowerResultBound = storm::utility::zero<ConstantType>();
245 upperResultBound = storm::utility::one<ConstantType>();
246
247 // The solution of the min-max equation system will always be unique (assuming graph-preserving instantiations, every induced DTMC has the same graph
248 // structure).
249 auto req = solverFactory->getRequirements(env, true, true, boost::none, !Robust);
250 req.clearBounds();
251 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
252 "Solver requirements " + req.getEnabledRequirementsAsString() + " not checked.");
253 solverFactory->setRequirementsChecked(true);
254
255 if (isOrderBasedMonotonicityBackend()) {
256 getOrderBasedMonotonicityBackend().initializeOrderExtender(statesWithProbability01.second, statesWithProbability01.first,
257 this->parametricModel->getTransitionMatrix());
258 }
259}
260
261template<typename SparseModelType, typename ConstantType, bool Robust>
264 // get the results for the subformula
266 STORM_LOG_THROW(propositionalChecker.canHandle(checkTask.getFormula().getSubformula()), storm::exceptions::NotSupportedException,
267 "Parameter lifting with non-propositional subformulas is not supported.");
268 storm::storage::BitVector targetStates = std::move(propositionalChecker.check(checkTask.getFormula().getSubformula())
269 ->template asExplicitQualitativeCheckResult<typename SparseModelType::ValueType>()
270 .getTruthValuesVector());
271 // get the maybeStates
273 this->parametricModel->getBackwardTransitions(), storm::storage::BitVector(this->parametricModel->getNumberOfStates(), true), targetStates);
274 infinityStates.complement();
275 maybeStates = ~(targetStates | infinityStates);
276
277 // set the result for all the non-maybe states
278 resultsForNonMaybeStates = std::vector<ExtendedConstantType>(this->parametricModel->getNumberOfStates(), storm::utility::zero<ConstantType>());
280
281 // if there are maybestates, create the parameterLifter
282 if (Robust || !maybeStates.empty()) {
283 // Create the reward vector
284 STORM_LOG_THROW((checkTask.isRewardModelSet() && this->parametricModel->hasRewardModel(checkTask.getRewardModel())) ||
285 (!checkTask.isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
286 storm::exceptions::InvalidPropertyException, "The reward model specified by the CheckTask is not available in the given model.");
287
288 typename SparseModelType::RewardModelType const& rewardModel =
289 checkTask.isRewardModelSet() ? this->parametricModel->getRewardModel(checkTask.getRewardModel()) : this->parametricModel->getUniqueRewardModel();
290
291 std::vector<ParametricType> b = rewardModel.getTotalRewardVector(this->parametricModel->getTransitionMatrix());
292
293 if constexpr (Robust) {
294 storm::storage::BitVector allTrue(maybeStates.size(), true);
295 if (!storm::pars::analysis::isGraphPreserving(this->graphPreservationStatus)) {
296 maybeStates = ~targetStates;
297 }
298 auto rowFilter = this->parametricModel->getTransitionMatrix().getRowFilter(maybeStates);
299 auto filteredMatrix = this->parametricModel->getTransitionMatrix().filterEntries(rowFilter);
300 maybeStates = allTrue;
301
302 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
303 filteredMatrix, b, allTrue, allTrue, isValueDeltaRegionSplitEstimates(), isOrderBasedMonotonicityBackend());
304 } else {
305 parameterLifter = std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(
306 this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates, isValueDeltaRegionSplitEstimates(),
307 isOrderBasedMonotonicityBackend());
308 }
309 }
310
311 // We only know a lower bound for the result
312 lowerResultBound = storm::utility::zero<ConstantType>();
313
314 // The solution of the min-max equation system will always be unique (assuming graph-preserving instantiations, every induced DTMC has the same graph
315 // structure).
316 auto req = solverFactory->getRequirements(env, true, true, boost::none, !Robust);
317 req.clearLowerBounds();
318 if (req.upperBounds()) {
319 solvingRequiresUpperRewardBounds = true;
320 req.clearUpperBounds();
321 }
322 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
323 "Solver requirements " + req.getEnabledRequirementsAsString() + " not checked.");
324 solverFactory->setRequirementsChecked(true);
325 STORM_LOG_WARN_COND(!isOrderBasedMonotonicityBackend(), "Order-based monotonicity not used for reachability reward formula.");
326}
327
328template<typename SparseModelType, typename ConstantType, bool Robust>
331 STORM_LOG_ERROR_COND(!Robust, "Not implemented for robust mode.");
332 // Obtain the stepBound
333 stepBound = checkTask.getFormula().getBound().evaluateAsInt();
334 if (checkTask.getFormula().isBoundStrict()) {
335 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException, "Expected a strict upper step bound that is greater than zero.");
336 --(*stepBound);
337 }
338 STORM_LOG_THROW(*stepBound > 0, storm::exceptions::NotSupportedException,
339 "Can not apply parameter lifting on step bounded formula: The step bound has to be positive.");
340
341 // Every state is a maybeState
342 maybeStates = storm::storage::BitVector(this->parametricModel->getTransitionMatrix().getColumnCount(), true);
343 resultsForNonMaybeStates = std::vector<ExtendedConstantType>(this->parametricModel->getNumberOfStates());
344
345 // Create the reward vector
346 STORM_LOG_THROW((checkTask.isRewardModelSet() && this->parametricModel->hasRewardModel(checkTask.getRewardModel())) ||
347 (!checkTask.isRewardModelSet() && this->parametricModel->hasUniqueRewardModel()),
348 storm::exceptions::InvalidPropertyException, "The reward model specified by the CheckTask is not available in the given model.");
349 typename SparseModelType::RewardModelType const& rewardModel =
350 checkTask.isRewardModelSet() ? this->parametricModel->getRewardModel(checkTask.getRewardModel()) : this->parametricModel->getUniqueRewardModel();
351 std::vector<ParametricType> b = rewardModel.getTotalRewardVector(this->parametricModel->getTransitionMatrix());
352
353 parameterLifter =
354 std::make_unique<ParameterLifterType<ParametricType, ConstantType, Robust>>(this->parametricModel->getTransitionMatrix(), b, maybeStates, maybeStates);
355 // We only know a lower bound for the result
356 lowerResultBound = storm::utility::zero<ConstantType>();
357
358 // No requirements for bounded reward formula
359 solverFactory->setRequirementsChecked(true);
360
361 STORM_LOG_WARN_COND(!isOrderBasedMonotonicityBackend(), "Order-based monotonicity not used for cumulative reward formula.");
362}
363
364template<typename SparseModelType, typename ConstantType, bool Robust>
367 if (!instantiationCheckerSAT) {
368 instantiationCheckerSAT =
369 std::make_unique<storm::modelchecker::SparseDtmcInstantiationModelChecker<SparseModelType, ConstantType>>(env, *this->parametricModel);
370 instantiationCheckerSAT->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
371 : this->currentCheckTask->template convertValueType<ParametricType>());
372 instantiationCheckerSAT->setInstantiationsAreGraphPreserving(true);
373 }
374 return *instantiationCheckerSAT;
375}
376
377template<typename SparseModelType, typename ConstantType, bool Robust>
380 if (!instantiationCheckerVIO) {
381 instantiationCheckerVIO =
382 std::make_unique<storm::modelchecker::SparseDtmcInstantiationModelChecker<SparseModelType, ConstantType>>(env, *this->parametricModel);
383 instantiationCheckerVIO->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
384 : this->currentCheckTask->template convertValueType<ParametricType>());
385 instantiationCheckerVIO->setInstantiationsAreGraphPreserving(true);
386 }
387 return *instantiationCheckerVIO;
388}
389
390template<typename SparseModelType, typename ConstantType, bool Robust>
393 if (!instantiationChecker) {
394 instantiationChecker =
395 std::make_unique<storm::modelchecker::SparseDtmcInstantiationModelChecker<SparseModelType, ConstantType>>(env, *this->parametricModel);
396 instantiationChecker->specifyFormula(quantitative ? *this->currentCheckTaskNoBound
397 : this->currentCheckTask->template convertValueType<ParametricType>());
398 instantiationChecker->setInstantiationsAreGraphPreserving(true);
399 }
400 return *instantiationChecker;
401}
402
403template<typename SparseModelType, typename ConstantType, bool Robust>
404std::vector<typename SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::ExtendedConstantType>
407 if (maybeStates.empty()) {
408 this->updateKnownValueBoundInRegion(region, dirForParameters, resultsForNonMaybeStates);
409 return resultsForNonMaybeStates;
410 }
411 parameterLifter->specifyRegion(region.region, dirForParameters);
412 auto liftedMatrix = parameterLifter->getMatrix();
413 auto liftedVector = parameterLifter->getVector();
414 bool nonTrivialEndComponents = false;
415 if constexpr (Robust) {
416 if (parameterLifter->isCurrentRegionAllIllDefined()) {
417 return std::vector<ExtendedConstantType>();
418 }
419 if (!storm::pars::analysis::isGraphPreserving(this->graphPreservationStatus)) {
420 transformer::IntervalEndComponentPreserver endComponentPreserver;
421 auto const& result = endComponentPreserver.eliminateMECs(liftedMatrix, liftedVector);
422 if (result) {
423 liftedMatrix = *result;
424 nonTrivialEndComponents = true;
425 }
426 }
427 }
428 const uint64_t resultVectorSize = liftedMatrix.getColumnCount();
429
430 if (stepBound) {
431 if constexpr (!Robust) {
432 STORM_LOG_ASSERT(*stepBound > 0, "Expected positive step bound.");
433 x = std::vector<ConstantType>(resultVectorSize, storm::utility::zero<ConstantType>());
434 auto multiplier = storm::solver::MultiplierFactory<ConstantType>().create(env, liftedMatrix);
435 multiplier->repeatedMultiplyAndReduce(env, dirForParameters, x, &liftedVector, *stepBound);
436 } else {
437 STORM_LOG_ERROR("Cannot check step-bounded formulas in robust mode.");
438 }
439 } else {
440 auto solver = solverFactory->create(env, liftedMatrix);
441 solver->setHasUniqueSolution();
442 solver->setHasNoEndComponents();
443 // Uncertainty is not robust (=adversarial)
444 solver->setUncertaintyResolutionMode(UncertaintyResolutionMode::Cooperative);
445 if (lowerResultBound) {
446 solver->setLowerBound(lowerResultBound.value());
447 }
448 if (upperResultBound) {
449 solver->setUpperBound(upperResultBound.value());
450 } else if (solvingRequiresUpperRewardBounds) {
451 if constexpr (!Robust) {
452 // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17).
453 std::vector<ConstantType> oneStepProbs;
454 oneStepProbs.reserve(liftedMatrix.getRowCount());
455 for (uint64_t row = 0; row < liftedMatrix.getRowCount(); ++row) {
456 oneStepProbs.push_back(storm::utility::one<ConstantType>() - liftedMatrix.getRowSum(row));
457 }
458 if (dirForParameters == storm::OptimizationDirection::Minimize) {
459 storm::modelchecker::helper::DsMpiMdpUpperRewardBoundsComputer<ConstantType> dsmpi(liftedMatrix, liftedVector, oneStepProbs);
460 solver->setUpperBounds(dsmpi.computeUpperBounds());
461 } else {
463 solver->setUpperBound(baier.computeTotalRewardBounds(liftedVector).upper);
464 }
465 } else {
466 STORM_LOG_ERROR("Cannot use upper reward bounds in robust mode.");
467 }
468 }
469 solver->setTrackScheduler(true);
470
471 // Get reference to relevant scheduler choices
472 auto& choices = storm::solver::minimize(dirForParameters) ? minSchedChoices : maxSchedChoices;
473
474 // Potentially fix some choices if order based monotonicity is known
475 if constexpr (!Robust) {
476 storm::storage::BitVector statesWithFixedChoice;
477 if (isOrderBasedMonotonicityBackend()) {
478 // Ensure choices are initialized
479 if (!choices.has_value()) {
480 choices.emplace(parameterLifter->getRowGroupCount(), 0u);
481 }
482 statesWithFixedChoice = getOrderBasedMonotonicityBackend().getChoicesToFixForPLASolver(region, dirForParameters, *choices);
483 }
484
485 // Set initial scheduler
486 if (choices.has_value()) {
487 solver->setInitialScheduler(std::move(choices.value()));
488 if (statesWithFixedChoice.size() != 0) {
489 // Choices need to be fixed after setting a scheduler
490 solver->setSchedulerFixedForRowGroup(std::move(statesWithFixedChoice));
491 }
492 }
493 } else {
494 // Set initial scheduler
495 if (!nonTrivialEndComponents && choices.has_value()) {
496 solver->setInitialScheduler(std::move(choices.value()));
497 }
498 }
499
500 if (this->currentCheckTask->isBoundSet() && solver->hasInitialScheduler()) {
501 // If we reach this point, we know that after applying the hint, the x-values can only become larger (if we maximize) or smaller (if we
502 // minimize).
503 std::unique_ptr<storm::solver::TerminationCondition<ConstantType>> termCond;
504 storm::storage::BitVector relevantStatesInSubsystem = this->currentCheckTask->isOnlyInitialStatesRelevantSet()
505 ? this->parametricModel->getInitialStates() % maybeStates
506 : storm::storage::BitVector(maybeStates.getNumberOfSetBits(), true);
507 if (storm::solver::minimize(dirForParameters)) {
508 // Terminate if the value for ALL relevant states is already below the threshold
509 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumBelowThreshold<ConstantType>>(
510 relevantStatesInSubsystem, true, this->currentCheckTask->getBoundThreshold(), false);
511 } else {
512 // Terminate if the value for ALL relevant states is already above the threshold
513 termCond = std::make_unique<storm::solver::TerminateIfFilteredExtremumExceedsThreshold<ConstantType>>(
514 relevantStatesInSubsystem, true, this->currentCheckTask->getBoundThreshold(), true);
515 }
516 solver->setTerminationCondition(std::move(termCond));
517 }
518
519 // Invoke the solver
520 x.resize(resultVectorSize, storm::utility::zero<ConstantType>());
521 solver->solveEquations(env, dirForParameters, x, liftedVector);
522 if (isValueDeltaRegionSplitEstimates()) {
523 computeStateValueDeltaRegionSplitEstimates(env, x, solver->getSchedulerChoices(), region.region, dirForParameters);
524 }
525 // Store choices for next time, if we have no non-trivial end components
526 if (!nonTrivialEndComponents) {
527 choices = solver->getSchedulerChoices();
528 }
529 }
530
531 // Get the result for the complete model (including maybestates)
532 std::vector<ExtendedConstantType> result = resultsForNonMaybeStates;
533 auto maybeStateResIt = x.begin();
534 for (uint64_t maybeState : maybeStates) {
535 result[maybeState] = *maybeStateResIt;
536 ++maybeStateResIt;
537 }
538
539 STORM_LOG_INFO(dirForParameters << " " << region.region << ": " << result[this->getUniqueInitialState()]);
540
541 this->updateKnownValueBoundInRegion(region, dirForParameters, result);
542 return result;
543}
544
545template<typename SparseModelType, typename ConstantType, bool Robust>
547 Environment const& env, std::vector<ConstantType> const& quantitativeResult, std::vector<uint64_t> const& schedulerChoices,
549 auto const& matrix = parameterLifter->getMatrix();
550 auto const& vector = parameterLifter->getVector();
551
552 std::vector<ConstantType> weighting = std::vector<ConstantType>(vector.size(), utility::one<ConstantType>());
554 // Instantiated on center, instantiate on choices instead?
555 // Kinda complicated tho
557 auto const instantiatedModel = instantiator.instantiate(region.getCenterPoint());
558 helper::SparseDeterministicVisitingTimesHelper<ConstantType> visitingTimesHelper(instantiatedModel.getTransitionMatrix());
559 auto const visitingTimes = visitingTimesHelper.computeExpectedVisitingTimes(env, this->parametricModel->getInitialStates());
560 uint64_t rowIndex = 0;
561 for (uint64_t state : maybeStates) {
562 ExtendedConstantType const& visitingTime = visitingTimes[state];
563 STORM_LOG_WARN_COND(!storm::utility::isInfinity(visitingTime), "Expected a finite number of visits to maybe-state " << state << ".");
564 if (!storm::utility::isInfinity(visitingTime)) {
565 weighting[rowIndex] = storm::utility::getFinite(visitingTime);
566 }
567 ++rowIndex;
568 }
569 }
570
571 switch (*this->specifiedRegionSplitEstimateKind) {
574 std::map<VariableType, ConstantType> deltaLower, deltaUpper;
575 for (auto const& p : region.getVariables()) {
576 deltaLower.emplace(p, storm::utility::zero<ConstantType>());
577 deltaUpper.emplace(p, storm::utility::zero<ConstantType>());
578 }
579 if constexpr (Robust) {
580 // Cache all derivatives of functions that turn up in pMC
581 static std::map<RationalFunction, RationalFunction> functionDerivatives;
582 static std::vector<std::pair<bool, double>> constantDerivatives;
583 if (constantDerivatives.empty()) {
584 for (uint64_t state : maybeStates) {
585 auto variables = parameterLifter->getOccurringVariablesAtState().at(state);
586 if (variables.size() == 0) {
587 continue;
588 }
589 STORM_LOG_ERROR_COND(variables.size() == 1,
590 "Cannot compute state-value-delta split estimates in robust mode if there are states with multiple parameters.");
591 auto const p = *variables.begin();
592 for (auto const& entry : this->parametricModel->getTransitionMatrix().getRow(state)) {
593 auto const& function = entry.getValue();
594 if (functionDerivatives.count(function)) {
595 constantDerivatives.emplace_back(false, 0);
596 continue;
597 }
598 auto const derivative = function.derivative(p);
599 if (derivative.isConstant()) {
600 constantDerivatives.emplace_back(true, utility::convertNumber<double>(derivative.constantPart()));
601 } else if (!storm::transformer::BigStep::lastSavedAnnotations.count(entry.getValue())) {
602 functionDerivatives.emplace(function, derivative);
603 constantDerivatives.emplace_back(false, 0);
604 } else {
605 constantDerivatives.emplace_back(false, 0);
606 }
607 }
608 }
609 }
610
611 cachedRegionSplitEstimates.clear();
612 for (auto const& p : region.getVariables()) {
613 cachedRegionSplitEstimates.emplace(p, utility::zero<ConstantType>());
614 }
615
616 uint64_t entryCount = 0;
617 // Assumption: Only one parameter per state
618 for (uint64_t state : maybeStates) {
619 auto variables = parameterLifter->getOccurringVariablesAtState().at(state);
620 if (variables.size() == 0) {
621 continue;
622 }
623 STORM_LOG_ERROR_COND(variables.size() == 1,
624 "Cannot compute state-value-delta split estimates in robust mode if there are states with multiple parameters.");
625
626 auto const p = *variables.begin();
627
628 const uint64_t rowIndex = maybeStates.getNumberOfSetBitsBeforeIndex(state);
629
630 std::vector<ConstantType> derivatives;
631 for (auto const& entry : this->parametricModel->getTransitionMatrix().getRow(state)) {
632 if (storm::transformer::BigStep::lastSavedAnnotations.count(entry.getValue())) {
633 auto& annotation = storm::transformer::BigStep::lastSavedAnnotations.at(entry.getValue());
634 ConstantType derivative =
635 annotation.derivative()->template evaluate<ConstantType>(utility::convertNumber<ConstantType>(region.getCenter(p)));
636 derivatives.push_back(derivative);
637 } else {
638 auto const& cDer = constantDerivatives.at(entryCount);
639 if (cDer.first) {
640 derivatives.push_back(cDer.second);
641 } else {
642 CoefficientType derivative = functionDerivatives.at(entry.getValue()).evaluate(region.getCenterPoint());
643 derivatives.push_back(utility::convertNumber<ConstantType>(derivative));
644 }
645 }
646 entryCount++;
647 }
648
649 std::vector<ConstantType> results(0);
650
651 ConstantType distrToNegativeDerivative = storm::utility::zero<ConstantType>();
652 ConstantType distrToPositiveDerivative = storm::utility::zero<ConstantType>();
653
654 for (auto const& direction : {OptimizationDirection::Maximize, OptimizationDirection::Minimize}) {
655 // Do a step of robust value iteration
656 // TODO I think it is a problem if we have probabilities and a state that is going to the vector, we don't count that
657 // Currently "fixed in preprocessing"
658 // It's different for rewards (same problem in ValueIterationOperator.h, search for word "octopus" in codebase)
659 ConstantType remainingValue = utility::one<ConstantType>();
660 ConstantType result = utility::zero<ConstantType>();
661
662 STORM_LOG_ASSERT(vector[rowIndex].upper() == vector[rowIndex].lower(),
663 "Non-constant vector indices not supported (this includes parametric rewards).");
664
665 std::vector<std::pair<ConstantType, std::pair<ConstantType, uint64_t>>> robustOrder;
666
667 uint64_t index = 0;
668 for (auto const& entry : matrix.getRow(rowIndex)) {
669 auto const lower = entry.getValue().lower();
670 result += quantitativeResult[entry.getColumn()] * lower;
671 remainingValue -= lower;
672 auto const diameter = entry.getValue().upper() - lower;
673 if (!storm::utility::isZero(diameter)) {
674 robustOrder.emplace_back(quantitativeResult[entry.getColumn()], std::make_pair(diameter, index));
675 }
676 index++;
677 }
678
679 std::sort(robustOrder.begin(), robustOrder.end(),
680 [direction](const std::pair<ConstantType, std::pair<ConstantType, uint64_t>>& a,
681 const std::pair<ConstantType, std::pair<ConstantType, uint64_t>>& b) {
682 if (direction == OptimizationDirection::Maximize) {
683 return a.first > b.first;
684 } else {
685 return a.first < b.first;
686 }
687 });
688
689 for (auto const& pair : robustOrder) {
690 auto availableMass = std::min(pair.second.first, remainingValue);
691 result += availableMass * pair.first;
692 // TODO hardcoded precision
693 if (direction == this->currentCheckTask->getOptimizationDirection()) {
694 if (derivatives[pair.second.second] > 1e-6) {
695 distrToPositiveDerivative += availableMass;
696 } else if (derivatives[pair.second.second] < 1e-6) {
697 distrToNegativeDerivative += availableMass;
698 }
699 }
700 remainingValue -= availableMass;
701 }
702
703 results.push_back(result);
704 }
705
706 ConstantType diff = std::abs(results[0] - results[1]);
707 if (distrToPositiveDerivative > distrToNegativeDerivative) { // Choose as upper
708 deltaUpper[p] += diff * weighting[rowIndex];
709 } else { // Choose as lower
710 deltaLower[p] += diff * weighting[rowIndex];
711 }
712 }
713 } else {
714 auto const& choiceValuations = parameterLifter->getRowLabels();
715
716 std::vector<ConstantType> stateResults;
717 for (uint64_t state = 0; state < schedulerChoices.size(); ++state) {
718 uint64_t rowOffset = matrix.getRowGroupIndices()[state];
719 uint64_t optimalChoice = schedulerChoices[state];
720 auto const& optimalChoiceVal = choiceValuations[rowOffset + optimalChoice];
721 STORM_LOG_ASSERT(optimalChoiceVal.getUnspecifiedParameters().empty(), "Expected no unspecified parameters.");
722 stateResults.clear();
723 for (uint64_t row = rowOffset; row < matrix.getRowGroupIndices()[state + 1]; ++row) {
724 stateResults.push_back(matrix.multiplyRowWithVector(row, quantitativeResult) + vector[row]);
725 }
726 // Do this twice, once for upperbound once for lowerbound
727 bool checkUpperParameters = false;
728 do {
729 auto const& consideredParameters = checkUpperParameters ? optimalChoiceVal.getUpperParameters() : optimalChoiceVal.getLowerParameters();
730 for (auto const& p : consideredParameters) {
731 // Find the 'best' choice that assigns the parameter to the other bound
732 ConstantType bestValue = 0;
733 bool foundBestValue = false;
734 for (uint64_t choice = 0; choice < stateResults.size(); ++choice) {
735 if (choice != optimalChoice) {
736 auto const& otherBoundParsOfChoice = checkUpperParameters ? choiceValuations[rowOffset + choice].getLowerParameters()
737 : choiceValuations[rowOffset + choice].getUpperParameters();
738 if (otherBoundParsOfChoice.find(p) != otherBoundParsOfChoice.end()) {
739 ConstantType const& choiceValue = stateResults[choice];
740 if (!foundBestValue ||
741 (storm::solver::minimize(dirForParameters) ? choiceValue < bestValue : choiceValue > bestValue)) {
742 foundBestValue = true;
743 bestValue = choiceValue;
744 }
745 }
746 }
747 }
748 auto const& optimal = stateResults[optimalChoice];
750 if (foundBestValue) {
751 if (checkUpperParameters) {
752 deltaLower[p] += diff * weighting[state];
753 } else {
754 deltaUpper[p] += diff * weighting[state];
755 }
756 }
757 }
758 checkUpperParameters = !checkUpperParameters;
759 } while (checkUpperParameters);
760 }
761 }
762
763 cachedRegionSplitEstimates.clear();
764 for (auto const& p : region.getVariables()) {
765 // TODO: previously, the reginSplitEstimates were only used in splitting if at least one parameter is possibly monotone. Why?
766 auto minDelta = std::min(deltaLower[p], deltaUpper[p]);
767 cachedRegionSplitEstimates.emplace(p, minDelta);
768 }
769
770 // large regionsplitestimate implies that parameter p occurs as p and 1-p at least once
771 break;
772 }
775 env, *this->parametricModel);
776 instantiationModelChecker.specifyFormula(*this->currentCheckTaskNoBound);
777
778 auto const center = region.getCenterPoint();
779
780 std::unique_ptr<storm::modelchecker::CheckResult> result = instantiationModelChecker.check(env, center);
781 auto const reachabilityProbabilities = result->asExplicitQuantitativeCheckResult<ConstantType>().getFiniteValueVector();
782
783 STORM_LOG_ASSERT(this->derivativeChecker, "Derivative checker not intialized.");
784
785 for (auto const& param : region.getVariables()) {
786 auto result = this->derivativeChecker->check(env, center, param, reachabilityProbabilities);
788 result->template asExplicitQuantitativeCheckResult<ConstantType>().getValueVector()[this->derivativeChecker->getInitialState()]);
789 cachedRegionSplitEstimates[param] = utility::abs(derivative) * utility::convertNumber<ConstantType>(region.getDifference(param));
790 }
791 break;
792 }
793 default:
794 STORM_LOG_ERROR("Region split estimate kind not handled by SparseDtmcParameterLiftingModelChecker.");
795 }
796}
797
798template<typename SparseModelType, typename ConstantType, bool Robust>
800 maybeStates.resize(0);
801 resultsForNonMaybeStates.clear();
802 stepBound = std::nullopt;
803 instantiationChecker = nullptr;
804 instantiationCheckerSAT = nullptr;
805 instantiationCheckerVIO = nullptr;
806 parameterLifter = nullptr;
807 minSchedChoices = std::nullopt;
808 maxSchedChoices = std::nullopt;
809 x.clear();
810 lowerResultBound = std::nullopt;
811 upperResultBound = std::nullopt;
812 cachedRegionSplitEstimates.clear();
813}
814
815template<typename ConstantType>
816std::optional<storm::storage::Scheduler<ConstantType>> getSchedulerHelper(std::optional<std::vector<uint64_t>> const& choices) {
817 std::optional<storm::storage::Scheduler<ConstantType>> result;
818 if (choices) {
819 result.emplace(choices->size());
820 uint64_t state = 0;
821 for (auto const& choice : choices.value()) {
822 result->setChoice(choice, state);
823 ++state;
824 }
825 }
826 return result;
827}
828
829template<typename SparseModelType, typename ConstantType, bool Robust>
831 return getSchedulerHelper<ConstantType>(minSchedChoices);
832}
833
834template<typename SparseModelType, typename ConstantType, bool Robust>
836 return getSchedulerHelper<ConstantType>(maxSchedChoices);
837}
838
840 if (f.isOperatorFormula()) {
841 auto const& sub = f.asOperatorFormula().getSubformula();
842 return sub.isUntilFormula() || sub.isEventuallyFormula();
843 }
844 return false;
845}
846
849 auto const& sub = f.asProbabilityOperatorFormula().getSubformula();
850 return sub.isUntilFormula() || sub.isEventuallyFormula() || sub.isBoundedUntilFormula();
851 }
852 return false;
853}
854
855template<typename SparseModelType, typename ConstantType, bool Robust>
863
864template<typename SparseModelType, typename ConstantType, bool Robust>
870
871template<typename SparseModelType, typename ConstantType, bool Robust>
872std::vector<typename SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::CoefficientType>
874 std::set<VariableType> const& relevantParameters) const {
875 if (isValueDeltaRegionSplitEstimates()) {
876 // Cached region split estimates are value-delta
877 std::vector<CoefficientType> result;
878 for (auto const& par : relevantParameters) {
879 auto est = cachedRegionSplitEstimates.find(par);
880 STORM_LOG_ASSERT(est != cachedRegionSplitEstimates.end(),
881 "Requested region split estimate for parameter " << par.name() << " but none was generated.");
882 result.push_back(storm::utility::convertNumber<CoefficientType>(est->second));
883 }
884 return result;
885 } else {
886 // Call super method, which might support the estimate type
888 }
889}
890
891template<typename SparseModelType, typename ConstantType, bool Robust>
901
902template<typename SparseModelType, typename ConstantType, bool Robust>
903bool SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::isOrderBasedMonotonicityBackend() const {
904 return dynamic_cast<OrderBasedMonotonicityBackend<ParametricType, ConstantType>*>(this->monotonicityBackend.get()) != nullptr;
905}
906
907template<typename SparseModelType, typename ConstantType, bool Robust>
908OrderBasedMonotonicityBackend<typename SparseModelType::ValueType, ConstantType>&
909SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::getOrderBasedMonotonicityBackend() {
910 return dynamic_cast<OrderBasedMonotonicityBackend<ParametricType, ConstantType>&>(*this->monotonicityBackend);
911}
912
913template<typename SparseModelType, typename ConstantType, bool Robust>
914bool SparseDtmcParameterLiftingModelChecker<SparseModelType, ConstantType, Robust>::isValueDeltaRegionSplitEstimates() const {
915 return this->getSpecifiedRegionSplitEstimateKind().has_value() &&
916 (this->getSpecifiedRegionSplitEstimateKind().value() == RegionSplitEstimateKind::StateValueDelta ||
917 this->getSpecifiedRegionSplitEstimateKind().value() == RegionSplitEstimateKind::StateValueDeltaWeighted ||
918 this->getSpecifiedRegionSplitEstimateKind().value() == RegionSplitEstimateKind::Derivative);
919}
920
921template class SparseDtmcParameterLiftingModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double, false>;
922template class SparseDtmcParameterLiftingModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, double, true>;
923template class SparseDtmcParameterLiftingModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>, storm::RationalNumber, false>;
924} // namespace modelchecker
925} // namespace storm
virtual bool isOperatorFormula() const
Definition Formula.cpp:202
virtual bool isProbabilityOperatorFormula() const
Definition Formula.cpp:194
ProbabilityOperatorFormula & asProbabilityOperatorFormula()
Definition Formula.cpp:506
OperatorFormula & asOperatorFormula()
Definition Formula.cpp:522
virtual bool isUntilFormula() const
Definition Formula.cpp:86
Formula const & getSubformula() const
virtual std::unique_ptr< CheckResult > check(Environment const &env, CheckTask< storm::logic::Formula, SolutionType > const &checkTask)
Checks the provided formula.
CheckTask< NewFormulaType, ValueType > substituteFormula(NewFormulaType const &newFormula) const
Copies the check task from the source while replacing the formula with the new one.
Definition CheckTask.h:53
bool isRewardModelSet() const
Retrieves whether a reward model was set.
Definition CheckTask.h:191
std::string const & getRewardModel() const
Retrieves the reward model over which to perform the checking (if set).
Definition CheckTask.h:198
FormulaType const & getFormula() const
Retrieves the formula from this task.
Definition CheckTask.h:141
virtual bool requiresInteractionWithRegionModelChecker() const
Returns true, if a region model checker needs to implement specific methods to properly use this back...
virtual bool isRegionSplitEstimateKindSupported(RegionSplitEstimateKind kind, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const
virtual RegionSplitEstimateKind getDefaultRegionSplitEstimateKind(CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const
virtual void specifyMonotonicity(std::shared_ptr< MonotonicityBackend< SparseModelType::ValueType > > backend, CheckTask< storm::logic::Formula, SparseModelType::ValueType > const &checkTask)
std::shared_ptr< MonotonicityBackend< SparseModelType::ValueType > > monotonicityBackend
virtual std::vector< CoefficientType > obtainRegionSplitEstimates(std::set< VariableType > const &relevantParameters) const
Returns an estimate of the benefit of splitting the last checked region with respect to each of the g...
virtual void specifySplitEstimates(std::optional< RegionSplitEstimateKind > splitEstimates, CheckTask< storm::logic::Formula, SparseModelType::ValueType > const &checkTask)
Class to efficiently check a formula on a parametric model with different parameter instantiations.
virtual std::unique_ptr< CheckResult > check(Environment const &env, storm::utility::parametric::Valuation< typename SparseModelType::ValueType > const &valuation) override
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentMinScheduler()
virtual bool isRegionSplitEstimateKindSupported(RegionSplitEstimateKind kind, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
typename RegionModelChecker< ParametricType >::CoefficientType CoefficientType
virtual std::vector< CoefficientType > obtainRegionSplitEstimates(std::set< VariableType > const &relevantParameters) const override
Returns an estimate of the benefit of splitting the last checked region with respect to each of the g...
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationCheckerVIO(Environment const &env, bool qualitative) override
virtual RegionSplitEstimateKind getDefaultRegionSplitEstimateKind(CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
virtual bool canHandle(std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
virtual std::vector< ExtendedConstantType > computeQuantitativeValues(Environment const &env, AnnotatedRegion< ParametricType > &region, storm::solver::OptimizationDirection const &dirForParameters) override
virtual void specifyBoundedUntilFormula(const CheckTask< storm::logic::BoundedUntilFormula, ConstantType > &checkTask) override
virtual void specifyCumulativeRewardFormula(const CheckTask< storm::logic::CumulativeRewardFormula, ConstantType > &checkTask) override
void computeStateValueDeltaRegionSplitEstimates(Environment const &env, std::vector< ConstantType > const &quantitativeResult, std::vector< uint64_t > const &schedulerChoices, storm::storage::ParameterRegion< ParametricType > const &region, storm::solver::OptimizationDirection const &dirForParameters)
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationCheckerSAT(Environment const &env, bool qualitative) override
virtual storm::modelchecker::SparseInstantiationModelChecker< SparseModelType, ConstantType > & getInstantiationChecker(Environment const &env, bool qualitative) override
std::optional< storm::storage::Scheduler< ConstantType > > getCurrentMaxScheduler()
virtual void specifyReachabilityRewardFormula(Environment const &env, CheckTask< storm::logic::EventuallyFormula, ConstantType > const &checkTask) override
virtual bool isMonotonicitySupported(MonotonicityBackend< ParametricType > const &backend, CheckTask< storm::logic::Formula, ParametricType > const &checkTask) const override
Returns whether this region model checker can work together with the given monotonicity backend.
virtual void specify(Environment const &env, std::shared_ptr< storm::models::ModelBase > parametricModel, CheckTask< storm::logic::Formula, ParametricType > const &checkTask, std::optional< RegionSplitEstimateKind > generateRegionSplitEstimates=std::nullopt, std::shared_ptr< MonotonicityBackend< ParametricType > > monotonicityBackend={}, bool allowModelSimplifications=true, storm::pars::analysis::GraphPreservationStatus graphPreservationStatus=storm::pars::analysis::GraphPreservationStatus::GraphPreserving) override
virtual void specifyUntilFormula(Environment const &env, CheckTask< storm::logic::UntilFormula, ConstantType > const &checkTask) override
typename SparseParameterLiftingModelChecker< SparseModelType, ConstantType >::ExtendedConstantType ExtendedConstantType
Class to efficiently check a formula on a parametric model with different parameter instantiations.
void specifyFormula(CheckTask< storm::logic::Formula, typename SparseModelType::ValueType > const &checkTask)
void updateKnownValueBoundInRegion(AnnotatedRegion< ParametricType > &region, storm::solver::OptimizationDirection dir, std::vector< ExtendedConstantType > const &newValues)
std::unique_ptr< CheckTask< storm::logic::Formula, ConstantType > > currentCheckTask
void specifyFormula(Environment const &env, CheckTask< storm::logic::Formula, ParametricType > const &checkTask)
virtual bool canHandle(CheckTask< storm::logic::Formula, SolutionType > const &checkTask) const override
Bounds computeTotalRewardBounds(std::vector< ValueType > const &rewards)
Computes a lower and an upper bound on the expected total rewards.
std::vector< ValueType > computeUpperBounds()
Computes upper bounds on the expected rewards.
Helper class for computing for each state the expected number of times to visit that state assuming a...
std::vector< ExtendedValueType > computeExpectedVisitingTimes(Environment const &env, storm::storage::BitVector const &initialStates)
Computes for each state the expected number of times we are visiting that state assuming the given in...
std::unique_ptr< Multiplier< ValueType, SolutionType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void complement()
Negates all bits in the bit vector.
size_t size() const
Retrieves the number of bits this bit vector can store.
static std::unordered_map< RationalFunction, Annotation > lastSavedAnnotations
Definition BigStep.h:207
std::optional< storage::SparseMatrix< Interval > > eliminateMECs(storm::storage::SparseMatrix< Interval > const &matrix, std::vector< Interval > const &vector)
This class performs different steps to simplify the given (parametric) model.
This class allows efficient instantiation of the given parametric model.
ConstantSparseModelType const & instantiate(storm::utility::parametric::Valuation< ParametricType > const &valuation)
Evaluates the occurring parametric functions and retrieves the instantiated model.
#define STORM_LOG_INFO(message)
Definition logging.h:34
#define STORM_LOG_ERROR(message)
Definition logging.h:36
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:54
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:68
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
FragmentSpecification reachability()
bool supportsStateValueDeltaEstimates(storm::logic::Formula const &f)
bool supportsOrderBasedMonotonicity(storm::logic::Formula const &f)
std::optional< storm::storage::Scheduler< ConstantType > > getSchedulerHelper(std::optional< std::vector< uint64_t > > const &choices)
std::conditional_t< Robust, storm::solver::MinMaxLinearEquationSolverFactory< storm::Interval, ConstantType >, storm::solver::MinMaxLinearEquationSolverFactory< ConstantType > > SolverFactoryType
std::conditional_t< Robust, storm::solver::GeneralMinMaxLinearEquationSolverFactory< storm::Interval, ConstantType >, storm::solver::GeneralMinMaxLinearEquationSolverFactory< ConstantType > > GeneralSolverFactoryType
GraphPreservationStatus
Describes to what extent a set of regions is known to be well-defined and to preserve the graph struc...
bool isGraphPreserving(GraphPreservationStatus status)
Returns whether the given status guarantees that the graph structure of the model is preserved.
bool constexpr minimize(OptimizationDirection d)
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01(storm::models::sparse::DeterministicModel< T > const &model, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi until psi i...
Definition graph.cpp:394
storm::storage::BitVector performProbGreater0(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Performs a backward depth-first search trough the underlying graph structure of the given model to de...
Definition graph.cpp:316
storm::storage::BitVector performProb1(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &, storm::storage::BitVector const &psiStates, storm::storage::BitVector const &statesWithProbabilityGreater0)
Computes the set of states of the given model for which all paths lead to the given set of target sta...
Definition graph.cpp:377
void setVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< S > const &values)
Sets the provided values at the provided positions in the given vector.
Definition vector.h:79
ExtendedValueType< ValueType > positiveInfinity()
bool isZero(ValueType const &a)
Definition constants.cpp:44
ValueType abs(ValueType const &number)
ValueType zero()
Definition constants.cpp:26
std::vector< ValueType > narrowFinite(std::vector< ExtendedValueType< ValueType > > &&values)
The counterpart of widen for a vector all of whose values are finite.
ValueType one()
Definition constants.cpp:21
bool isInfinity(ValueType const &a)
ValueType const & getFinite(ExtendedNumber< ValueType > const &value)
TargetType convertNumber(SourceType const &number)
solver::OptimizationDirection OptimizationDirection