Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SparseDeterministicVisitingTimesHelper.cpp
Go to the documentation of this file.
2
3#include <algorithm>
5
9
11
17
20#include "storm/utility/graph.h"
21
22namespace storm {
23namespace modelchecker {
24namespace helper {
25template<typename ValueType>
27 : transitionMatrix(transitionMatrix),
28 exitRates(storm::NullRef),
29 backwardTransitions(storm::NullRef),
30 sccDecomposition(storm::NullRef),
31 nonBsccStates(transitionMatrix.getRowCount(), false) {
32 // Intentionally left empty
33}
34
35template<typename ValueType>
37 std::vector<ValueType> const& exitRates)
38 : transitionMatrix(transitionMatrix),
39 exitRates(exitRates),
40 backwardTransitions(storm::NullRef),
41 sccDecomposition(storm::NullRef),
42 nonBsccStates(transitionMatrix.getRowCount(), false) {
43 // For the CTMC case we assert that the caller actually provided the probabilistic transitions
44 STORM_LOG_ASSERT(this->transitionMatrix.isProbabilistic(), "Non-probabilistic transitions");
45}
46
47template<typename ValueType>
49 STORM_LOG_WARN_COND(!backwardTransitions, "Backward transition matrix was provided but it was already computed or provided before.");
50 backwardTransitions.reset(providedBackwardTransitions);
51}
52
53template<typename ValueType>
56 STORM_LOG_WARN_COND(!sccDecomposition, "SCC Decomposition was provided but it was already computed or provided before.");
57 sccDecomposition.reset(decomposition);
58}
59
60template<typename ValueType>
62 storm::storage::BitVector const& initialStates) {
63 STORM_LOG_ASSERT(!initialStates.empty(), "provided an empty set of initial states.");
64 STORM_LOG_ASSERT(initialStates.size() == transitionMatrix.getRowCount(), "Dimension mismatch.");
65 ValueType const p = storm::utility::one<ValueType>() / storm::utility::convertNumber<ValueType, uint64_t>(initialStates.getNumberOfSetBits());
66 std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::zero<ValueType>());
67 storm::utility::vector::setVectorValues(result, initialStates, p);
68 computeExpectedVisitingTimes(env, result);
69 return result;
70}
71
72template<typename ValueType>
74 STORM_LOG_ASSERT(initialState < transitionMatrix.getRowCount(), "Invalid initial state index.");
75 std::vector<ValueType> result(transitionMatrix.getRowCount(), storm::utility::zero<ValueType>());
76 result[initialState] = storm::utility::one<ValueType>();
77 computeExpectedVisitingTimes(env, result);
78 return result;
79}
80
81template<typename ValueType>
83 ValueGetter const& initialStateValueGetter) {
84 std::vector<ValueType> result;
85 result.reserve(transitionMatrix.getRowCount());
86 for (uint64_t s = 0; s != transitionMatrix.getRowCount(); ++s) {
87 result.push_back(initialStateValueGetter(s));
88 }
89 computeExpectedVisitingTimes(env, result);
90 return result;
91}
92
93template<typename ValueType>
95 STORM_LOG_ASSERT(stateValues.size() == transitionMatrix.getRowCount(), "Dimension missmatch.");
96 createBackwardTransitions();
97 createDecomposition(env);
98 createNonBsccStateVector();
99
100 // Create auxiliary data and lambdas
101 storm::storage::BitVector sccAsBitVector(stateValues.size(), false);
102 auto isLeavingTransition = [&sccAsBitVector](auto const& e) { return !sccAsBitVector.get(e.getColumn()); };
103 auto isLeavingTransitionWithNonZeroValue = [&isLeavingTransition, &stateValues](auto const& e) {
104 return isLeavingTransition(e) && !storm::utility::isZero(stateValues[e.getColumn()]);
105 };
106 auto isReachableInState = [this, &isLeavingTransitionWithNonZeroValue, &stateValues](uint64_t state) {
107 if (!storm::utility::isZero(stateValues[state])) {
108 return true;
109 }
110 auto row = this->backwardTransitions->getRow(state);
111 return std::any_of(row.begin(), row.end(), isLeavingTransitionWithNonZeroValue);
112 };
113
114 if (env.solver().getLinearEquationSolverType() == storm::solver::EquationSolverType::Topological) {
115 // Compute EVTs SCC wise in topological order
116 // We need to adapt precision if we solve each SCC separately (in topological order) and/or consider CTMCs
117 auto sccEnv = getEnvironmentForSolver(env, true);
118
119 // We solve each SCC individually in *forward* topological order
121 progress.setMaxCount(sccDecomposition->size());
122 progress.startNewMeasurement(0);
123 uint64_t sccIndex = 0;
124 auto sccItEnd = std::make_reverse_iterator(sccDecomposition->begin());
125 for (auto sccIt = std::make_reverse_iterator(sccDecomposition->end()); sccIt != sccItEnd; ++sccIt) {
126 auto const& scc = *sccIt;
127 if (scc.size() == 1) {
128 processSingletonScc(*scc.begin(), stateValues);
129 } else {
130 sccAsBitVector.set(scc.begin(), scc.end(), true);
131 if (sccAsBitVector.isSubsetOf(nonBsccStates)) {
132 // This is not a BSCC
133 auto sccResult = computeValueForStateSet(sccEnv, sccAsBitVector, stateValues);
134 storm::utility::vector::setVectorValues(stateValues, sccAsBitVector, sccResult);
135 } else {
136 // This is a BSCC
137 if (std::any_of(sccAsBitVector.begin(), sccAsBitVector.end(), isReachableInState)) {
138 storm::utility::vector::setVectorValues(stateValues, sccAsBitVector, storm::utility::infinity<ValueType>());
139 } else {
140 storm::utility::vector::setVectorValues(stateValues, sccAsBitVector, storm::utility::zero<ValueType>());
141 }
142 }
143 sccAsBitVector.clear();
144 }
145 ++sccIndex;
146 progress.updateProgress(sccIndex);
148 STORM_LOG_WARN("Visiting times computation aborted after analyzing " << sccIndex << "/" << this->computedSccDecomposition->size() << " SCCs.");
149 break;
150 }
151 }
152 } else {
153 // We solve the equation system for all non-BSCC in one step (not each SCC individually - adaption of precision is not necessary).
154 if (!nonBsccStates.empty()) {
155 // We need to adapt precision if we consider CTMCs.
156 Environment adjustedEnv = getEnvironmentForSolver(env, false);
157 auto result = computeValueForStateSet(adjustedEnv, nonBsccStates, stateValues);
158 storm::utility::vector::setVectorValues(stateValues, nonBsccStates, result);
159 }
160
161 // After computing the state values for the non-BSCCs, we can set the values of the BSCC states.
162 auto sccItEnd = std::make_reverse_iterator(sccDecomposition->begin());
163 for (auto sccIt = std::make_reverse_iterator(sccDecomposition->end()); sccIt != sccItEnd; ++sccIt) {
164 auto const& scc = *sccIt;
165 sccAsBitVector.set(scc.begin(), scc.end(), true);
166 if (sccAsBitVector.isSubsetOf(~nonBsccStates)) {
167 // This is a BSCC, we set the values of the states to infinity or 0.
168 if (std::any_of(sccAsBitVector.begin(), sccAsBitVector.end(), isReachableInState)) {
169 // The BSCC is reachable: The EVT is infinity
170 storm::utility::vector::setVectorValues(stateValues, sccAsBitVector, storm::utility::infinity<ValueType>());
171 } else {
172 // The BSCC is not reachable: The EVT is zero
173 storm::utility::vector::setVectorValues(stateValues, sccAsBitVector, storm::utility::zero<ValueType>());
174 }
175 }
176 sccAsBitVector.clear();
177 }
178 }
179
180 if (isContinuousTime()) {
181 // Divide with the exit rates
182 // Since storm::utility::infinity<storm::RationalNumber>() is just set to some big number, we have to treat the infinity-case explicitly.
183 storm::utility::vector::applyPointwise(stateValues, *exitRates, stateValues, [](ValueType const& xi, ValueType const& yi) -> ValueType {
184 return storm::utility::isInfinity(xi) ? xi : xi / yi;
185 });
186 }
187}
188
189template<typename ValueType>
191 return exitRates;
192}
193
194template<typename ValueType>
195void SparseDeterministicVisitingTimesHelper<ValueType>::createBackwardTransitions() {
196 if (!this->backwardTransitions) {
197 this->computedBackwardTransitions =
198 std::make_unique<storm::storage::SparseMatrix<ValueType>>(transitionMatrix.transpose(true, false)); // will drop zeroes
199 this->backwardTransitions.reset(*this->computedBackwardTransitions);
200 }
201}
202
203template<typename ValueType>
204void SparseDeterministicVisitingTimesHelper<ValueType>::createDecomposition(Environment const& env) {
205 if (this->sccDecomposition && !this->sccDecomposition->hasSccDepth() && env.solver().isForceSoundness()) {
206 // We are missing SCCDepths in the given decomposition.
207 STORM_LOG_WARN("Recomputing SCC Decomposition because the currently available decomposition is computed without SCCDepths.");
208 this->computedSccDecomposition.reset();
209 this->sccDecomposition.reset();
210 }
211
212 if (!this->sccDecomposition) {
213 // The decomposition has not been provided or computed, yet.
214 auto options =
216 this->computedSccDecomposition = std::make_unique<storm::storage::StronglyConnectedComponentDecomposition<ValueType>>(this->transitionMatrix, options);
217 this->sccDecomposition.reset(*this->computedSccDecomposition);
218 }
219}
220
221template<typename ValueType>
222void SparseDeterministicVisitingTimesHelper<ValueType>::createNonBsccStateVector() {
223 // Create auxiliary data and lambdas
224 storm::storage::BitVector sccAsBitVector(transitionMatrix.getRowCount(), false);
225 auto isLeavingTransition = [&sccAsBitVector](auto const& e) { return !sccAsBitVector.get(e.getColumn()); };
226 auto isExitState = [this, &isLeavingTransition](uint64_t state) {
227 auto row = this->transitionMatrix.getRow(state);
228 return std::any_of(row.begin(), row.end(), isLeavingTransition);
229 };
230
231 auto sccItEnd = std::make_reverse_iterator(sccDecomposition->begin());
232 for (auto sccIt = std::make_reverse_iterator(sccDecomposition->end()); sccIt != sccItEnd; ++sccIt) {
233 auto const& scc = *sccIt;
234 sccAsBitVector.set(scc.begin(), scc.end(), true);
235 if (std::any_of(sccAsBitVector.begin(), sccAsBitVector.end(), isExitState)) {
236 // This is not a BSCC, mark the states correspondingly.
237 nonBsccStates = nonBsccStates | sccAsBitVector;
238 }
239 sccAsBitVector.clear();
240 }
241}
242
243template<>
244std::vector<storm::RationalFunction> SparseDeterministicVisitingTimesHelper<storm::RationalFunction>::computeUpperBounds(
245 storm::storage::BitVector const& /*stateSetAsBitvector*/) const {
246 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException,
247 "Computing upper bounds for expected visiting times over rational functions is not supported.");
248}
249
250template<typename ValueType>
251std::vector<ValueType> SparseDeterministicVisitingTimesHelper<ValueType>::computeUpperBounds(storm::storage::BitVector const& stateSetAsBitvector) const {
252 // Compute the one-step probabilities that lead to states outside stateSetAsBitvector
253 std::vector<ValueType> leavingTransitions = transitionMatrix.getConstrainedRowGroupSumVector(stateSetAsBitvector, ~stateSetAsBitvector);
254
255 // Build the submatrix that only has the transitions between states in the state set.
256 storm::storage::SparseMatrix<ValueType> subTransitionMatrix = transitionMatrix.getSubmatrix(false, stateSetAsBitvector, stateSetAsBitvector);
257
258 // Compute the upper bounds on EVTs for non-BSCC states (using the same state-to-scc mapping).
260 subTransitionMatrix, leavingTransitions);
261 return upperBounds;
262}
263
264template<typename ValueType>
265storm::Environment SparseDeterministicVisitingTimesHelper<ValueType>::getEnvironmentForSolver(storm::Environment const& env, bool topological) const {
266 storm::Environment newEnv(env);
267
268 if (topological) {
269 // Overwrite the environment with the environment for the underlying solver.
270 newEnv = getEnvironmentForTopologicalSolver(env);
271 }
272
273 // Adjust precision for CTMCs, because the EVTs are divided by the exit rates at the end.
274 if (isContinuousTime()) {
275 auto prec = newEnv.solver().getPrecisionOfLinearEquationSolver(newEnv.solver().getLinearEquationSolverType());
276
277 bool needAdaptPrecision =
278 env.solver().isForceSoundness() && prec.first.is_initialized() && prec.second.is_initialized() &&
279 !newEnv.solver().getPrecisionOfLinearEquationSolver(newEnv.solver().getLinearEquationSolverType()).second.get(); // only for the absolute criterion
280
281 // Assert that we only adapt the precision for native solvers
283 !needAdaptPrecision || env.solver().getLinearEquationSolverType() == storm::solver::EquationSolverType::Native,
284 "The precision for the current solver type is not adjusted for this solving method. Ensure that this is correct for topological computation.");
285
286 if (needAdaptPrecision) {
287 // the precision is relevant (e.g. not the case for elimination, sparselu etc.)
288 ValueType min = *std::min_element(exitRates->begin(), exitRates->end());
289 STORM_LOG_THROW(!storm::utility::isZero(min), storm::exceptions::InvalidOperationException,
290 "An error occurred during the adjustment of the precision. Min. rate = " << min);
291 newEnv.solver().setLinearEquationSolverPrecision(
292 static_cast<storm::RationalNumber>(prec.first.get() * storm::utility::convertNumber<storm::RationalNumber>(min)));
293 }
294 }
295
296 auto prec = newEnv.solver().getPrecisionOfLinearEquationSolver(newEnv.solver().getLinearEquationSolverType());
297 if (prec.first.is_initialized()) {
298 STORM_LOG_INFO("Precision for EVTs computation: " << storm::utility::convertNumber<double>(prec.first.get()) << " (exact: " << prec.first.get() << ")"
299 << '\n');
300 }
301
302 return newEnv;
303}
304
305template<typename ValueType>
306storm::Environment SparseDeterministicVisitingTimesHelper<ValueType>::getEnvironmentForTopologicalSolver(storm::Environment const& env) const {
307 storm::Environment subEnv(env);
308 subEnv.solver().setLinearEquationSolverType(env.solver().topological().getUnderlyingEquationSolverType(),
310
311 // To guarantee soundness for OVI, II, SVI we need to increase the precision in each SCC.
312 auto subEnvPrec = subEnv.solver().getPrecisionOfLinearEquationSolver(subEnv.solver().getLinearEquationSolverType());
313
314 bool singletonSCCs = true; // true if each SCC is a singleton (self-loops are allowed)
315 storm::storage::BitVector sccAsBitVector(transitionMatrix.getRowCount(), false);
316 auto sccItEnd = std::make_reverse_iterator(sccDecomposition->begin());
317 for (auto sccIt = std::make_reverse_iterator(sccDecomposition->end()); sccIt != sccItEnd; ++sccIt) {
318 auto const& scc = *sccIt;
319 sccAsBitVector.set(scc.begin(), scc.end(), true);
320 if (sccAsBitVector.isSubsetOf(nonBsccStates)) {
321 // This is not a BSCC, mark the states correspondingly.
322 if (sccAsBitVector.getNumberOfSetBits() > 1) {
323 singletonSCCs = false;
324 break;
325 }
326 }
327 sccAsBitVector.clear();
328 }
329
330 bool needAdaptPrecision = env.solver().isForceSoundness() && subEnvPrec.first.is_initialized() && subEnvPrec.second.is_initialized() &&
331 !singletonSCCs; // singleton sccs are solved directly
332
333 // Assert that we only adapt the precision for native solvers
335 !needAdaptPrecision || subEnv.solver().getLinearEquationSolverType() == storm::solver::EquationSolverType::Native,
336 "The precision for the current solver type is not adjusted for this solving method. Ensure that this is correct for topological computation.");
337
338 if (needAdaptPrecision && subEnvPrec.second.get()) {
339 STORM_LOG_ASSERT(sccDecomposition->hasSccDepth(), "Did not compute the longest SCC chain size although it is needed.");
340 // Sound computations wrt. relative precision:
341 // We need to increase the solver's relative precision that is used in an SCC depending on the maximal SCC chain length.
342 auto subEnvPrec = subEnv.solver().getPrecisionOfLinearEquationSolver(subEnv.solver().getLinearEquationSolverType());
343
344 double scaledPrecision1 = 1 - std::pow(1 - storm::utility::convertNumber<double>(subEnvPrec.first.get()), 1.0 / sccDecomposition->getMaxSccDepth());
345
346 // set new precision
347 subEnv.solver().setLinearEquationSolverPrecision(storm::utility::convertNumber<storm::RationalNumber>(scaledPrecision1));
348
349 } else if (needAdaptPrecision && !subEnv.solver().getPrecisionOfLinearEquationSolver(subEnv.solver().getLinearEquationSolverType()).second.get()) {
350 // Sound computations wrt. absolute precision:
351 // STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Sound computations of EVTs wrt. absolute precision is not supported.");
352
353 // TODO: there is probably a better way to implement this
354 if (sccDecomposition->getMaxSccDepth() > 1) {
355 // The chain length exceeds one, we need to adjust the precision
356 // The adjustment of the precision used in each SCC depends on the maximal SCC chain length,
357 // the maximal number of incoming transitions, and the maximal probability <1 to reach another states in an SCC.
358
359 storm::storage::BitVector sccAsBitVector(transitionMatrix.getRowCount(), false);
360
361 // maxNumInc: the maximal number of incoming transitions to an SCC.
362 uint_fast64_t maxNumInc = 0;
363
364 // maxEVT: the maximal value of 1/(1-p), where p is the recurrence probability within an SCC (this value stays 0 if there are no cycles)
365 ValueType boundEVT = storm::utility::zero<ValueType>();
366
367 auto sccItEnd = std::make_reverse_iterator(sccDecomposition->begin());
368 for (auto sccIt = std::make_reverse_iterator(sccDecomposition->end()); sccIt != sccItEnd; ++sccIt) {
369 auto const& scc = *sccIt;
370 sccAsBitVector.set(scc.begin(), scc.end(), true);
371 if (sccAsBitVector.isSubsetOf(nonBsccStates)) {
372 // This is NOT a BSCC.
373
374 // Get number of incoming transitions to this scc (from different sccs)
375 auto toSccMatrix = transitionMatrix.getSubmatrix(false, ~sccAsBitVector, sccAsBitVector);
376 uint_fast64_t localNumInc =
377 std::count_if(toSccMatrix.begin(), toSccMatrix.end(), [](auto const& e) { return !storm::utility::isZero(e.getValue()); });
378 maxNumInc = std::max(maxNumInc, localNumInc);
379
380 // Compute the upper bounds on 1/(1-p) within the SCC
381 // p is the maximal recurrence probability, i.e., 1/(1-p) is an upperBound on the EVTs of the DTMC restricted to the SCC (Baier)
382 std::vector<ValueType> upperBounds = computeUpperBounds(sccAsBitVector);
383 boundEVT = std::max(boundEVT, (*std::max_element(upperBounds.begin(), upperBounds.end())));
384
385 sccAsBitVector.clear();
386 }
387 }
388
389 storm::RationalNumber one = storm::RationalNumber(1);
390 storm::RationalNumber scale = one;
391
392 if (maxNumInc != 0) {
393 // As the maximal number of incoming transitions is greater than one, adjustment is necessary.
394 // For this, we need the number of SCCs in the longest SCC chain -1, i.e., sccDecomposition->getMaxSccDepth() -1
395 for (uint64_t i = 1; i < sccDecomposition->getMaxSccDepth(); i++) {
396 scale = scale + storm::utility::pow(storm::utility::convertNumber<storm::RationalNumber>(maxNumInc), i) *
397 storm::utility::convertNumber<storm::RationalNumber>(boundEVT);
398 }
399 }
400 subEnv.solver().setLinearEquationSolverPrecision(static_cast<storm::RationalNumber>(subEnvPrec.first.get() / scale));
401 }
402 }
403
404 return subEnv;
405}
406
407template<typename ValueType>
408void SparseDeterministicVisitingTimesHelper<ValueType>::processSingletonScc(uint64_t sccState, std::vector<ValueType>& stateValues) const {
409 auto& stateVal = stateValues[sccState];
410 auto forwardRow = transitionMatrix.getRow(sccState);
411 auto backwardRow = backwardTransitions->getRow(sccState);
412 if (forwardRow.getNumberOfEntries() == 1 && forwardRow.begin()->getColumn() == sccState) {
413 // This is a BSCC. We only have to check if there is some non-zero "input"
414 if (!storm::utility::isZero(stateVal) || std::any_of(backwardRow.begin(), backwardRow.end(),
415 [&stateValues](auto const& e) { return !storm::utility::isZero(stateValues[e.getColumn()]); })) {
416 stateVal = storm::utility::infinity<ValueType>();
417 } // else stateVal = 0 (already implied by !(if-condition))
418 } else {
419 // This is not a BSCC. Compute the state value
420 ValueType divisor = storm::utility::one<ValueType>();
421 for (auto const& entry : backwardRow) {
422 if (entry.getColumn() == sccState) {
423 STORM_LOG_ASSERT(!storm::utility::isOne(entry.getValue()), "found a self-loop state. This is not expected");
424 divisor -= entry.getValue();
425 } else {
426 stateVal += entry.getValue() * stateValues[entry.getColumn()];
427 }
428 }
429 stateVal /= divisor;
430 }
431}
432
433template<typename ValueType>
434std::vector<ValueType> SparseDeterministicVisitingTimesHelper<ValueType>::computeValueForStateSet(storm::Environment const& env,
435 storm::storage::BitVector const& stateSetAsBitvector,
436 std::vector<ValueType> const& stateValues) const {
437 // Get the vector for the equation system
438 auto sccVector = storm::utility::vector::filterVector(stateValues, stateSetAsBitvector);
439 auto valIt = sccVector.begin();
440 for (auto sccState : stateSetAsBitvector) {
441 for (auto const& entry : backwardTransitions->getRow(sccState)) {
442 if (!stateSetAsBitvector.get(entry.getColumn())) {
443 (*valIt) += entry.getValue() * stateValues[entry.getColumn()];
444 }
445 }
446 ++valIt;
447 }
448 return computeExpectedVisitingTimes(env, stateSetAsBitvector, sccVector);
449}
450
451template<typename ValueType>
453 storm::storage::BitVector const& subsystem,
454 std::vector<ValueType> const& initialValues) const {
455 STORM_LOG_ASSERT(subsystem.getNumberOfSetBits() == initialValues.size(), "Inconsistent size of subsystem.");
456
457 if (initialValues.empty()) { // Catch the case where the subsystem is empty.
458 return {};
459 }
460
461 // Here we assume that the subsystem does not contain a BSCC
462 // Let P be the subsystem matrix. We solve the equation system
463 // x * P + b = x
464 // <=> P^T * x + b = x <- fixpoint system
465 // <=> (1-P^T) * x = b <- equation system
466
467 // TODO We need to check if SVI works on this kind of equation system (OVI and II are correct)
469 bool isFixpointFormat = linearEquationSolverFactory.getEquationProblemFormat(env) == storm::solver::LinearEquationSolverProblemFormat::FixedPointSystem;
470
471 // Get the matrix for the equation system
472 auto sccMatrix = backwardTransitions->getSubmatrix(false, subsystem, subsystem, !isFixpointFormat);
473 if (!isFixpointFormat) {
474 sccMatrix.convertToEquationSystem();
475 }
476
477 // Get the solver object and satisfy requirements
478 auto solver = linearEquationSolverFactory.create(env, std::move(sccMatrix));
479 solver->setLowerBound(storm::utility::zero<ValueType>());
480 auto req = solver->getRequirements(env);
481 req.clearLowerBounds();
482 if (req.upperBounds().isCritical()) {
483 // Compute upper bounds on EVTs using techniques from Baier et al. [CAV'17] (https://doi.org/10.1007/978-3-319-63387-9_8)
484 std::vector<ValueType> upperBounds = computeUpperBounds(subsystem);
485 solver->setUpperBounds(upperBounds);
486 req.clearUpperBounds();
487 }
488
489 if (req.acyclic().isCritical()) {
490 STORM_LOG_THROW(!storm::utility::graph::hasCycle(sccMatrix), storm::exceptions::UnmetRequirementException,
491 "The solver requires an acyclic model, but the model is not acyclic.");
492 req.clearAcyclic();
493 }
494
495 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UnmetRequirementException,
496 "Solver requirements " + req.getEnabledRequirementsAsString() + " not checked.");
497 std::vector<ValueType> eqSysValues(initialValues.size());
498 solver->solveEquations(env, eqSysValues, initialValues);
499 return eqSysValues;
500}
501
505} // namespace helper
506} // namespace modelchecker
507} // namespace storm
SolverEnvironment & solver()
TopologicalSolverEnvironment & topological()
storm::solver::EquationSolverType const & getLinearEquationSolverType() const
storm::solver::EquationSolverType const & getUnderlyingEquationSolverType() const
static std::vector< ValueType > computeUpperBoundOnExpectedVisitingTimes(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, std::vector< ValueType > const &oneStepTargetProbabilities)
Computes for each state an upper bound for the maximal expected times each state is visited.
Helper class for computing for each state the expected number of times to visit that state assuming a...
std::vector< ValueType > computeExpectedVisitingTimes(Environment const &env, storm::storage::BitVector const &initialStates)
Computes for each state the expected number of times we are visiting that state assuming the given in...
void provideSCCDecomposition(storm::storage::StronglyConnectedComponentDecomposition< ValueType > const &decomposition)
Provides the decomposition into SCCs that can be used during the computation.
void provideBackwardTransitions(storm::storage::SparseMatrix< ValueType > const &backwardTransitions)
Provides the backward transitions that can be used during the computation.
std::function< ValueType(uint64_t)> ValueGetter
Function mapping from indices to values.
SparseDeterministicVisitingTimesHelper(storm::storage::SparseMatrix< ValueType > const &transitionMatrix)
Initializes the helper for a DTMC.
virtual std::unique_ptr< LinearEquationSolver< ValueType > > create(Environment const &env) const override
Creates an equation solver with the current settings, but without a matrix.
virtual LinearEquationSolverProblemFormat getEquationProblemFormat(Environment const &env) const
Retrieves the problem format that the solver expects if it was created with the current settings.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
const_iterator end() const
Returns an iterator pointing at the element past the back of the bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
void clear()
Removes all set bits from the bit vector.
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
A class that holds a possibly non-square matrix in the compressed row storage format.
bool isProbabilistic() const
Checks for each row whether it sums to one.
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 ...
This class represents the decomposition of a graph-like structure into its strongly connected compone...
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.
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_WARN_COND(cond, message)
Definition macros.h:38
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool scale(int exp, storm::RationalNumber &r, storm::RationalNumber acc)
SFTBDDChecker::ValueType ValueType
bool hasCycle(storm::storage::SparseMatrix< T > const &transitionMatrix, boost::optional< storm::storage::BitVector > const &subsystem)
Returns true if the graph represented by the given matrix has a cycle.
Definition graph.cpp:143
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
void setVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Sets the provided values at the provided positions in the given vector.
Definition vector.h:83
void applyPointwise(std::vector< InValueType1 > const &firstOperand, std::vector< InValueType2 > const &secondOperand, std::vector< OutValueType > &target, Operation f=Operation())
Applies the given operation pointwise on the two given vectors and writes the result to the third vec...
Definition vector.h:398
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
Definition vector.h:1213
bool isOne(ValueType const &a)
Definition constants.cpp:36
ValueType min(ValueType const &first, ValueType const &second)
bool isZero(ValueType const &a)
Definition constants.cpp:41
ValueType pow(ValueType const &value, int_fast64_t exponent)
ValueType one()
Definition constants.cpp:21
bool isInfinity(ValueType const &a)
Definition constants.cpp:71
LabParser.cpp.
Definition cli.cpp:18
constexpr NullRefType NullRef
Definition OptionalRef.h:31
StronglyConnectedComponentDecompositionOptions & computeSccDepths(bool value=true)
Sets if scc depths can be retrieved.
StronglyConnectedComponentDecompositionOptions & forceTopologicalSort(bool value=true)
Enforces that the returned SCCs are sorted in a topological order.