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