Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseDtmcPrctlHelper.cpp
Go to the documentation of this file.
2
9#include "storm/io/export.h"
28#include "storm/utility/graph.h"
31
32namespace storm {
33namespace modelchecker {
34namespace helper {
35
36template<>
37std::map<storm::storage::sparse::state_type, storm::RationalFunction> SparseDtmcPrctlHelper<storm::RationalFunction>::computeRewardBoundedValues(
39 std::shared_ptr<storm::logic::OperatorFormula const> /*rewardBoundedFormula*/) {
40 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The specified property is not supported by this value type.");
41 return std::map<storm::storage::sparse::state_type, storm::RationalFunction>();
42}
43
44template<typename ValueType, typename RewardModelType, typename SolutionType>
46 Environment const& env, storm::models::sparse::Dtmc<ValueType> const& model, std::shared_ptr<storm::logic::OperatorFormula const> rewardBoundedFormula) {
47 if constexpr (storm::IsIntervalType<ValueType>) {
48 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reward bounded values with interval models.");
49 } else {
50 storm::utility::Stopwatch swAll(true), swBuild, swCheck;
51
53
54 // Get lower and upper bounds for the solution.
55 auto lowerBound = rewardUnfolding.getLowerObjectiveBound();
56 auto upperBound = rewardUnfolding.getUpperObjectiveBound();
57
58 // Initialize epoch models
59 auto initEpoch = rewardUnfolding.getStartEpoch();
60 auto epochOrder = rewardUnfolding.getEpochComputationOrder(initEpoch);
61
62 // initialize data that will be needed for each epoch
63 std::vector<ValueType> x, b;
64 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> linEqSolver;
65
66 Environment preciseEnv = env;
67 ValueType precision = rewardUnfolding.getRequiredEpochModelPrecision(
68 initEpoch, storm::utility::convertNumber<ValueType>(storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision()));
69 preciseEnv.solver().setLinearEquationSolverPrecision(storm::utility::convertNumber<storm::RationalNumber>(precision));
70
71 // In case of cdf export we store the necessary data.
72 std::vector<std::vector<ValueType>> cdfData;
73
74 // Set the correct equation problem format.
76 rewardUnfolding.setEquationSystemFormatForEpochModel(linearEquationSolverFactory.getEquationProblemFormat(preciseEnv));
77
78 storm::utility::ProgressMeasurement progress("epochs");
79 progress.setMaxCount(epochOrder.size());
80 progress.startNewMeasurement(0);
81 uint64_t numCheckedEpochs = 0;
82 for (auto const& epoch : epochOrder) {
83 swBuild.start();
84 auto& epochModel = rewardUnfolding.setCurrentEpoch(epoch);
85 swBuild.stop();
86 swCheck.start();
87 rewardUnfolding.setSolutionForCurrentEpoch(epochModel.analyzeSingleObjective(preciseEnv, x, b, linEqSolver, lowerBound, upperBound));
88 swCheck.stop();
89 if (storm::settings::getModule<storm::settings::modules::IOSettings>().isExportCdfSet() &&
90 !rewardUnfolding.getEpochManager().hasBottomDimension(epoch)) {
91 std::vector<ValueType> cdfEntry;
92 for (uint64_t i = 0; i < rewardUnfolding.getEpochManager().getDimensionCount(); ++i) {
93 uint64_t offset = rewardUnfolding.getDimension(i).boundType == helper::rewardbounded::DimensionBoundType::LowerBound ? 1 : 0;
94 cdfEntry.push_back(storm::utility::convertNumber<ValueType>(rewardUnfolding.getEpochManager().getDimensionOfEpoch(epoch, i) + offset) *
95 rewardUnfolding.getDimension(i).scalingFactor);
96 }
97 cdfEntry.push_back(rewardUnfolding.getInitialStateResult(epoch));
98 cdfData.push_back(std::move(cdfEntry));
99 }
100 ++numCheckedEpochs;
101 progress.updateProgress(numCheckedEpochs);
103 break;
104 }
105 }
106
107 std::map<storm::storage::sparse::state_type, ValueType> result;
108 for (auto initState : model.getInitialStates()) {
109 result[initState] = rewardUnfolding.getInitialStateResult(initEpoch, initState);
110 }
111
112 swAll.stop();
113
114 if (storm::settings::getModule<storm::settings::modules::IOSettings>().isExportCdfSet()) {
115 std::vector<std::string> headers;
116 for (uint64_t i = 0; i < rewardUnfolding.getEpochManager().getDimensionCount(); ++i) {
117 headers.push_back(rewardUnfolding.getDimension(i).formula->toString());
118 }
119 headers.push_back("Result");
120 storm::io::exportDataToCSVFile<ValueType, std::string, std::string>(
121 storm::settings::getModule<storm::settings::modules::IOSettings>().getExportCdfDirectory() + "cdf.csv", cdfData, headers);
122 }
123
124 if (storm::settings::getModule<storm::settings::modules::CoreSettings>().isShowStatisticsSet()) {
125 STORM_PRINT_AND_LOG("---------------------------------\n");
126 STORM_PRINT_AND_LOG("Statistics:\n");
127 STORM_PRINT_AND_LOG("---------------------------------\n");
128 STORM_PRINT_AND_LOG(" #checked epochs: " << epochOrder.size() << ".\n");
129 STORM_PRINT_AND_LOG(" overall Time: " << swAll << ".\n");
130 STORM_PRINT_AND_LOG("Epoch Model building Time: " << swBuild << ".\n");
131 STORM_PRINT_AND_LOG("Epoch Model checking Time: " << swCheck << ".\n");
132 STORM_PRINT_AND_LOG("---------------------------------\n");
133 }
134
135 return result;
136 }
137}
138
139template<typename ValueType, typename SolutionType>
141 storm::storage::SparseMatrix<ValueType>&& submatrix, std::vector<ValueType> const& b,
142 bool computeReward) {
143 // Initialize the solution vector.
144 std::vector<SolutionType> x = std::vector<SolutionType>(submatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
145
146 // Set up the solver.
148 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = storm::solver::configureMinMaxLinearEquationSolver(
149 env, std::move(goal), minMaxLinearEquationSolverFactory, std::move(submatrix),
150 convert(OptimizationDirection::Maximize)); // default to maximize for IDTMCs; does not affect the result
151 solver->setUncertaintyResolutionMode(goal.getUncertaintyResolutionMode());
152 solver->setHasUniqueSolution(computeReward); // As we check for graph-preservation, in case of rewards on IDTMCs, we have a unique solution
153 solver->setHasNoEndComponents(false);
154
155 // check requirements of solver
156 auto req = solver->getRequirements(env);
157 if (!computeReward) {
158 solver->setLowerBound(storm::utility::zero<SolutionType>());
159 solver->setUpperBound(storm::utility::one<SolutionType>());
160 req.clearBounds();
161 }
162 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
163 "Solver requirements " + req.getEnabledRequirementsAsString() + " not checked.");
164
165 solver->setRequirementsChecked();
166
167 // Solve the corresponding system of equations.
168 solver->solveEquations(env, x, b);
169
170 return x;
171}
172
173template<typename ValueType, typename RewardModelType, typename SolutionType>
176 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
177 bool qualitative, ModelCheckerHint const& hint) {
178 std::vector<SolutionType> result(transitionMatrix.getRowCount(), storm::utility::zero<SolutionType>());
179
180 // We need to identify the maybe states (states which have a probability for satisfying the until formula
181 // that is strictly between 0 and 1) and the states that satisfy the formula with probability 1.
182 storm::storage::BitVector maybeStates, statesWithProbability1;
183
184 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
185 maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
186
187 // Treat the states with probability one
188 std::vector<SolutionType> const& resultsForNonMaybeStates = hint.template asExplicitModelCheckerHint<SolutionType>().getResultHint();
189 statesWithProbability1 = storm::storage::BitVector(maybeStates.size(), false);
190 storm::storage::BitVector nonMaybeStates = ~maybeStates;
191 for (auto state : nonMaybeStates) {
192 if (storm::utility::isOne(resultsForNonMaybeStates[state])) {
193 statesWithProbability1.set(state, true);
194 result[state] = storm::utility::one<SolutionType>();
195 } else {
196 STORM_LOG_THROW(storm::utility::isZero(resultsForNonMaybeStates[state]), storm::exceptions::IllegalArgumentException,
197 "Expected that the result hint specifies probabilities in {0,1} for non-maybe states");
198 }
199 }
200
201 STORM_LOG_INFO("Preprocessing: " << statesWithProbability1.getNumberOfSetBits() << " states with probability 1 (" << maybeStates.getNumberOfSetBits()
202 << " states remaining).");
203 } else {
204 // Get all states that have probability 0 and 1 of satisfying the until-formula.
205 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
206 storm::utility::graph::performProb01(backwardTransitions, phiStates, psiStates);
207 storm::storage::BitVector statesWithProbability0 = std::move(statesWithProbability01.first);
208 statesWithProbability1 = std::move(statesWithProbability01.second);
209 maybeStates = ~(statesWithProbability0 | statesWithProbability1);
210
211 STORM_LOG_INFO("Preprocessing: " << statesWithProbability1.getNumberOfSetBits() << " states with probability 1, "
212 << statesWithProbability0.getNumberOfSetBits() << " with probability 0 (" << maybeStates.getNumberOfSetBits()
213 << " states remaining).");
214
215 // Set values of resulting vector that are known exactly.
216 storm::utility::vector::setVectorValues<SolutionType>(result, statesWithProbability0, storm::utility::zero<SolutionType>());
217 storm::utility::vector::setVectorValues<SolutionType>(result, statesWithProbability1, storm::utility::one<SolutionType>());
218 }
219
220 // Check if the values of the maybe states are relevant for the SolveGoal
221 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(maybeStates);
222
223 // Check whether we need to compute exact probabilities for some states.
224 if (qualitative || maybeStatesNotRelevant) {
225 // Set the values for all maybe-states to 0.5 to indicate that their probability values are neither 0 nor 1.
226 storm::utility::vector::setVectorValues<SolutionType>(result, maybeStates, storm::utility::convertNumber<SolutionType>(0.5));
227 } else {
228 if (!maybeStates.empty()) {
229 // In this case we have to compute the probabilities.
230 if constexpr (storm::IsIntervalType<ValueType>) {
231 // Compute probabilities in a robust fashion by using the logic as for MDPs
233 std::vector<ValueType> b;
234
235 submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates));
236
237 // Prepare the right-hand side of the equation system. For entry i this corresponds to
238 // the accumulated probability of going from state i to some state that has probability 1.
239 storm::utility::vector::setAllValues(b, transitionMatrix.getRowFilter(statesWithProbability1));
240
241 std::vector<SolutionType> x = computeRobustValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, false);
242
243 // Set values of resulting vector according to result.
244 storm::utility::vector::setVectorValues<SolutionType>(result, maybeStates, x);
245 } else {
246 // Check whether we need to convert the input to equation system format.
248 bool convertToEquationSystem =
250
251 // We can eliminate the rows and columns from the original transition probability matrix.
252 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, convertToEquationSystem);
253 if (convertToEquationSystem) {
254 // Converting the matrix from the fixpoint notation to the form needed for the equation
255 // system. That is, we go from x = A*x + b to (I-A)x = b.
256 submatrix.convertToEquationSystem();
257 }
258
259 // Initialize the x vector with the hint (if available) or with 0.5 for each element.
260 // This is the initial guess for the iterative solvers. It should be safe as for all
261 // 'maybe' states we know that the probability is strictly larger than 0.
262 std::vector<SolutionType> x;
263 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasResultHint()) {
264 x = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint<SolutionType>().getResultHint(), maybeStates);
265 } else {
266 x = std::vector<SolutionType>(maybeStates.getNumberOfSetBits(), storm::utility::convertNumber<SolutionType>(0.5));
267 }
268
269 // Prepare the right-hand side of the equation system. For entry i this corresponds to
270 // the accumulated probability of going from state i to some 'yes' state.
271 std::vector<SolutionType> b = transitionMatrix.getConstrainedRowSumVector(maybeStates, statesWithProbability1);
272
273 // Now solve the created system of linear equations.
274 goal.restrictRelevantValues(maybeStates);
275 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver =
276 storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix));
277 solver->setBounds(storm::utility::zero<ValueType>(), storm::utility::one<ValueType>());
278 solver->solveEquations(env, x, b);
279
280 // Set values of resulting vector according to result.
281 storm::utility::vector::setVectorValues<SolutionType>(result, maybeStates, x);
282 }
283 }
284 }
285 return result;
286}
287
288template<typename ValueType, typename RewardModelType, typename SolutionType>
291 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
292 if constexpr (storm::IsIntervalType<ValueType>) {
293 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing all until probabilities with interval models.");
294 } else {
295 uint_fast64_t numberOfStates = transitionMatrix.getRowCount();
296 std::vector<SolutionType> result(numberOfStates, storm::utility::zero<SolutionType>());
297
298 // All states are relevant
299 storm::storage::BitVector relevantStates(numberOfStates, true);
300
301 // Compute exact probabilities for some states.
302 if (!relevantStates.empty()) {
303 // Check whether we need to convert the input to equation system format.
305 bool convertToEquationSystem =
307
308 storm::storage::SparseMatrix<ValueType> submatrix(transitionMatrix);
309 submatrix.makeRowsAbsorbing(phiStates);
310 submatrix.makeRowsAbsorbing(psiStates);
311 // submatrix.deleteDiagonalEntries(psiStates);
312 // storm::storage::BitVector failState(numberOfStates, false);
313 // failState.set(0, true);
314 submatrix.deleteDiagonalEntries();
315 submatrix = submatrix.transpose();
316 submatrix = submatrix.getSubmatrix(true, relevantStates, relevantStates, convertToEquationSystem);
317
318 if (convertToEquationSystem) {
319 // Converting the matrix from the fixpoint notation to the form needed for the equation
320 // system. That is, we go from x = A*x + b to (I-A)x = b.
321 submatrix.convertToEquationSystem();
322 }
323
324 // Initialize the x vector with 0.5 for each element.
325 // This is the initial guess for the iterative solvers. It should be safe as for all
326 // 'maybe' states we know that the probability is strictly larger than 0.
327 std::vector<SolutionType> x = std::vector<SolutionType>(relevantStates.getNumberOfSetBits(), storm::utility::convertNumber<SolutionType>(0.5));
328
329 // Prepare the right-hand side of the equation system.
330 std::vector<SolutionType> b(relevantStates.getNumberOfSetBits(), storm::utility::zero<SolutionType>());
331 // Set initial states
332 size_t i = 0;
333 ValueType initDist = storm::utility::one<ValueType>() / storm::utility::convertNumber<ValueType>(initialStates.getNumberOfSetBits());
334 for (auto state : relevantStates) {
335 if (initialStates.get(state)) {
336 b[i] = initDist;
337 }
338 ++i;
339 }
340
341 // Now solve the created system of linear equations.
342 goal.restrictRelevantValues(relevantStates);
343 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver =
344 storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix));
345 solver->setBounds(storm::utility::zero<ValueType>(), storm::utility::one<ValueType>());
346 solver->solveEquations(env, x, b);
347
348 // Set values of resulting vector according to result.
349 storm::utility::vector::setVectorValues<SolutionType>(result, relevantStates, x);
350 }
351 return result;
352 }
353}
354
355template<typename ValueType, typename RewardModelType, typename SolutionType>
358 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative) {
359 if constexpr (storm::IsIntervalType<ValueType>) {
360 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing globally probabilities with interval models.");
361 } else {
362 goal.oneMinus();
363 std::vector<SolutionType> result = computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions,
364 storm::storage::BitVector(transitionMatrix.getRowCount(), true), ~psiStates, qualitative);
365 for (auto& entry : result) {
366 entry = storm::utility::one<SolutionType>() - entry;
367 }
368 return result;
369 }
370}
371
372template<typename ValueType, typename RewardModelType, typename SolutionType>
374 Environment const& env, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& nextStates) {
375 if constexpr (storm::IsIntervalType<ValueType>) {
376 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with interval models.");
377 } else {
378 // Create the vector with which to multiply and initialize it correctly.
379 std::vector<ValueType> result(transitionMatrix.getRowCount());
380 storm::utility::vector::setVectorValues(result, nextStates, storm::utility::one<ValueType>());
381
382 // Perform one single matrix-vector multiplication.
383 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
384 multiplier->multiply(env, result, nullptr, result);
385 return result;
386 }
387}
388
389template<typename ValueType, typename RewardModelType, typename SolutionType>
392 RewardModelType const& rewardModel, uint_fast64_t stepBound) {
393 if constexpr (storm::IsIntervalType<ValueType>) {
394 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models.");
395 } else {
396 // Initialize result to the null vector.
397 std::vector<ValueType> result(transitionMatrix.getRowCount());
398
399 // Compute the reward vector to add in each step based on the available reward models.
400 std::vector<ValueType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
401
402 // Perform the matrix vector multiplication as often as required by the formula bound.
403 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
404 multiplier->repeatedMultiply(env, result, &totalRewardVector, stepBound);
405
406 return result;
407 }
408}
409
410template<typename ValueType, typename RewardModelType, typename SolutionType>
413 RewardModelType const& rewardModel, uint_fast64_t stepCount) {
414 if constexpr (storm::IsIntervalType<ValueType>) {
415 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantaneous rewards with interval models.");
416 } else {
417 // Only compute the result if the model has a state-based reward this->getModel().
418 STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException,
419 "Computing instantaneous rewards for a reward model that does not define any state-rewards. The result is trivially 0.");
420
421 // Initialize result to state rewards of the model.
422 std::vector<ValueType> result = rewardModel.getStateRewardVector();
423
424 // Perform the matrix vector multiplication as often as required by the formula bound.
425 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
426 multiplier->repeatedMultiply(env, result, nullptr, stepCount);
427
428 return result;
429 }
430}
431
432template<typename ValueType, typename RewardModelType, typename SolutionType>
435 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, ModelCheckerHint const& hint) {
436 if constexpr (storm::IsIntervalType<ValueType>) {
437 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing total rewards with interval models.");
438 } else {
439 // Identify the states from which only states with zero reward are reachable.
440 // We can then compute reachability rewards assuming these states as target set.
441 storm::storage::BitVector statesWithoutReward = rewardModel.getStatesWithZeroReward(transitionMatrix);
442 storm::storage::BitVector rew0States = storm::utility::graph::performProbGreater0(backwardTransitions, statesWithoutReward, ~statesWithoutReward);
443 rew0States.complement();
444 return computeReachabilityRewards(env, std::move(goal), transitionMatrix, backwardTransitions, rewardModel, rew0States, qualitative, hint);
445 }
446}
447
448template<>
452 storm::models::sparse::StandardRewardModel<storm::RationalFunction> const& rewardModel, uint_fast64_t stepBound, storm::RationalFunction discountFactor) {
453 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The specified property is not supported by this value type.");
454 return {};
455}
456
457template<typename ValueType, typename RewardModelType, typename SolutionType>
460 RewardModelType const& rewardModel, uint_fast64_t stepBound, ValueType discountFactor) {
461 if constexpr (storm::IsIntervalType<ValueType>) {
462 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support discounted cumulative rewards with interval models.");
463 } else {
464 // Only compute the result if the model has at least one reward this->getModel().
465 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
466
467 // Compute the reward vector to add in each step based on the available reward models.
468 std::vector<ValueType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
469
470 // Initialize result to the zero vector.
471 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
472
473 auto multiplier = storm::solver::MultiplierFactory<SolutionType>().create(env, transitionMatrix);
474 multiplier->repeatedMultiplyWithFactor(env, result, &totalRewardVector, stepBound, discountFactor);
475
476 return result;
477 }
478}
479
480template<>
485 storm::models::sparse::StandardRewardModel<storm::RationalFunction> const& rewardModel, bool qualitative, storm::RationalFunction discountFactor,
486 ModelCheckerHint const& hint) {
487 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The specified property is not supported by this value type.");
488 return {};
489}
490
491template<typename ValueType, typename RewardModelType, typename SolutionType>
494 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, ValueType discountFactor,
495 ModelCheckerHint const& hint) {
496 if constexpr (storm::IsIntervalType<ValueType>) {
497 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support discounted total rewards with interval models.");
498 } else {
499 // If the solver is set to force exact results, throw an error if the method is not explicitly set to a value iteration type.
500 STORM_LOG_THROW(!env.solver().isForceExact(), storm::exceptions::NotSupportedException,
501 "Exact solving of discounted total reward objectives is currently not supported.");
502
503 // Reduce to reachability rewards
504 std::vector<ValueType> b;
505
506 std::vector<ValueType> x = std::vector<ValueType>(transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
507 b = rewardModel.getTotalRewardVector(transitionMatrix);
508 storm::modelchecker::helper::DiscountingHelper<SolutionType, true> discountingHelper(transitionMatrix, discountFactor);
509 discountingHelper.solveWithDiscountedValueIteration(env, std::nullopt, x, b);
510 return std::vector<SolutionType>(std::move(x));
511 }
512}
513
514template<typename ValueType, typename RewardModelType, typename SolutionType>
517 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates,
518 bool qualitative, ModelCheckerHint const& hint) {
519 return computeReachabilityRewards(
520 env, std::move(goal), transitionMatrix, backwardTransitions,
521 [&](uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
522 return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
523 },
524 targetStates, qualitative, [&]() { return rewardModel.getStatesWithZeroReward(transitionMatrix); }, hint);
525}
526
527template<typename ValueType, typename RewardModelType, typename SolutionType>
530 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& totalStateRewardVector,
531 storm::storage::BitVector const& targetStates, bool qualitative, ModelCheckerHint const& hint) {
532 return computeReachabilityRewards(
533 env, std::move(goal), transitionMatrix, backwardTransitions,
534 [&](uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const& maybeStates) {
535 std::vector<ValueType> result(numberOfRows, storm::utility::zero<ValueType>());
536 storm::utility::vector::selectVectorValues(result, maybeStates, totalStateRewardVector);
537 return result;
538 },
539 targetStates, qualitative, [&]() { return storm::utility::vector::filterZero(totalStateRewardVector); }, hint);
540}
541
542template<typename ValueType, typename RewardModelType, typename SolutionType>
545 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates, bool qualitative,
546 ModelCheckerHint const& hint) {
547 if constexpr (storm::IsIntervalType<ValueType>) {
548 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reachability times with interval models.");
549 } else {
550 return computeReachabilityRewards(
551 env, std::move(goal), transitionMatrix, backwardTransitions,
552 [&](uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&) {
553 return std::vector<ValueType>(numberOfRows, storm::utility::one<ValueType>());
554 },
555 targetStates, qualitative, [&]() { return storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); }, hint);
556 }
557}
558
559// This function computes an upper bound on the reachability rewards (see Baier et al, CAV'17).
560template<typename ValueType, typename SolutionType>
561std::vector<SolutionType> computeUpperRewardBounds(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType> const& rewards,
562 std::vector<SolutionType> const& oneStepTargetProbabilities) {
563 if constexpr (storm::IsIntervalType<ValueType>) {
564 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models.");
565 } else {
566 DsMpiDtmcUpperRewardBoundsComputer<ValueType> dsmpi(transitionMatrix, rewards, oneStepTargetProbabilities);
567 std::vector<ValueType> bounds = dsmpi.computeUpperBounds();
568 return bounds;
569 }
570}
571
572template<>
573std::vector<storm::RationalFunction> computeUpperRewardBounds(storm::storage::SparseMatrix<storm::RationalFunction> const& /*transitionMatrix*/,
574 std::vector<storm::RationalFunction> const& /*rewards*/,
575 std::vector<storm::RationalFunction> const& /*oneStepTargetProbabilities*/) {
576 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Computing upper reward bounds is not supported for rational functions.");
577}
578
579template<typename ValueType, typename RewardModelType, typename SolutionType>
582 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
583 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
584 totalStateRewardVectorGetter,
585 storm::storage::BitVector const& targetStates, bool qualitative, std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter,
586 ModelCheckerHint const& hint) {
587 std::vector<SolutionType> result(transitionMatrix.getRowCount(), storm::utility::zero<SolutionType>());
588
589 // Determine which states have reward zero
590 storm::storage::BitVector rew0States;
591 if (storm::settings::getModule<storm::settings::modules::ModelCheckerSettings>().isFilterRewZeroSet()) {
592 rew0States = storm::utility::graph::performProb1(backwardTransitions, zeroRewardStatesGetter(), targetStates);
593 } else {
594 rew0States = targetStates;
595 }
596
597 // Determine which states have a reward that is less than infinity.
598 storm::storage::BitVector maybeStates;
599 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
600 maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
601 storm::utility::vector::setVectorValues(result, ~(maybeStates | rew0States), storm::utility::infinity<SolutionType>());
602
603 STORM_LOG_INFO("Preprocessing: " << rew0States.getNumberOfSetBits() << " States with reward zero (" << maybeStates.getNumberOfSetBits()
604 << " states remaining).");
605 } else {
606 storm::storage::BitVector trueStates(transitionMatrix.getRowCount(), true);
607 storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(backwardTransitions, trueStates, rew0States);
608 infinityStates.complement();
609 maybeStates = ~(rew0States | infinityStates);
610
611 STORM_LOG_INFO("Preprocessing: " << infinityStates.getNumberOfSetBits() << " states with reward infinity, " << rew0States.getNumberOfSetBits()
612 << " states with reward zero (" << maybeStates.getNumberOfSetBits() << " states remaining).");
613
614 storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity<SolutionType>());
615 }
616
617 // Check if the values of the maybe states are relevant for the SolveGoal
618 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(maybeStates);
619
620 // Check whether we need to compute exact rewards for some states.
621 if (qualitative || maybeStatesNotRelevant) {
622 // Set the values for all maybe-states to 1 to indicate that their reward values
623 // are neither 0 nor infinity.
624 storm::utility::vector::setVectorValues<SolutionType>(result, maybeStates, storm::utility::one<SolutionType>());
625 } else {
626 if (!maybeStates.empty()) {
627 if constexpr (storm::IsIntervalType<ValueType>) {
628 // In this case we have to compute the reward values for the remaining states.
629 // We can eliminate the rows and columns from the original transition probability matrix.
630 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates));
631
632 // Prepare the right-hand side of the equation system.
633 std::vector<ValueType> b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, maybeStates);
634
635 // Compute values for maybe states.
636 std::vector<SolutionType> x = computeRobustValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, true);
637
638 // Set values of resulting vector according to result.
639 storm::utility::vector::setVectorValues<SolutionType>(result, maybeStates, x);
640 } else {
641 // Check whether we need to convert the input to equation system format.
643 bool convertToEquationSystem =
645
646 // In this case we have to compute the reward values for the remaining states.
647 // We can eliminate the rows and columns from the original transition probability matrix.
648 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, convertToEquationSystem);
649
650 // Initialize the x vector with the hint (if available) or with 1 for each element.
651 // This is the initial guess for the iterative solvers.
652 std::vector<ValueType> x;
653 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasResultHint()) {
654 x = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint<ValueType>().getResultHint(), maybeStates);
655 } else {
656 x = std::vector<ValueType>(submatrix.getColumnCount(), storm::utility::one<ValueType>());
657 }
658
659 // Prepare the right-hand side of the equation system.
660 std::vector<ValueType> b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, maybeStates);
661
662 storm::solver::LinearEquationSolverRequirements requirements = linearEquationSolverFactory.getRequirements(env);
663 boost::optional<std::vector<ValueType>> upperRewardBounds;
664 requirements.clearLowerBounds();
665 if (requirements.upperBounds()) {
666 upperRewardBounds = computeUpperRewardBounds(submatrix, b, transitionMatrix.getConstrainedRowSumVector(maybeStates, rew0States));
667 requirements.clearUpperBounds();
668 }
669 STORM_LOG_THROW(!requirements.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
670 "Solver requirements " + requirements.getEnabledRequirementsAsString() + " not checked.");
671
672 // If necessary, convert the matrix from the fixpoint notation to the form needed for the equation system.
673 if (convertToEquationSystem) {
674 // go from x = A*x + b to (I-A)x = b.
675 submatrix.convertToEquationSystem();
676 }
677
678 // Create the solver.
679 goal.restrictRelevantValues(maybeStates);
680 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver =
681 storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix));
682 solver->setLowerBound(storm::utility::zero<ValueType>());
683 if (upperRewardBounds) {
684 solver->setUpperBounds(std::move(upperRewardBounds.get()));
685 }
686
687 // Now solve the resulting equation system.
688 solver->solveEquations(env, x, b);
689
690 // Set values of resulting vector according to result.
691 storm::utility::vector::setVectorValues<SolutionType>(result, maybeStates, x);
692 }
693 }
694 }
695 return result;
696}
697
698template<typename ValueType, typename RewardModelType, typename SolutionType>
699typename SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::BaierTransformedModel
700SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::computeBaierTransformation(Environment const& env,
701 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
702 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
703 storm::storage::BitVector const& targetStates,
704 storm::storage::BitVector const& conditionStates,
705 boost::optional<std::vector<ValueType>> const& stateRewards) {
706 if constexpr (storm::IsIntervalType<ValueType>) {
707 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support baier transformation with interval models.");
708 } else {
709 BaierTransformedModel result;
710
711 // Start by computing all 'before' states, i.e. the states for which the conditional probability is defined.
712 std::vector<ValueType> probabilitiesToReachConditionStates =
713 computeUntilProbabilities(env, storm::solver::SolveGoal<ValueType>(), transitionMatrix, backwardTransitions,
714 storm::storage::BitVector(transitionMatrix.getRowCount(), true), conditionStates, false);
715
716 result.beforeStates = storm::storage::BitVector(targetStates.size(), true);
717 uint_fast64_t state = 0;
718 uint_fast64_t beforeStateIndex = 0;
719 for (auto const& value : probabilitiesToReachConditionStates) {
720 if (value == storm::utility::zero<ValueType>()) {
721 result.beforeStates.set(state, false);
722 } else {
723 probabilitiesToReachConditionStates[beforeStateIndex] = value;
724 ++beforeStateIndex;
725 }
726 ++state;
727 }
728 probabilitiesToReachConditionStates.resize(beforeStateIndex);
729
730 if (targetStates.empty()) {
731 result.noTargetStates = true;
732 return result;
733 } else if (!result.beforeStates.empty()) {
734 // If there are some states for which the conditional probability is defined and there are some
735 // states that can reach the target states without visiting condition states first, we need to
736 // do more work.
737
738 // First, compute the relevant states and some offsets.
739 storm::storage::BitVector allStates(targetStates.size(), true);
740 std::vector<uint_fast64_t> numberOfBeforeStatesUpToState = result.beforeStates.getNumberOfSetBitsBeforeIndices();
741 storm::storage::BitVector statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, allStates, targetStates);
742 statesWithProbabilityGreater0 &= storm::utility::graph::getReachableStates(transitionMatrix, conditionStates, allStates, targetStates);
743 uint_fast64_t normalStatesOffset = result.beforeStates.getNumberOfSetBits();
744 std::vector<uint_fast64_t> numberOfNormalStatesUpToState = statesWithProbabilityGreater0.getNumberOfSetBitsBeforeIndices();
745
746 // All transitions going to states with probability zero, need to be redirected to a deadlock state.
747 bool addDeadlockState = false;
748 uint_fast64_t deadlockState = normalStatesOffset + statesWithProbabilityGreater0.getNumberOfSetBits();
749
750 // Now, we create the matrix of 'before' and 'normal' states.
752
753 // Start by creating the transitions of the 'before' states.
754 uint_fast64_t currentRow = 0;
755 for (auto beforeState : result.beforeStates) {
756 if (conditionStates.get(beforeState)) {
757 // For condition states, we move to the 'normal' states.
758 ValueType zeroProbability = storm::utility::zero<ValueType>();
759 for (auto const& successorEntry : transitionMatrix.getRow(beforeState)) {
760 if (statesWithProbabilityGreater0.get(successorEntry.getColumn())) {
761 builder.addNextValue(currentRow, normalStatesOffset + numberOfNormalStatesUpToState[successorEntry.getColumn()],
762 successorEntry.getValue());
763 } else {
764 zeroProbability += successorEntry.getValue();
765 }
766 }
767 if (!storm::utility::isZero(zeroProbability)) {
768 builder.addNextValue(currentRow, deadlockState, zeroProbability);
769 }
770 } else {
771 // For non-condition states, we scale the probabilities going to other before states.
772 for (auto const& successorEntry : transitionMatrix.getRow(beforeState)) {
773 if (result.beforeStates.get(successorEntry.getColumn())) {
774 builder.addNextValue(currentRow, numberOfBeforeStatesUpToState[successorEntry.getColumn()],
775 successorEntry.getValue() *
776 probabilitiesToReachConditionStates[numberOfBeforeStatesUpToState[successorEntry.getColumn()]] /
777 probabilitiesToReachConditionStates[currentRow]);
778 }
779 }
780 }
781 ++currentRow;
782 }
783
784 // Then, create the transitions of the 'normal' states.
785 for (auto state : statesWithProbabilityGreater0) {
786 ValueType zeroProbability = storm::utility::zero<ValueType>();
787 for (auto const& successorEntry : transitionMatrix.getRow(state)) {
788 if (statesWithProbabilityGreater0.get(successorEntry.getColumn())) {
789 builder.addNextValue(currentRow, normalStatesOffset + numberOfNormalStatesUpToState[successorEntry.getColumn()],
790 successorEntry.getValue());
791 } else {
792 zeroProbability += successorEntry.getValue();
793 }
794 }
795 if (!storm::utility::isZero(zeroProbability)) {
796 addDeadlockState = true;
797 builder.addNextValue(currentRow, deadlockState, zeroProbability);
798 }
799 ++currentRow;
800 }
801 if (addDeadlockState) {
802 builder.addNextValue(deadlockState, deadlockState, storm::utility::one<ValueType>());
803 }
804
805 // Build the new transition matrix and the new targets.
806 result.transitionMatrix = builder.build(addDeadlockState ? (deadlockState + 1) : deadlockState);
807 storm::storage::BitVector newTargetStates = targetStates % result.beforeStates;
808 newTargetStates.resize(result.transitionMatrix.get().getRowCount());
809 for (auto state : targetStates % statesWithProbabilityGreater0) {
810 newTargetStates.set(normalStatesOffset + state, true);
811 }
812 result.targetStates = std::move(newTargetStates);
813
814 // If a reward model was given, we need to compute the rewards for the transformed model.
815 if (stateRewards) {
816 std::vector<ValueType> newStateRewards(result.beforeStates.getNumberOfSetBits());
817 storm::utility::vector::selectVectorValues(newStateRewards, result.beforeStates, stateRewards.get());
818
819 newStateRewards.reserve(result.transitionMatrix.get().getRowCount());
820 for (auto state : statesWithProbabilityGreater0) {
821 newStateRewards.push_back(stateRewards.get()[state]);
822 }
823 // Add a zero reward to the deadlock state.
824 if (addDeadlockState) {
825 newStateRewards.push_back(storm::utility::zero<ValueType>());
826 }
827 result.stateRewards = std::move(newStateRewards);
828 }
829 }
830
831 return result;
832 }
833}
834
835template<typename ValueType, typename RewardModelType, typename SolutionType>
836storm::storage::BitVector SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::BaierTransformedModel::getNewRelevantStates() const {
837 storm::storage::BitVector newRelevantStates(transitionMatrix.get().getRowCount());
838 for (uint64_t i = 0; i < this->beforeStates.getNumberOfSetBits(); ++i) {
839 newRelevantStates.set(i);
840 }
841 return newRelevantStates;
842}
843
844template<typename ValueType, typename RewardModelType, typename SolutionType>
845storm::storage::BitVector SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::BaierTransformedModel::getNewRelevantStates(
846 storm::storage::BitVector const& oldRelevantStates) const {
847 storm::storage::BitVector result = oldRelevantStates % this->beforeStates;
848 result.resize(transitionMatrix.get().getRowCount());
849 return result;
850}
851
852template<typename ValueType, typename RewardModelType, typename SolutionType>
855 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
856 storm::storage::BitVector const& conditionStates, bool qualitative) {
857 if constexpr (storm::IsIntervalType<ValueType>) {
858 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional probabilities with interval models.");
859 } else {
860 // Prepare result vector.
861 std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::infinity<ValueType>());
862
863 if (!conditionStates.empty()) {
864 BaierTransformedModel transformedModel =
865 computeBaierTransformation(env, transitionMatrix, backwardTransitions, targetStates, conditionStates, boost::none);
866
867 if (transformedModel.noTargetStates) {
868 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, storm::utility::zero<ValueType>());
869 } else {
870 // At this point, we do not need to check whether there are 'before' states, since the condition
871 // states were non-empty so there is at least one state with a positive probability of satisfying
872 // the condition.
873
874 // Now compute reachability probabilities in the transformed model.
875 storm::storage::SparseMatrix<ValueType> const& newTransitionMatrix = transformedModel.transitionMatrix.get();
876 storm::storage::BitVector newRelevantValues;
877 if (goal.hasRelevantValues()) {
878 newRelevantValues = transformedModel.getNewRelevantStates(goal.relevantValues());
879 } else {
880 newRelevantValues = transformedModel.getNewRelevantStates();
881 }
882 goal.setRelevantValues(std::move(newRelevantValues));
883 std::vector<ValueType> conditionalProbabilities = computeUntilProbabilities(
884 env, std::move(goal), newTransitionMatrix, newTransitionMatrix.transpose(),
885 storm::storage::BitVector(newTransitionMatrix.getRowCount(), true), transformedModel.targetStates.get(), qualitative);
886
887 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, conditionalProbabilities);
888 }
889 }
890
891 return result;
892 }
893}
894
895template<typename ValueType, typename RewardModelType, typename SolutionType>
898 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates,
899 storm::storage::BitVector const& conditionStates, bool qualitative) {
900 if constexpr (storm::IsIntervalType<ValueType>) {
901 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional rewards with interval models.");
902 } else {
903 // Prepare result vector.
904 std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::infinity<ValueType>());
905
906 if (!conditionStates.empty()) {
907 BaierTransformedModel transformedModel = computeBaierTransformation(env, transitionMatrix, backwardTransitions, targetStates, conditionStates,
908 rewardModel.getTotalRewardVector(transitionMatrix));
909
910 if (transformedModel.noTargetStates) {
911 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, storm::utility::zero<ValueType>());
912 } else {
913 // At this point, we do not need to check whether there are 'before' states, since the condition
914 // states were non-empty so there is at least one state with a positive probability of satisfying
915 // the condition.
916
917 // Now compute reachability probabilities in the transformed model.
918 storm::storage::SparseMatrix<ValueType> const& newTransitionMatrix = transformedModel.transitionMatrix.get();
919 storm::storage::BitVector newRelevantValues;
920 if (goal.hasRelevantValues()) {
921 newRelevantValues = transformedModel.getNewRelevantStates(goal.relevantValues());
922 } else {
923 newRelevantValues = transformedModel.getNewRelevantStates();
924 }
925 goal.setRelevantValues(std::move(newRelevantValues));
926 std::vector<ValueType> conditionalRewards =
927 computeReachabilityRewards(env, std::move(goal), newTransitionMatrix, newTransitionMatrix.transpose(), transformedModel.stateRewards.get(),
928 transformedModel.targetStates.get(), qualitative);
929 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, conditionalRewards);
930 }
931 }
932
933 return result;
934 }
935}
936
937template class SparseDtmcPrctlHelper<double>;
938
942} // namespace helper
943} // namespace modelchecker
944} // namespace storm
SolverEnvironment & solver()
void setLinearEquationSolverPrecision(boost::optional< storm::RationalNumber > const &newPrecision, boost::optional< bool > const &relativePrecision=boost::none)
This class contains information that might accelerate the model checking process.
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.
static std::vector< 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, ModelCheckerHint const &hint=ModelCheckerHint())
static std::vector< SolutionType > computeConditionalProbabilities(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 &targetStates, storm::storage::BitVector const &conditionStates, bool qualitative)
static std::vector< SolutionType > computeReachabilityTimes(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 &targetStates, bool qualitative, ModelCheckerHint const &hint=ModelCheckerHint())
static std::vector< SolutionType > computeReachabilityRewards(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, RewardModelType const &rewardModel, storm::storage::BitVector const &targetStates, bool qualitative, ModelCheckerHint const &hint=ModelCheckerHint())
static std::vector< SolutionType > computeDiscountedCumulativeRewards(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, RewardModelType const &rewardModel, uint_fast64_t stepBound, ValueType discountFactor)
static std::vector< SolutionType > computeConditionalRewards(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, RewardModelType const &rewardModel, storm::storage::BitVector const &targetStates, storm::storage::BitVector const &conditionStates, bool qualitative)
static std::vector< SolutionType > computeDiscountedTotalRewards(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, ValueType discountFactor, ModelCheckerHint const &hint=ModelCheckerHint())
static std::map< storm::storage::sparse::state_type, SolutionType > computeRewardBoundedValues(Environment const &env, storm::models::sparse::Dtmc< ValueType > const &model, std::shared_ptr< storm::logic::OperatorFormula const > rewardBoundedFormula)
static std::vector< SolutionType > computeAllUntilProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
static std::vector< 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)
static std::vector< 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, 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::vector< SolutionType > computeNextProbabilities(Environment const &env, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &nextStates)
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...
void setEquationSystemFormatForEpochModel(storm::solver::LinearEquationSolverProblemFormat eqSysFormat)
This class represents a discrete-time Markov chain.
Definition Dtmc.h:13
storm::storage::BitVector const & getInitialStates() const
Retrieves the initial states of the model.
Definition Model.cpp:179
LinearEquationSolverRequirements getRequirements(Environment const &env) const
Retrieves the requirements of the solver if it was created with the current settings.
virtual LinearEquationSolverProblemFormat getEquationProblemFormat(Environment const &env) const
Retrieves the problem format that the solver expects if it was created with the current settings.
std::string getEnabledRequirementsAsString() const
Checks whether there are no critical requirements left.
std::unique_ptr< Multiplier< ValueType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void complement()
Negates all bits in the bit vector.
std::vector< uint64_t > getNumberOfSetBitsBeforeIndices() const
Retrieves a vector that holds at position i the number of bits set before index i.
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.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
void convertToEquationSystem()
Transforms the matrix into an equation system.
void makeRowsAbsorbing(storm::storage::BitVector const &rows, bool dropZeroEntries=false)
This function makes the given rows absorbing.
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...
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.
void deleteDiagonalEntries(bool dropZeroEntries=false)
Sets all diagonal elements to zero.
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
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.
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_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_PRINT_AND_LOG(message)
Definition macros.h:68
SFTBDDChecker::ValueType ValueType
std::vector< SolutionType > computeRobustValuesForMaybeStates(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > &&submatrix, std::vector< ValueType > const &b, bool computeReward)
std::vector< ValueType > computeUpperRewardBounds(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, std::vector< ValueType > const &rewards, std::vector< ValueType > const &oneStepTargetProbabilities)
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, OptimizationDirectionSetting optimizationDirectionSetting=OptimizationDirectionSetting::Unset)
Definition SolveGoal.h:108
std::unique_ptr< storm::solver::LinearEquationSolver< ValueType > > configureLinearEquationSolver(Environment const &env, SolveGoal< ValueType, SolutionType > &&goal, storm::solver::LinearEquationSolverFactory< ValueType > const &factory, MatrixType &&matrix)
Definition SolveGoal.h:130
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01(storm::models::sparse::DeterministicModel< T > const &model, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi until psi i...
Definition graph.cpp:393
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
Definition graph.cpp:41
storm::storage::BitVector performProbGreater0(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Performs a backward depth-first search trough the underlying graph structure of the given model to de...
Definition graph.cpp:315
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
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
storm::storage::BitVector filterZero(std::vector< T > const &values)
Retrieves a bit vector containing all the indices for which the value at this position is equal to ze...
Definition vector.h:519
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