Storm 1.11.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseMdpPrctlHelper.cpp
Go to the documentation of this file.
2
3#include <boost/container/flat_map.hpp>
4
6
13
15
17
18#include "storm/utility/graph.h"
21
25
29
35
36#include "storm/io/export.h"
41
43
45
54
55namespace storm {
56namespace modelchecker {
57namespace helper {
58
59template<typename ValueType, typename SolutionType>
60std::map<storm::storage::sparse::state_type, SolutionType> SparseMdpPrctlHelper<ValueType, SolutionType>::computeRewardBoundedValues(
62 storm::storage::BitVector const& initialStates) {
63 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
64 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reward bounded values with interval models.");
65 } else {
66 storm::utility::Stopwatch swAll(true), swBuild, swCheck;
67
68 // Get lower and upper bounds for the solution.
69 auto lowerBound = rewardUnfolding.getLowerObjectiveBound();
70 auto upperBound = rewardUnfolding.getUpperObjectiveBound();
71
72 // Initialize epoch models
73 auto initEpoch = rewardUnfolding.getStartEpoch();
74 auto epochOrder = rewardUnfolding.getEpochComputationOrder(initEpoch);
75
76 // initialize data that will be needed for each epoch
77 std::vector<ValueType> x, b;
78 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> minMaxSolver;
79
80 ValueType precision = rewardUnfolding.getRequiredEpochModelPrecision(
81 initEpoch, storm::utility::convertNumber<ValueType>(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()));
82 Environment preciseEnv = env;
83 preciseEnv.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(precision));
84
85 // In case of cdf export we store the necessary data.
86 std::vector<std::vector<ValueType>> cdfData;
87
88 storm::utility::ProgressMeasurement progress("epochs");
89 progress.setMaxCount(epochOrder.size());
90 progress.startNewMeasurement(0);
91 uint64_t numCheckedEpochs = 0;
92 for (auto const& epoch : epochOrder) {
93 swBuild.start();
94 auto& epochModel = rewardUnfolding.setCurrentEpoch(epoch);
95 swBuild.stop();
96 swCheck.start();
97 rewardUnfolding.setSolutionForCurrentEpoch(epochModel.analyzeSingleObjective(preciseEnv, dir, x, b, minMaxSolver, lowerBound, upperBound));
98 swCheck.stop();
99 if (storm::settings::getModule<storm::settings::modules::IOSettings>().isExportCdfSet() &&
100 !rewardUnfolding.getEpochManager().hasBottomDimension(epoch)) {
101 std::vector<ValueType> cdfEntry;
102 for (uint64_t i = 0; i < rewardUnfolding.getEpochManager().getDimensionCount(); ++i) {
103 uint64_t offset = rewardUnfolding.getDimension(i).boundType == helper::rewardbounded::DimensionBoundType::LowerBound ? 1 : 0;
104 cdfEntry.push_back(storm::utility::convertNumber<ValueType>(rewardUnfolding.getEpochManager().getDimensionOfEpoch(epoch, i) + offset) *
105 rewardUnfolding.getDimension(i).scalingFactor);
106 }
107 cdfEntry.push_back(rewardUnfolding.getInitialStateResult(epoch));
108 cdfData.push_back(std::move(cdfEntry));
109 }
110 ++numCheckedEpochs;
111 progress.updateProgress(numCheckedEpochs);
113 break;
114 }
115 }
116
117 std::map<storm::storage::sparse::state_type, ValueType> result;
118 for (auto initState : initialStates) {
119 result[initState] = rewardUnfolding.getInitialStateResult(initEpoch, initState);
120 }
121
122 swAll.stop();
123
124 if (storm::settings::getModule<storm::settings::modules::IOSettings>().isExportCdfSet()) {
125 std::vector<std::string> headers;
126 for (uint64_t i = 0; i < rewardUnfolding.getEpochManager().getDimensionCount(); ++i) {
127 headers.push_back(rewardUnfolding.getDimension(i).formula->toString());
128 }
129 headers.push_back("Result");
130 storm::io::exportDataToCSVFile<ValueType, std::string, std::string>(
131 storm::settings::getModule<storm::settings::modules::IOSettings>().getExportCdfDirectory() + "cdf.csv", cdfData, headers);
132 }
133
134 if (storm::settings::getModule<storm::settings::modules::CoreSettings>().isShowStatisticsSet()) {
135 STORM_PRINT_AND_LOG("---------------------------------\n");
136 STORM_PRINT_AND_LOG("Statistics:\n");
137 STORM_PRINT_AND_LOG("---------------------------------\n");
138 STORM_PRINT_AND_LOG(" #checked epochs: " << epochOrder.size() << ".\n");
139 STORM_PRINT_AND_LOG(" overall Time: " << swAll << ".\n");
140 STORM_PRINT_AND_LOG("Epoch Model building Time: " << swBuild << ".\n");
141 STORM_PRINT_AND_LOG("Epoch Model checking Time: " << swCheck << ".\n");
142 STORM_PRINT_AND_LOG("---------------------------------\n");
143 }
144
145 return result;
146 }
147}
148
149template<typename ValueType, typename SolutionType>
151 Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
152 storm::storage::BitVector const& nextStates) {
153 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
154 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with reward models.");
155 } else {
156 // Create the vector with which to multiply and initialize it correctly.
157 std::vector<ValueType> result(transitionMatrix.getRowGroupCount());
158 storm::utility::vector::setVectorValues(result, nextStates, storm::utility::one<ValueType>());
159
160 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
161 multiplier->multiplyAndReduce(env, dir, result, nullptr, result);
162
163 return result;
164 }
165}
166
167template<typename ValueType, typename SolutionType = ValueType>
168std::vector<uint_fast64_t> computeValidSchedulerHint(Environment const& env, SemanticSolutionType const& type,
169 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
170 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
171 storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& filterStates,
172 storm::storage::BitVector const& targetStates,
173 boost::optional<storm::storage::BitVector> const& selectedChoices) {
174 storm::storage::Scheduler<SolutionType> validScheduler(maybeStates.size());
175
177 storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, filterStates, targetStates, validScheduler,
178 selectedChoices);
179 } else if (type == SemanticSolutionType::ExpectedRewards) {
180 storm::utility::graph::computeSchedulerProb1E(maybeStates | targetStates, transitionMatrix, backwardTransitions, filterStates, targetStates,
181 validScheduler, selectedChoices);
182 } else {
183 STORM_LOG_ASSERT(false, "Unexpected equation system type.");
184 }
185
186 // Extract the relevant parts of the scheduler for the solver.
187 std::vector<uint64_t> schedulerHint;
188 schedulerHint.reserve(maybeStates.getNumberOfSetBits());
189 if (selectedChoices) {
190 // There might be unselected choices so the local choice indices from the scheduler need to be adapted
191 for (auto maybeState : maybeStates) {
192 auto choice = validScheduler.getChoice(maybeState).getDeterministicChoice();
193 auto const groupStart = transitionMatrix.getRowGroupIndices()[maybeState];
194 auto const origGlobalChoiceIndex = groupStart + choice;
195 STORM_LOG_ASSERT(selectedChoices->get(origGlobalChoiceIndex), "The computed scheduler selects an illegal choice.");
196 // Count the number of unselected choices in [groupStart, origGlobalChoiceIndex) and subtract that from choice
197 for (auto pos = selectedChoices->getNextUnsetIndex(groupStart); pos < origGlobalChoiceIndex; pos = selectedChoices->getNextUnsetIndex(pos + 1)) {
198 --choice;
199 }
200 schedulerHint.push_back(choice);
201 }
202 } else {
203 for (auto maybeState : maybeStates) {
204 schedulerHint.push_back(validScheduler.getChoice(maybeState).getDeterministicChoice());
205 }
206 }
207 return schedulerHint;
208}
209
210template<typename ValueType>
213 // Intentionally left empty.
214 }
215
216 bool hasSchedulerHint() const {
217 return static_cast<bool>(schedulerHint);
218 }
219
220 bool hasValueHint() const {
221 return static_cast<bool>(valueHint);
222 }
223
224 bool hasLowerResultBound() const {
225 return static_cast<bool>(lowerResultBound);
226 }
227
228 ValueType const& getLowerResultBound() const {
229 return lowerResultBound.get();
230 }
231
232 bool hasUpperResultBound() const {
233 return static_cast<bool>(upperResultBound);
234 }
235
236 bool hasUpperResultBounds() const {
237 return static_cast<bool>(upperResultBounds);
238 }
239
240 ValueType const& getUpperResultBound() const {
241 return upperResultBound.get();
242 }
243
244 std::vector<ValueType>& getUpperResultBounds() {
245 return upperResultBounds.get();
246 }
247
248 std::vector<ValueType> const& getUpperResultBounds() const {
249 return upperResultBounds.get();
250 }
251
252 std::vector<uint64_t>& getSchedulerHint() {
253 return schedulerHint.get();
254 }
255
256 std::vector<ValueType>& getValueHint() {
257 return valueHint.get();
258 }
259
262 }
263
265 return computeUpperBounds;
266 }
267
268 bool hasUniqueSolution() const {
269 return uniqueSolution;
270 }
271
272 bool hasNoEndComponents() const {
273 return noEndComponents;
274 }
275
276 boost::optional<std::vector<uint64_t>> schedulerHint;
277 boost::optional<std::vector<ValueType>> valueHint;
278 boost::optional<ValueType> lowerResultBound;
279 boost::optional<ValueType> upperResultBound;
280 boost::optional<std::vector<ValueType>> upperResultBounds;
285};
286
287template<typename ValueType, typename SolutionType>
289 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& maybeStates,
290 boost::optional<storm::storage::BitVector> const& selectedChoices, ModelCheckerHint const& hint,
291 bool skipECWithinMaybeStatesCheck) {
292 // Deal with scheduler hint.
293 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasSchedulerHint()) {
294 if (hintStorage.hasSchedulerHint()) {
295 STORM_LOG_WARN("A scheduler hint was provided, but the solver requires a specific one. The provided scheduler hint will be ignored.");
296 } else {
297 auto const& schedulerHint = hint.template asExplicitModelCheckerHint<ValueType>().getSchedulerHint();
298 std::vector<uint64_t> hintChoices;
299
300 // The scheduler hint is only applicable if it induces no BSCC consisting of maybe states.
301 bool hintApplicable;
302 if (!skipECWithinMaybeStatesCheck) {
303 hintChoices.reserve(maybeStates.size());
304 for (uint_fast64_t state = 0; state < maybeStates.size(); ++state) {
305 hintChoices.push_back(schedulerHint.getChoice(state).getDeterministicChoice());
306 }
307 hintApplicable =
308 storm::utility::graph::performProb1(transitionMatrix.transposeSelectedRowsFromRowGroups(hintChoices), maybeStates, ~maybeStates).full();
309 } else {
310 hintApplicable = true;
311 }
312
313 if (hintApplicable) {
314 // Compute the hint w.r.t. the given subsystem.
315 hintChoices.clear();
316 hintChoices.reserve(maybeStates.getNumberOfSetBits());
317 for (auto state : maybeStates) {
318 uint_fast64_t hintChoice = schedulerHint.getChoice(state).getDeterministicChoice();
319 if (selectedChoices) {
320 uint_fast64_t firstChoice = transitionMatrix.getRowGroupIndices()[state];
321 uint_fast64_t lastChoice = firstChoice + hintChoice;
322 hintChoice = 0;
323 for (uint_fast64_t choice = selectedChoices->getNextSetIndex(firstChoice); choice < lastChoice;
324 choice = selectedChoices->getNextSetIndex(choice + 1)) {
325 ++hintChoice;
326 }
327 }
328 hintChoices.push_back(hintChoice);
329 }
330 hintStorage.schedulerHint = std::move(hintChoices);
331 }
332 }
333 }
334
335 // Deal with solution value hint. Only applicable if there are no End Components consisting of maybe states.
336 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasResultHint() &&
337 (skipECWithinMaybeStatesCheck || hintStorage.hasSchedulerHint() ||
338 storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, maybeStates, ~maybeStates)
339 .full())) {
340 hintStorage.valueHint = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint<SolutionType>().getResultHint(), maybeStates);
341 }
342}
343
344template<typename ValueType, typename SolutionType>
347 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& maybeStates,
348 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& targetStates, bool produceScheduler,
349 boost::optional<storm::storage::BitVector> const& selectedChoices = boost::none) {
351
352 // There are no end components if we minimize until probabilities or
353 // maximize reachability rewards or if the hint tells us so.
354 result.noEndComponents = (dir == storm::solver::OptimizationDirection::Minimize && type == SemanticSolutionType::UntilProbabilities) ||
355 (dir == storm::solver::OptimizationDirection::Maximize && type == SemanticSolutionType::ExpectedRewards) ||
356 (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint<ValueType>().getNoEndComponentsInMaybeStates());
357
358 // If there are no end components, the solution is unique. (Note that the other direction does not hold,
359 // e.g., end components in which infinite reward is collected.
360 result.uniqueSolution = result.hasNoEndComponents();
361
362 // Check for requirements of the solver.
363 bool hasSchedulerHint = hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasSchedulerHint();
366 minMaxLinearEquationSolverFactory.getRequirements(env, result.uniqueSolution, result.noEndComponents, dir, hasSchedulerHint, produceScheduler);
367 if (requirements.hasEnabledRequirement()) {
368 // If the solver still requires no end-components, we have to eliminate them later.
369 if (requirements.uniqueSolution()) {
371 "The solver requires to eliminate the end components although the solution is already assumed to be unique.");
372 STORM_LOG_DEBUG("Scheduling EC elimination, because the solver requires a unique solution.");
373 result.eliminateEndComponents = true;
374 // If end components have been eliminated we can assume a unique solution.
375 result.uniqueSolution = true;
376 requirements.clearUniqueSolution();
377 // If we compute until probabilities, we can even assume the absence of end components.
378 // Note that in the case of minimizing expected rewards there might still be end components in which reward is collected.
380 }
381
382 // If the solver requires an initial scheduler, compute one now. Note that any scheduler is valid if there are no end components.
383 if (requirements.validInitialScheduler() && !result.noEndComponents) {
384 STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
385 result.schedulerHint = computeValidSchedulerHint<ValueType, SolutionType>(env, type, transitionMatrix, backwardTransitions, maybeStates, phiStates,
386 targetStates, selectedChoices);
387 requirements.clearValidInitialScheduler();
388 }
389
390 // Finally, we have information on the bounds depending on the problem type.
392 requirements.clearBounds();
393 } else if (type == SemanticSolutionType::ExpectedRewards) {
394 requirements.clearLowerBounds();
395 }
396 if (requirements.upperBounds()) {
397 result.computeUpperBounds = true;
398 requirements.clearUpperBounds();
399 }
400 STORM_LOG_THROW(!requirements.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
401 "Solver requirements " + requirements.getEnabledRequirementsAsString() + " not checked.");
402 } else {
403 STORM_LOG_DEBUG("Solver has no requirements.");
404 }
405
406 // Only if there is no end component decomposition that we will need to do later, we use value and scheduler
407 // hints from the provided hint.
408 if (!result.eliminateEndComponents) {
409 extractValueAndSchedulerHint(result, transitionMatrix, backwardTransitions, maybeStates, selectedChoices, hint, result.uniqueSolution);
410 } else {
411 if (hint.isEmpty()) {
412 STORM_LOG_TRACE("Warn A non-empty hint was provided, but its information will be disregarded.");
413 }
414 }
415
416 // Only set bounds if we did not obtain them from the hint.
417 if (!result.hasLowerResultBound()) {
418 result.lowerResultBound = storm::utility::zero<SolutionType>();
419 }
421 result.upperResultBound = storm::utility::one<SolutionType>();
422 }
423
424 // If we received an upper bound, we can drop the requirement to compute one.
425 if (result.hasUpperResultBound()) {
426 result.computeUpperBounds = false;
427 }
428
429 return result;
430}
431
432template<typename ValueType>
434 MaybeStateResult(std::vector<ValueType>&& values) : values(std::move(values)) {
435 // Intentionally left empty.
436 }
437
438 bool hasScheduler() const {
439 return static_cast<bool>(scheduler);
440 }
441
442 std::vector<uint64_t> const& getScheduler() const {
443 return scheduler.get();
444 }
445
446 std::vector<ValueType> const& getValues() const {
447 return values;
448 }
449
450 std::vector<ValueType> values;
451 boost::optional<std::vector<uint64_t>> scheduler;
452};
453
454template<typename ValueType, typename SolutionType>
456 storm::storage::SparseMatrix<ValueType>&& submatrix, std::vector<ValueType> const& b,
457 bool produceScheduler, SparseMdpHintType<SolutionType>& hint) {
458 // Initialize the solution vector.
459 std::vector<SolutionType> x =
460 hint.hasValueHint() ? std::move(hint.getValueHint())
461 : std::vector<SolutionType>(submatrix.getRowGroupCount(),
462 hint.hasLowerResultBound() ? hint.getLowerResultBound() : storm::utility::zero<SolutionType>());
463
464 // Set up the solver.
466 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType, SolutionType>> solver =
467 storm::solver::configureMinMaxLinearEquationSolver(env, std::move(goal), minMaxLinearEquationSolverFactory, std::move(submatrix));
468 solver->setRequirementsChecked();
469 solver->setUncertaintyIsRobust(goal.isRobust());
470 solver->setHasUniqueSolution(hint.hasUniqueSolution());
471 solver->setHasNoEndComponents(hint.hasNoEndComponents());
472 if (hint.hasLowerResultBound()) {
473 solver->setLowerBound(hint.getLowerResultBound());
474 }
475 if (hint.hasUpperResultBound()) {
476 solver->setUpperBound(hint.getUpperResultBound());
477 }
478 if (hint.hasUpperResultBounds()) {
479 solver->setUpperBounds(std::move(hint.getUpperResultBounds()));
480 }
481 if (hint.hasSchedulerHint()) {
482 solver->setInitialScheduler(std::move(hint.getSchedulerHint()));
483 }
484 solver->setTrackScheduler(produceScheduler);
485
486 // Solve the corresponding system of equations.
487 solver->solveEquations(env, x, b);
488
489#ifndef NDEBUG
490 // As a sanity check, make sure our local upper bounds were in fact correct.
492 auto resultIt = x.begin();
493 for (auto const& entry : solver->getUpperBounds()) {
495 *resultIt <= entry + storm::utility::convertNumber<ValueType>(env.solver().minMax().getPrecision()),
496 "Expecting result value for state " << std::distance(x.begin(), resultIt) << " to be <= " << entry << ", but got " << *resultIt << ".");
497 ++resultIt;
498 }
499 }
500#endif
501
502 // Create result.
503 MaybeStateResult<SolutionType> result(std::move(x));
504
505 // If requested, return the requested scheduler.
506 if (produceScheduler) {
507 result.scheduler = std::move(solver->getSchedulerChoices());
508 }
509 return result;
510}
511
517
518template<typename ValueType>
521 result.maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
522
523 // Treat the states with probability zero/one.
524 std::vector<ValueType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getResultHint();
527 storm::storage::BitVector nonMaybeStates = ~result.maybeStates;
528 for (auto state : nonMaybeStates) {
529 if (storm::utility::isOne(resultsForNonMaybeStates[state])) {
530 result.statesWithProbability1.set(state, true);
531 } else {
532 STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException,
533 "Expected that the result hint specifies probabilities in {0,1} for non-maybe states");
534 result.statesWithProbability0.set(state, true);
535 }
536 }
537
538 return result;
539}
540
541template<typename ValueType, typename SolutionType>
543 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
544 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
545 storm::storage::BitVector const& phiStates,
546 storm::storage::BitVector const& psiStates) {
548
549 // Get all states that have probability 0 and 1 of satisfying the until-formula.
550 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01;
551 if (goal.minimize()) {
552 statesWithProbability01 =
553 storm::utility::graph::performProb01Min(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
554 } else {
555 statesWithProbability01 =
556 storm::utility::graph::performProb01Max(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
557 }
558 result.statesWithProbability0 = std::move(statesWithProbability01.first);
559 result.statesWithProbability1 = std::move(statesWithProbability01.second);
561
562 return result;
563}
564
565template<typename ValueType, typename SolutionType>
567 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
568 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
569 storm::storage::BitVector const& phiStates,
570 storm::storage::BitVector const& psiStates, ModelCheckerHint const& hint) {
571 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
572 return getQualitativeStateSetsUntilProbabilitiesFromHint<ValueType>(hint);
573 } else {
574 return computeQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates);
575 }
576}
577
578template<typename SolutionType, bool subChoicesCoverOnlyMaybeStates = true>
579void extractSchedulerChoices(storm::storage::Scheduler<SolutionType>& scheduler, std::vector<uint64_t> const& subChoices,
580 storm::storage::BitVector const& maybeStates) {
581 if constexpr (subChoicesCoverOnlyMaybeStates) {
582 auto subChoiceIt = subChoices.begin();
583 for (auto maybeState : maybeStates) {
584 scheduler.setChoice(*subChoiceIt, maybeState);
585 ++subChoiceIt;
586 }
587 assert(subChoiceIt == subChoices.end());
588 } else {
589 // See computeFixedPointSystemUntilProbabilities, where we create a different equation system.
590 // Consequentially, we run a slightly different code here for interval-based models.
591 STORM_LOG_ASSERT(maybeStates.size() == subChoices.size(), "Sizes do not coincide.");
592 for (auto maybeState : maybeStates) {
593 scheduler.setChoice(subChoices[maybeState], maybeState);
594 }
595 }
596}
597
598template<typename ValueType, typename SolutionType>
600 QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
601 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates,
602 storm::storage::BitVector const& psiStates) {
603 // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for
604 // the states with probability 1 or 0 (depending on whether we maximize or minimize).
605 // We also need to define some arbitrary choice for the remaining states to obtain a fully defined scheduler.
606 if (goal.minimize()) {
607 storm::utility::graph::computeSchedulerProb0E(qualitativeStateSets.statesWithProbability0, transitionMatrix, scheduler);
608 for (auto prob1State : qualitativeStateSets.statesWithProbability1) {
609 scheduler.setChoice(0, prob1State);
610 }
611 } else {
612 storm::utility::graph::computeSchedulerProb1E(qualitativeStateSets.statesWithProbability1, transitionMatrix, backwardTransitions, phiStates, psiStates,
613 scheduler);
614 for (auto prob0State : qualitativeStateSets.statesWithProbability0) {
615 scheduler.setChoice(0, prob0State);
616 }
617 }
618}
619
620template<typename ValueType, typename SolutionType>
622 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
623 QualitativeStateSetsUntilProbabilities const& qualitativeStateSets,
624 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b) {
625 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
626 // For non-interval based models, we can eliminate the rows and columns from the original transition probability matrix for states
627 // whose probabilities are already known... However, there is information in the transition to those states.
628 // Thus, we cannot eliminate them all.
629 // We can however drop all the outgoing transitions from these states.
630 // TODO: we can drop more than those entries and actually remove many states (all but the ones reachable in one step from the maybe states),
631 // TODO ctned: however, there is quite some bookkeeping involved in projecting the right vectors.
632 // TODO ctned: Instead is likely easier to just do a pass and make a unique sink and a unique target state.
633 // TODO ctned: If this is ever changed, extractSchedulerChoices must also be updated.
634 submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(qualitativeStateSets.maybeStates));
635
636 // Prepare the right-hand side of the equation system. For entry i this corresponds to
637 // the accumulated probability of going from state i to some state that has probability 1.
638 storm::utility::vector::setAllValues(b, transitionMatrix.getRowFilter(qualitativeStateSets.statesWithProbability1));
639 } else {
640 // First, we can eliminate the rows and columns from the original transition probability matrix for states
641 // whose probabilities are already known.
642 submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false);
643
644 // Prepare the right-hand side of the equation system. For entry i this corresponds to
645 // the accumulated probability of going from state i to some state that has probability 1.
646 b = transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, qualitativeStateSets.statesWithProbability1);
647 }
648 // If the solve goal has relevant values, we need to adjust them.
649 goal.restrictRelevantValues(qualitativeStateSets.maybeStates);
650}
651
652template<typename ValueType, typename SolutionType>
653boost::optional<SparseMdpEndComponentInformation<ValueType>> computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(
655 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets,
656 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b, bool produceScheduler) {
657 // Get the set of states that (under some scheduler) can stay in the set of maybestates forever
659 transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, qualitativeStateSets.maybeStates, ~qualitativeStateSets.maybeStates);
660
661 bool doDecomposition = !candidateStates.empty();
662
664 if (doDecomposition) {
665 // Compute the states that are in MECs.
666 endComponentDecomposition = storm::storage::MaximalEndComponentDecomposition<ValueType>(transitionMatrix, backwardTransitions, candidateStates);
667 STORM_LOG_INFO(endComponentDecomposition.statistics(transitionMatrix.getRowGroupCount()));
668 }
669
670 // Only do more work if there are actually end-components.
671 if (doDecomposition && !endComponentDecomposition.empty()) {
672 STORM_LOG_DEBUG("Eliminating " << endComponentDecomposition.size() << " EC(s).");
674 endComponentDecomposition, transitionMatrix, qualitativeStateSets.maybeStates, &qualitativeStateSets.statesWithProbability1, nullptr, nullptr,
675 submatrix, &b, nullptr, produceScheduler);
676
677 // If the solve goal has relevant values, we need to adjust them.
678 if (goal.hasRelevantValues()) {
679 storm::storage::BitVector newRelevantValues(submatrix.getRowGroupCount());
680 for (auto state : goal.relevantValues()) {
681 if (qualitativeStateSets.maybeStates.get(state)) {
682 newRelevantValues.set(result.getRowGroupAfterElimination(state));
683 }
684 }
685 if (!newRelevantValues.empty()) {
686 goal.setRelevantValues(std::move(newRelevantValues));
687 }
688 }
689
690 return result;
691 } else {
692 STORM_LOG_DEBUG("Not eliminating ECs as there are none.");
693 computeFixedPointSystemUntilProbabilities(goal, transitionMatrix, qualitativeStateSets, submatrix, b);
694
695 return boost::none;
696 }
697}
698
699template<typename ValueType, typename SolutionType>
702 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
703 bool qualitative, bool produceScheduler, ModelCheckerHint const& hint) {
704 STORM_LOG_THROW(!qualitative || !produceScheduler, storm::exceptions::InvalidSettingsException,
705 "Cannot produce scheduler when performing qualitative model checking only.");
706
707 // Prepare resulting vector.
708 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
709
710 // We need to identify the maybe states (states which have a probability for satisfying the until formula
711 // that is strictly between 0 and 1) and the states that satisfy the formula with probablity 1 and 0, respectively.
712 QualitativeStateSetsUntilProbabilities qualitativeStateSets =
713 getQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates, hint);
714
715 STORM_LOG_INFO("Preprocessing: " << qualitativeStateSets.statesWithProbability1.getNumberOfSetBits() << " states with probability 1, "
716 << qualitativeStateSets.statesWithProbability0.getNumberOfSetBits() << " with probability 0 ("
717 << qualitativeStateSets.maybeStates.getNumberOfSetBits() << " states remaining).");
718
719 // Set values of resulting vector that are known exactly.
720 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.statesWithProbability1, storm::utility::one<SolutionType>());
721
722 // Check if the values of the maybe states are relevant for the SolveGoal
723 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(qualitativeStateSets.maybeStates);
724
725 // If requested, we will produce a scheduler.
726 std::unique_ptr<storm::storage::Scheduler<SolutionType>> scheduler;
727 if (produceScheduler) {
728 scheduler = std::make_unique<storm::storage::Scheduler<SolutionType>>(transitionMatrix.getRowGroupCount());
729 // If maybeStatesNotRelevant is true, we have to set the scheduler for maybe states as "dontCare"
730 if (maybeStatesNotRelevant) {
731 for (auto state : qualitativeStateSets.maybeStates) {
732 scheduler->setDontCare(state);
733 }
734 }
735 }
736
737 // Check whether we need to compute exact probabilities for some states.
738 if (qualitative || maybeStatesNotRelevant) {
739 // Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1.
740 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, storm::utility::convertNumber<SolutionType>(0.5));
741 } else {
742 if (!qualitativeStateSets.maybeStates.empty()) {
743 // In this case we have have to compute the remaining probabilities.
744
745 // Obtain proper hint information either from the provided hint or from requirements of the solver.
746 SparseMdpHintType<SolutionType> hintInformation = computeHints<ValueType, SolutionType>(
747 env, SemanticSolutionType::UntilProbabilities, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates,
748 phiStates, qualitativeStateSets.statesWithProbability1, produceScheduler);
749
750 // Declare the components of the equation system we will solve.
752 std::vector<ValueType> b;
753
754 // If the hint information tells us that we have to eliminate MECs, we do so now.
755 boost::optional<SparseMdpEndComponentInformation<ValueType>> ecInformation;
756 if (hintInformation.getEliminateEndComponents()) {
757 ecInformation = computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(goal, transitionMatrix, backwardTransitions,
758 qualitativeStateSets, submatrix, b, produceScheduler);
759 } else {
760 // Otherwise, we compute the standard equations.
761 computeFixedPointSystemUntilProbabilities(goal, transitionMatrix, qualitativeStateSets, submatrix, b);
762 }
763
764 // Now compute the results for the maybe states.
765 MaybeStateResult<SolutionType> resultForMaybeStates =
766 computeValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, produceScheduler, hintInformation);
767
768 // If we eliminated end components, we need to extract the result differently.
769 if (ecInformation && ecInformation.get().getEliminatedEndComponents()) {
770 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
771 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support this end component with interval models.");
772 } else {
773 ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
774 if (produceScheduler) {
775 ecInformation.get().setScheduler(*scheduler, qualitativeStateSets.maybeStates, transitionMatrix, backwardTransitions,
776 resultForMaybeStates.getScheduler());
777 }
778 }
779 } else {
780 // Set values of resulting vector according to result.
781 if constexpr (!std::is_same_v<ValueType, storm::Interval>) {
782 // For non-interval models, we only operated on the maybe states, and we must recover the qualitative values for the other state.
783 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
784 } else {
785 // For interval models, the result for maybe states indeed also holds values for all qualitative states.
786 STORM_LOG_ASSERT(resultForMaybeStates.getValues().size() == transitionMatrix.getColumnCount(), "Dimensions do not match");
787 result = resultForMaybeStates.getValues();
788 }
789 if (produceScheduler) {
790 extractSchedulerChoices<SolutionType, !std::is_same_v<ValueType, storm::Interval>>(*scheduler, resultForMaybeStates.getScheduler(),
791 qualitativeStateSets.maybeStates);
792 }
793 }
794 }
795 }
796
797 // Extend scheduler with choices for the states in the qualitative state sets.
798 if (produceScheduler) {
799 extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, backwardTransitions, phiStates, psiStates);
800 }
801
802 // Sanity check for created scheduler.
803 STORM_LOG_ASSERT(!produceScheduler || scheduler, "Expected that a scheduler was obtained.");
804 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || !scheduler->isPartialScheduler(), "Expected a fully defined scheduler");
805 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isDeterministicScheduler(), "Expected a deterministic scheduler");
806 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler");
807
808 // Return result.
809 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(result), std::move(scheduler));
810}
811
812template<typename ValueType, typename SolutionType>
815 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler,
816 bool useMecBasedTechnique) {
817 if (useMecBasedTechnique) {
818 // TODO: does this really work for minimizing objectives?
819 storm::storage::MaximalEndComponentDecomposition<ValueType> mecDecomposition(transitionMatrix, backwardTransitions, psiStates);
820 storm::storage::BitVector statesInPsiMecs(transitionMatrix.getRowGroupCount());
821 for (auto const& mec : mecDecomposition) {
822 for (auto const& stateActionsPair : mec) {
823 statesInPsiMecs.set(stateActionsPair.first, true);
824 }
825 }
826
827 return computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions, psiStates, statesInPsiMecs, qualitative,
828 produceScheduler);
829 } else {
830 goal.oneMinus();
831 auto result =
832 computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions,
833 storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), ~psiStates, qualitative, produceScheduler);
834 for (auto& element : result.values) {
835 element = storm::utility::one<SolutionType>() - element;
836 }
837 return result;
838 }
839}
840
841template<typename ValueType, typename SolutionType>
842template<typename RewardModelType>
845 RewardModelType const& rewardModel, uint_fast64_t stepCount) {
846 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
847 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantenous rewards with interval models.");
848 } else {
849 // Only compute the result if the model has a state-based reward this->getModel().
850 STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException,
851 "Computing instantaneous rewards for a reward model that does not define any state-rewards. The result is trivially 0.");
852 // Initialize result to state rewards of the this->getModel().
853 std::vector<SolutionType> result(rewardModel.getStateRewardVector());
854
855 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
856 multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, nullptr, stepCount);
857
858 return result;
859 }
860}
861
862template<typename ValueType, typename SolutionType>
863template<typename RewardModelType>
866 RewardModelType const& rewardModel, uint_fast64_t stepBound) {
867 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
868 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models.");
869 } else {
870 // Only compute the result if the model has at least one reward this->getModel().
871 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
872
873 // Compute the reward vector to add in each step based on the available reward models.
874 std::vector<ValueType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
875
876 // Initialize result to the zero vector.
877 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
878
879 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
880 multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, &totalRewardVector, stepBound);
881
882 return result;
883 }
884}
885
886template<typename ValueType, typename SolutionType>
887template<typename RewardModelType>
890 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, bool produceScheduler,
891 ModelCheckerHint const& hint) {
892 STORM_LOG_THROW(!rewardModel.hasNegativeRewards(), storm::exceptions::NotImplementedException,
893 "The reward model contains negative rewards. This is not implemented by the total rewards computation.");
894 // Reduce to reachability rewards
895 if (goal.minimize()) {
896 // Identify the states from which no reward can be collected under some scheduler
897 storm::storage::BitVector choicesWithoutReward = rewardModel.getChoicesWithZeroReward(transitionMatrix);
898 storm::storage::BitVector statesWithZeroRewardChoice(transitionMatrix.getRowGroupCount(), false);
899 for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) {
900 if (choicesWithoutReward.getNextSetIndex(transitionMatrix.getRowGroupIndices()[state]) < transitionMatrix.getRowGroupIndices()[state + 1]) {
901 statesWithZeroRewardChoice.set(state);
902 }
903 }
904 storm::storage::BitVector rew0EStates =
905 storm::utility::graph::performProbGreater0A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions,
906 statesWithZeroRewardChoice, ~statesWithZeroRewardChoice, false, 0, choicesWithoutReward);
907 rew0EStates.complement();
908 auto result = computeReachabilityRewards(env, std::move(goal), transitionMatrix, backwardTransitions, rewardModel, rew0EStates, qualitative,
909 produceScheduler, hint);
910 if (result.scheduler) {
911 storm::utility::graph::computeSchedulerStayingInStates(rew0EStates, transitionMatrix, *result.scheduler, choicesWithoutReward);
912 }
913 return result;
914 } else {
915 // Identify the states from which only states with zero reward are reachable.
916 storm::storage::BitVector statesWithoutReward = rewardModel.getStatesWithZeroReward(transitionMatrix);
917 storm::storage::BitVector rew0AStates = storm::utility::graph::performProbGreater0E(backwardTransitions, statesWithoutReward, ~statesWithoutReward);
918 rew0AStates.complement();
919
920 // There might be end components that consists only of states/choices with zero rewards. The reachability reward semantics would assign such
921 // end components reward infinity. To avoid this, we potentially need to eliminate such end components
922 storm::storage::BitVector trueStates(transitionMatrix.getRowGroupCount(), true);
923 if (storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, rew0AStates)
924 .full()) {
925 return computeReachabilityRewards(env, std::move(goal), transitionMatrix, backwardTransitions, rewardModel, rew0AStates, qualitative,
926 produceScheduler, hint);
927 } else {
928 // The transformation of schedulers for the ec-eliminated system back to the original one is not implemented.
929 STORM_LOG_ERROR_COND(!produceScheduler, "Can not produce scheduler for this property (functionality not implemented");
930 storm::storage::BitVector choicesWithoutReward = rewardModel.getChoicesWithZeroReward(transitionMatrix);
932 transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), choicesWithoutReward, rew0AStates, true);
933 storm::storage::BitVector newRew0AStates(ecElimResult.matrix.getRowGroupCount(), false);
934 for (auto oldRew0AState : rew0AStates) {
935 newRew0AStates.set(ecElimResult.oldToNewStateMapping[oldRew0AState]);
936 }
937
938 if (goal.hasRelevantValues()) {
939 storm::storage::BitVector newRelevantValues(ecElimResult.matrix.getRowGroupCount(), false);
940 for (auto oldRelevantState : goal.relevantValues()) {
941 newRelevantValues.set(ecElimResult.oldToNewStateMapping[oldRelevantState]);
942 }
943 goal.relevantValues() = std::move(newRelevantValues);
944 }
945
946 MDPSparseModelCheckingHelperReturnType<SolutionType> result = computeReachabilityRewardsHelper(
947 env, std::move(goal), ecElimResult.matrix, ecElimResult.matrix.transpose(true),
948 [&](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const& newTransitionMatrix, storm::storage::BitVector const& maybeStates) {
949 std::vector<ValueType> result;
950 std::vector<ValueType> oldChoiceRewards = rewardModel.getTotalRewardVector(transitionMatrix);
951 result.reserve(rowCount);
952 for (uint64_t newState : maybeStates) {
953 for (auto newChoice : newTransitionMatrix.getRowGroupIndices(newState)) {
954 uint64_t oldChoice = ecElimResult.newToOldRowMapping[newChoice];
955 result.push_back(oldChoiceRewards[oldChoice]);
956 }
957 }
958 STORM_LOG_ASSERT(result.size() == rowCount, "Unexpected size of reward vector.");
959 return result;
960 },
961 newRew0AStates, qualitative, false,
962 [&]() {
963 storm::storage::BitVector newStatesWithoutReward(ecElimResult.matrix.getRowGroupCount(), false);
964 for (auto oldStateWithoutRew : statesWithoutReward) {
965 newStatesWithoutReward.set(ecElimResult.oldToNewStateMapping[oldStateWithoutRew]);
966 }
967 return newStatesWithoutReward;
968 },
969 [&]() {
970 storm::storage::BitVector newChoicesWithoutReward(ecElimResult.matrix.getRowGroupCount(), false);
971 for (uint64_t newChoice = 0; newChoice < ecElimResult.matrix.getRowCount(); ++newChoice) {
972 if (choicesWithoutReward.get(ecElimResult.newToOldRowMapping[newChoice])) {
973 newChoicesWithoutReward.set(newChoice);
974 }
975 }
976 return newChoicesWithoutReward;
977 });
978
979 std::vector<SolutionType> resultInEcQuotient = std::move(result.values);
980 result.values.resize(ecElimResult.oldToNewStateMapping.size());
981 storm::utility::vector::selectVectorValues(result.values, ecElimResult.oldToNewStateMapping, resultInEcQuotient);
982 return result;
983 }
984 }
985}
986
987template<typename ValueType, typename SolutionType>
988template<typename RewardModelType>
991 RewardModelType const& rewardModel, uint_fast64_t stepBound, ValueType discountFactor) {
992 // Only compute the result if the model has at least one reward this->getModel().
993 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
994
995 // Compute the reward vector to add in each step based on the available reward models.
996 std::vector<SolutionType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
997
998 // Initialize result to the zero vector.
999 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
1000
1001 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
1002 multiplier->repeatedMultiplyAndReduceWithFactor(env, goal.direction(), result, &totalRewardVector, stepBound, discountFactor);
1003
1004 return result;
1005}
1006
1007template<typename ValueType, typename SolutionType>
1008template<typename RewardModelType>
1011 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, bool produceScheduler,
1012 ValueType discountFactor, ModelCheckerHint const& hint) {
1013 // If the solver is set to force exact results, throw an error
1014 STORM_LOG_THROW(!env.solver().isForceExact(), storm::exceptions::NotSupportedException,
1015 "Exact solving of discounted total reward objectives is currently not supported.");
1016
1017 std::vector<ValueType> b;
1018
1019 std::vector<SolutionType> x = std::vector<SolutionType>(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
1020 b = rewardModel.getTotalRewardVector(transitionMatrix);
1021 storm::modelchecker::helper::DiscountingHelper<ValueType> discountingHelper(transitionMatrix, discountFactor, produceScheduler);
1022
1023 discountingHelper.solveWithDiscountedValueIteration(env, goal.direction(), x, b);
1024
1025 std::unique_ptr<storm::storage::Scheduler<SolutionType>> scheduler;
1026 if (produceScheduler) {
1027 scheduler = std::make_unique<storm::storage::Scheduler<ValueType>>(discountingHelper.computeScheduler());
1028 }
1029 STORM_LOG_ASSERT(!produceScheduler || scheduler, "Expected that a scheduler was obtained.");
1030 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || !scheduler->isPartialScheduler(), "Expected a fully defined scheduler");
1031 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isDeterministicScheduler(), "Expected a deterministic scheduler");
1032 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler");
1033 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(x), std::move(scheduler));
1034}
1035
1036template<typename ValueType, typename SolutionType>
1037template<typename RewardModelType>
1040 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates,
1041 bool qualitative, bool produceScheduler, ModelCheckerHint const& hint) {
1042 // Only compute the result if the model has at least one reward this->getModel().
1043 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Reward model for formula is empty. Skipping formula.");
1044 return computeReachabilityRewardsHelper(
1045 env, std::move(goal), transitionMatrix, backwardTransitions,
1046 [&rewardModel](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
1047 return rewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates);
1048 },
1049 targetStates, qualitative, produceScheduler, [&]() { return rewardModel.getStatesWithZeroReward(transitionMatrix); },
1050 [&]() { return rewardModel.getChoicesWithZeroReward(transitionMatrix); }, hint);
1051}
1052
1053template<typename ValueType, typename SolutionType>
1056 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler,
1057 ModelCheckerHint const& hint) {
1058 return computeReachabilityRewardsHelper(
1059 env, std::move(goal), transitionMatrix, backwardTransitions,
1060 [](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&) {
1061 return std::vector<ValueType>(rowCount, storm::utility::one<ValueType>());
1062 },
1063 targetStates, qualitative, produceScheduler, [&]() { return storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); },
1064 [&]() { return storm::storage::BitVector(transitionMatrix.getRowCount(), false); }, hint);
1065}
1066
1067#ifdef STORM_HAVE_CARL
1068template<typename ValueType, typename SolutionType>
1072 bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative) {
1073 // Only compute the result if the reward model is not empty.
1074 STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
1075 return computeReachabilityRewardsHelper(
1076 env, std::move(goal), transitionMatrix, backwardTransitions,
1077 [&](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
1078 std::vector<ValueType> result;
1079 result.reserve(rowCount);
1080 std::vector<storm::Interval> subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates);
1081 for (auto const& interval : subIntervalVector) {
1082 result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper());
1083 }
1084 return result;
1085 },
1086 targetStates, qualitative, false,
1087 [&]() {
1088 return intervalRewardModel.getStatesWithFilter(
1089 transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); });
1090 },
1091 [&]() {
1092 return intervalRewardModel.getChoicesWithFilter(
1093 transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); });
1094 })
1095 .values;
1096}
1097
1098template<>
1099std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeReachabilityRewards(
1102 storm::storage::BitVector const&, bool) {
1103 STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type.");
1104}
1105#endif
1106
1112
1113template<typename ValueType>
1115 storm::storage::BitVector const& targetStates) {
1117 result.maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
1118
1119 // Treat the states with reward zero/infinity.
1120 std::vector<ValueType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getResultHint();
1123 storm::storage::BitVector nonMaybeStates = ~result.maybeStates;
1124 for (auto state : nonMaybeStates) {
1125 if (storm::utility::isZero(resultsForNonMaybeStates[state])) {
1126 result.rewardZeroStates.set(state, true);
1127 } else {
1128 STORM_LOG_THROW(storm::utility::isInfinity(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException,
1129 "Expected that the result hint specifies probabilities in {0,infinity} for non-maybe states");
1130 result.infinityStates.set(state, true);
1131 }
1132 }
1133 return result;
1134}
1135
1136template<typename ValueType, typename SolutionType>
1139 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
1140 std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter, std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter) {
1142 storm::storage::BitVector trueStates(transitionMatrix.getRowGroupCount(), true);
1143 if (goal.minimize()) {
1144 result.infinityStates =
1145 storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, targetStates);
1146 } else {
1147 result.infinityStates =
1148 storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, targetStates);
1149 }
1150 result.infinityStates.complement();
1151
1152 if (storm::settings::getModule<storm::settings::modules::ModelCheckerSettings>().isFilterRewZeroSet()) {
1153 if (goal.minimize()) {
1154 result.rewardZeroStates = storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions,
1155 trueStates, targetStates, zeroRewardChoicesGetter());
1156 } else {
1157 result.rewardZeroStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions,
1158 zeroRewardStatesGetter(), targetStates);
1159 }
1160 } else {
1161 result.rewardZeroStates = targetStates;
1162 }
1163 result.maybeStates = ~(result.rewardZeroStates | result.infinityStates);
1164 return result;
1165}
1166
1167template<typename ValueType, typename SolutionType>
1169 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
1170 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
1171 storm::storage::BitVector const& targetStates, ModelCheckerHint const& hint,
1172 std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter,
1173 std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter) {
1174 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
1175 return getQualitativeStateSetsReachabilityRewardsFromHint<ValueType>(hint, targetStates);
1176 } else {
1177 return computeQualitativeStateSetsReachabilityRewards(goal, transitionMatrix, backwardTransitions, targetStates, zeroRewardStatesGetter,
1178 zeroRewardChoicesGetter);
1179 }
1180}
1181
1182template<typename ValueType, typename SolutionType>
1184 QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
1185 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
1186 std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter) {
1187 // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for
1188 // the states with reward zero/infinity.
1189 if (goal.minimize()) {
1190 storm::utility::graph::computeSchedulerProb1E(qualitativeStateSets.rewardZeroStates, transitionMatrix, backwardTransitions,
1191 qualitativeStateSets.rewardZeroStates, targetStates, scheduler, zeroRewardChoicesGetter());
1192 for (auto state : qualitativeStateSets.infinityStates) {
1193 scheduler.setChoice(0, state);
1194 }
1195 } else {
1196 storm::utility::graph::computeSchedulerRewInf(qualitativeStateSets.infinityStates, transitionMatrix, backwardTransitions, scheduler);
1197 for (auto state : qualitativeStateSets.rewardZeroStates) {
1198 scheduler.setChoice(0, state);
1199 }
1200 }
1201}
1202
1203template<typename ValueType, typename SolutionType>
1205 std::vector<uint_fast64_t> const& subChoices, storm::storage::BitVector const& maybeStates,
1206 boost::optional<storm::storage::BitVector> const& selectedChoices) {
1207 auto subChoiceIt = subChoices.begin();
1208 if (selectedChoices) {
1209 for (auto maybeState : maybeStates) {
1210 // find the rowindex that corresponds to the selected row of the submodel
1211 uint_fast64_t firstRowIndex = transitionMatrix.getRowGroupIndices()[maybeState];
1212 uint_fast64_t selectedRowIndex = selectedChoices->getNextSetIndex(firstRowIndex);
1213 for (uint_fast64_t choice = 0; choice < *subChoiceIt; ++choice) {
1214 selectedRowIndex = selectedChoices->getNextSetIndex(selectedRowIndex + 1);
1215 }
1216 scheduler.setChoice(selectedRowIndex - firstRowIndex, maybeState);
1217 ++subChoiceIt;
1218 }
1219 } else {
1220 for (auto maybeState : maybeStates) {
1221 scheduler.setChoice(*subChoiceIt, maybeState);
1222 ++subChoiceIt;
1223 }
1224 }
1225 assert(subChoiceIt == subChoices.end());
1226}
1227
1228template<typename ValueType, typename SolutionType>
1231 QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, boost::optional<storm::storage::BitVector> const& selectedChoices,
1232 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
1233 totalStateRewardVectorGetter,
1234 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b, std::vector<ValueType>* oneStepTargetProbabilities = nullptr) {
1235 // Remove rows and columns from the original transition probability matrix for states whose reward values are already known.
1236 // If there are infinity states, we additionally have to remove choices of maybeState that lead to infinity.
1237 if (qualitativeStateSets.infinityStates.empty()) {
1238 submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false);
1239 b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, qualitativeStateSets.maybeStates);
1240 if (oneStepTargetProbabilities) {
1241 (*oneStepTargetProbabilities) =
1242 transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, qualitativeStateSets.rewardZeroStates);
1243 }
1244 } else {
1245 submatrix = transitionMatrix.getSubmatrix(false, *selectedChoices, qualitativeStateSets.maybeStates, false);
1246 b = totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix,
1247 storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true));
1249 if (oneStepTargetProbabilities) {
1250 (*oneStepTargetProbabilities) = transitionMatrix.getConstrainedRowSumVector(*selectedChoices, qualitativeStateSets.rewardZeroStates);
1251 }
1252 }
1253
1254 // If the solve goal has relevant values, we need to adjust them.
1255 goal.restrictRelevantValues(qualitativeStateSets.maybeStates);
1256}
1257
1258template<typename ValueType, typename SolutionType>
1259boost::optional<SparseMdpEndComponentInformation<ValueType>> computeFixedPointSystemReachabilityRewardsEliminateEndComponents(
1261 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, QualitativeStateSetsReachabilityRewards const& qualitativeStateSets,
1262 boost::optional<storm::storage::BitVector> const& selectedChoices,
1263 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
1264 totalStateRewardVectorGetter,
1265 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b, boost::optional<std::vector<ValueType>>& oneStepTargetProbabilities,
1266 bool produceScheduler) {
1267 // Start by computing the choices with reward 0, as we only want ECs within this fragment.
1268 storm::storage::BitVector zeroRewardChoices(transitionMatrix.getRowCount());
1269
1270 // Get the rewards of all choices.
1271 std::vector<ValueType> rewardVector =
1272 totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true));
1273
1274 uint64_t index = 0;
1275 for (auto const& e : rewardVector) {
1276 if (storm::utility::isZero(e)) {
1277 zeroRewardChoices.set(index);
1278 }
1279 ++index;
1280 }
1281
1282 // Compute the states that have some zero reward choice.
1283 storm::storage::BitVector candidateStates(qualitativeStateSets.maybeStates);
1284 for (auto state : qualitativeStateSets.maybeStates) {
1285 bool keepState = false;
1286
1287 for (auto row = transitionMatrix.getRowGroupIndices()[state], rowEnd = transitionMatrix.getRowGroupIndices()[state + 1]; row < rowEnd; ++row) {
1288 if (zeroRewardChoices.get(row)) {
1289 keepState = true;
1290 break;
1291 }
1292 }
1293
1294 if (!keepState) {
1295 candidateStates.set(state, false);
1296 }
1297 }
1298
1299 // Only keep the candidate states that (under some scheduler) can stay in the set of candidates forever
1300 candidateStates =
1301 storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, candidateStates, ~candidateStates);
1302
1303 bool doDecomposition = !candidateStates.empty();
1304
1306 if (doDecomposition) {
1307 // Then compute the states that are in MECs with zero reward.
1308 endComponentDecomposition =
1309 storm::storage::MaximalEndComponentDecomposition<ValueType>(transitionMatrix, backwardTransitions, candidateStates, zeroRewardChoices);
1310 STORM_LOG_INFO(endComponentDecomposition.statistics(transitionMatrix.getRowGroupCount()));
1311 }
1312
1313 // Only do more work if there are actually end-components.
1314 if (doDecomposition && !endComponentDecomposition.empty()) {
1315 STORM_LOG_DEBUG("Eliminating " << endComponentDecomposition.size() << " ECs.");
1317 endComponentDecomposition, transitionMatrix, qualitativeStateSets.maybeStates,
1318 oneStepTargetProbabilities ? &qualitativeStateSets.rewardZeroStates : nullptr, selectedChoices ? &selectedChoices.get() : nullptr, &rewardVector,
1319 submatrix, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr, &b, produceScheduler);
1320
1321 // If the solve goal has relevant values, we need to adjust them.
1322 if (goal.hasRelevantValues()) {
1323 storm::storage::BitVector newRelevantValues(submatrix.getRowGroupCount());
1324 for (auto state : goal.relevantValues()) {
1325 if (qualitativeStateSets.maybeStates.get(state)) {
1326 newRelevantValues.set(result.getRowGroupAfterElimination(state));
1327 }
1328 }
1329 if (!newRelevantValues.empty()) {
1330 goal.setRelevantValues(std::move(newRelevantValues));
1331 }
1332 }
1333
1334 return result;
1335 } else {
1336 STORM_LOG_DEBUG("Not eliminating ECs as there are none.");
1337 computeFixedPointSystemReachabilityRewards(goal, transitionMatrix, qualitativeStateSets, selectedChoices, totalStateRewardVectorGetter, submatrix, b,
1338 oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr);
1339 return boost::none;
1340 }
1341}
1342
1343template<typename ValueType, typename SolutionType>
1345 storm::storage::SparseMatrix<ValueType> const& submatrix, std::vector<ValueType> const& choiceRewards,
1346 std::vector<ValueType> const& oneStepTargetProbabilities) {
1347 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1348 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models.");
1349 } else {
1350 // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17).
1351 if (direction == storm::OptimizationDirection::Minimize) {
1352 DsMpiMdpUpperRewardBoundsComputer<ValueType> dsmpi(submatrix, choiceRewards, oneStepTargetProbabilities);
1353 hintInformation.upperResultBounds = dsmpi.computeUpperBounds();
1354 } else {
1355 BaierUpperRewardBoundsComputer<ValueType> baier(submatrix, choiceRewards, oneStepTargetProbabilities);
1356 hintInformation.upperResultBound = baier.computeUpperBound();
1357 }
1358 }
1359}
1360
1361template<typename ValueType, typename SolutionType>
1362MDPSparseModelCheckingHelperReturnType<SolutionType> SparseMdpPrctlHelper<ValueType, SolutionType>::computeReachabilityRewardsHelper(
1364 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
1365 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
1366 totalStateRewardVectorGetter,
1367 storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler,
1368 std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter, std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter,
1369 ModelCheckerHint const& hint) {
1370 // Prepare resulting vector.
1371 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
1372
1373 // Determine which states have a reward that is infinity or less than infinity.
1374 QualitativeStateSetsReachabilityRewards qualitativeStateSets = getQualitativeStateSetsReachabilityRewards(
1375 goal, transitionMatrix, backwardTransitions, targetStates, hint, zeroRewardStatesGetter, zeroRewardChoicesGetter);
1376
1377 STORM_LOG_INFO("Preprocessing: " << qualitativeStateSets.infinityStates.getNumberOfSetBits() << " states with reward infinity, "
1378 << qualitativeStateSets.rewardZeroStates.getNumberOfSetBits() << " states with reward zero ("
1379 << qualitativeStateSets.maybeStates.getNumberOfSetBits() << " states remaining).");
1380
1381 storm::utility::vector::setVectorValues(result, qualitativeStateSets.infinityStates, storm::utility::infinity<SolutionType>());
1382
1383 // If requested, we will produce a scheduler.
1384 std::unique_ptr<storm::storage::Scheduler<SolutionType>> scheduler;
1385 if (produceScheduler) {
1386 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1387 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support producing schedulers in this function with interval models.");
1388 } else {
1389 scheduler = std::make_unique<storm::storage::Scheduler<SolutionType>>(transitionMatrix.getRowGroupCount());
1390 }
1391 }
1392
1393 // Check if the values of the maybe states are relevant for the SolveGoal
1394 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(qualitativeStateSets.maybeStates);
1395
1396 // Check whether we need to compute exact rewards for some states.
1397 if (qualitative || maybeStatesNotRelevant) {
1398 STORM_LOG_INFO("The rewards for the initial states were determined in a preprocessing step. No exact rewards were computed.");
1399 // Set the values for all maybe-states to 1 to indicate that their reward values
1400 // are neither 0 nor infinity.
1401 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, storm::utility::one<SolutionType>());
1402 } else {
1403 if (!qualitativeStateSets.maybeStates.empty()) {
1404 // In this case we have to compute the reward values for the remaining states.
1405
1406 // Store the choices that lead to non-infinity values. If none, all choices im maybe states can be selected.
1407 boost::optional<storm::storage::BitVector> selectedChoices;
1408 if (!qualitativeStateSets.infinityStates.empty()) {
1409 selectedChoices = transitionMatrix.getRowFilter(qualitativeStateSets.maybeStates, ~qualitativeStateSets.infinityStates);
1410 }
1411
1412 // Obtain proper hint information either from the provided hint or from requirements of the solver.
1413 SparseMdpHintType<SolutionType> hintInformation = computeHints<ValueType, SolutionType>(
1414 env, SemanticSolutionType::ExpectedRewards, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates,
1415 ~qualitativeStateSets.rewardZeroStates, qualitativeStateSets.rewardZeroStates, produceScheduler, selectedChoices);
1416
1417 // Declare the components of the equation system we will solve.
1419 std::vector<ValueType> b;
1420
1421 // If we need to compute upper bounds on the reward values, we need the one step probabilities
1422 // to a target state.
1423 boost::optional<std::vector<ValueType>> oneStepTargetProbabilities;
1424 if (hintInformation.getComputeUpperBounds()) {
1425 oneStepTargetProbabilities = std::vector<ValueType>();
1426 }
1427
1428 // If the hint information tells us that we have to eliminate MECs, we do so now.
1429 boost::optional<SparseMdpEndComponentInformation<ValueType>> ecInformation;
1430 if (hintInformation.getEliminateEndComponents()) {
1431 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1432 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models.");
1433 } else {
1435 goal, transitionMatrix, backwardTransitions, qualitativeStateSets, selectedChoices, totalStateRewardVectorGetter, submatrix, b,
1436 oneStepTargetProbabilities, produceScheduler);
1437 }
1438 } else {
1439 // Otherwise, we compute the standard equations.
1440 computeFixedPointSystemReachabilityRewards(goal, transitionMatrix, qualitativeStateSets, selectedChoices, totalStateRewardVectorGetter,
1441 submatrix, b, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr);
1442 }
1443
1444 // If we need to compute upper bounds, do so now.
1445 if (hintInformation.getComputeUpperBounds()) {
1446 STORM_LOG_ASSERT(oneStepTargetProbabilities, "Expecting one step target probability vector to be available.");
1447 computeUpperRewardBounds(hintInformation, goal.direction(), submatrix, b, oneStepTargetProbabilities.get());
1448 }
1449
1450 // Now compute the results for the maybe states.
1451 MaybeStateResult<SolutionType> resultForMaybeStates =
1452 computeValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, produceScheduler, hintInformation);
1453
1454 // If we eliminated end components, we need to extract the result differently.
1455 if (ecInformation && ecInformation.get().getEliminatedEndComponents()) {
1456 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1457 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models.");
1458 } else {
1459 ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
1460 if (produceScheduler) {
1461 ecInformation.get().setScheduler(*scheduler, qualitativeStateSets.maybeStates, transitionMatrix, backwardTransitions,
1462 resultForMaybeStates.getScheduler());
1463 }
1464 }
1465 } else {
1466 // Set values of resulting vector according to result.
1467 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
1468 if (produceScheduler) {
1469 extractSchedulerChoices(*scheduler, transitionMatrix, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates,
1470 selectedChoices);
1471 }
1472 }
1473 }
1474 }
1475
1476 // Extend scheduler with choices for the states in the qualitative state sets.
1477 if (produceScheduler) {
1478 extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, backwardTransitions, targetStates, zeroRewardChoicesGetter);
1479 }
1480
1481 // Sanity check for created scheduler.
1482 STORM_LOG_ASSERT(!produceScheduler || scheduler, "Expected that a scheduler was obtained.");
1483 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || !scheduler->isPartialScheduler(), "Expected a fully defined scheduler");
1484 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isDeterministicScheduler(), "Expected a deterministic scheduler");
1485 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler");
1486
1487 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1488 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(result));
1489 } else {
1490 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(result), std::move(scheduler));
1491 }
1492}
1493
1494template class SparseMdpPrctlHelper<double>;
1495template std::vector<double> SparseMdpPrctlHelper<double>::computeInstantaneousRewards(Environment const& env, storm::solver::SolveGoal<double>&& goal,
1496 storm::storage::SparseMatrix<double> const& transitionMatrix,
1498 uint_fast64_t stepCount);
1499template std::vector<double> SparseMdpPrctlHelper<double>::computeCumulativeRewards(Environment const& env, storm::solver::SolveGoal<double>&& goal,
1500 storm::storage::SparseMatrix<double> const& transitionMatrix,
1502 uint_fast64_t stepBound);
1503template std::vector<double> SparseMdpPrctlHelper<double>::computeDiscountedCumulativeRewards(
1504 Environment const& env, storm::solver::SolveGoal<double>&& goal, storm::storage::SparseMatrix<double> const& transitionMatrix,
1505 storm::models::sparse::StandardRewardModel<double> const& rewardModel, uint_fast64_t stepBound, double discountFactor);
1506template MDPSparseModelCheckingHelperReturnType<double> SparseMdpPrctlHelper<double>::computeReachabilityRewards(
1507 Environment const& env, storm::solver::SolveGoal<double>&& goal, storm::storage::SparseMatrix<double> const& transitionMatrix,
1509 storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint);
1510template MDPSparseModelCheckingHelperReturnType<double> SparseMdpPrctlHelper<double>::computeTotalRewards(
1511 Environment const& env, storm::solver::SolveGoal<double>&& goal, storm::storage::SparseMatrix<double> const& transitionMatrix,
1512 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::models::sparse::StandardRewardModel<double> const& rewardModel, bool qualitative,
1513 bool produceScheduler, ModelCheckerHint const& hint);
1514template MDPSparseModelCheckingHelperReturnType<double> SparseMdpPrctlHelper<double>::computeDiscountedTotalRewards(
1515 Environment const& env, storm::solver::SolveGoal<double>&& goal, storm::storage::SparseMatrix<double> const& transitionMatrix,
1516 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::models::sparse::StandardRewardModel<double> const& rewardModel, bool qualitative,
1517 bool produceScheduler, double discountFactor, ModelCheckerHint const& hint);
1518
1519#ifdef STORM_HAVE_CARL
1520template class SparseMdpPrctlHelper<storm::RationalNumber>;
1521template std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeInstantaneousRewards(
1523 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, uint_fast64_t stepCount);
1524template std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeCumulativeRewards(
1526 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, uint_fast64_t stepBound);
1527template std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeDiscountedCumulativeRewards(
1529 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, uint_fast64_t stepBound, storm::RationalNumber discountFactor);
1530template MDPSparseModelCheckingHelperReturnType<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeReachabilityRewards(
1532 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
1533 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative,
1534 bool produceScheduler, ModelCheckerHint const& hint);
1535template MDPSparseModelCheckingHelperReturnType<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeTotalRewards(
1537 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
1538 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, bool qualitative, bool produceScheduler,
1539 ModelCheckerHint const& hint);
1540template MDPSparseModelCheckingHelperReturnType<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeDiscountedTotalRewards(
1542 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
1543 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, bool qualitative, bool produceScheduler,
1544 storm::RationalNumber discountFactor, ModelCheckerHint const& hint);
1545#endif
1546
1547template class SparseMdpPrctlHelper<storm::Interval, double>;
1548template std::vector<double> SparseMdpPrctlHelper<storm::Interval, double>::computeInstantaneousRewards(
1549 Environment const& env, storm::solver::SolveGoal<storm::Interval, double>&& goal, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
1550 storm::models::sparse::StandardRewardModel<storm::Interval> const& rewardModel, uint_fast64_t stepCount);
1551template std::vector<double> SparseMdpPrctlHelper<storm::Interval, double>::computeCumulativeRewards(
1552 Environment const& env, storm::solver::SolveGoal<storm::Interval, double>&& goal, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
1553 storm::models::sparse::StandardRewardModel<storm::Interval> const& rewardModel, uint_fast64_t stepBound);
1554template MDPSparseModelCheckingHelperReturnType<double> SparseMdpPrctlHelper<storm::Interval, double>::computeReachabilityRewards(
1555 Environment const& env, storm::solver::SolveGoal<storm::Interval, double>&& goal, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
1557 storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint);
1558template MDPSparseModelCheckingHelperReturnType<double> SparseMdpPrctlHelper<storm::Interval, double>::computeTotalRewards(
1559 Environment const& env, storm::solver::SolveGoal<storm::Interval, double>&& goal, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
1561 bool qualitative, bool produceScheduler, ModelCheckerHint const& hint);
1562
1563} // namespace helper
1564} // namespace modelchecker
1565} // namespace storm
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
void setPrecision(storm::RationalNumber value)
MinMaxSolverEnvironment & minMax()
This class contains information that might accelerate the model checking process.
ExplicitModelCheckerHint< ValueType > & asExplicitModelCheckerHint()
ValueType computeUpperBound()
Computes an upper bound on the expected rewards.
storm::storage::Scheduler< ValueType > computeScheduler() const
Retrieves the generated scheduler.
bool solveWithDiscountedValueIteration(Environment const &env, std::optional< OptimizationDirection > dir, std::vector< ValueType > &x, std::vector< ValueType > const &b) const
std::vector< ValueType > computeUpperBounds()
Computes upper bounds on the expected rewards.
uint64_t getRowGroupAfterElimination(uint64_t state) const
Retrieves the row group of the state after end component elimination.
static SparseMdpEndComponentInformation< ValueType > eliminateEndComponents(storm::storage::MaximalEndComponentDecomposition< ValueType > const &endComponentDecomposition, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &maybeStates, storm::storage::BitVector const *sumColumns, storm::storage::BitVector const *selectedChoices, std::vector< ValueType > const *summand, storm::storage::SparseMatrix< ValueType > &submatrix, std::vector< ValueType > *columnSumVector, std::vector< ValueType > *summandResultVector, bool gatherExitChoices=false)
static MDPSparseModelCheckingHelperReturnType< SolutionType > computeGloballyProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &psiStates, bool qualitative, bool produceScheduler, bool useMecBasedTechnique=false)
static MDPSparseModelCheckingHelperReturnType< SolutionType > computeTotalRewards(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, RewardModelType const &rewardModel, bool qualitative, bool produceScheduler, ModelCheckerHint const &hint=ModelCheckerHint())
static std::vector< SolutionType > computeCumulativeRewards(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, RewardModelType const &rewardModel, uint_fast64_t stepBound)
static std::vector< SolutionType > computeInstantaneousRewards(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, RewardModelType const &rewardModel, uint_fast64_t stepCount)
static std::map< storm::storage::sparse::state_type, SolutionType > computeRewardBoundedValues(Environment const &env, OptimizationDirection dir, rewardbounded::MultiDimensionalRewardUnfolding< ValueType, true > &rewardUnfolding, storm::storage::BitVector const &initialStates)
static std::vector< SolutionType > computeNextProbabilities(Environment const &env, OptimizationDirection dir, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &nextStates)
static MDPSparseModelCheckingHelperReturnType< SolutionType > computeUntilProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool qualitative, bool produceScheduler, ModelCheckerHint const &hint=ModelCheckerHint())
uint64_t getDimensionOfEpoch(Epoch const &epoch, uint64_t const &dimension) const
Epoch getStartEpoch(bool setUnknownDimsToBottom=false)
Retrieves the desired epoch that needs to be analyzed to compute the reward bounded values.
EpochModel< ValueType, SingleObjectiveMode > & setCurrentEpoch(Epoch const &epoch)
std::vector< Epoch > getEpochComputationOrder(Epoch const &startEpoch, bool stopAtComputedEpochs=false)
Computes a sequence of epochs that need to be analyzed to get a result at the start epoch.
ValueType getRequiredEpochModelPrecision(Epoch const &startEpoch, ValueType const &precision)
Returns the precision required for the analyzis of each epoch model in order to achieve the given ove...
boost::optional< ValueType > getUpperObjectiveBound(uint64_t objectiveIndex=0)
Returns an upper/lower bound for the objective result in every state (if this bound could be computed...
bool empty() const
Retrieves whether the reward model is empty, i.e.
std::vector< ValueType > getTotalRewardVector(storm::storage::SparseMatrix< MatrixValueType > const &transitionMatrix) const
Creates a vector representing the complete reward vector based on the state-, state-action- and trans...
storm::storage::BitVector getChoicesWithFilter(storm::storage::SparseMatrix< MatrixValueType > const &transitionMatrix, std::function< bool(ValueType const &)> const &filter) const
Returns the set of choices for which all associated rewards (state, action or transition rewards) sat...
storm::storage::BitVector getStatesWithFilter(storm::storage::SparseMatrix< MatrixValueType > const &transitionMatrix, std::function< bool(ValueType const &)> const &filter) const
Returns the set of states for which all associated rewards (state, action or transition rewards) sati...
MinMaxLinearEquationSolverRequirements getRequirements(Environment const &env, bool hasUniqueSolution=false, bool hasNoEndComponents=false, boost::optional< storm::solver::OptimizationDirection > const &direction=boost::none, bool hasInitialScheduler=false, bool trackScheduler=false) const
Retrieves the requirements of the solver that would be created when calling create() right now.
std::string getEnabledRequirementsAsString() const
Returns a string that enumerates the enabled requirements.
std::unique_ptr< Multiplier< ValueType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
bool hasRelevantValues() const
void restrictRelevantValues(storm::storage::BitVector const &filter)
storm::storage::BitVector & relevantValues()
void setRelevantValues(storm::storage::BitVector &&values)
OptimizationDirection direction() const
Definition SolveGoal.cpp:92
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.
uint64_t getNextSetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
bool isDisjointFrom(BitVector const &other) const
Checks whether none of the bits that are set in the current bit vector are also set in the given bit ...
bool full() const
Retrieves whether all bits are set in this bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
bool empty() const
Checks if the decomposition is empty.
std::size_t size() const
Retrieves the number of blocks of this decomposition.
This class represents the decomposition of a nondeterministic model into its maximal end components.
std::string statistics(uint64_t totalNumberOfStates) const
Returns a string containing statistics about the MEC decomposition, e.g., the number of (trivial/non-...
This class defines which action is chosen in a particular state of a non-deterministic model.
Definition Scheduler.h:18
SchedulerChoice< ValueType > const & getChoice(uint_fast64_t modelState, uint_fast64_t memoryState=0) const
Gets the choice defined by the scheduler for the given model and memory state.
Definition Scheduler.cpp:86
void setChoice(SchedulerChoice< ValueType > const &choice, uint_fast64_t modelState, uint_fast64_t memoryState=0)
Sets the choice defined by the scheduler for the given state.
Definition Scheduler.cpp:37
A class that holds a possibly non-square matrix in the compressed row storage format.
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
std::vector< value_type > getConstrainedRowSumVector(storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose i-th entry is the sum of the entries in the i-th selected row where only thos...
SparseMatrix< ValueType > transposeSelectedRowsFromRowGroups(std::vector< uint64_t > const &rowGroupChoices, bool keepZeros=false) const
Transposes the matrix w.r.t.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
index_type getColumnCount() const
Returns the number of columns of the matrix.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
std::vector< value_type > getConstrainedRowGroupSumVector(storm::storage::BitVector const &rowGroupConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose entries represent the sums of selected columns for all rows in selected row g...
index_type getRowCount() const
Returns the number of rows of the matrix.
storm::storage::BitVector getRowFilter(storm::storage::BitVector const &groupConstraint) const
Returns a bitvector representing the set of rows, with all indices set that correspond to one of the ...
SparseMatrix filterEntries(storm::storage::BitVector const &rowFilter) const
Returns a copy of this matrix that only considers entries in the selected rows.
static EndComponentEliminatorReturnType transform(storm::storage::SparseMatrix< ValueType > const &originalMatrix, storm::storage::MaximalEndComponentDecomposition< ValueType > ecs, storm::storage::BitVector const &subsystemStates, storm::storage::BitVector const &addSinkRowStates, bool addSelfLoopAtSinkStates=false)
A class that provides convenience operations to display run times.
bool updateProgress(uint64_t count)
Updates the progress to the current count and prints it if the delay passed.
void setMaxCount(uint64_t maxCount)
Sets the maximal possible count.
void startNewMeasurement(uint64_t startCount)
Starts a new measurement, dropping all progress information collected so far.
A class that provides convenience operations to display run times.
Definition Stopwatch.h:14
void start()
Start stopwatch (again) and start measuring time.
Definition Stopwatch.cpp:48
void stop()
Stop stopwatch and add measured time to total time.
Definition Stopwatch.cpp:42
#define STORM_LOG_INFO(message)
Definition logging.h:24
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:52
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_PRINT_AND_LOG(message)
Definition macros.h:68
void extractSchedulerChoices(storm::storage::Scheduler< SolutionType > &scheduler, std::vector< uint64_t > const &subChoices, storm::storage::BitVector const &maybeStates)
boost::optional< SparseMdpEndComponentInformation< ValueType > > computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(storm::solver::SolveGoal< ValueType, SolutionType > &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, QualitativeStateSetsUntilProbabilities const &qualitativeStateSets, storm::storage::SparseMatrix< ValueType > &submatrix, std::vector< ValueType > &b, bool produceScheduler)
QualitativeStateSetsReachabilityRewards computeQualitativeStateSetsReachabilityRewards(storm::solver::SolveGoal< ValueType, SolutionType > const &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &targetStates, std::function< storm::storage::BitVector()> const &zeroRewardStatesGetter, std::function< storm::storage::BitVector()> const &zeroRewardChoicesGetter)
QualitativeStateSetsUntilProbabilities computeQualitativeStateSetsUntilProbabilities(storm::solver::SolveGoal< ValueType, SolutionType > const &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
void extractValueAndSchedulerHint(SparseMdpHintType< SolutionType > &hintStorage, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &maybeStates, boost::optional< storm::storage::BitVector > const &selectedChoices, ModelCheckerHint const &hint, bool skipECWithinMaybeStatesCheck)
std::vector< uint_fast64_t > computeValidSchedulerHint(Environment const &env, SemanticSolutionType const &type, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &maybeStates, storm::storage::BitVector const &filterStates, storm::storage::BitVector const &targetStates, boost::optional< storm::storage::BitVector > const &selectedChoices)
SparseMdpHintType< SolutionType > computeHints(Environment const &env, SemanticSolutionType const &type, ModelCheckerHint const &hint, storm::OptimizationDirection const &dir, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &maybeStates, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &targetStates, bool produceScheduler, boost::optional< storm::storage::BitVector > const &selectedChoices=boost::none)
QualitativeStateSetsUntilProbabilities getQualitativeStateSetsUntilProbabilitiesFromHint(ModelCheckerHint const &hint)
std::vector< ValueType > computeUpperRewardBounds(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, std::vector< ValueType > const &rewards, std::vector< ValueType > const &oneStepTargetProbabilities)
QualitativeStateSetsReachabilityRewards getQualitativeStateSetsReachabilityRewards(storm::solver::SolveGoal< ValueType, SolutionType > const &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &targetStates, ModelCheckerHint const &hint, std::function< storm::storage::BitVector()> const &zeroRewardStatesGetter, std::function< storm::storage::BitVector()> const &zeroRewardChoicesGetter)
void computeFixedPointSystemUntilProbabilities(storm::solver::SolveGoal< ValueType, SolutionType > &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, QualitativeStateSetsUntilProbabilities const &qualitativeStateSets, storm::storage::SparseMatrix< ValueType > &submatrix, std::vector< ValueType > &b)
MaybeStateResult< SolutionType > computeValuesForMaybeStates(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > &&submatrix, std::vector< ValueType > const &b, bool produceScheduler, SparseMdpHintType< SolutionType > &hint)
void extendScheduler(storm::storage::Scheduler< SolutionType > &scheduler, storm::solver::SolveGoal< ValueType, SolutionType > const &goal, QualitativeStateSetsUntilProbabilities const &qualitativeStateSets, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
QualitativeStateSetsReachabilityRewards getQualitativeStateSetsReachabilityRewardsFromHint(ModelCheckerHint const &hint, storm::storage::BitVector const &targetStates)
boost::optional< SparseMdpEndComponentInformation< ValueType > > computeFixedPointSystemReachabilityRewardsEliminateEndComponents(storm::solver::SolveGoal< ValueType, SolutionType > &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, QualitativeStateSetsReachabilityRewards const &qualitativeStateSets, boost::optional< storm::storage::BitVector > const &selectedChoices, std::function< std::vector< ValueType >(uint_fast64_t, storm::storage::SparseMatrix< ValueType > const &, storm::storage::BitVector const &)> const &totalStateRewardVectorGetter, storm::storage::SparseMatrix< ValueType > &submatrix, std::vector< ValueType > &b, boost::optional< std::vector< ValueType > > &oneStepTargetProbabilities, bool produceScheduler)
QualitativeStateSetsUntilProbabilities getQualitativeStateSetsUntilProbabilities(storm::solver::SolveGoal< ValueType, SolutionType > const &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, ModelCheckerHint const &hint)
void computeFixedPointSystemReachabilityRewards(storm::solver::SolveGoal< ValueType, SolutionType > &goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, QualitativeStateSetsReachabilityRewards const &qualitativeStateSets, boost::optional< storm::storage::BitVector > const &selectedChoices, std::function< std::vector< ValueType >(uint_fast64_t, storm::storage::SparseMatrix< ValueType > const &, storm::storage::BitVector const &)> const &totalStateRewardVectorGetter, storm::storage::SparseMatrix< ValueType > &submatrix, std::vector< ValueType > &b, std::vector< ValueType > *oneStepTargetProbabilities=nullptr)
std::unique_ptr< storm::solver::MinMaxLinearEquationSolver< ValueType, SolutionType > > configureMinMaxLinearEquationSolver(Environment const &env, SolveGoal< ValueType, SolutionType > &&goal, storm::solver::MinMaxLinearEquationSolverFactory< ValueType, SolutionType > const &factory, MatrixType &&matrix)
Definition SolveGoal.h:107
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01Max(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:825
void computeSchedulerStayingInStates(storm::storage::BitVector const &states, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the given states that chooses an action that stays completely in the very sa...
Definition graph.cpp:489
void computeSchedulerProbGreater0E(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the ProbGreater0E-States such that in the induced system the given psiStates...
Definition graph.cpp:541
storm::storage::BitVector performProbGreater0A(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability greater 0 of satisfying phi until psi under any pos...
Definition graph.cpp:847
void computeSchedulerProb1E(storm::storage::BitVector const &prob1EStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the given prob1EStates such that in the induced system the given psiStates a...
Definition graph.cpp:614
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
Definition graph.cpp:987
storm::storage::BitVector performProbGreater0E(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Computes the sets of states that have probability greater 0 of satisfying phi until psi under at leas...
Definition graph.cpp:679
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
storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 of satisfying phi until psi under at least one po...
Definition graph.cpp:966
void computeSchedulerProb0E(storm::storage::BitVector const &prob0EStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::Scheduler< SchedulerValueType > &scheduler)
Computes a scheduler for the given states that have a scheduler that has a probability 0.
Definition graph.cpp:592
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01Min(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:1069
storm::storage::BitVector performProb1E(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability 1 of satisfying phi until psi under at least one po...
Definition graph.cpp:747
void computeSchedulerRewInf(storm::storage::BitVector const &rewInfStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::Scheduler< SchedulerValueType > &scheduler)
Computes a scheduler for the given states that have a scheduler that has a reward infinity.
Definition graph.cpp:598
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
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
void setAllValues(std::vector< T > &vec, storm::storage::BitVector const &positions, T const &positiveValue=storm::utility::one< T >(), T const &negativeValue=storm::utility::zero< T >())
Definition vector.h:57
void selectVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Selects the elements from a vector at the specified positions and writes them consecutively into anot...
Definition vector.h:188
void filterVectorInPlace(std::vector< Type > &v, storm::storage::BitVector const &filter)
Definition vector.h:1075
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
Definition vector.h:1064
bool isOne(ValueType const &a)
Definition constants.cpp:36
bool isZero(ValueType const &a)
Definition constants.cpp:41
bool isInfinity(ValueType const &a)
Definition constants.cpp:71
LabParser.cpp.
boost::optional< std::vector< uint64_t > > scheduler
MaybeStateResult(std::vector< ValueType > &&values)
std::vector< uint64_t > const & getScheduler() const
std::vector< ValueType > const & getValues() const
boost::optional< std::vector< uint64_t > > schedulerHint
boost::optional< std::vector< ValueType > > valueHint
std::vector< ValueType > const & getUpperResultBounds() const
boost::optional< std::vector< ValueType > > upperResultBounds