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