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