Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
TopologicalMinMaxLinearEquationSolver.cpp
Go to the documentation of this file.
2
5
15
16namespace storm {
17namespace solver {
18
19template<typename ValueType, typename SolutionType>
23
24template<typename ValueType, typename SolutionType>
29
30template<typename ValueType, typename SolutionType>
35
36template<typename ValueType, typename SolutionType>
37storm::Environment TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::getEnvironmentForUnderlyingSolver(storm::Environment const& env,
38 bool adaptPrecision) const {
39 storm::Environment subEnv(env);
40 subEnv.solver().minMax().setMethod(env.solver().topological().getUnderlyingMinMaxMethod(),
42 if (adaptPrecision) {
43 STORM_LOG_ASSERT(this->longestSccChainSize, "Did not compute the longest SCC chain size although it is needed.");
44 storm::RationalNumber const prec = subEnv.solver().minMax().getPrecision();
45 storm::RationalNumber divisor = storm::utility::convertNumber<storm::RationalNumber>(this->longestSccChainSize.get());
46 if (subEnv.solver().minMax().getRelativeTerminationCriterion()) {
47 // Relative errors compose multiplicatively along a chain, so dividing by its length alone leaves
48 // (1 + prec/k)^k - 1 > prec. Dividing by k(1 + prec) as well brings the product back below prec.
50 }
51 subEnv.solver().minMax().setPrecision(prec / divisor);
52 }
53 return subEnv;
54}
55
56template<typename ValueType, typename SolutionType>
58 std::vector<SolutionType>& x,
59 std::vector<ValueType> const& b) const {
60 STORM_LOG_ASSERT(x.size() == this->A->getRowGroupCount(), "Provided x-vector has invalid size.");
61 STORM_LOG_ASSERT(b.size() == this->A->getRowCount(), "Provided b-vector has invalid size.");
62
63 // For sound computations we need to increase the precision in each SCC
64 bool needAdaptPrecision = env.solver().isForceSoundness();
65
66 if (!this->sortedSccDecomposition || (needAdaptPrecision && !this->longestSccChainSize)) {
67 STORM_LOG_TRACE("Creating SCC decomposition.");
68 storm::utility::Stopwatch sccSw(true);
69 createSortedSccDecomposition(needAdaptPrecision);
70 sccSw.stop();
71 STORM_LOG_INFO("SCC decomposition computed in "
72 << sccSw << ". Found " << this->sortedSccDecomposition->size() << " SCC(s) containing a total of " << x.size()
73 << " states. Average SCC size is "
74 << static_cast<double>(this->A->getRowGroupCount()) / static_cast<double>(this->sortedSccDecomposition->size()) << ".");
75 }
76
77 // We do not need to adapt the precision if all SCCs are trivial (i.e., the system is acyclic)
78 needAdaptPrecision = needAdaptPrecision && (this->sortedSccDecomposition->size() != this->A->getRowGroupCount());
79
80 storm::Environment sccSolverEnvironment = getEnvironmentForUnderlyingSolver(env, needAdaptPrecision);
81
82 if (this->longestSccChainSize) {
83 STORM_LOG_INFO("Longest SCC chain size is " << this->longestSccChainSize.get());
84 }
85
86 bool returnValue = true;
87 bool aborted = false;
88 // Trivial SCCs are settled by substitution, so they only ever inherit the error of their successors. SCCs come
89 // in topological order, so conjoining as we go is enough.
90 bool allSccsExact = true;
91 bool allSccsPrecise = true;
92 if (this->sortedSccDecomposition->size() == 1 && (!this->choiceFixedForRowGroup || this->choiceFixedForRowGroup.get().empty())) {
93 // Handle the case where there is just one large SCC, as there are no fixed choices for states, we solve it like this
94 if (auto const& scc = *this->sortedSccDecomposition->begin(); scc.size() == 1) {
95 // Catch the trivial case where the whole system is just a single state.
96 if (this->isTrackSchedulerSet()) {
97 this->schedulerChoices = std::vector<uint64_t>(1);
98 }
99 returnValue = solveTrivialScc(*scc.begin(), dir, x, b);
100 } else {
101 returnValue = solveFullyConnectedEquationSystem(sccSolverEnvironment, dir, x, b);
102 allSccsExact = this->sccSolver->hasExactSolutionBounds();
103 allSccsPrecise = lastSccMetPrecision(sccSolverEnvironment, x);
104 }
105 } else {
106 // Solve each SCC individually
107 if (this->isTrackSchedulerSet()) {
108 if (this->schedulerChoices) {
109 this->schedulerChoices.get().resize(x.size());
110 } else {
111 this->schedulerChoices = std::vector<uint64_t>(x.size());
112 }
113 }
114 std::optional<storm::storage::BitVector> newRelevantValues;
115 if (env.solver().topological().isExtendRelevantValues() && this->hasRelevantValues() &&
116 this->sortedSccDecomposition->size() < this->A->getRowGroupCount()) {
117 newRelevantValues = this->getRelevantValues();
118 // Extend the relevant values towards those that have an incoming transition from another SCC
119 std::vector<uint64_t> rowGroupToScc = this->sortedSccDecomposition->computeStateToSccIndexMap(this->A->getRowGroupCount());
120 for (uint64_t rowGroup = 0; rowGroup < this->A->getRowGroupCount(); ++rowGroup) {
121 auto currScc = rowGroupToScc[rowGroup];
122 for (auto const& successor : this->A->getRowGroup(rowGroup)) {
123 if (rowGroupToScc[successor.getColumn()] != currScc) {
124 newRelevantValues->set(successor.getColumn(), true);
125 }
126 }
127 }
128 }
129 storm::storage::BitVector sccAsBitVector(x.size(), false);
130 uint64_t sccIndex = 0;
132 progress.setMaxCount(x.size());
133 progress.startNewMeasurement(0);
134 for (auto const& scc : *this->sortedSccDecomposition) {
135 if (scc.size() == 1) {
136 returnValue = solveTrivialScc(*scc.begin(), dir, x, b) && returnValue;
137 } else {
138 STORM_LOG_TRACE("Solving SCC of size " << scc.size() << ".");
139 for (auto const& state : scc) {
140 sccAsBitVector.set(state, true);
141 }
142 bool sccMetPrecision = false;
143 returnValue = solveScc(sccSolverEnvironment, dir, scc, sccAsBitVector, x, b, newRelevantValues, sccMetPrecision) && returnValue;
144 allSccsExact = allSccsExact && this->sccSolver->hasExactSolutionBounds();
145 allSccsPrecise = allSccsPrecise && sccMetPrecision;
146 // clear sccAsBitVector, either by clearing all bits or by clearing the bits of the current SCC (if its small)
147 if (scc.size() * 64 < sccAsBitVector.size()) {
148 for (auto const& state : scc) {
149 sccAsBitVector.set(state, false);
150 }
151 } else {
152 sccAsBitVector.clear();
153 }
154 }
155 ++sccIndex;
156 progress.updateProgress(sccIndex);
158 STORM_LOG_WARN("Topological solver aborted after analyzing " << sccIndex << "/" << this->sortedSccDecomposition->size() << " SCCs.");
159 aborted = true;
160 break;
161 }
162 }
163 }
164
165 if (returnValue && !aborted) {
166 trySetSolutionBounds(env, x, allSccsExact, allSccsPrecise && needAdaptPrecision);
167 }
168
169 if (!this->isCachingEnabled()) {
170 clearCache();
171 }
172
173 return returnValue;
174}
175
176template<typename ValueType, typename SolutionType>
177void TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::trySetSolutionBounds(Environment const& env, std::vector<SolutionType> const& x,
178 bool allSccsExact, bool allSccsPrecise) const {
179 if (allSccsExact) {
180 this->setSolutionBoundsExact(x);
181 return;
182 }
183 if (!allSccsPrecise) {
184 return;
185 }
186 this->setSolutionBoundsFromPrecision(x, storm::utility::convertNumber<SolutionType>(env.solver().minMax().getPrecision()),
188}
189
190template<typename ValueType, typename SolutionType>
191bool TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::lastSccMetPrecision(Environment const& sccSolverEnvironment,
192 std::vector<SolutionType> const& sccValues) const {
193 return this->sccSolver->getSolutionBounds().isWithinPrecision(
194 sccValues, storm::utility::convertNumber<SolutionType>(sccSolverEnvironment.solver().minMax().getPrecision()),
195 sccSolverEnvironment.solver().minMax().getRelativeTerminationCriterion());
196}
197
198template<typename ValueType, typename SolutionType>
199void TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::createSortedSccDecomposition(bool needLongestChainSize) const {
200 // Obtain the scc decomposition
201 this->sortedSccDecomposition = std::make_unique<storm::storage::StronglyConnectedComponentDecomposition<ValueType>>(
202 *this->A, storm::storage::StronglyConnectedComponentDecompositionOptions().forceTopologicalSort().computeSccDepths(needLongestChainSize));
203 if (needLongestChainSize) {
204 this->longestSccChainSize = this->sortedSccDecomposition->getMaxSccDepth() + 1;
205 }
206}
207
208template<typename ValueType, typename SolutionType>
209bool TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::solveTrivialScc(uint64_t const& sccState, OptimizationDirection dir,
210 std::vector<SolutionType>& globalX,
211 std::vector<ValueType> const& globalB) const {
212 SolutionType& xi = globalX[sccState];
213 if (this->choiceFixedForRowGroup && this->choiceFixedForRowGroup.get()[sccState]) {
214 // if the choice in the scheduler is fixed we only update for the fixed choice
215 uint_fast64_t row = this->A->getRowGroupIndices()[sccState] + this->getInitialScheduler()[sccState];
216 ValueType rowValue = globalB[row];
217 bool hasDiagonalEntry = false;
219 for (auto const& entry : this->A->getRow(row)) {
220 if (entry.getColumn() == sccState) {
221 hasDiagonalEntry = true;
222 denominator = storm::utility::one<ValueType>() - entry.getValue();
223 } else {
224 rowValue += entry.getValue() * globalX[entry.getColumn()];
225 }
226 }
227 if (hasDiagonalEntry) {
230 "State " << sccState << " has a selfloop with probability '1-(" << denominator << ")'. This could be an indication for numerical issues.");
231 if (storm::utility::isZero(denominator)) {
232 // In this case we have a selfloop on this state. This can never an optimal choice:
233 // When minimizing, we are looking for the largest fixpoint (which will never be attained by this action)
234 // When maximizing, this choice reflects probability zero (non-optimal) or reward infinity (should already be handled during preprocessing).
235 } else {
236 rowValue /= denominator;
237 }
238 }
239 xi = std::move(rowValue);
240 } else {
241 bool firstRow = true;
242 uint64_t bestRow;
243 for (uint64_t row = this->A->getRowGroupIndices()[sccState]; row < this->A->getRowGroupIndices()[sccState + 1]; ++row) {
244 ValueType rowValue = globalB[row];
245 bool hasDiagonalEntry = false;
247 for (auto const& entry : this->A->getRow(row)) {
248 if (entry.getColumn() == sccState) {
249 hasDiagonalEntry = true;
250 denominator = storm::utility::one<ValueType>() - entry.getValue();
251 } else {
252 rowValue += entry.getValue() * globalX[entry.getColumn()];
253 }
254 }
255 if (hasDiagonalEntry) {
258 "State " << sccState << " has a selfloop with probability '1-(" << denominator << ")'. This could be an indication for numerical issues.");
259 if (storm::utility::isZero(denominator)) {
260 // In this case we have a selfloop on this state. This can never be an optimal choice:
261 // When minimizing, we are looking for the largest fixpoint (which will never be attained by this action)
262 // When maximizing, this choice reflects probability zero (non-optimal) or reward infinity (should already be handled during preprocessing).
263 continue;
264 } else {
265 rowValue /= denominator;
266 }
267 }
268 if (firstRow) {
269 xi = std::move(rowValue);
270 bestRow = row;
271 firstRow = false;
272 } else {
273 if (minimize(dir)) {
274 if (rowValue < xi) {
275 xi = std::move(rowValue);
276 bestRow = row;
277 }
278 } else {
279 if (rowValue > xi) {
280 xi = std::move(rowValue);
281 bestRow = row;
282 }
283 }
284 }
285 }
286 if (this->isTrackSchedulerSet()) {
287 this->schedulerChoices.get()[sccState] = bestRow - this->A->getRowGroupIndices()[sccState];
288 }
289 STORM_LOG_THROW(!firstRow, storm::exceptions::UnexpectedException, "Empty row group in MinMax equation system.");
290 }
291 return true;
292}
293
294template<typename ValueType, typename SolutionType>
295bool TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::solveFullyConnectedEquationSystem(storm::Environment const& sccSolverEnvironment,
296 OptimizationDirection dir, std::vector<SolutionType>& x,
297 std::vector<ValueType> const& b) const {
298 STORM_LOG_ASSERT(!this->choiceFixedForRowGroup || this->choiceFixedForRowGroup.get().empty(),
299 "Expecting no fixed choices for states when solving the fully connected equation system.");
300 if (!this->sccSolver) {
301 this->sccSolver = GeneralMinMaxLinearEquationSolverFactory<ValueType>().create(sccSolverEnvironment);
302 this->sccSolver->setCachingEnabled(true);
303 }
304 this->sccSolver->setMatrix(*this->A);
305 this->sccSolver->setHasUniqueSolution(this->hasUniqueSolution());
306 this->sccSolver->setHasNoEndComponents(this->hasNoEndComponents());
307 this->sccSolver->setTrackScheduler(this->isTrackSchedulerSet());
308 if (this->hasInitialScheduler()) {
309 auto choices = this->getInitialScheduler();
310 this->sccSolver->setInitialScheduler(std::move(choices));
311 }
312 if (this->hasRelevantValues()) {
313 this->sccSolver->setRelevantValues(this->getRelevantValues());
314 }
315 auto req = this->sccSolver->getRequirements(sccSolverEnvironment, dir);
316 this->sccSolver->setBoundsFromOtherSolver(*this);
317 if (req.upperBounds() && this->hasUpperBound()) {
318 req.clearUpperBounds();
319 }
320 if (req.lowerBounds() && this->hasLowerBound()) {
321 req.clearLowerBounds();
322 }
323 if (req.validInitialScheduler() && this->hasInitialScheduler()) {
324 req.clearValidInitialScheduler();
325 }
326 if (req.uniqueSolution() && this->hasUniqueSolution()) {
327 req.clearUniqueSolution();
328 }
329 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
330 "Solver requirements " + req.getEnabledRequirementsAsString() + " not checked.");
331 this->sccSolver->setRequirementsChecked(true);
332
333 bool res = this->sccSolver->solveEquations(sccSolverEnvironment, dir, x, b);
334 if (this->isTrackSchedulerSet()) {
335 this->schedulerChoices = this->sccSolver->getSchedulerChoices();
336 }
337 return res;
338}
339
340template<typename ValueType, typename SolutionType>
341bool TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>::solveScc(storm::Environment const& sccSolverEnvironment, OptimizationDirection dir,
342 storm::storage::StronglyConnectedComponent const& scc,
343 storm::storage::BitVector const& sccAsBitVector,
344 std::vector<SolutionType>& globalX, std::vector<ValueType> const& globalB,
345 std::optional<storm::storage::BitVector> const& globalRelevantValues,
346 bool& metPrecision) const {
347 // Restricts a vector indexed by row groups to the states of the scc
348 auto restrictToScc = [&scc](auto const& globalVector) {
349 std::vector<std::decay_t<decltype(globalVector[0])>> result;
350 result.reserve(scc.size());
351 for (uint64_t const state : scc) {
352 result.push_back(globalVector[state]);
353 }
354 return result;
355 };
356
357 // Set up the SCC solver
358 if (!this->sccSolver) {
359 this->sccSolver = GeneralMinMaxLinearEquationSolverFactory<ValueType>().create(sccSolverEnvironment);
360 this->sccSolver->setCachingEnabled(true);
361 }
362 if (!this->sccSubmatrixBuilder) {
363 this->sccSubmatrixBuilder = std::make_unique<storm::storage::SubmatrixBuilder<ValueType>>(*this->A);
364 }
365 this->sccSolver->setHasUniqueSolution(this->hasUniqueSolution());
366 this->sccSolver->setHasNoEndComponents(this->hasNoEndComponents());
367 this->sccSolver->setTrackScheduler(this->isTrackSchedulerSet());
368 if (globalRelevantValues) {
369 storm::storage::BitVector sccRelevantValues(scc.size(), false);
370 uint64_t sccState = 0;
371 for (uint64_t const state : scc) {
372 sccRelevantValues.set(sccState++, globalRelevantValues->get(state));
373 }
374 this->sccSolver->setRelevantValues(std::move(sccRelevantValues));
375 }
376
377 auto const& rowGroupIndices = this->A->getRowGroupIndices();
378 bool const hasFixedChoices = this->choiceFixedForRowGroup && !this->choiceFixedForRowGroup->empty();
379 auto const isChoiceFixed = [&](uint64_t state) { return hasFixedChoices && (*this->choiceFixedForRowGroup)[state]; };
380
381 // Rows (of the global matrix) that are considered for the given state: all of its rows, or just the fixed one.
382 auto const rowRange = [&](uint64_t state) {
383 if (isChoiceFixed(state)) {
384 auto const row = rowGroupIndices[state] + this->getInitialScheduler()[state];
385 STORM_LOG_TRACE("Fixing state " << state << " to choice " << this->getInitialScheduler()[state] << ".");
386 return std::make_pair(row, row + 1);
387 } else {
388 return std::make_pair(rowGroupIndices[state], rowGroupIndices[state + 1]);
389 }
390 };
391
392 // Set up the matrix and the initial scheduler
393 std::vector<uint64_t> sccRows; // only used if there are fixed choices
394 uint64_t sccRowCount = 0;
395 for (uint64_t const state : scc) {
396 auto const [rowBegin, rowEnd] = rowRange(state);
397 sccRowCount += rowEnd - rowBegin;
398 if (hasFixedChoices) {
399 for (uint64_t row = rowBegin; row < rowEnd; ++row) {
400 sccRows.push_back(row);
401 }
402 }
403 }
404 if (hasFixedChoices) {
405 this->sccSolver->setMatrix(this->sccSubmatrixBuilder->getByRowConstraint(sccRows, scc, false));
406 } else {
407 this->sccSolver->setMatrix(this->sccSubmatrixBuilder->getByRowGroupConstraint(scc, scc, false));
408 }
409 if (this->hasInitialScheduler()) {
410 auto sccInitChoices = restrictToScc(this->getInitialScheduler());
411 if (hasFixedChoices) {
412 // As we removed the entries where the choice was fixed, we need to change the scheduler.
413 // We set the scheduler to 0 for those states.
414 uint64_t sccState = 0;
415 for (uint64_t const state : scc) {
416 if (isChoiceFixed(state)) {
417 sccInitChoices[sccState] = 0;
418 }
419 ++sccState;
420 }
421 }
422 this->sccSolver->setInitialScheduler(std::move(sccInitChoices));
423 }
424
425 // x Vector
426 auto sccX = restrictToScc(globalX);
427
428 // b Vector
429 std::vector<ValueType> sccB;
430 sccB.reserve(sccRowCount);
431 for (uint64_t const state : scc) {
432 auto const [rowBegin, rowEnd] = rowRange(state);
433 for (uint64_t row = rowBegin; row < rowEnd; ++row) {
434 ValueType bi = globalB[row];
435 for (auto const& entry : this->A->getRow(row)) {
436 if (!sccAsBitVector.get(entry.getColumn())) {
437 bi += entry.getValue() * globalX[entry.getColumn()];
438 }
439 }
440 sccB.push_back(std::move(bi));
441 }
442 }
443
444 auto req = this->sccSolver->getRequirements(sccSolverEnvironment, dir);
445 this->sccSolver->clearBounds();
446 // lower/upper bounds
447 if (this->hasLowerBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Global)) {
448 this->sccSolver->setLowerBound(this->getLowerBound());
449 req.clearLowerBounds();
450 } else if (this->hasLowerBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Local)) {
451 this->sccSolver->setLowerBounds(restrictToScc(this->getLowerBounds()));
452 req.clearLowerBounds();
453 }
454 if (this->hasUpperBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Global)) {
455 this->sccSolver->setUpperBound(this->getUpperBound());
456 req.clearUpperBounds();
457 } else if (this->hasUpperBound(storm::solver::AbstractEquationSolver<ValueType>::BoundType::Local)) {
458 this->sccSolver->setUpperBounds(restrictToScc(this->getUpperBounds()));
459 req.clearUpperBounds();
460 }
461
462 // Requirements
463 if (req.validInitialScheduler() && (this->hasInitialScheduler() || this->hasNoEndComponents())) {
464 req.clearValidInitialScheduler();
465 }
466 if (req.uniqueSolution() && this->hasUniqueSolution()) {
467 req.clearUniqueSolution();
468 }
469 STORM_LOG_THROW(!req.hasEnabledCriticalRequirement(), storm::exceptions::UncheckedRequirementException,
470 "Solver requirements " + req.getEnabledRequirementsAsString() + " not checked.");
471 this->sccSolver->setRequirementsChecked(true);
472
473 // Invoke scc solver
474 bool res = this->sccSolver->solveEquations(sccSolverEnvironment, dir, sccX, sccB);
475 metPrecision = lastSccMetPrecision(sccSolverEnvironment, sccX);
476
477 // Set Scheduler choices and solution
478 if (this->isTrackSchedulerSet()) {
479 auto const& sccChoices = this->sccSolver->getSchedulerChoices();
480 uint64_t sccState = 0;
481 for (uint64_t const state : scc) {
482 this->schedulerChoices.get()[state] = sccChoices[sccState++];
483 }
484 }
485 uint64_t sccState = 0;
486 for (uint64_t const state : scc) {
487 globalX[state] = std::move(sccX[sccState++]);
488 }
489
490 return res;
491}
492
493template<typename ValueType, typename SolutionType>
495 Environment const& env, boost::optional<storm::solver::OptimizationDirection> const& direction, bool const& hasInitialScheduler) const {
496 // Return the requirements of the underlying solver
497 return GeneralMinMaxLinearEquationSolverFactory<ValueType>().getRequirements(getEnvironmentForUnderlyingSolver(env), this->hasUniqueSolution(),
499 this->isTrackSchedulerSet());
500}
501
502template<typename ValueType, typename SolutionType>
504 sortedSccDecomposition.reset();
505 longestSccChainSize = boost::none;
506 sccSolver.reset();
507 sccSubmatrixBuilder.reset();
508 auxiliaryRowGroupVector.reset();
510}
511
512// Explicitly instantiate the min max linear equation solver.
515// TODO implement topological mode for intervals
516// template class TopologicalMinMaxLinearEquationSolver<storm::Interval, double>;
517
518} // namespace solver
519} // namespace storm
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
bool const & getRelativeTerminationCriterion() const
TopologicalSolverEnvironment & topological()
MinMaxSolverEnvironment & minMax()
uint64_t getShowProgressDelay() const
storm::solver::MinMaxMethod const & getUnderlyingMinMaxMethod() const
storm::storage::BitVector const & getRelevantValues() const
virtual std::unique_ptr< MinMaxLinearEquationSolver< ValueType, SolutionType > > create(Environment const &env) const override
MinMaxLinearEquationSolverRequirements getRequirements(Environment const &env, bool hasUniqueSolution=false, bool hasNoEndComponents=false, boost::optional< storm::solver::OptimizationDirection > const &direction=boost::none, bool hasInitialScheduler=false, bool trackScheduler=false) const
Retrieves the requirements of the solver that would be created when calling create() right now.
virtual bool internalSolveEquations(storm::Environment const &env, OptimizationDirection d, std::vector< SolutionType > &x, std::vector< ValueType > const &b) const override
virtual void clearCache() const override
Clears the currently cached data that has been stored during previous calls of the solver.
virtual MinMaxLinearEquationSolverRequirements getRequirements(Environment const &env, boost::optional< storm::solver::OptimizationDirection > const &direction=boost::none, bool const &hasInitialScheduler=false) const override
Retrieves the requirements of this solver for solving equations with the current settings.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void clear()
Removes all set bits from the bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
A class that holds a possibly non-square matrix in the compressed row storage format.
std::size_t size() const
Retrieves the number of states in this SCC.
A class that provides convenience operations to display run times.
bool updateProgress(uint64_t count)
Updates the progress to the current count and logs it (on the progress log channel) if the delay pass...
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:13
void stop()
Stop stopwatch and add measured time to total time.
Definition Stopwatch.cpp:42
#define STORM_LOG_INFO(message)
Definition logging.h:34
#define STORM_LOG_WARN(message)
Definition logging.h:35
#define STORM_LOG_TRACE(message)
Definition logging.h:22
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
#define STORM_LOG_WARN_COND_DEBUG(cond, message)
Definition macros.h:16
SFTBDDChecker::ValueType ValueType
bool constexpr minimize(OptimizationDirection d)
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
bool isAlmostZero(ValueType const &a)
Definition constants.cpp:98
bool isZero(ValueType const &a)
Definition constants.cpp:44
ValueType one()
Definition constants.cpp:21
TargetType convertNumber(SourceType const &number)
static const bool IsExact