Storm
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
12
14
16
17#include "storm/utility/graph.h"
20
24
28
34
35#include "storm/io/export.h"
40
42
44
52
53namespace storm {
54namespace modelchecker {
55namespace helper {
56
57template<typename ValueType, typename SolutionType>
58std::map<storm::storage::sparse::state_type, SolutionType> SparseMdpPrctlHelper<ValueType, SolutionType>::computeRewardBoundedValues(
60 storm::storage::BitVector const& initialStates) {
61 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
62 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reward bounded values with interval models.");
63 } else {
64 storm::utility::Stopwatch swAll(true), swBuild, swCheck;
65
66 // Get lower and upper bounds for the solution.
67 auto lowerBound = rewardUnfolding.getLowerObjectiveBound();
68 auto upperBound = rewardUnfolding.getUpperObjectiveBound();
69
70 // Initialize epoch models
71 auto initEpoch = rewardUnfolding.getStartEpoch();
72 auto epochOrder = rewardUnfolding.getEpochComputationOrder(initEpoch);
73
74 // initialize data that will be needed for each epoch
75 std::vector<ValueType> x, b;
76 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> minMaxSolver;
77
78 ValueType precision = rewardUnfolding.getRequiredEpochModelPrecision(
79 initEpoch, storm::utility::convertNumber<ValueType>(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()));
80 Environment preciseEnv = env;
81 preciseEnv.solver().minMax().setPrecision(storm::utility::convertNumber<storm::RationalNumber>(precision));
82
83 // In case of cdf export we store the necessary data.
84 std::vector<std::vector<ValueType>> cdfData;
85
86 storm::utility::ProgressMeasurement progress("epochs");
87 progress.setMaxCount(epochOrder.size());
88 progress.startNewMeasurement(0);
89 uint64_t numCheckedEpochs = 0;
90 for (auto const& epoch : epochOrder) {
91 swBuild.start();
92 auto& epochModel = rewardUnfolding.setCurrentEpoch(epoch);
93 swBuild.stop();
94 swCheck.start();
95 rewardUnfolding.setSolutionForCurrentEpoch(epochModel.analyzeSingleObjective(preciseEnv, dir, x, b, minMaxSolver, lowerBound, upperBound));
96 swCheck.stop();
98 !rewardUnfolding.getEpochManager().hasBottomDimension(epoch)) {
99 std::vector<ValueType> cdfEntry;
100 for (uint64_t i = 0; i < rewardUnfolding.getEpochManager().getDimensionCount(); ++i) {
101 uint64_t offset = rewardUnfolding.getDimension(i).boundType == helper::rewardbounded::DimensionBoundType::LowerBound ? 1 : 0;
102 cdfEntry.push_back(storm::utility::convertNumber<ValueType>(rewardUnfolding.getEpochManager().getDimensionOfEpoch(epoch, i) + offset) *
103 rewardUnfolding.getDimension(i).scalingFactor);
104 }
105 cdfEntry.push_back(rewardUnfolding.getInitialStateResult(epoch));
106 cdfData.push_back(std::move(cdfEntry));
107 }
108 ++numCheckedEpochs;
109 progress.updateProgress(numCheckedEpochs);
111 break;
112 }
113 }
114
115 std::map<storm::storage::sparse::state_type, ValueType> result;
116 for (auto initState : initialStates) {
117 result[initState] = rewardUnfolding.getInitialStateResult(initEpoch, initState);
118 }
119
120 swAll.stop();
121
123 std::vector<std::string> headers;
124 for (uint64_t i = 0; i < rewardUnfolding.getEpochManager().getDimensionCount(); ++i) {
125 headers.push_back(rewardUnfolding.getDimension(i).formula->toString());
126 }
127 headers.push_back("Result");
128 storm::io::exportDataToCSVFile<ValueType, std::string, std::string>(
129 storm::settings::getModule<storm::settings::modules::IOSettings>().getExportCdfDirectory() + "cdf.csv", cdfData, headers);
130 }
131
133 STORM_PRINT_AND_LOG("---------------------------------\n");
134 STORM_PRINT_AND_LOG("Statistics:\n");
135 STORM_PRINT_AND_LOG("---------------------------------\n");
136 STORM_PRINT_AND_LOG(" #checked epochs: " << epochOrder.size() << ".\n");
137 STORM_PRINT_AND_LOG(" overall Time: " << swAll << ".\n");
138 STORM_PRINT_AND_LOG("Epoch Model building Time: " << swBuild << ".\n");
139 STORM_PRINT_AND_LOG("Epoch Model checking Time: " << swCheck << ".\n");
140 STORM_PRINT_AND_LOG("---------------------------------\n");
141 }
142
143 return result;
144 }
145}
146
147template<typename ValueType, typename SolutionType>
149 Environment const& env, OptimizationDirection dir, storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
150 storm::storage::BitVector const& nextStates) {
151 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
152 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with reward models.");
153 } else {
154 // Create the vector with which to multiply and initialize it correctly.
155 std::vector<ValueType> result(transitionMatrix.getRowGroupCount());
156 storm::utility::vector::setVectorValues(result, nextStates, storm::utility::one<ValueType>());
157
158 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
159 multiplier->multiplyAndReduce(env, dir, result, nullptr, result);
160
161 return result;
162 }
163}
164
165template<typename ValueType, typename SolutionType = ValueType>
166std::vector<uint_fast64_t> computeValidSchedulerHint(Environment const& env, SemanticSolutionType const& type,
167 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
168 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
169 storm::storage::BitVector const& maybeStates, storm::storage::BitVector const& filterStates,
170 storm::storage::BitVector const& targetStates,
171 boost::optional<storm::storage::BitVector> const& selectedChoices) {
172 storm::storage::Scheduler<SolutionType> validScheduler(maybeStates.size());
173
175 storm::utility::graph::computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, filterStates, targetStates, validScheduler,
176 selectedChoices);
177 } else if (type == SemanticSolutionType::ExpectedRewards) {
178 storm::utility::graph::computeSchedulerProb1E(maybeStates | targetStates, transitionMatrix, backwardTransitions, filterStates, targetStates,
179 validScheduler, selectedChoices);
180 } else {
181 STORM_LOG_ASSERT(false, "Unexpected equation system type.");
182 }
183
184 // Extract the relevant parts of the scheduler for the solver.
185 std::vector<uint64_t> schedulerHint;
186 schedulerHint.reserve(maybeStates.getNumberOfSetBits());
187 if (selectedChoices) {
188 // There might be unselected choices so the local choice indices from the scheduler need to be adapted
189 for (auto maybeState : maybeStates) {
190 auto choice = validScheduler.getChoice(maybeState).getDeterministicChoice();
191 auto const groupStart = transitionMatrix.getRowGroupIndices()[maybeState];
192 auto const origGlobalChoiceIndex = groupStart + choice;
193 STORM_LOG_ASSERT(selectedChoices->get(origGlobalChoiceIndex), "The computed scheduler selects an illegal choice.");
194 // Count the number of unselected choices in [groupStart, origGlobalChoiceIndex) and subtract that from choice
195 for (auto pos = selectedChoices->getNextUnsetIndex(groupStart); pos < origGlobalChoiceIndex; pos = selectedChoices->getNextUnsetIndex(pos + 1)) {
196 --choice;
197 }
198 schedulerHint.push_back(choice);
199 }
200 } else {
201 for (auto maybeState : maybeStates) {
202 schedulerHint.push_back(validScheduler.getChoice(maybeState).getDeterministicChoice());
203 }
204 }
205 return schedulerHint;
206}
207
208template<typename ValueType>
211 // Intentionally left empty.
212 }
213
214 bool hasSchedulerHint() const {
215 return static_cast<bool>(schedulerHint);
216 }
217
218 bool hasValueHint() const {
219 return static_cast<bool>(valueHint);
220 }
221
222 bool hasLowerResultBound() const {
223 return static_cast<bool>(lowerResultBound);
224 }
225
226 ValueType const& getLowerResultBound() const {
227 return lowerResultBound.get();
228 }
229
230 bool hasUpperResultBound() const {
231 return static_cast<bool>(upperResultBound);
232 }
233
234 bool hasUpperResultBounds() const {
235 return static_cast<bool>(upperResultBounds);
236 }
237
238 ValueType const& getUpperResultBound() const {
239 return upperResultBound.get();
240 }
241
242 std::vector<ValueType>& getUpperResultBounds() {
243 return upperResultBounds.get();
244 }
245
246 std::vector<ValueType> const& getUpperResultBounds() const {
247 return upperResultBounds.get();
248 }
249
250 std::vector<uint64_t>& getSchedulerHint() {
251 return schedulerHint.get();
252 }
253
254 std::vector<ValueType>& getValueHint() {
255 return valueHint.get();
256 }
257
260 }
261
263 return computeUpperBounds;
264 }
265
266 bool hasUniqueSolution() const {
267 return uniqueSolution;
268 }
269
270 bool hasNoEndComponents() const {
271 return noEndComponents;
272 }
273
274 boost::optional<std::vector<uint64_t>> schedulerHint;
275 boost::optional<std::vector<ValueType>> valueHint;
276 boost::optional<ValueType> lowerResultBound;
277 boost::optional<ValueType> upperResultBound;
278 boost::optional<std::vector<ValueType>> upperResultBounds;
283};
284
285template<typename ValueType, typename SolutionType>
287 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& maybeStates,
288 boost::optional<storm::storage::BitVector> const& selectedChoices, ModelCheckerHint const& hint,
289 bool skipECWithinMaybeStatesCheck) {
290 // Deal with scheduler hint.
291 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasSchedulerHint()) {
292 if (hintStorage.hasSchedulerHint()) {
293 STORM_LOG_WARN("A scheduler hint was provided, but the solver requires a specific one. The provided scheduler hint will be ignored.");
294 } else {
295 auto const& schedulerHint = hint.template asExplicitModelCheckerHint<ValueType>().getSchedulerHint();
296 std::vector<uint64_t> hintChoices;
297
298 // The scheduler hint is only applicable if it induces no BSCC consisting of maybe states.
299 bool hintApplicable;
300 if (!skipECWithinMaybeStatesCheck) {
301 hintChoices.reserve(maybeStates.size());
302 for (uint_fast64_t state = 0; state < maybeStates.size(); ++state) {
303 hintChoices.push_back(schedulerHint.getChoice(state).getDeterministicChoice());
304 }
305 hintApplicable =
306 storm::utility::graph::performProb1(transitionMatrix.transposeSelectedRowsFromRowGroups(hintChoices), maybeStates, ~maybeStates).full();
307 } else {
308 hintApplicable = true;
309 }
310
311 if (hintApplicable) {
312 // Compute the hint w.r.t. the given subsystem.
313 hintChoices.clear();
314 hintChoices.reserve(maybeStates.getNumberOfSetBits());
315 for (auto state : maybeStates) {
316 uint_fast64_t hintChoice = schedulerHint.getChoice(state).getDeterministicChoice();
317 if (selectedChoices) {
318 uint_fast64_t firstChoice = transitionMatrix.getRowGroupIndices()[state];
319 uint_fast64_t lastChoice = firstChoice + hintChoice;
320 hintChoice = 0;
321 for (uint_fast64_t choice = selectedChoices->getNextSetIndex(firstChoice); choice < lastChoice;
322 choice = selectedChoices->getNextSetIndex(choice + 1)) {
323 ++hintChoice;
324 }
325 }
326 hintChoices.push_back(hintChoice);
327 }
328 hintStorage.schedulerHint = std::move(hintChoices);
329 }
330 }
331 }
332
333 // Deal with solution value hint. Only applicable if there are no End Components consisting of maybe states.
334 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasResultHint() &&
335 (skipECWithinMaybeStatesCheck || hintStorage.hasSchedulerHint() ||
336 storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, maybeStates, ~maybeStates)
337 .full())) {
338 hintStorage.valueHint = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint<SolutionType>().getResultHint(), maybeStates);
339 }
340}
341
342template<typename ValueType, typename SolutionType>
345 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& maybeStates,
346 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& targetStates, bool produceScheduler,
347 boost::optional<storm::storage::BitVector> const& selectedChoices = boost::none) {
349
350 // There are no end components if we minimize until probabilities or
351 // maximize reachability rewards or if the hint tells us so.
352 result.noEndComponents = (dir == storm::solver::OptimizationDirection::Minimize && type == SemanticSolutionType::UntilProbabilities) ||
353 (dir == storm::solver::OptimizationDirection::Maximize && type == SemanticSolutionType::ExpectedRewards) ||
354 (hint.isExplicitModelCheckerHint() && hint.asExplicitModelCheckerHint<ValueType>().getNoEndComponentsInMaybeStates());
355
356 // If there are no end components, the solution is unique. (Note that the other direction does not hold,
357 // e.g., end components in which infinite reward is collected.
358 result.uniqueSolution = result.hasNoEndComponents();
359
360 // Check for requirements of the solver.
361 bool hasSchedulerHint = hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasSchedulerHint();
364 minMaxLinearEquationSolverFactory.getRequirements(env, result.uniqueSolution, result.noEndComponents, dir, hasSchedulerHint, produceScheduler);
365 if (requirements.hasEnabledRequirement()) {
366 // If the solver still requires no end-components, we have to eliminate them later.
367 if (requirements.uniqueSolution()) {
369 "The solver requires to eliminate the end components although the solution is already assumed to be unique.");
370 STORM_LOG_DEBUG("Scheduling EC elimination, because the solver requires a unique solution.");
371 result.eliminateEndComponents = true;
372 // If end components have been eliminated we can assume a unique solution.
373 result.uniqueSolution = true;
374 requirements.clearUniqueSolution();
375 // If we compute until probabilities, we can even assume the absence of end components.
376 // Note that in the case of minimizing expected rewards there might still be end components in which reward is collected.
378 }
379
380 // If the solver requires an initial scheduler, compute one now. Note that any scheduler is valid if there are no end components.
381 if (requirements.validInitialScheduler() && !result.noEndComponents) {
382 STORM_LOG_DEBUG("Computing valid scheduler, because the solver requires it.");
383 result.schedulerHint = computeValidSchedulerHint<ValueType, SolutionType>(env, type, transitionMatrix, backwardTransitions, maybeStates, phiStates,
384 targetStates, selectedChoices);
385 requirements.clearValidInitialScheduler();
386 }
387
388 // Finally, we have information on the bounds depending on the problem type.
390 requirements.clearBounds();
391 } else if (type == SemanticSolutionType::ExpectedRewards) {
392 requirements.clearLowerBounds();
393 }
394 if (requirements.upperBounds()) {
395 result.computeUpperBounds = true;
396 requirements.clearUpperBounds();
397 }
398 STORM_LOG_THROW(!requirements.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
399 "Solver requirements " + requirements.getEnabledRequirementsAsString() + " not checked.");
400 } else {
401 STORM_LOG_DEBUG("Solver has no requirements.");
402 }
403
404 // Only if there is no end component decomposition that we will need to do later, we use value and scheduler
405 // hints from the provided hint.
406 if (!result.eliminateEndComponents) {
407 extractValueAndSchedulerHint(result, transitionMatrix, backwardTransitions, maybeStates, selectedChoices, hint, result.uniqueSolution);
408 } else {
409 if (hint.isEmpty()) {
410 STORM_LOG_TRACE("Warn A non-empty hint was provided, but its information will be disregarded.");
411 }
412 }
413
414 // Only set bounds if we did not obtain them from the hint.
415 if (!result.hasLowerResultBound()) {
416 result.lowerResultBound = storm::utility::zero<SolutionType>();
417 }
419 result.upperResultBound = storm::utility::one<SolutionType>();
420 }
421
422 // If we received an upper bound, we can drop the requirement to compute one.
423 if (result.hasUpperResultBound()) {
424 result.computeUpperBounds = false;
425 }
426
427 return result;
428}
429
430template<typename ValueType>
432 MaybeStateResult(std::vector<ValueType>&& values) : values(std::move(values)) {
433 // Intentionally left empty.
434 }
435
436 bool hasScheduler() const {
437 return static_cast<bool>(scheduler);
438 }
439
440 std::vector<uint64_t> const& getScheduler() const {
441 return scheduler.get();
442 }
443
444 std::vector<ValueType> const& getValues() const {
445 return values;
446 }
447
448 std::vector<ValueType> values;
449 boost::optional<std::vector<uint64_t>> scheduler;
450};
451
452template<typename ValueType, typename SolutionType>
454 storm::storage::SparseMatrix<ValueType>&& submatrix, std::vector<ValueType> const& b,
455 bool produceScheduler, SparseMdpHintType<SolutionType>& hint) {
456 // Initialize the solution vector.
457 std::vector<SolutionType> x =
458 hint.hasValueHint() ? std::move(hint.getValueHint())
459 : std::vector<SolutionType>(submatrix.getRowGroupCount(),
460 hint.hasLowerResultBound() ? hint.getLowerResultBound() : storm::utility::zero<SolutionType>());
461
462 // Set up the solver.
464 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType, SolutionType>> solver =
465 storm::solver::configureMinMaxLinearEquationSolver(env, std::move(goal), minMaxLinearEquationSolverFactory, std::move(submatrix));
466 solver->setRequirementsChecked();
467 solver->setUncertaintyIsRobust(goal.isRobust());
468 solver->setHasUniqueSolution(hint.hasUniqueSolution());
469 solver->setHasNoEndComponents(hint.hasNoEndComponents());
470 if (hint.hasLowerResultBound()) {
471 solver->setLowerBound(hint.getLowerResultBound());
472 }
473 if (hint.hasUpperResultBound()) {
474 solver->setUpperBound(hint.getUpperResultBound());
475 }
476 if (hint.hasUpperResultBounds()) {
477 solver->setUpperBounds(std::move(hint.getUpperResultBounds()));
478 }
479 if (hint.hasSchedulerHint()) {
480 solver->setInitialScheduler(std::move(hint.getSchedulerHint()));
481 }
482 solver->setTrackScheduler(produceScheduler);
483
484 // Solve the corresponding system of equations.
485 solver->solveEquations(env, x, b);
486
487#ifndef NDEBUG
488 // As a sanity check, make sure our local upper bounds were in fact correct.
490 auto resultIt = x.begin();
491 for (auto const& entry : solver->getUpperBounds()) {
493 *resultIt <= entry + storm::utility::convertNumber<ValueType>(env.solver().minMax().getPrecision()),
494 "Expecting result value for state " << std::distance(x.begin(), resultIt) << " to be <= " << entry << ", but got " << *resultIt << ".");
495 ++resultIt;
496 }
497 }
498#endif
499
500 // Create result.
501 MaybeStateResult<SolutionType> result(std::move(x));
502
503 // If requested, return the requested scheduler.
504 if (produceScheduler) {
505 result.scheduler = std::move(solver->getSchedulerChoices());
506 }
507 return result;
508}
509
515
516template<typename ValueType>
519 result.maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
520
521 // Treat the states with probability zero/one.
522 std::vector<ValueType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getResultHint();
525 storm::storage::BitVector nonMaybeStates = ~result.maybeStates;
526 for (auto state : nonMaybeStates) {
527 if (storm::utility::isOne(resultsForNonMaybeStates[state])) {
528 result.statesWithProbability1.set(state, true);
529 } else {
530 STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException,
531 "Expected that the result hint specifies probabilities in {0,1} for non-maybe states");
532 result.statesWithProbability0.set(state, true);
533 }
534 }
535
536 return result;
537}
538
539template<typename ValueType, typename SolutionType>
541 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
542 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
543 storm::storage::BitVector const& phiStates,
544 storm::storage::BitVector const& psiStates) {
546
547 // Get all states that have probability 0 and 1 of satisfying the until-formula.
548 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01;
549 if (goal.minimize()) {
550 statesWithProbability01 =
551 storm::utility::graph::performProb01Min(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
552 } else {
553 statesWithProbability01 =
554 storm::utility::graph::performProb01Max(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, phiStates, psiStates);
555 }
556 result.statesWithProbability0 = std::move(statesWithProbability01.first);
557 result.statesWithProbability1 = std::move(statesWithProbability01.second);
559
560 return result;
561}
562
563template<typename ValueType, typename SolutionType>
565 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
566 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
567 storm::storage::BitVector const& phiStates,
568 storm::storage::BitVector const& psiStates, ModelCheckerHint const& hint) {
569 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
570 return getQualitativeStateSetsUntilProbabilitiesFromHint<ValueType>(hint);
571 } else {
572 return computeQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates);
573 }
574}
575
576template<typename SolutionType, bool subChoicesCoverOnlyMaybeStates = true>
577void extractSchedulerChoices(storm::storage::Scheduler<SolutionType>& scheduler, std::vector<uint64_t> const& subChoices,
578 storm::storage::BitVector const& maybeStates) {
579 if constexpr (subChoicesCoverOnlyMaybeStates) {
580 auto subChoiceIt = subChoices.begin();
581 for (auto maybeState : maybeStates) {
582 scheduler.setChoice(*subChoiceIt, maybeState);
583 ++subChoiceIt;
584 }
585 assert(subChoiceIt == subChoices.end());
586 } else {
587 // See computeFixedPointSystemUntilProbabilities, where we create a different equation system.
588 // Consequentially, we run a slightly different code here for interval-based models.
589 STORM_LOG_ASSERT(maybeStates.size() == subChoices.size(), "Sizes do not coincide.");
590 for (auto maybeState : maybeStates) {
591 scheduler.setChoice(subChoices[maybeState], maybeState);
592 }
593 }
594}
595
596template<typename ValueType, typename SolutionType>
598 QualitativeStateSetsUntilProbabilities const& qualitativeStateSets, storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
599 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates,
600 storm::storage::BitVector const& psiStates) {
601 // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for
602 // the states with probability 1 or 0 (depending on whether we maximize or minimize).
603 // We also need to define some arbitrary choice for the remaining states to obtain a fully defined scheduler.
604 if (goal.minimize()) {
605 storm::utility::graph::computeSchedulerProb0E(qualitativeStateSets.statesWithProbability0, transitionMatrix, scheduler);
606 for (auto prob1State : qualitativeStateSets.statesWithProbability1) {
607 scheduler.setChoice(0, prob1State);
608 }
609 } else {
610 storm::utility::graph::computeSchedulerProb1E(qualitativeStateSets.statesWithProbability1, transitionMatrix, backwardTransitions, phiStates, psiStates,
611 scheduler);
612 for (auto prob0State : qualitativeStateSets.statesWithProbability0) {
613 scheduler.setChoice(0, prob0State);
614 }
615 }
616}
617
618template<typename ValueType, typename SolutionType>
620 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
621 QualitativeStateSetsUntilProbabilities const& qualitativeStateSets,
622 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b) {
623 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
624 // For non-interval based models, we can eliminate the rows and columns from the original transition probability matrix for states
625 // whose probabilities are already known... However, there is information in the transition to those states.
626 // Thus, we cannot eliminate them all.
627 // We can however drop all the outgoing transitions from these states.
628 // 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),
629 // TODO ctned: however, there is quite some bookkeeping involved in projecting the right vectors.
630 // TODO ctned: Instead is likely easier to just do a pass and make a unique sink and a unique target state.
631 // TODO ctned: If this is ever changed, extractSchedulerChoices must also be updated.
632 submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(qualitativeStateSets.maybeStates));
633
634 // Prepare the right-hand side of the equation system. For entry i this corresponds to
635 // the accumulated probability of going from state i to some state that has probability 1.
636 storm::utility::vector::setAllValues(b, transitionMatrix.getRowFilter(qualitativeStateSets.statesWithProbability1));
637 } else {
638 // First, we can eliminate the rows and columns from the original transition probability matrix for states
639 // whose probabilities are already known.
640 submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false);
641
642 // Prepare the right-hand side of the equation system. For entry i this corresponds to
643 // the accumulated probability of going from state i to some state that has probability 1.
644 b = transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, qualitativeStateSets.statesWithProbability1);
645 }
646 // If the solve goal has relevant values, we need to adjust them.
647 goal.restrictRelevantValues(qualitativeStateSets.maybeStates);
648}
649
650template<typename ValueType, typename SolutionType>
651boost::optional<SparseMdpEndComponentInformation<ValueType>> computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(
653 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, QualitativeStateSetsUntilProbabilities const& qualitativeStateSets,
654 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b, bool produceScheduler) {
655 // Get the set of states that (under some scheduler) can stay in the set of maybestates forever
657 transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, qualitativeStateSets.maybeStates, ~qualitativeStateSets.maybeStates);
658
659 bool doDecomposition = !candidateStates.empty();
660
662 if (doDecomposition) {
663 // Compute the states that are in MECs.
664 endComponentDecomposition = storm::storage::MaximalEndComponentDecomposition<ValueType>(transitionMatrix, backwardTransitions, candidateStates);
665 STORM_LOG_INFO(endComponentDecomposition.statistics(transitionMatrix.getRowGroupCount()));
666 }
667
668 // Only do more work if there are actually end-components.
669 if (doDecomposition && !endComponentDecomposition.empty()) {
670 STORM_LOG_DEBUG("Eliminating " << endComponentDecomposition.size() << " EC(s).");
672 endComponentDecomposition, transitionMatrix, qualitativeStateSets.maybeStates, &qualitativeStateSets.statesWithProbability1, nullptr, nullptr,
673 submatrix, &b, nullptr, produceScheduler);
674
675 // If the solve goal has relevant values, we need to adjust them.
676 if (goal.hasRelevantValues()) {
677 storm::storage::BitVector newRelevantValues(submatrix.getRowGroupCount());
678 for (auto state : goal.relevantValues()) {
679 if (qualitativeStateSets.maybeStates.get(state)) {
680 newRelevantValues.set(result.getRowGroupAfterElimination(state));
681 }
682 }
683 if (!newRelevantValues.empty()) {
684 goal.setRelevantValues(std::move(newRelevantValues));
685 }
686 }
687
688 return result;
689 } else {
690 STORM_LOG_DEBUG("Not eliminating ECs as there are none.");
691 computeFixedPointSystemUntilProbabilities(goal, transitionMatrix, qualitativeStateSets, submatrix, b);
692
693 return boost::none;
694 }
695}
696
697template<typename ValueType, typename SolutionType>
700 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
701 bool qualitative, bool produceScheduler, ModelCheckerHint const& hint) {
702 STORM_LOG_THROW(!qualitative || !produceScheduler, storm::exceptions::InvalidSettingsException,
703 "Cannot produce scheduler when performing qualitative model checking only.");
704
705 // Prepare resulting vector.
706 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
707
708 // We need to identify the maybe states (states which have a probability for satisfying the until formula
709 // that is strictly between 0 and 1) and the states that satisfy the formula with probablity 1 and 0, respectively.
710 QualitativeStateSetsUntilProbabilities qualitativeStateSets =
711 getQualitativeStateSetsUntilProbabilities(goal, transitionMatrix, backwardTransitions, phiStates, psiStates, hint);
712
713 STORM_LOG_INFO("Preprocessing: " << qualitativeStateSets.statesWithProbability1.getNumberOfSetBits() << " states with probability 1, "
714 << qualitativeStateSets.statesWithProbability0.getNumberOfSetBits() << " with probability 0 ("
715 << qualitativeStateSets.maybeStates.getNumberOfSetBits() << " states remaining).");
716
717 // Set values of resulting vector that are known exactly.
718 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.statesWithProbability1, storm::utility::one<SolutionType>());
719
720 // Check if the values of the maybe states are relevant for the SolveGoal
721 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(qualitativeStateSets.maybeStates);
722
723 // If requested, we will produce a scheduler.
724 std::unique_ptr<storm::storage::Scheduler<SolutionType>> scheduler;
725 if (produceScheduler) {
726 scheduler = std::make_unique<storm::storage::Scheduler<SolutionType>>(transitionMatrix.getRowGroupCount());
727 // If maybeStatesNotRelevant is true, we have to set the scheduler for maybe states as "dontCare"
728 if (maybeStatesNotRelevant) {
729 for (auto state : qualitativeStateSets.maybeStates) {
730 scheduler->setDontCare(state);
731 }
732 }
733 }
734
735 // Check whether we need to compute exact probabilities for some states.
736 if (qualitative || maybeStatesNotRelevant) {
737 // Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1.
738 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, storm::utility::convertNumber<SolutionType>(0.5));
739 } else {
740 if (!qualitativeStateSets.maybeStates.empty()) {
741 // In this case we have have to compute the remaining probabilities.
742
743 // Obtain proper hint information either from the provided hint or from requirements of the solver.
744 SparseMdpHintType<SolutionType> hintInformation = computeHints<ValueType, SolutionType>(
745 env, SemanticSolutionType::UntilProbabilities, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates,
746 phiStates, qualitativeStateSets.statesWithProbability1, produceScheduler);
747
748 // Declare the components of the equation system we will solve.
750 std::vector<ValueType> b;
751
752 // If the hint information tells us that we have to eliminate MECs, we do so now.
753 boost::optional<SparseMdpEndComponentInformation<ValueType>> ecInformation;
754 if (hintInformation.getEliminateEndComponents()) {
755 ecInformation = computeFixedPointSystemUntilProbabilitiesEliminateEndComponents(goal, transitionMatrix, backwardTransitions,
756 qualitativeStateSets, submatrix, b, produceScheduler);
757 } else {
758 // Otherwise, we compute the standard equations.
759 computeFixedPointSystemUntilProbabilities(goal, transitionMatrix, qualitativeStateSets, submatrix, b);
760 }
761
762 // Now compute the results for the maybe states.
763 MaybeStateResult<SolutionType> resultForMaybeStates =
764 computeValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, produceScheduler, hintInformation);
765
766 // If we eliminated end components, we need to extract the result differently.
767 if (ecInformation && ecInformation.get().getEliminatedEndComponents()) {
768 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
769 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support this end component with interval models.");
770 } else {
771 ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
772 if (produceScheduler) {
773 ecInformation.get().setScheduler(*scheduler, qualitativeStateSets.maybeStates, transitionMatrix, backwardTransitions,
774 resultForMaybeStates.getScheduler());
775 }
776 }
777 } else {
778 // Set values of resulting vector according to result.
779 if constexpr (!std::is_same_v<ValueType, storm::Interval>) {
780 // For non-interval models, we only operated on the maybe states, and we must recover the qualitative values for the other state.
781 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
782 } else {
783 // For interval models, the result for maybe states indeed also holds values for all qualitative states.
784 STORM_LOG_ASSERT(resultForMaybeStates.getValues().size() == transitionMatrix.getColumnCount(), "Dimensions do not match");
785 result = resultForMaybeStates.getValues();
786 }
787 if (produceScheduler) {
788 extractSchedulerChoices<SolutionType, !std::is_same_v<ValueType, storm::Interval>>(*scheduler, resultForMaybeStates.getScheduler(),
789 qualitativeStateSets.maybeStates);
790 }
791 }
792 }
793 }
794
795 // Extend scheduler with choices for the states in the qualitative state sets.
796 if (produceScheduler) {
797 extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, backwardTransitions, phiStates, psiStates);
798 }
799
800 // Sanity check for created scheduler.
801 STORM_LOG_ASSERT(!produceScheduler || scheduler, "Expected that a scheduler was obtained.");
802 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || !scheduler->isPartialScheduler(), "Expected a fully defined scheduler");
803 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isDeterministicScheduler(), "Expected a deterministic scheduler");
804 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler");
805
806 // Return result.
807 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(result), std::move(scheduler));
808}
809
810template<typename ValueType, typename SolutionType>
813 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative, bool produceScheduler,
814 bool useMecBasedTechnique) {
815 if (useMecBasedTechnique) {
816 // TODO: does this really work for minimizing objectives?
817 storm::storage::MaximalEndComponentDecomposition<ValueType> mecDecomposition(transitionMatrix, backwardTransitions, psiStates);
818 storm::storage::BitVector statesInPsiMecs(transitionMatrix.getRowGroupCount());
819 for (auto const& mec : mecDecomposition) {
820 for (auto const& stateActionsPair : mec) {
821 statesInPsiMecs.set(stateActionsPair.first, true);
822 }
823 }
824
825 return computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions, psiStates, statesInPsiMecs, qualitative,
826 produceScheduler);
827 } else {
828 goal.oneMinus();
829 auto result =
830 computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions,
831 storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), ~psiStates, qualitative, produceScheduler);
832 for (auto& element : result.values) {
833 element = storm::utility::one<SolutionType>() - element;
834 }
835 return result;
836 }
837}
838
839template<typename ValueType, typename SolutionType>
840template<typename RewardModelType>
843 RewardModelType const& rewardModel, uint_fast64_t stepCount) {
844 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
845 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantenous rewards with interval models.");
846 } else {
847 // Only compute the result if the model has a state-based reward this->getModel().
848 STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException,
849 "Computing instantaneous rewards for a reward model that does not define any state-rewards. The result is trivially 0.");
850 // Initialize result to state rewards of the this->getModel().
851 std::vector<SolutionType> result(rewardModel.getStateRewardVector());
852
853 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
854 multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, nullptr, stepCount);
855
856 return result;
857 }
858}
859
860template<typename ValueType, typename SolutionType>
861template<typename RewardModelType>
864 RewardModelType const& rewardModel, uint_fast64_t stepBound) {
865 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
866 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models.");
867 } else {
868 // Only compute the result if the model has at least one reward this->getModel().
869 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
870
871 // Compute the reward vector to add in each step based on the available reward models.
872 std::vector<ValueType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
873
874 // Initialize result to the zero vector.
875 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
876
877 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
878 multiplier->repeatedMultiplyAndReduce(env, goal.direction(), result, &totalRewardVector, stepBound);
879
880 return result;
881 }
882}
883
884template<typename ValueType, typename SolutionType>
885template<typename RewardModelType>
888 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, bool produceScheduler,
889 ModelCheckerHint const& hint) {
890 // Reduce to reachability rewards
891 if (goal.minimize()) {
892 // Identify the states from which no reward can be collected under some scheduler
893 storm::storage::BitVector choicesWithoutReward = rewardModel.getChoicesWithZeroReward(transitionMatrix);
894 storm::storage::BitVector statesWithZeroRewardChoice(transitionMatrix.getRowGroupCount(), false);
895 for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) {
896 if (choicesWithoutReward.getNextSetIndex(transitionMatrix.getRowGroupIndices()[state]) < transitionMatrix.getRowGroupIndices()[state + 1]) {
897 statesWithZeroRewardChoice.set(state);
898 }
899 }
900 storm::storage::BitVector rew0EStates =
901 storm::utility::graph::performProbGreater0A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions,
902 statesWithZeroRewardChoice, ~statesWithZeroRewardChoice, false, 0, choicesWithoutReward);
903 rew0EStates.complement();
904 auto result = computeReachabilityRewards(env, std::move(goal), transitionMatrix, backwardTransitions, rewardModel, rew0EStates, qualitative,
905 produceScheduler, hint);
906 if (result.scheduler) {
907 storm::utility::graph::computeSchedulerStayingInStates(rew0EStates, transitionMatrix, *result.scheduler, choicesWithoutReward);
908 }
909 return result;
910 } else {
911 // Identify the states from which only states with zero reward are reachable.
912 storm::storage::BitVector statesWithoutReward = rewardModel.getStatesWithZeroReward(transitionMatrix);
913 storm::storage::BitVector rew0AStates = storm::utility::graph::performProbGreater0E(backwardTransitions, statesWithoutReward, ~statesWithoutReward);
914 rew0AStates.complement();
915
916 // There might be end components that consists only of states/choices with zero rewards. The reachability reward semantics would assign such
917 // end components reward infinity. To avoid this, we potentially need to eliminate such end components
918 storm::storage::BitVector trueStates(transitionMatrix.getRowGroupCount(), true);
919 if (storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, rew0AStates)
920 .full()) {
921 return computeReachabilityRewards(env, std::move(goal), transitionMatrix, backwardTransitions, rewardModel, rew0AStates, qualitative,
922 produceScheduler, hint);
923 } else {
924 // The transformation of schedulers for the ec-eliminated system back to the original one is not implemented.
925 STORM_LOG_ERROR_COND(!produceScheduler, "Can not produce scheduler for this property (functionality not implemented");
926 storm::storage::BitVector choicesWithoutReward = rewardModel.getChoicesWithZeroReward(transitionMatrix);
928 transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true), choicesWithoutReward, rew0AStates, true);
929 storm::storage::BitVector newRew0AStates(ecElimResult.matrix.getRowGroupCount(), false);
930 for (auto oldRew0AState : rew0AStates) {
931 newRew0AStates.set(ecElimResult.oldToNewStateMapping[oldRew0AState]);
932 }
933
934 if (goal.hasRelevantValues()) {
935 storm::storage::BitVector newRelevantValues(ecElimResult.matrix.getRowGroupCount(), false);
936 for (auto oldRelevantState : goal.relevantValues()) {
937 newRelevantValues.set(ecElimResult.oldToNewStateMapping[oldRelevantState]);
938 }
939 goal.relevantValues() = std::move(newRelevantValues);
940 }
941
942 MDPSparseModelCheckingHelperReturnType<SolutionType> result = computeReachabilityRewardsHelper(
943 env, std::move(goal), ecElimResult.matrix, ecElimResult.matrix.transpose(true),
944 [&](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const& newTransitionMatrix, storm::storage::BitVector const& maybeStates) {
945 std::vector<ValueType> result;
946 std::vector<ValueType> oldChoiceRewards = rewardModel.getTotalRewardVector(transitionMatrix);
947 result.reserve(rowCount);
948 for (uint64_t newState : maybeStates) {
949 for (auto newChoice : newTransitionMatrix.getRowGroupIndices(newState)) {
950 uint64_t oldChoice = ecElimResult.newToOldRowMapping[newChoice];
951 result.push_back(oldChoiceRewards[oldChoice]);
952 }
953 }
954 STORM_LOG_ASSERT(result.size() == rowCount, "Unexpected size of reward vector.");
955 return result;
956 },
957 newRew0AStates, qualitative, false,
958 [&]() {
959 storm::storage::BitVector newStatesWithoutReward(ecElimResult.matrix.getRowGroupCount(), false);
960 for (auto oldStateWithoutRew : statesWithoutReward) {
961 newStatesWithoutReward.set(ecElimResult.oldToNewStateMapping[oldStateWithoutRew]);
962 }
963 return newStatesWithoutReward;
964 },
965 [&]() {
966 storm::storage::BitVector newChoicesWithoutReward(ecElimResult.matrix.getRowGroupCount(), false);
967 for (uint64_t newChoice = 0; newChoice < ecElimResult.matrix.getRowCount(); ++newChoice) {
968 if (choicesWithoutReward.get(ecElimResult.newToOldRowMapping[newChoice])) {
969 newChoicesWithoutReward.set(newChoice);
970 }
971 }
972 return newChoicesWithoutReward;
973 });
974
975 std::vector<SolutionType> resultInEcQuotient = std::move(result.values);
976 result.values.resize(ecElimResult.oldToNewStateMapping.size());
977 storm::utility::vector::selectVectorValues(result.values, ecElimResult.oldToNewStateMapping, resultInEcQuotient);
978 return result;
979 }
980 }
981}
982
983template<typename ValueType, typename SolutionType>
984template<typename RewardModelType>
987 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates,
988 bool qualitative, bool produceScheduler, ModelCheckerHint const& hint) {
989 // Only compute the result if the model has at least one reward this->getModel().
990 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Reward model for formula is empty. Skipping formula.");
991 return computeReachabilityRewardsHelper(
992 env, std::move(goal), transitionMatrix, backwardTransitions,
993 [&rewardModel](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
994 return rewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates);
995 },
996 targetStates, qualitative, produceScheduler, [&]() { return rewardModel.getStatesWithZeroReward(transitionMatrix); },
997 [&]() { return rewardModel.getChoicesWithZeroReward(transitionMatrix); }, hint);
998}
999
1000template<typename ValueType, typename SolutionType>
1003 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler,
1004 ModelCheckerHint const& hint) {
1005 return computeReachabilityRewardsHelper(
1006 env, std::move(goal), transitionMatrix, backwardTransitions,
1007 [](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&) {
1008 return std::vector<ValueType>(rowCount, storm::utility::one<ValueType>());
1009 },
1010 targetStates, qualitative, produceScheduler, [&]() { return storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); },
1011 [&]() { return storm::storage::BitVector(transitionMatrix.getRowCount(), false); }, hint);
1012}
1013
1014#ifdef STORM_HAVE_CARL
1015template<typename ValueType, typename SolutionType>
1019 bool lowerBoundOfIntervals, storm::storage::BitVector const& targetStates, bool qualitative) {
1020 // Only compute the result if the reward model is not empty.
1021 STORM_LOG_THROW(!intervalRewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
1022 return computeReachabilityRewardsHelper(
1023 env, std::move(goal), transitionMatrix, backwardTransitions,
1024 [&](uint_fast64_t rowCount, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
1025 std::vector<ValueType> result;
1026 result.reserve(rowCount);
1027 std::vector<storm::Interval> subIntervalVector = intervalRewardModel.getTotalRewardVector(rowCount, transitionMatrix, maybeStates);
1028 for (auto const& interval : subIntervalVector) {
1029 result.push_back(lowerBoundOfIntervals ? interval.lower() : interval.upper());
1030 }
1031 return result;
1032 },
1033 targetStates, qualitative, false,
1034 [&]() {
1035 return intervalRewardModel.getStatesWithFilter(
1036 transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); });
1037 },
1038 [&]() {
1039 return intervalRewardModel.getChoicesWithFilter(
1040 transitionMatrix, [&](storm::Interval const& i) { return storm::utility::isZero(lowerBoundOfIntervals ? i.lower() : i.upper()); });
1041 })
1042 .values;
1043}
1044
1045template<>
1046std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeReachabilityRewards(
1049 storm::storage::BitVector const&, bool) {
1050 STORM_LOG_THROW(false, storm::exceptions::IllegalFunctionCallException, "Computing reachability rewards is unsupported for this data type.");
1051}
1052#endif
1053
1059
1060template<typename ValueType>
1062 storm::storage::BitVector const& targetStates) {
1064 result.maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
1065
1066 // Treat the states with reward zero/infinity.
1067 std::vector<ValueType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getResultHint();
1070 storm::storage::BitVector nonMaybeStates = ~result.maybeStates;
1071 for (auto state : nonMaybeStates) {
1072 if (storm::utility::isZero(resultsForNonMaybeStates[state])) {
1073 result.rewardZeroStates.set(state, true);
1074 } else {
1075 STORM_LOG_THROW(storm::utility::isInfinity(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException,
1076 "Expected that the result hint specifies probabilities in {0,infinity} for non-maybe states");
1077 result.infinityStates.set(state, true);
1078 }
1079 }
1080 return result;
1081}
1082
1083template<typename ValueType, typename SolutionType>
1086 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
1087 std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter, std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter) {
1089 storm::storage::BitVector trueStates(transitionMatrix.getRowGroupCount(), true);
1090 if (goal.minimize()) {
1091 result.infinityStates =
1092 storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, targetStates);
1093 } else {
1094 result.infinityStates =
1095 storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, trueStates, targetStates);
1096 }
1097 result.infinityStates.complement();
1098
1100 if (goal.minimize()) {
1101 result.rewardZeroStates = storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions,
1102 trueStates, targetStates, zeroRewardChoicesGetter());
1103 } else {
1104 result.rewardZeroStates = storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions,
1105 zeroRewardStatesGetter(), targetStates);
1106 }
1107 } else {
1108 result.rewardZeroStates = targetStates;
1109 }
1110 result.maybeStates = ~(result.rewardZeroStates | result.infinityStates);
1111 return result;
1112}
1113
1114template<typename ValueType, typename SolutionType>
1116 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
1117 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
1118 storm::storage::BitVector const& targetStates, ModelCheckerHint const& hint,
1119 std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter,
1120 std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter) {
1121 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
1122 return getQualitativeStateSetsReachabilityRewardsFromHint<ValueType>(hint, targetStates);
1123 } else {
1124 return computeQualitativeStateSetsReachabilityRewards(goal, transitionMatrix, backwardTransitions, targetStates, zeroRewardStatesGetter,
1125 zeroRewardChoicesGetter);
1126 }
1127}
1128
1129template<typename ValueType, typename SolutionType>
1131 QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
1132 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
1133 std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter) {
1134 // Finally, if we need to produce a scheduler, we also need to figure out the parts of the scheduler for
1135 // the states with reward zero/infinity.
1136 if (goal.minimize()) {
1137 storm::utility::graph::computeSchedulerProb1E(qualitativeStateSets.rewardZeroStates, transitionMatrix, backwardTransitions,
1138 qualitativeStateSets.rewardZeroStates, targetStates, scheduler, zeroRewardChoicesGetter());
1139 for (auto state : qualitativeStateSets.infinityStates) {
1140 scheduler.setChoice(0, state);
1141 }
1142 } else {
1143 storm::utility::graph::computeSchedulerRewInf(qualitativeStateSets.infinityStates, transitionMatrix, backwardTransitions, scheduler);
1144 for (auto state : qualitativeStateSets.rewardZeroStates) {
1145 scheduler.setChoice(0, state);
1146 }
1147 }
1148}
1149
1150template<typename ValueType, typename SolutionType>
1152 std::vector<uint_fast64_t> const& subChoices, storm::storage::BitVector const& maybeStates,
1153 boost::optional<storm::storage::BitVector> const& selectedChoices) {
1154 auto subChoiceIt = subChoices.begin();
1155 if (selectedChoices) {
1156 for (auto maybeState : maybeStates) {
1157 // find the rowindex that corresponds to the selected row of the submodel
1158 uint_fast64_t firstRowIndex = transitionMatrix.getRowGroupIndices()[maybeState];
1159 uint_fast64_t selectedRowIndex = selectedChoices->getNextSetIndex(firstRowIndex);
1160 for (uint_fast64_t choice = 0; choice < *subChoiceIt; ++choice) {
1161 selectedRowIndex = selectedChoices->getNextSetIndex(selectedRowIndex + 1);
1162 }
1163 scheduler.setChoice(selectedRowIndex - firstRowIndex, maybeState);
1164 ++subChoiceIt;
1165 }
1166 } else {
1167 for (auto maybeState : maybeStates) {
1168 scheduler.setChoice(*subChoiceIt, maybeState);
1169 ++subChoiceIt;
1170 }
1171 }
1172 assert(subChoiceIt == subChoices.end());
1173}
1174
1175template<typename ValueType, typename SolutionType>
1178 QualitativeStateSetsReachabilityRewards const& qualitativeStateSets, boost::optional<storm::storage::BitVector> const& selectedChoices,
1179 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
1180 totalStateRewardVectorGetter,
1181 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b, std::vector<ValueType>* oneStepTargetProbabilities = nullptr) {
1182 // Remove rows and columns from the original transition probability matrix for states whose reward values are already known.
1183 // If there are infinity states, we additionally have to remove choices of maybeState that lead to infinity.
1184 if (qualitativeStateSets.infinityStates.empty()) {
1185 submatrix = transitionMatrix.getSubmatrix(true, qualitativeStateSets.maybeStates, qualitativeStateSets.maybeStates, false);
1186 b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, qualitativeStateSets.maybeStates);
1187 if (oneStepTargetProbabilities) {
1188 (*oneStepTargetProbabilities) =
1189 transitionMatrix.getConstrainedRowGroupSumVector(qualitativeStateSets.maybeStates, qualitativeStateSets.rewardZeroStates);
1190 }
1191 } else {
1192 submatrix = transitionMatrix.getSubmatrix(false, *selectedChoices, qualitativeStateSets.maybeStates, false);
1193 b = totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix,
1194 storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true));
1196 if (oneStepTargetProbabilities) {
1197 (*oneStepTargetProbabilities) = transitionMatrix.getConstrainedRowSumVector(*selectedChoices, qualitativeStateSets.rewardZeroStates);
1198 }
1199 }
1200
1201 // If the solve goal has relevant values, we need to adjust them.
1202 goal.restrictRelevantValues(qualitativeStateSets.maybeStates);
1203}
1204
1205template<typename ValueType, typename SolutionType>
1206boost::optional<SparseMdpEndComponentInformation<ValueType>> computeFixedPointSystemReachabilityRewardsEliminateEndComponents(
1208 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, QualitativeStateSetsReachabilityRewards const& qualitativeStateSets,
1209 boost::optional<storm::storage::BitVector> const& selectedChoices,
1210 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
1211 totalStateRewardVectorGetter,
1212 storm::storage::SparseMatrix<ValueType>& submatrix, std::vector<ValueType>& b, boost::optional<std::vector<ValueType>>& oneStepTargetProbabilities,
1213 bool produceScheduler) {
1214 // Start by computing the choices with reward 0, as we only want ECs within this fragment.
1215 storm::storage::BitVector zeroRewardChoices(transitionMatrix.getRowCount());
1216
1217 // Get the rewards of all choices.
1218 std::vector<ValueType> rewardVector =
1219 totalStateRewardVectorGetter(transitionMatrix.getRowCount(), transitionMatrix, storm::storage::BitVector(transitionMatrix.getRowGroupCount(), true));
1220
1221 uint64_t index = 0;
1222 for (auto const& e : rewardVector) {
1223 if (storm::utility::isZero(e)) {
1224 zeroRewardChoices.set(index);
1225 }
1226 ++index;
1227 }
1228
1229 // Compute the states that have some zero reward choice.
1230 storm::storage::BitVector candidateStates(qualitativeStateSets.maybeStates);
1231 for (auto state : qualitativeStateSets.maybeStates) {
1232 bool keepState = false;
1233
1234 for (auto row = transitionMatrix.getRowGroupIndices()[state], rowEnd = transitionMatrix.getRowGroupIndices()[state + 1]; row < rowEnd; ++row) {
1235 if (zeroRewardChoices.get(row)) {
1236 keepState = true;
1237 break;
1238 }
1239 }
1240
1241 if (!keepState) {
1242 candidateStates.set(state, false);
1243 }
1244 }
1245
1246 // Only keep the candidate states that (under some scheduler) can stay in the set of candidates forever
1247 candidateStates =
1248 storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, candidateStates, ~candidateStates);
1249
1250 bool doDecomposition = !candidateStates.empty();
1251
1253 if (doDecomposition) {
1254 // Then compute the states that are in MECs with zero reward.
1255 endComponentDecomposition =
1256 storm::storage::MaximalEndComponentDecomposition<ValueType>(transitionMatrix, backwardTransitions, candidateStates, zeroRewardChoices);
1257 STORM_LOG_INFO(endComponentDecomposition.statistics(transitionMatrix.getRowGroupCount()));
1258 }
1259
1260 // Only do more work if there are actually end-components.
1261 if (doDecomposition && !endComponentDecomposition.empty()) {
1262 STORM_LOG_DEBUG("Eliminating " << endComponentDecomposition.size() << " ECs.");
1264 endComponentDecomposition, transitionMatrix, qualitativeStateSets.maybeStates,
1265 oneStepTargetProbabilities ? &qualitativeStateSets.rewardZeroStates : nullptr, selectedChoices ? &selectedChoices.get() : nullptr, &rewardVector,
1266 submatrix, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr, &b, produceScheduler);
1267
1268 // If the solve goal has relevant values, we need to adjust them.
1269 if (goal.hasRelevantValues()) {
1270 storm::storage::BitVector newRelevantValues(submatrix.getRowGroupCount());
1271 for (auto state : goal.relevantValues()) {
1272 if (qualitativeStateSets.maybeStates.get(state)) {
1273 newRelevantValues.set(result.getRowGroupAfterElimination(state));
1274 }
1275 }
1276 if (!newRelevantValues.empty()) {
1277 goal.setRelevantValues(std::move(newRelevantValues));
1278 }
1279 }
1280
1281 return result;
1282 } else {
1283 STORM_LOG_DEBUG("Not eliminating ECs as there are none.");
1284 computeFixedPointSystemReachabilityRewards(goal, transitionMatrix, qualitativeStateSets, selectedChoices, totalStateRewardVectorGetter, submatrix, b,
1285 oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr);
1286 return boost::none;
1287 }
1288}
1289
1290template<typename ValueType, typename SolutionType>
1292 storm::storage::SparseMatrix<ValueType> const& submatrix, std::vector<ValueType> const& choiceRewards,
1293 std::vector<ValueType> const& oneStepTargetProbabilities) {
1294 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1295 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models.");
1296 } else {
1297 // For the min-case, we use DS-MPI, for the max-case variant 2 of the Baier et al. paper (CAV'17).
1298 if (direction == storm::OptimizationDirection::Minimize) {
1299 DsMpiMdpUpperRewardBoundsComputer<ValueType> dsmpi(submatrix, choiceRewards, oneStepTargetProbabilities);
1300 hintInformation.upperResultBounds = dsmpi.computeUpperBounds();
1301 } else {
1302 BaierUpperRewardBoundsComputer<ValueType> baier(submatrix, choiceRewards, oneStepTargetProbabilities);
1303 hintInformation.upperResultBound = baier.computeUpperBound();
1304 }
1305 }
1306}
1307
1308template<typename ValueType, typename SolutionType>
1309MDPSparseModelCheckingHelperReturnType<SolutionType> SparseMdpPrctlHelper<ValueType, SolutionType>::computeReachabilityRewardsHelper(
1311 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
1312 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
1313 totalStateRewardVectorGetter,
1314 storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler,
1315 std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter, std::function<storm::storage::BitVector()> const& zeroRewardChoicesGetter,
1316 ModelCheckerHint const& hint) {
1317 // Prepare resulting vector.
1318 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
1319
1320 // Determine which states have a reward that is infinity or less than infinity.
1321 QualitativeStateSetsReachabilityRewards qualitativeStateSets = getQualitativeStateSetsReachabilityRewards(
1322 goal, transitionMatrix, backwardTransitions, targetStates, hint, zeroRewardStatesGetter, zeroRewardChoicesGetter);
1323
1324 STORM_LOG_INFO("Preprocessing: " << qualitativeStateSets.infinityStates.getNumberOfSetBits() << " states with reward infinity, "
1325 << qualitativeStateSets.rewardZeroStates.getNumberOfSetBits() << " states with reward zero ("
1326 << qualitativeStateSets.maybeStates.getNumberOfSetBits() << " states remaining).");
1327
1328 storm::utility::vector::setVectorValues(result, qualitativeStateSets.infinityStates, storm::utility::infinity<SolutionType>());
1329
1330 // If requested, we will produce a scheduler.
1331 std::unique_ptr<storm::storage::Scheduler<SolutionType>> scheduler;
1332 if (produceScheduler) {
1333 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1334 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support producing schedulers in this function with interval models.");
1335 } else {
1336 scheduler = std::make_unique<storm::storage::Scheduler<SolutionType>>(transitionMatrix.getRowGroupCount());
1337 }
1338 }
1339
1340 // Check if the values of the maybe states are relevant for the SolveGoal
1341 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(qualitativeStateSets.maybeStates);
1342
1343 // Check whether we need to compute exact rewards for some states.
1344 if (qualitative || maybeStatesNotRelevant) {
1345 STORM_LOG_INFO("The rewards for the initial states were determined in a preprocessing step. No exact rewards were computed.");
1346 // Set the values for all maybe-states to 1 to indicate that their reward values
1347 // are neither 0 nor infinity.
1348 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, storm::utility::one<SolutionType>());
1349 } else {
1350 if (!qualitativeStateSets.maybeStates.empty()) {
1351 // In this case we have to compute the reward values for the remaining states.
1352
1353 // Store the choices that lead to non-infinity values. If none, all choices im maybe states can be selected.
1354 boost::optional<storm::storage::BitVector> selectedChoices;
1355 if (!qualitativeStateSets.infinityStates.empty()) {
1356 selectedChoices = transitionMatrix.getRowFilter(qualitativeStateSets.maybeStates, ~qualitativeStateSets.infinityStates);
1357 }
1358
1359 // Obtain proper hint information either from the provided hint or from requirements of the solver.
1360 SparseMdpHintType<SolutionType> hintInformation = computeHints<ValueType, SolutionType>(
1361 env, SemanticSolutionType::ExpectedRewards, hint, goal.direction(), transitionMatrix, backwardTransitions, qualitativeStateSets.maybeStates,
1362 ~qualitativeStateSets.rewardZeroStates, qualitativeStateSets.rewardZeroStates, produceScheduler, selectedChoices);
1363
1364 // Declare the components of the equation system we will solve.
1366 std::vector<ValueType> b;
1367
1368 // If we need to compute upper bounds on the reward values, we need the one step probabilities
1369 // to a target state.
1370 boost::optional<std::vector<ValueType>> oneStepTargetProbabilities;
1371 if (hintInformation.getComputeUpperBounds()) {
1372 oneStepTargetProbabilities = std::vector<ValueType>();
1373 }
1374
1375 // If the hint information tells us that we have to eliminate MECs, we do so now.
1376 boost::optional<SparseMdpEndComponentInformation<ValueType>> ecInformation;
1377 if (hintInformation.getEliminateEndComponents()) {
1378 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1379 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models.");
1380 } else {
1382 goal, transitionMatrix, backwardTransitions, qualitativeStateSets, selectedChoices, totalStateRewardVectorGetter, submatrix, b,
1383 oneStepTargetProbabilities, produceScheduler);
1384 }
1385 } else {
1386 // Otherwise, we compute the standard equations.
1387 computeFixedPointSystemReachabilityRewards(goal, transitionMatrix, qualitativeStateSets, selectedChoices, totalStateRewardVectorGetter,
1388 submatrix, b, oneStepTargetProbabilities ? &oneStepTargetProbabilities.get() : nullptr);
1389 }
1390
1391 // If we need to compute upper bounds, do so now.
1392 if (hintInformation.getComputeUpperBounds()) {
1393 STORM_LOG_ASSERT(oneStepTargetProbabilities, "Expecting one step target probability vector to be available.");
1394 computeUpperRewardBounds(hintInformation, goal.direction(), submatrix, b, oneStepTargetProbabilities.get());
1395 }
1396
1397 // Now compute the results for the maybe states.
1398 MaybeStateResult<SolutionType> resultForMaybeStates =
1399 computeValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, produceScheduler, hintInformation);
1400
1401 // If we eliminated end components, we need to extract the result differently.
1402 if (ecInformation && ecInformation.get().getEliminatedEndComponents()) {
1403 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1404 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support eliminating end components with interval models.");
1405 } else {
1406 ecInformation.get().setValues(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
1407 if (produceScheduler) {
1408 ecInformation.get().setScheduler(*scheduler, qualitativeStateSets.maybeStates, transitionMatrix, backwardTransitions,
1409 resultForMaybeStates.getScheduler());
1410 }
1411 }
1412 } else {
1413 // Set values of resulting vector according to result.
1414 storm::utility::vector::setVectorValues<SolutionType>(result, qualitativeStateSets.maybeStates, resultForMaybeStates.getValues());
1415 if (produceScheduler) {
1416 extractSchedulerChoices(*scheduler, transitionMatrix, resultForMaybeStates.getScheduler(), qualitativeStateSets.maybeStates,
1417 selectedChoices);
1418 }
1419 }
1420 }
1421 }
1422
1423 // Extend scheduler with choices for the states in the qualitative state sets.
1424 if (produceScheduler) {
1425 extendScheduler(*scheduler, goal, qualitativeStateSets, transitionMatrix, backwardTransitions, targetStates, zeroRewardChoicesGetter);
1426 }
1427
1428 // Sanity check for created scheduler.
1429 STORM_LOG_ASSERT(!produceScheduler || scheduler, "Expected that a scheduler was obtained.");
1430 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || !scheduler->isPartialScheduler(), "Expected a fully defined scheduler");
1431 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isDeterministicScheduler(), "Expected a deterministic scheduler");
1432 STORM_LOG_ASSERT((!produceScheduler && !scheduler) || scheduler->isMemorylessScheduler(), "Expected a memoryless scheduler");
1433
1434 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1435 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(result));
1436 } else {
1437 return MDPSparseModelCheckingHelperReturnType<SolutionType>(std::move(result), std::move(scheduler));
1438 }
1439}
1440
1441template<typename ValueType, typename SolutionType>
1444 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
1445 storm::storage::BitVector const& conditionStates) {
1446 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
1447 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional probabilities with interval models.");
1448 } else {
1449 std::chrono::high_resolution_clock::time_point start = std::chrono::high_resolution_clock::now();
1450
1451 // For the max-case, we can simply take the given target states. For the min-case, however, we need to
1452 // find the MECs of non-target states and make them the new target states.
1453 storm::storage::BitVector fixedTargetStates;
1454 if (!goal.minimize()) {
1455 fixedTargetStates = targetStates;
1456 } else {
1457 fixedTargetStates = storm::storage::BitVector(targetStates.size());
1458 storm::storage::MaximalEndComponentDecomposition<ValueType> mecDecomposition(transitionMatrix, backwardTransitions, ~targetStates);
1459 for (auto const& mec : mecDecomposition) {
1460 for (auto const& stateActionsPair : mec) {
1461 fixedTargetStates.set(stateActionsPair.first);
1462 }
1463 }
1464 }
1465
1466 storm::storage::BitVector allStates(fixedTargetStates.size(), true);
1467
1468 // Extend the target states by computing all states that have probability 1 to go to a target state
1469 // under *all* schedulers.
1470 fixedTargetStates =
1471 storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, fixedTargetStates);
1472
1473 // We solve the max-case and later adjust the result if the optimization direction was to minimize.
1474 storm::storage::BitVector initialStatesBitVector = goal.relevantValues();
1475 STORM_LOG_THROW(initialStatesBitVector.getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException,
1476 "Computing conditional probabilities in MDPs is only supported for models with exactly one initial state.");
1477 storm::storage::sparse::state_type initialState = *initialStatesBitVector.begin();
1478
1479 // Extend the condition states by computing all states that have probability 1 to go to a condition state
1480 // under *all* schedulers.
1481 storm::storage::BitVector extendedConditionStates =
1482 storm::utility::graph::performProb1A(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates);
1483
1484 STORM_LOG_DEBUG("Computing probabilities to satisfy condition.");
1485 std::chrono::high_resolution_clock::time_point conditionStart = std::chrono::high_resolution_clock::now();
1486 std::vector<ValueType> conditionProbabilities =
1487 std::move(computeUntilProbabilities(env, OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, extendedConditionStates,
1488 false, false)
1489 .values);
1490 std::chrono::high_resolution_clock::time_point conditionEnd = std::chrono::high_resolution_clock::now();
1491 STORM_LOG_DEBUG("Computed probabilities to satisfy for condition in "
1492 << std::chrono::duration_cast<std::chrono::milliseconds>(conditionEnd - conditionStart).count() << "ms.");
1493
1494 // If the conditional probability is undefined for the initial state, we return directly.
1495 if (storm::utility::isZero(conditionProbabilities[initialState])) {
1496 return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(initialState, storm::utility::infinity<ValueType>()));
1497 }
1498
1499 STORM_LOG_DEBUG("Computing probabilities to reach target.");
1500 std::chrono::high_resolution_clock::time_point targetStart = std::chrono::high_resolution_clock::now();
1501 std::vector<ValueType> targetProbabilities = std::move(
1502 computeUntilProbabilities(env, OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, fixedTargetStates, false, false)
1503 .values);
1504 std::chrono::high_resolution_clock::time_point targetEnd = std::chrono::high_resolution_clock::now();
1505 STORM_LOG_DEBUG("Computed probabilities to reach target in " << std::chrono::duration_cast<std::chrono::milliseconds>(targetEnd - targetStart).count()
1506 << "ms.");
1507
1508 storm::storage::BitVector statesWithProbabilityGreater0E(transitionMatrix.getRowGroupCount(), true);
1510 for (auto const& element : conditionProbabilities) {
1511 if (storm::utility::isZero(element)) {
1512 statesWithProbabilityGreater0E.set(state, false);
1513 }
1514 ++state;
1515 }
1516
1517 // Determine those states that need to be equipped with a restart mechanism.
1518 STORM_LOG_DEBUG("Computing problematic states.");
1519 storm::storage::BitVector pureResetStates = storm::utility::graph::performProb0A(backwardTransitions, allStates, extendedConditionStates);
1521 transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, extendedConditionStates | fixedTargetStates);
1522
1523 // Otherwise, we build the transformed MDP.
1524 storm::storage::BitVector relevantStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStatesBitVector, allStates,
1525 extendedConditionStates | fixedTargetStates | pureResetStates);
1526 STORM_LOG_TRACE("Found " << relevantStates.getNumberOfSetBits() << " relevant states for conditional probability computation.");
1527 std::vector<uint_fast64_t> numberOfStatesBeforeRelevantStates = relevantStates.getNumberOfSetBitsBeforeIndices();
1528 storm::storage::sparse::state_type newGoalState = relevantStates.getNumberOfSetBits();
1529 storm::storage::sparse::state_type newStopState = newGoalState + 1;
1530 storm::storage::sparse::state_type newFailState = newStopState + 1;
1531
1532 // Build the transitions of the (relevant) states of the original model.
1533 storm::storage::SparseMatrixBuilder<ValueType> builder(0, newFailState + 1, 0, true, true);
1534 uint_fast64_t currentRow = 0;
1535 for (auto state : relevantStates) {
1536 builder.newRowGroup(currentRow);
1537 if (fixedTargetStates.get(state)) {
1538 if (!storm::utility::isZero(conditionProbabilities[state])) {
1539 builder.addNextValue(currentRow, newGoalState, conditionProbabilities[state]);
1540 }
1541 if (!storm::utility::isOne(conditionProbabilities[state])) {
1542 builder.addNextValue(currentRow, newFailState, storm::utility::one<ValueType>() - conditionProbabilities[state]);
1543 }
1544 ++currentRow;
1545 } else if (extendedConditionStates.get(state)) {
1546 if (!storm::utility::isZero(targetProbabilities[state])) {
1547 builder.addNextValue(currentRow, newGoalState, targetProbabilities[state]);
1548 }
1549 if (!storm::utility::isOne(targetProbabilities[state])) {
1550 builder.addNextValue(currentRow, newStopState, storm::utility::one<ValueType>() - targetProbabilities[state]);
1551 }
1552 ++currentRow;
1553 } else if (pureResetStates.get(state)) {
1554 builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one<ValueType>());
1555 ++currentRow;
1556 } else {
1557 for (uint_fast64_t row = transitionMatrix.getRowGroupIndices()[state]; row < transitionMatrix.getRowGroupIndices()[state + 1]; ++row) {
1558 for (auto const& successorEntry : transitionMatrix.getRow(row)) {
1559 builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[successorEntry.getColumn()], successorEntry.getValue());
1560 }
1561 ++currentRow;
1562 }
1563 if (problematicStates.get(state)) {
1564 builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one<ValueType>());
1565 ++currentRow;
1566 }
1567 }
1568 }
1569
1570 // Now build the transitions of the newly introduced states.
1571 builder.newRowGroup(currentRow);
1572 builder.addNextValue(currentRow, newGoalState, storm::utility::one<ValueType>());
1573 ++currentRow;
1574 builder.newRowGroup(currentRow);
1575 builder.addNextValue(currentRow, newStopState, storm::utility::one<ValueType>());
1576 ++currentRow;
1577 builder.newRowGroup(currentRow);
1578 builder.addNextValue(currentRow, numberOfStatesBeforeRelevantStates[initialState], storm::utility::one<ValueType>());
1579 ++currentRow;
1580
1581 std::chrono::high_resolution_clock::time_point end = std::chrono::high_resolution_clock::now();
1582 STORM_LOG_DEBUG("Computed transformed model in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms.");
1583
1584 // Finally, build the matrix and dispatch the query as a reachability query.
1585 STORM_LOG_DEBUG("Computing conditional probabilties.");
1586 storm::storage::BitVector newGoalStates(newFailState + 1);
1587 newGoalStates.set(newGoalState);
1588 storm::storage::SparseMatrix<ValueType> newTransitionMatrix = builder.build();
1589 STORM_LOG_DEBUG("Transformed model has " << newTransitionMatrix.getRowGroupCount() << " states and " << newTransitionMatrix.getNonzeroEntryCount()
1590 << " transitions.");
1591 storm::storage::SparseMatrix<ValueType> newBackwardTransitions = newTransitionMatrix.transpose(true);
1592
1594 if (goal.minimize()) {
1595 goal.oneMinus();
1596 }
1597
1598 std::chrono::high_resolution_clock::time_point conditionalStart = std::chrono::high_resolution_clock::now();
1599 std::vector<ValueType> goalProbabilities =
1600 std::move(computeUntilProbabilities(env, std::move(goal), newTransitionMatrix, newBackwardTransitions,
1601 storm::storage::BitVector(newFailState + 1, true), newGoalStates, false, false)
1602 .values);
1603 std::chrono::high_resolution_clock::time_point conditionalEnd = std::chrono::high_resolution_clock::now();
1604 STORM_LOG_DEBUG("Computed conditional probabilities in transformed model in "
1605 << std::chrono::duration_cast<std::chrono::milliseconds>(conditionalEnd - conditionalStart).count() << "ms.");
1606
1607 return std::unique_ptr<CheckResult>(new ExplicitQuantitativeCheckResult<ValueType>(
1608 initialState, dir == OptimizationDirection::Maximize
1609 ? goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]]
1610 : storm::utility::one<ValueType>() - goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]]));
1611 }
1612}
1613
1614template class SparseMdpPrctlHelper<double>;
1616 storm::storage::SparseMatrix<double> const& transitionMatrix,
1618 uint_fast64_t stepCount);
1620 storm::storage::SparseMatrix<double> const& transitionMatrix,
1622 uint_fast64_t stepBound);
1624 Environment const& env, storm::solver::SolveGoal<double>&& goal, storm::storage::SparseMatrix<double> const& transitionMatrix,
1626 storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint);
1628 Environment const& env, storm::solver::SolveGoal<double>&& goal, storm::storage::SparseMatrix<double> const& transitionMatrix,
1629 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::models::sparse::StandardRewardModel<double> const& rewardModel, bool qualitative,
1630 bool produceScheduler, ModelCheckerHint const& hint);
1631
1632#ifdef STORM_HAVE_CARL
1634template std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeInstantaneousRewards(
1636 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, uint_fast64_t stepCount);
1637template std::vector<storm::RationalNumber> SparseMdpPrctlHelper<storm::RationalNumber>::computeCumulativeRewards(
1639 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, uint_fast64_t stepBound);
1642 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
1643 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, storm::storage::BitVector const& targetStates, bool qualitative,
1644 bool produceScheduler, ModelCheckerHint const& hint);
1647 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
1648 storm::models::sparse::StandardRewardModel<storm::RationalNumber> const& rewardModel, bool qualitative, bool produceScheduler,
1649 ModelCheckerHint const& hint);
1650#endif
1651
1655 storm::models::sparse::StandardRewardModel<storm::Interval> const& rewardModel, uint_fast64_t stepCount);
1658 storm::models::sparse::StandardRewardModel<storm::Interval> const& rewardModel, uint_fast64_t stepBound);
1662 storm::storage::BitVector const& targetStates, bool qualitative, bool produceScheduler, ModelCheckerHint const& hint);
1666 bool qualitative, bool produceScheduler, ModelCheckerHint const& hint);
1667
1668} // namespace helper
1669} // namespace modelchecker
1670} // 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.
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)
void oneMinus()
Flips the comparison type, the direction, and computes the new threshold as 1 - old threshold.
Definition SolveGoal.cpp:57
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:18
void complement()
Negates all bits 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.
uint_fast64_t getNextSetIndex(uint_fast64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
void set(uint_fast64_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.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
std::vector< uint_fast64_t > getNumberOfSetBitsBeforeIndices() const
Retrieves a vector that holds at position i the number of bits set before index i.
bool get(uint_fast64_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 can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
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...
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
index_type getNonzeroEntryCount() const
Returns the cached number of nonzero entries in 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:29
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#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)
SettingsType const & getModule()
Get module.
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:835
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:490
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:542
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
Definition graph.cpp:48
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:857
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:624
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:997
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:689
storm::storage::BitVector performProb0A(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:749
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:383
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:976
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:593
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:1079
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:757
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:599
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:83
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:58
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:189
void filterVectorInPlace(std::vector< Type > &v, storm::storage::BitVector const &filter)
Definition vector.h:1224
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
Definition vector.h:1213
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.
Definition cli.cpp:18
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