Storm 1.13.0.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) {
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(
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();
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
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");
121 storm::settings::getModule<storm::settings::modules::IOSettings>().getExportCdfDirectory() + "cdf.csv", cdfData, headers);
122 }
123
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) {
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.
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.
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> resultForMaybeStates = computeRobustValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, false);
242
243 // For interval models, the result for maybe states indeed also holds values for all qualitative states.
244 STORM_LOG_ASSERT(resultForMaybeStates.size() == transitionMatrix.getColumnCount(), "Dimensions do not match");
245 result = std::move(resultForMaybeStates);
246 } else {
247 // Check whether we need to convert the input to equation system format.
249 bool convertToEquationSystem =
251
252 // We can eliminate the rows and columns from the original transition probability matrix.
253 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, convertToEquationSystem);
254 if (convertToEquationSystem) {
255 // Converting the matrix from the fixpoint notation to the form needed for the equation
256 // system. That is, we go from x = A*x + b to (I-A)x = b.
257 submatrix.convertToEquationSystem();
258 }
259
260 // Initialize the x vector with the hint (if available) or with 0.5 for each element.
261 // This is the initial guess for the iterative solvers. It should be safe as for all
262 // 'maybe' states we know that the probability is strictly larger than 0.
263 std::vector<SolutionType> x;
264 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasResultHint()) {
265 x = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint<SolutionType>().getResultHint(), maybeStates);
266 } else {
267 x = std::vector<SolutionType>(maybeStates.getNumberOfSetBits(), storm::utility::convertNumber<SolutionType>(0.5));
268 }
269
270 // Prepare the right-hand side of the equation system. For entry i this corresponds to
271 // the accumulated probability of going from state i to some 'yes' state.
272 std::vector<SolutionType> b = transitionMatrix.getConstrainedRowSumVector(maybeStates, statesWithProbability1);
273
274 // Now solve the created system of linear equations.
275 goal.restrictRelevantValues(maybeStates);
276 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver =
277 storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix));
279 solver->solveEquations(env, x, b);
280
281 // Set values of resulting vector according to result.
283 }
284 }
285 }
286 return result;
287}
288
289template<typename ValueType, typename RewardModelType, typename SolutionType>
292 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates) {
293 if constexpr (storm::IsIntervalType<ValueType>) {
294 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing all until probabilities with interval models.");
295 } else {
296 uint_fast64_t numberOfStates = transitionMatrix.getRowCount();
297 std::vector<SolutionType> result(numberOfStates, storm::utility::zero<SolutionType>());
298
299 // All states are relevant
300 storm::storage::BitVector relevantStates(numberOfStates, true);
301
302 // Compute exact probabilities for some states.
303 if (!relevantStates.empty()) {
304 // Check whether we need to convert the input to equation system format.
306 bool convertToEquationSystem =
308
309 storm::storage::SparseMatrix<ValueType> submatrix(transitionMatrix);
310 submatrix.makeRowsAbsorbing(phiStates);
311 submatrix.makeRowsAbsorbing(psiStates);
312 // submatrix.deleteDiagonalEntries(psiStates);
313 // storm::storage::BitVector failState(numberOfStates, false);
314 // failState.set(0, true);
315 submatrix.deleteDiagonalEntries();
316 submatrix = submatrix.transpose();
317 submatrix = submatrix.getSubmatrix(true, relevantStates, relevantStates, convertToEquationSystem);
318
319 if (convertToEquationSystem) {
320 // Converting the matrix from the fixpoint notation to the form needed for the equation
321 // system. That is, we go from x = A*x + b to (I-A)x = b.
322 submatrix.convertToEquationSystem();
323 }
324
325 // Initialize the x vector with 0.5 for each element.
326 // This is the initial guess for the iterative solvers. It should be safe as for all
327 // 'maybe' states we know that the probability is strictly larger than 0.
328 std::vector<SolutionType> x = std::vector<SolutionType>(relevantStates.getNumberOfSetBits(), storm::utility::convertNumber<SolutionType>(0.5));
329
330 // Prepare the right-hand side of the equation system.
331 std::vector<SolutionType> b(relevantStates.getNumberOfSetBits(), storm::utility::zero<SolutionType>());
332 // Set initial states
333 size_t i = 0;
335 for (auto state : relevantStates) {
336 if (initialStates.get(state)) {
337 b[i] = initDist;
338 }
339 ++i;
340 }
341
342 // Now solve the created system of linear equations.
343 goal.restrictRelevantValues(relevantStates);
344 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver =
345 storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix));
347 solver->solveEquations(env, x, b);
348
349 // Set values of resulting vector according to result.
351 }
352 return result;
353 }
354}
355
356template<typename ValueType, typename RewardModelType, typename SolutionType>
359 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& psiStates, bool qualitative) {
360 if constexpr (storm::IsIntervalType<ValueType>) {
361 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing globally probabilities with interval models.");
362 } else {
363 goal.oneMinus();
364 std::vector<SolutionType> result = computeUntilProbabilities(env, std::move(goal), transitionMatrix, backwardTransitions,
365 storm::storage::BitVector(transitionMatrix.getRowCount(), true), ~psiStates, qualitative);
366 for (auto& entry : result) {
367 entry = storm::utility::one<SolutionType>() - entry;
368 }
369 return result;
370 }
371}
372
373template<typename ValueType, typename RewardModelType, typename SolutionType>
375 Environment const& env, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& nextStates) {
376 if constexpr (storm::IsIntervalType<ValueType>) {
377 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support next probabilities with interval models.");
378 } else {
379 // Create the vector with which to multiply and initialize it correctly.
380 std::vector<ValueType> result(transitionMatrix.getRowCount());
382
383 // Perform one single matrix-vector multiplication.
384 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
385 multiplier->multiply(env, result, nullptr, result);
386 return result;
387 }
388}
389
390template<typename ValueType, typename RewardModelType, typename SolutionType>
393 RewardModelType const& rewardModel, uint_fast64_t stepBound) {
394 if constexpr (storm::IsIntervalType<ValueType>) {
395 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support cumulative rewards with interval models.");
396 } else {
397 // Initialize result to the null vector.
398 std::vector<ValueType> result(transitionMatrix.getRowCount());
399
400 // Compute the reward vector to add in each step based on the available reward models.
401 std::vector<ValueType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
402
403 // Perform the matrix vector multiplication as often as required by the formula bound.
404 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
405 multiplier->repeatedMultiply(env, result, &totalRewardVector, stepBound);
406
407 return result;
408 }
409}
410
411template<typename ValueType, typename RewardModelType, typename SolutionType>
414 RewardModelType const& rewardModel, uint_fast64_t stepCount) {
415 if constexpr (storm::IsIntervalType<ValueType>) {
416 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support instantaneous rewards with interval models.");
417 } else {
418 // Only compute the result if the model has a state-based reward this->getModel().
419 STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException,
420 "Computing instantaneous rewards for a reward model that does not define any state-rewards. The result is trivially 0.");
421
422 // Initialize result to state rewards of the model.
423 std::vector<ValueType> result = rewardModel.getStateRewardVector();
424
425 // Perform the matrix vector multiplication as often as required by the formula bound.
426 auto multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, transitionMatrix);
427 multiplier->repeatedMultiply(env, result, nullptr, stepCount);
428
429 return result;
430 }
431}
432
433template<typename ValueType, typename RewardModelType, typename SolutionType>
436 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, ModelCheckerHint const& hint) {
437 if constexpr (storm::IsIntervalType<ValueType>) {
438 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing total rewards with interval models.");
439 } else {
440 // Identify the states from which only states with zero reward are reachable.
441 // We can then compute reachability rewards assuming these states as target set.
442 storm::storage::BitVector statesWithoutReward = rewardModel.getStatesWithZeroReward(transitionMatrix);
443 storm::storage::BitVector rew0States = storm::utility::graph::performProbGreater0(backwardTransitions, statesWithoutReward, ~statesWithoutReward);
444 rew0States.complement();
445 return computeReachabilityRewards(env, std::move(goal), transitionMatrix, backwardTransitions, rewardModel, rew0States, qualitative, hint);
446 }
447}
448
449template<>
453 storm::models::sparse::StandardRewardModel<storm::RationalFunction> const& rewardModel, uint_fast64_t stepBound, storm::RationalFunction discountFactor) {
454 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The specified property is not supported by this value type.");
455 return {};
456}
457
458template<typename ValueType, typename RewardModelType, typename SolutionType>
461 RewardModelType const& rewardModel, uint_fast64_t stepBound, ValueType discountFactor) {
462 if constexpr (storm::IsIntervalType<ValueType>) {
463 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support discounted cumulative rewards with interval models.");
464 } else {
465 // Only compute the result if the model has at least one reward this->getModel().
466 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
467
468 // Compute the reward vector to add in each step based on the available reward models.
469 std::vector<ValueType> totalRewardVector = rewardModel.getTotalRewardVector(transitionMatrix);
470
471 // Initialize result to the zero vector.
472 std::vector<SolutionType> result(transitionMatrix.getRowGroupCount(), storm::utility::zero<SolutionType>());
473
474 auto multiplier = storm::solver::MultiplierFactory<SolutionType>().create(env, transitionMatrix);
475 multiplier->repeatedMultiplyWithFactor(env, result, &totalRewardVector, stepBound, discountFactor);
476
477 return result;
478 }
479}
480
481template<>
486 storm::models::sparse::StandardRewardModel<storm::RationalFunction> const& rewardModel, bool qualitative, storm::RationalFunction discountFactor,
487 ModelCheckerHint const& hint) {
488 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "The specified property is not supported by this value type.");
489 return {};
490}
491
492template<typename ValueType, typename RewardModelType, typename SolutionType>
495 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, bool qualitative, ValueType discountFactor,
496 ModelCheckerHint const& hint) {
497 if constexpr (storm::IsIntervalType<ValueType>) {
498 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support discounted total rewards with interval models.");
499 } else {
500 // If the solver is set to force exact results, throw an error if the method is not explicitly set to a value iteration type.
501 STORM_LOG_THROW(!env.solver().isForceExact(), storm::exceptions::NotSupportedException,
502 "Exact solving of discounted total reward objectives is currently not supported.");
503
504 // Reduce to reachability rewards
505 std::vector<ValueType> b;
506
507 std::vector<ValueType> x = std::vector<ValueType>(transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
508 b = rewardModel.getTotalRewardVector(transitionMatrix);
509 storm::modelchecker::helper::DiscountingHelper<SolutionType, true> discountingHelper(transitionMatrix, discountFactor);
510 discountingHelper.solveWithDiscountedValueIteration(env, std::nullopt, x, b);
511 return std::vector<SolutionType>(std::move(x));
512 }
513}
514
515template<typename ValueType, typename RewardModelType, typename SolutionType>
518 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates,
519 bool qualitative, ModelCheckerHint const& hint) {
521 env, std::move(goal), transitionMatrix, backwardTransitions,
522 [&](uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::BitVector const& maybeStates) {
523 return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
524 },
525 targetStates, qualitative, [&]() { return rewardModel.getStatesWithZeroReward(transitionMatrix); }, hint);
526}
527
528template<typename ValueType, typename RewardModelType, typename SolutionType>
531 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, std::vector<ValueType> const& totalStateRewardVector,
532 storm::storage::BitVector const& targetStates, bool qualitative, ModelCheckerHint const& hint) {
534 env, std::move(goal), transitionMatrix, backwardTransitions,
535 [&](uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const& maybeStates) {
536 std::vector<ValueType> result(numberOfRows, storm::utility::zero<ValueType>());
537 storm::utility::vector::selectVectorValues(result, maybeStates, totalStateRewardVector);
538 return result;
539 },
540 targetStates, qualitative, [&]() { return storm::utility::vector::filterZero(totalStateRewardVector); }, hint);
541}
542
543template<typename ValueType, typename RewardModelType, typename SolutionType>
546 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates, bool qualitative,
547 ModelCheckerHint const& hint) {
548 if constexpr (storm::IsIntervalType<ValueType>) {
549 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing reachability times with interval models.");
550 } else {
552 env, std::move(goal), transitionMatrix, backwardTransitions,
553 [&](uint_fast64_t numberOfRows, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&) {
554 return std::vector<ValueType>(numberOfRows, storm::utility::one<ValueType>());
555 },
556 targetStates, qualitative, [&]() { return storm::storage::BitVector(transitionMatrix.getRowGroupCount(), false); }, hint);
557 }
558}
559
560// This function computes an upper bound on the reachability rewards (see Baier et al, CAV'17).
561template<typename ValueType, typename SolutionType>
562std::vector<SolutionType> computeUpperRewardBounds(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType> const& rewards,
563 std::vector<SolutionType> const& oneStepTargetProbabilities) {
564 if constexpr (storm::IsIntervalType<ValueType>) {
565 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing upper reward bounds with interval models.");
566 } else {
567 DsMpiDtmcUpperRewardBoundsComputer<ValueType> dsmpi(transitionMatrix, rewards, oneStepTargetProbabilities);
568 std::vector<ValueType> bounds = dsmpi.computeUpperBounds();
569 return bounds;
570 }
571}
572
573template<>
574std::vector<storm::RationalFunction> computeUpperRewardBounds(storm::storage::SparseMatrix<storm::RationalFunction> const& /*transitionMatrix*/,
575 std::vector<storm::RationalFunction> const& /*rewards*/,
576 std::vector<storm::RationalFunction> const& /*oneStepTargetProbabilities*/) {
577 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Computing upper reward bounds is not supported for rational functions.");
578}
579
580template<typename ValueType, typename RewardModelType, typename SolutionType>
583 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
584 std::function<std::vector<ValueType>(uint_fast64_t, storm::storage::SparseMatrix<ValueType> const&, storm::storage::BitVector const&)> const&
585 totalStateRewardVectorGetter,
586 storm::storage::BitVector const& targetStates, bool qualitative, std::function<storm::storage::BitVector()> const& zeroRewardStatesGetter,
587 ModelCheckerHint const& hint) {
588 std::vector<SolutionType> result(transitionMatrix.getRowCount(), storm::utility::zero<SolutionType>());
589
590 // Determine which states have reward zero
591 storm::storage::BitVector rew0States;
593 rew0States = storm::utility::graph::performProb1(backwardTransitions, zeroRewardStatesGetter(), targetStates);
594 } else {
595 rew0States = targetStates;
596 }
597
598 // Determine which states have a reward that is less than infinity.
599 storm::storage::BitVector maybeStates;
600 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().getComputeOnlyMaybeStates()) {
601 maybeStates = hint.template asExplicitModelCheckerHint<ValueType>().getMaybeStates();
603
604 STORM_LOG_INFO("Preprocessing: " << rew0States.getNumberOfSetBits() << " States with reward zero (" << maybeStates.getNumberOfSetBits()
605 << " states remaining).");
606 } else {
607 storm::storage::BitVector trueStates(transitionMatrix.getRowCount(), true);
608 storm::storage::BitVector infinityStates = storm::utility::graph::performProb1(backwardTransitions, trueStates, rew0States);
609 infinityStates.complement();
610 maybeStates = ~(rew0States | infinityStates);
611
612 STORM_LOG_INFO("Preprocessing: " << infinityStates.getNumberOfSetBits() << " states with reward infinity, " << rew0States.getNumberOfSetBits()
613 << " states with reward zero (" << maybeStates.getNumberOfSetBits() << " states remaining).");
614
616 }
617
618 // Check if the values of the maybe states are relevant for the SolveGoal
619 bool maybeStatesNotRelevant = goal.hasRelevantValues() && goal.relevantValues().isDisjointFrom(maybeStates);
620
621 // Check whether we need to compute exact rewards for some states.
622 if (qualitative || maybeStatesNotRelevant) {
623 // Set the values for all maybe-states to 1 to indicate that their reward values
624 // are neither 0 nor infinity.
626 } else {
627 if (!maybeStates.empty()) {
628 if constexpr (storm::IsIntervalType<ValueType>) {
629 // In this case we have to compute the reward values for the remaining states.
630 // We can eliminate the rows and columns from the original transition probability matrix.
631 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.filterEntries(transitionMatrix.getRowFilter(maybeStates));
632
633 // Prepare the right-hand side of the equation system.
634 std::vector<ValueType> b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, maybeStates);
635
636 // Compute values for maybe states.
637 std::vector<SolutionType> x = computeRobustValuesForMaybeStates(env, std::move(goal), std::move(submatrix), b, true);
638
639 // Set values of resulting vector according to result.
641 } else {
642 // Check whether we need to convert the input to equation system format.
643 storm::solver::GeneralLinearEquationSolverFactory<ValueType> linearEquationSolverFactory;
644 bool convertToEquationSystem =
646
647 // In this case we have to compute the reward values for the remaining states.
648 // We can eliminate the rows and columns from the original transition probability matrix.
649 storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates, convertToEquationSystem);
650
651 // Initialize the x vector with the hint (if available) or with 1 for each element.
652 // This is the initial guess for the iterative solvers.
653 std::vector<ValueType> x;
654 if (hint.isExplicitModelCheckerHint() && hint.template asExplicitModelCheckerHint<ValueType>().hasResultHint()) {
655 x = storm::utility::vector::filterVector(hint.template asExplicitModelCheckerHint<ValueType>().getResultHint(), maybeStates);
656 } else {
657 x = std::vector<ValueType>(submatrix.getColumnCount(), storm::utility::one<ValueType>());
658 }
659
660 // Prepare the right-hand side of the equation system.
661 std::vector<ValueType> b = totalStateRewardVectorGetter(submatrix.getRowCount(), transitionMatrix, maybeStates);
662
663 storm::solver::LinearEquationSolverRequirements requirements = linearEquationSolverFactory.getRequirements(env);
664 boost::optional<std::vector<ValueType>> upperRewardBounds;
665 requirements.clearLowerBounds();
666 if (requirements.upperBounds()) {
667 upperRewardBounds = computeUpperRewardBounds(submatrix, b, transitionMatrix.getConstrainedRowSumVector(maybeStates, rew0States));
668 requirements.clearUpperBounds();
669 }
670 STORM_LOG_THROW(!requirements.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
671 "Solver requirements " + requirements.getEnabledRequirementsAsString() + " not checked.");
672
673 // If necessary, convert the matrix from the fixpoint notation to the form needed for the equation system.
674 if (convertToEquationSystem) {
675 // go from x = A*x + b to (I-A)x = b.
676 submatrix.convertToEquationSystem();
677 }
678
679 // Create the solver.
680 goal.restrictRelevantValues(maybeStates);
681 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver =
682 storm::solver::configureLinearEquationSolver(env, std::move(goal), linearEquationSolverFactory, std::move(submatrix));
683 solver->setLowerBound(storm::utility::zero<ValueType>());
684 if (upperRewardBounds) {
685 solver->setUpperBounds(std::move(upperRewardBounds.get()));
686 }
687
688 // Now solve the resulting equation system.
689 solver->solveEquations(env, x, b);
690
691 // Set values of resulting vector according to result.
693 }
694 }
695 }
696 return result;
697}
698
699template<typename ValueType, typename RewardModelType, typename SolutionType>
700typename SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::BaierTransformedModel
701SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::computeBaierTransformation(Environment const& env,
702 storm::storage::SparseMatrix<ValueType> const& transitionMatrix,
703 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
704 storm::storage::BitVector const& targetStates,
705 storm::storage::BitVector const& conditionStates,
706 boost::optional<std::vector<ValueType>> const& stateRewards) {
707 if constexpr (storm::IsIntervalType<ValueType>) {
708 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support baier transformation with interval models.");
709 } else {
710 BaierTransformedModel result;
711
712 // Start by computing all 'before' states, i.e. the states for which the conditional probability is defined.
713 std::vector<ValueType> probabilitiesToReachConditionStates =
714 computeUntilProbabilities(env, storm::solver::SolveGoal<ValueType>(), transitionMatrix, backwardTransitions,
715 storm::storage::BitVector(transitionMatrix.getRowCount(), true), conditionStates, false);
716
717 result.beforeStates = storm::storage::BitVector(targetStates.size(), true);
718 uint_fast64_t state = 0;
719 uint_fast64_t beforeStateIndex = 0;
720 for (auto const& value : probabilitiesToReachConditionStates) {
721 if (value == storm::utility::zero<ValueType>()) {
722 result.beforeStates.set(state, false);
723 } else {
724 probabilitiesToReachConditionStates[beforeStateIndex] = value;
725 ++beforeStateIndex;
726 }
727 ++state;
728 }
729 probabilitiesToReachConditionStates.resize(beforeStateIndex);
730
731 if (targetStates.empty()) {
732 result.noTargetStates = true;
733 return result;
734 } else if (!result.beforeStates.empty()) {
735 // If there are some states for which the conditional probability is defined and there are some
736 // states that can reach the target states without visiting condition states first, we need to
737 // do more work.
738
739 // First, compute the relevant states and some offsets.
740 storm::storage::BitVector allStates(targetStates.size(), true);
741 std::vector<uint_fast64_t> numberOfBeforeStatesUpToState = result.beforeStates.getNumberOfSetBitsBeforeIndices();
742 storm::storage::BitVector statesWithProbabilityGreater0 = storm::utility::graph::performProbGreater0(backwardTransitions, allStates, targetStates);
743 statesWithProbabilityGreater0 &= storm::utility::graph::getReachableStates(transitionMatrix, conditionStates, allStates, targetStates);
744 uint_fast64_t normalStatesOffset = result.beforeStates.getNumberOfSetBits();
745 std::vector<uint_fast64_t> numberOfNormalStatesUpToState = statesWithProbabilityGreater0.getNumberOfSetBitsBeforeIndices();
746
747 // All transitions going to states with probability zero, need to be redirected to a deadlock state.
748 bool addDeadlockState = false;
749 uint_fast64_t deadlockState = normalStatesOffset + statesWithProbabilityGreater0.getNumberOfSetBits();
750
751 // Now, we create the matrix of 'before' and 'normal' states.
752 storm::storage::SparseMatrixBuilder<ValueType> builder;
753
754 // Start by creating the transitions of the 'before' states.
755 uint_fast64_t currentRow = 0;
756 for (auto beforeState : result.beforeStates) {
757 if (conditionStates.get(beforeState)) {
758 // For condition states, we move to the 'normal' states.
759 ValueType zeroProbability = storm::utility::zero<ValueType>();
760 for (auto const& successorEntry : transitionMatrix.getRow(beforeState)) {
761 if (statesWithProbabilityGreater0.get(successorEntry.getColumn())) {
762 builder.addNextValue(currentRow, normalStatesOffset + numberOfNormalStatesUpToState[successorEntry.getColumn()],
763 successorEntry.getValue());
764 } else {
765 zeroProbability += successorEntry.getValue();
766 }
767 }
768 if (!storm::utility::isZero(zeroProbability)) {
769 builder.addNextValue(currentRow, deadlockState, zeroProbability);
770 }
771 } else {
772 // For non-condition states, we scale the probabilities going to other before states.
773 for (auto const& successorEntry : transitionMatrix.getRow(beforeState)) {
774 if (result.beforeStates.get(successorEntry.getColumn())) {
775 builder.addNextValue(currentRow, numberOfBeforeStatesUpToState[successorEntry.getColumn()],
776 successorEntry.getValue() *
777 probabilitiesToReachConditionStates[numberOfBeforeStatesUpToState[successorEntry.getColumn()]] /
778 probabilitiesToReachConditionStates[currentRow]);
779 }
780 }
781 }
782 ++currentRow;
783 }
784
785 // Then, create the transitions of the 'normal' states.
786 for (auto state : statesWithProbabilityGreater0) {
787 ValueType zeroProbability = storm::utility::zero<ValueType>();
788 for (auto const& successorEntry : transitionMatrix.getRow(state)) {
789 if (statesWithProbabilityGreater0.get(successorEntry.getColumn())) {
790 builder.addNextValue(currentRow, normalStatesOffset + numberOfNormalStatesUpToState[successorEntry.getColumn()],
791 successorEntry.getValue());
792 } else {
793 zeroProbability += successorEntry.getValue();
794 }
795 }
796 if (!storm::utility::isZero(zeroProbability)) {
797 addDeadlockState = true;
798 builder.addNextValue(currentRow, deadlockState, zeroProbability);
799 }
800 ++currentRow;
801 }
802 if (addDeadlockState) {
803 builder.addNextValue(deadlockState, deadlockState, storm::utility::one<ValueType>());
804 }
805
806 // Build the new transition matrix and the new targets.
807 result.transitionMatrix = builder.build(addDeadlockState ? (deadlockState + 1) : deadlockState);
808 storm::storage::BitVector newTargetStates = targetStates % result.beforeStates;
809 newTargetStates.resize(result.transitionMatrix.get().getRowCount());
810 for (auto state : targetStates % statesWithProbabilityGreater0) {
811 newTargetStates.set(normalStatesOffset + state, true);
812 }
813 result.targetStates = std::move(newTargetStates);
814
815 // If a reward model was given, we need to compute the rewards for the transformed model.
816 if (stateRewards) {
817 std::vector<ValueType> newStateRewards(result.beforeStates.getNumberOfSetBits());
818 storm::utility::vector::selectVectorValues(newStateRewards, result.beforeStates, stateRewards.get());
819
820 newStateRewards.reserve(result.transitionMatrix.get().getRowCount());
821 for (auto state : statesWithProbabilityGreater0) {
822 newStateRewards.push_back(stateRewards.get()[state]);
823 }
824 // Add a zero reward to the deadlock state.
825 if (addDeadlockState) {
826 newStateRewards.push_back(storm::utility::zero<ValueType>());
827 }
828 result.stateRewards = std::move(newStateRewards);
829 }
830 }
831
832 return result;
833 }
834}
835
836template<typename ValueType, typename RewardModelType, typename SolutionType>
837storm::storage::BitVector SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::BaierTransformedModel::getNewRelevantStates() const {
838 storm::storage::BitVector newRelevantStates(transitionMatrix.get().getRowCount());
839 for (uint64_t i = 0; i < this->beforeStates.getNumberOfSetBits(); ++i) {
840 newRelevantStates.set(i);
841 }
842 return newRelevantStates;
843}
844
845template<typename ValueType, typename RewardModelType, typename SolutionType>
846storm::storage::BitVector SparseDtmcPrctlHelper<ValueType, RewardModelType, SolutionType>::BaierTransformedModel::getNewRelevantStates(
847 storm::storage::BitVector const& oldRelevantStates) const {
848 storm::storage::BitVector result = oldRelevantStates % this->beforeStates;
849 result.resize(transitionMatrix.get().getRowCount());
850 return result;
851}
852
853template<typename ValueType, typename RewardModelType, typename SolutionType>
856 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, storm::storage::BitVector const& targetStates,
857 storm::storage::BitVector const& conditionStates, bool qualitative) {
858 if constexpr (storm::IsIntervalType<ValueType>) {
859 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional probabilities with interval models.");
860 } else {
861 // Prepare result vector.
862 std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::infinity<ValueType>());
863
864 if (!conditionStates.empty()) {
865 BaierTransformedModel transformedModel =
866 computeBaierTransformation(env, transitionMatrix, backwardTransitions, targetStates, conditionStates, boost::none);
867
868 if (transformedModel.noTargetStates) {
869 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, storm::utility::zero<ValueType>());
870 } else {
871 // At this point, we do not need to check whether there are 'before' states, since the condition
872 // states were non-empty so there is at least one state with a positive probability of satisfying
873 // the condition.
874
875 // Now compute reachability probabilities in the transformed model.
876 storm::storage::SparseMatrix<ValueType> const& newTransitionMatrix = transformedModel.transitionMatrix.get();
877 storm::storage::BitVector newRelevantValues;
878 if (goal.hasRelevantValues()) {
879 newRelevantValues = transformedModel.getNewRelevantStates(goal.relevantValues());
880 } else {
881 newRelevantValues = transformedModel.getNewRelevantStates();
882 }
883 goal.setRelevantValues(std::move(newRelevantValues));
884 std::vector<ValueType> conditionalProbabilities = computeUntilProbabilities(
885 env, std::move(goal), newTransitionMatrix, newTransitionMatrix.transpose(),
886 storm::storage::BitVector(newTransitionMatrix.getRowCount(), true), transformedModel.targetStates.get(), qualitative);
887
888 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, conditionalProbabilities);
889 }
890 }
891
892 return result;
893 }
894}
895
896template<typename ValueType, typename RewardModelType, typename SolutionType>
899 storm::storage::SparseMatrix<ValueType> const& backwardTransitions, RewardModelType const& rewardModel, storm::storage::BitVector const& targetStates,
900 storm::storage::BitVector const& conditionStates, bool qualitative) {
901 if constexpr (storm::IsIntervalType<ValueType>) {
902 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "We do not support computing conditional rewards with interval models.");
903 } else {
904 // Prepare result vector.
905 std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::infinity<ValueType>());
906
907 if (!conditionStates.empty()) {
908 BaierTransformedModel transformedModel = computeBaierTransformation(env, transitionMatrix, backwardTransitions, targetStates, conditionStates,
909 rewardModel.getTotalRewardVector(transitionMatrix));
910
911 if (transformedModel.noTargetStates) {
912 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, storm::utility::zero<ValueType>());
913 } else {
914 // At this point, we do not need to check whether there are 'before' states, since the condition
915 // states were non-empty so there is at least one state with a positive probability of satisfying
916 // the condition.
917
918 // Now compute reachability probabilities in the transformed model.
919 storm::storage::SparseMatrix<ValueType> const& newTransitionMatrix = transformedModel.transitionMatrix.get();
920 storm::storage::BitVector newRelevantValues;
921 if (goal.hasRelevantValues()) {
922 newRelevantValues = transformedModel.getNewRelevantStates(goal.relevantValues());
923 } else {
924 newRelevantValues = transformedModel.getNewRelevantStates();
925 }
926 goal.setRelevantValues(std::move(newRelevantValues));
927 std::vector<ValueType> conditionalRewards =
928 computeReachabilityRewards(env, std::move(goal), newTransitionMatrix, newTransitionMatrix.transpose(), transformedModel.stateRewards.get(),
929 transformedModel.targetStates.get(), qualitative);
930 storm::utility::vector::setVectorValues(result, transformedModel.beforeStates, conditionalRewards);
931 }
932 }
933
934 return result;
935 }
936}
937
938template class SparseDtmcPrctlHelper<double>;
939
944} // namespace helper
945} // namespace modelchecker
946} // 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:178
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, SolutionType > > 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.
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 ...
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.
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.
const_rows getRow(index_type row) const
Returns an object representing the given row.
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_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_PRINT_AND_LOG(message)
Definition macros.h:68
SFTBDDChecker::ValueType ValueType
void exportDataToCSVFile(std::string filepath, std::vector< std::vector< DataType > > const &data, boost::optional< std::vector< Header1Type > > const &header1=boost::none, boost::optional< std::vector< Header2Type > > const &header2=boost::none)
Definition export.h:13
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)
SettingsType const & getModule()
Get module.
std::unique_ptr< storm::solver::MinMaxLinearEquationSolver< ValueType, SolutionType > > configureMinMaxLinearEquationSolver(Environment const &env, SolveGoal< ValueType, SolutionType > &&goal, storm::solver::MinMaxLinearEquationSolverFactory< ValueType, SolutionType > const &factory, MatrixType &&matrix, OptimizationDirectionSetting optimizationDirectionSetting=OptimizationDirectionSetting::Unset)
Definition SolveGoal.h:110
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:132
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
ValueType zero()
Definition constants.cpp:24
ValueType infinity()
Definition constants.cpp:29
ValueType one()
Definition constants.cpp:19
TargetType convertNumber(SourceType const &number)
constexpr bool IsIntervalType
Helper to check if a type is an interval.
carl::RationalFunction< Polynomial, true > RationalFunction