22template<
typename ValueType>
26 : linearEquationSolverFactory(
std::move(linearEquationSolverFactory)),
27 localPlayer1Grouping(nullptr),
28 localPlayer1Matrix(nullptr),
29 localPlayer2Matrix(nullptr),
30 player1Grouping(nullptr),
31 player1Matrix(&player1Matrix),
32 player2Matrix(player2Matrix) {}
34template<
typename ValueType>
38 : linearEquationSolverFactory(
std::move(linearEquationSolverFactory)),
39 localPlayer1Grouping(nullptr),
41 localPlayer2Matrix(
std::make_unique<
storm::
storage::SparseMatrix<ValueType>>(
std::move(player2Matrix))),
42 player1Grouping(nullptr),
43 player1Matrix(localPlayer1Matrix.get()),
44 player2Matrix(*localPlayer2Matrix) {}
46template<
typename ValueType>
49 : linearEquationSolverFactory(
std::move(linearEquationSolverFactory)),
50 localPlayer1Grouping(nullptr),
51 localPlayer1Matrix(nullptr),
52 localPlayer2Matrix(nullptr),
53 player1Grouping(&player1Grouping),
54 player1Matrix(nullptr),
55 player2Matrix(player2Matrix) {}
57template<
typename ValueType>
60 : linearEquationSolverFactory(
std::move(linearEquationSolverFactory)),
61 localPlayer1Grouping(
std::make_unique<
std::vector<uint64_t>>(
std::move(player1Grouping))),
62 localPlayer1Matrix(nullptr),
63 localPlayer2Matrix(
std::make_unique<
storm::
storage::SparseMatrix<ValueType>>(
std::move(player2Matrix))),
64 player1Grouping(localPlayer1Grouping.get()),
65 player1Matrix(nullptr),
66 player2Matrix(*localPlayer2Matrix) {}
68template<
typename ValueType>
69GameMethod StandardGameSolver<ValueType>::getMethod(
Environment const& env,
bool isExactMode)
const {
71 if (isExactMode && method != GameMethod::PolicyIteration) {
73 method = GameMethod::PolicyIteration;
74 STORM_LOG_INFO(
"Changing game method to policy-iteration to guarantee exact results. If you want to override this, specify another method.");
76 STORM_LOG_WARN(
"The selected game method does not guarantee exact results.");
80 method = GameMethod::PolicyIteration;
81 STORM_LOG_INFO(
"Changing game method to policy-iteration to guarantee sound results. If you want to override this, specify another method.");
83 STORM_LOG_WARN(
"The selected game method does not guarantee sound results.");
89template<
typename ValueType>
91 std::vector<ValueType>& x, std::vector<ValueType>
const& b, std::vector<uint64_t>* player1Choices,
92 std::vector<uint64_t>* player2Choices)
const {
93 auto method = getMethod(env, std::is_same<ValueType, storm::RationalNumber>::value || env.
solver().
isForceExact());
94 STORM_LOG_INFO(
"Solving stochastic two player game over " << x.size() <<
" states using " <<
toString(method) <<
".");
96 case GameMethod::ValueIteration:
97 return solveGameValueIteration(env, player1Dir, player2Dir, x, b, player1Choices, player2Choices);
98 case GameMethod::PolicyIteration:
99 return solveGamePolicyIteration(env, player1Dir, player2Dir, x, b, player1Choices, player2Choices);
101 STORM_LOG_THROW(
false, storm::exceptions::InvalidEnvironmentException,
"This solver does not implement the selected solution method.");
106template<
typename ValueType>
108 std::vector<ValueType>& x, std::vector<ValueType>
const& b,
109 std::vector<uint64_t>* providedPlayer1Choices,
110 std::vector<uint64_t>* providedPlayer2Choices)
const {
112 std::vector<storm::storage::sparse::state_type>* player1Choices;
113 std::unique_ptr<std::vector<storm::storage::sparse::state_type>> localPlayer1Choices;
114 std::vector<storm::storage::sparse::state_type>* player2Choices;
115 std::unique_ptr<std::vector<storm::storage::sparse::state_type>> localPlayer2Choices;
117 if (providedPlayer1Choices && providedPlayer2Choices) {
118 player1Choices = providedPlayer1Choices;
119 player2Choices = providedPlayer2Choices;
121 localPlayer1Choices = std::make_unique<std::vector<uint64_t>>();
122 player1Choices = localPlayer1Choices.get();
123 localPlayer2Choices = std::make_unique<std::vector<uint64_t>>();
124 player2Choices = localPlayer2Choices.get();
127 if (this->hasSchedulerHints()) {
128 *player1Choices = this->player1ChoicesHint.get();
129 }
else if (this->player1RepresentedByMatrix()) {
131 *player1Choices = std::vector<storm::storage::sparse::state_type>(this->getPlayer1Matrix().getRowGroupCount(), 0);
134 player1Choices->resize(player1Choices->size() - 1);
136 if (this->hasSchedulerHints()) {
137 *player2Choices = this->player2ChoicesHint.get();
138 }
else if (!(providedPlayer1Choices && providedPlayer2Choices)) {
139 player2Choices->resize(this->player2Matrix.getRowGroupCount());
142 if (!auxiliaryP2RowGroupVector) {
143 auxiliaryP2RowGroupVector = std::make_unique<std::vector<ValueType>>(this->player2Matrix.getRowGroupCount());
145 if (!auxiliaryP1RowGroupVector) {
146 auxiliaryP1RowGroupVector = std::make_unique<std::vector<ValueType>>(this->player1RepresentedByMatrix() ? this->player1Matrix->getRowGroupCount()
147 : this->player1Grouping->size() - 1);
149 std::vector<ValueType>& subB = *auxiliaryP1RowGroupVector;
154 std::unique_ptr<storm::Environment> environmentOfSolverStorage;
157 bool changePrecision = precOfSolver.first && precOfSolver.first.get() > env.
solver().
game().
getPrecision();
159 if (changePrecision || changeRelative) {
160 environmentOfSolverStorage = std::make_unique<storm::Environment>(env);
161 boost::optional<storm::RationalNumber> newPrecision;
162 boost::optional<bool> newRelative;
163 if (changePrecision) {
166 if (changeRelative) {
169 environmentOfSolverStorage->solver().setLinearEquationSolverPrecision(newPrecision, newRelative);
172 storm::Environment
const& environmentOfSolver = environmentOfSolverStorage ? *environmentOfSolverStorage : env;
175 storm::storage::SparseMatrix<ValueType> submatrix;
176 getInducedMatrixVector(x, b, *player1Choices, *player2Choices, submatrix, subB);
178 storm::storage::BitVector targetStates;
179 storm::storage::BitVector zeroStates;
180 if (!this->hasUniqueSolution()) {
185 bool asEquationSystem =
false;
188 asEquationSystem =
true;
190 if (!this->hasUniqueSolution()) {
191 for (uint64_t state : zeroStates) {
192 for (
auto& element : submatrix.
getRow(state)) {
193 if (element.getColumn() == state) {
202 auto submatrixSolver = linearEquationSolverFactory->create(environmentOfSolver, std::move(submatrix));
203 if (this->lowerBound) {
204 submatrixSolver->setLowerBound(this->lowerBound.get());
206 if (this->upperBound) {
207 submatrixSolver->setUpperBound(this->upperBound.get());
209 submatrixSolver->setCachingEnabled(
true);
212 uint64_t iterations = 0;
214 submatrixSolver->solveEquations(environmentOfSolver, x, subB);
217 bool schedulerImproved =
218 extractChoices(environmentOfSolver, player1Dir, player2Dir, x, b, *auxiliaryP2RowGroupVector, *player1Choices, *player2Choices);
221 if (!schedulerImproved) {
225 getInducedMatrixVector(x, b, *player1Choices, *player2Choices, submatrix, subB);
227 if (!this->hasUniqueSolution()) {
236 if (!this->hasUniqueSolution()) {
237 for (uint64_t state : zeroStates) {
238 for (
auto& element : submatrix.
getRow(state)) {
239 if (element.getColumn() == state) {
249 submatrixSolver->setMatrix(std::move(submatrix));
257 this->reportStatus(status, iterations);
260 if (this->isTrackSchedulersSet() && !(providedPlayer1Choices && providedPlayer2Choices)) {
261 this->player1SchedulerChoices = std::move(*player1Choices);
262 this->player2SchedulerChoices = std::move(*player2Choices);
265 if (!this->isCachingEnabled()) {
272template<
typename ValueType>
273bool StandardGameSolver<ValueType>::valueImproved(
OptimizationDirection dir, storm::utility::ConstantsComparator<ValueType>
const& comparator,
274 ValueType
const& value1, ValueType
const& value2)
const {
275 if (dir == OptimizationDirection::Minimize) {
276 return comparator.
isLess(value2, value1);
278 return comparator.
isLess(value1, value2);
282template<
typename ValueType>
284 std::vector<ValueType>& x, std::vector<ValueType>
const& b, std::vector<uint64_t>* player1Choices,
285 std::vector<uint64_t>* player2Choices)
const {
286 if (!multiplierPlayer2Matrix) {
287 multiplierPlayer2Matrix = storm::solver::MultiplierFactory<ValueType>().create(env, player2Matrix);
290 if (!auxiliaryP2RowGroupVector) {
291 auxiliaryP2RowGroupVector = std::make_unique<std::vector<ValueType>>(player2Matrix.getRowGroupCount());
294 if (!auxiliaryP1RowGroupVector) {
295 auxiliaryP1RowGroupVector = std::make_unique<std::vector<ValueType>>(this->getNumberOfPlayer1States());
299 bool relative = env.solver().game().getRelativeTerminationCriterion();
300 uint64_t maxIter = env.solver().game().getMaximalNumberOfIterations();
302 std::vector<ValueType>& reducedPlayer2Result = *auxiliaryP2RowGroupVector;
304 bool trackingSchedulersInProvidedStorage = player1Choices && player2Choices;
305 bool trackSchedulers = this->isTrackSchedulersSet() || trackingSchedulersInProvidedStorage;
306 bool trackSchedulersInValueIteration = trackSchedulers && !this->hasUniqueSolution();
307 if (this->hasSchedulerHints()) {
309 storm::storage::SparseMatrix<ValueType> submatrix;
310 getInducedMatrixVector(x, b, this->player1ChoicesHint.get(), this->player2ChoicesHint.get(), submatrix, *auxiliaryP1RowGroupVector);
314 auto submatrixSolver = linearEquationSolverFactory->create(env, std::move(submatrix));
315 if (this->lowerBound) {
316 submatrixSolver->setLowerBound(this->lowerBound.get());
318 if (this->upperBound) {
319 submatrixSolver->setUpperBound(this->upperBound.get());
321 submatrixSolver->solveEquations(env, x, *auxiliaryP1RowGroupVector);
324 if (trackSchedulersInValueIteration && !trackingSchedulersInProvidedStorage) {
325 this->player1SchedulerChoices = this->player1ChoicesHint.get();
326 this->player2SchedulerChoices = this->player2ChoicesHint.get();
328 }
else if (trackSchedulersInValueIteration && !trackingSchedulersInProvidedStorage) {
331 this->player1SchedulerChoices = std::vector<uint_fast64_t>(this->getNumberOfPlayer1States(), 0);
332 this->player2SchedulerChoices = std::vector<uint_fast64_t>(this->getNumberOfPlayer2States(), 0);
335 std::vector<ValueType>* newX = auxiliaryP1RowGroupVector.get();
336 std::vector<ValueType>* currentX = &x;
339 uint64_t iterations = 0;
344 env, player1Dir, player2Dir, *currentX, &b, *multiplierPlayer2Matrix, reducedPlayer2Result, *newX,
345 trackSchedulersInValueIteration ? (trackingSchedulersInProvidedStorage ? player1Choices : &this->player1SchedulerChoices.get()) :
nullptr,
346 trackSchedulersInValueIteration ? (trackingSchedulersInProvidedStorage ? player2Choices : &this->player2SchedulerChoices.get()) :
nullptr);
354 std::swap(currentX, newX);
359 this->reportStatus(status, iterations);
363 if (currentX == auxiliaryP1RowGroupVector.get()) {
364 std::swap(x, *currentX);
368 if (trackSchedulers && this->hasUniqueSolution()) {
369 if (trackingSchedulersInProvidedStorage) {
370 extractChoices(env, player1Dir, player2Dir, x, b, *auxiliaryP2RowGroupVector, *player1Choices, *player2Choices);
372 this->player1SchedulerChoices = std::vector<uint_fast64_t>(this->getNumberOfPlayer1States(), 0);
373 this->player2SchedulerChoices = std::vector<uint_fast64_t>(this->getNumberOfPlayer2States(), 0);
374 extractChoices(env, player1Dir, player2Dir, x, b, *auxiliaryP2RowGroupVector, this->player1SchedulerChoices.get(),
375 this->player2SchedulerChoices.get());
379 if (!this->isCachingEnabled()) {
386template<
typename ValueType>
388 std::vector<ValueType>& x, std::vector<ValueType>
const* b, uint_fast64_t n)
const {
389 if (!multiplierPlayer2Matrix) {
393 if (!auxiliaryP2RowGroupVector) {
394 auxiliaryP2RowGroupVector = std::make_unique<std::vector<ValueType>>(player2Matrix.getRowGroupCount());
396 std::vector<ValueType>& reducedPlayer2Result = *auxiliaryP2RowGroupVector;
398 for (uint_fast64_t iteration = 0; iteration < n; ++iteration) {
399 multiplyAndReduce(env, player1Dir, player2Dir, x, b, *multiplierPlayer2Matrix, reducedPlayer2Result, x);
407template<
typename ValueType>
409 std::vector<ValueType>& x, std::vector<ValueType>
const* b,
411 std::vector<ValueType>& player1ReducedResult, std::vector<uint64_t>* player1SchedulerChoices,
412 std::vector<uint64_t>* player2SchedulerChoices)
const {
413 multiplier.
multiplyAndReduce(env, player2Dir, x, b, player2ReducedResult, UncertaintyResolutionMode::Unset, player2SchedulerChoices);
415 if (this->player1RepresentedByMatrix()) {
417 uint_fast64_t player1State = 0;
418 for (
auto& result : player1ReducedResult) {
421 auto it = relevantRows.
begin();
422 auto ite = relevantRows.
end();
425 result = player2ReducedResult[it->getColumn()];
429 if (player1Dir == OptimizationDirection::Minimize) {
430 for (; it != ite; ++it) {
431 result = std::min(result, player2ReducedResult[it->getColumn()]);
434 for (; it != ite; ++it) {
435 result = std::max(result, player2ReducedResult[it->getColumn()]);
443 player1SchedulerChoices);
447template<
typename ValueType>
449 std::vector<ValueType>
const& x, std::vector<ValueType>
const& b,
450 std::vector<ValueType>& player2ChoiceValues, std::vector<uint_fast64_t>& player1Choices,
451 std::vector<uint_fast64_t>& player2Choices)
const {
452 storm::utility::ConstantsComparator<ValueType> comparator(
459 bool schedulerImproved =
false;
460 auto currentValueIt = player2ChoiceValues.begin();
461 for (uint_fast64_t p2Group = 0; p2Group < this->player2Matrix.getRowGroupCount(); ++p2Group, ++currentValueIt) {
462 uint_fast64_t firstRowInGroup = this->player2Matrix.getRowGroupIndices()[p2Group];
463 uint_fast64_t rowGroupSize = this->player2Matrix.getRowGroupIndices()[p2Group + 1] - firstRowInGroup;
466 uint_fast64_t currentP2Choice = player2Choices[p2Group];
468 for (
auto const& entry : this->player2Matrix.getRow(firstRowInGroup + currentP2Choice)) {
469 *currentValueIt += entry.getValue() * x[entry.getColumn()];
471 *currentValueIt += b[firstRowInGroup + currentP2Choice];
474 for (uint_fast64_t p2Choice = 0; p2Choice < rowGroupSize; ++p2Choice) {
475 if (p2Choice == currentP2Choice) {
479 for (
auto const& entry : this->player2Matrix.getRow(firstRowInGroup + p2Choice)) {
480 choiceValue += entry.getValue() * x[entry.getColumn()];
482 choiceValue += b[firstRowInGroup + p2Choice];
484 if (valueImproved(player2Dir, comparator, *currentValueIt, choiceValue)) {
485 schedulerImproved =
true;
486 player2Choices[p2Group] = p2Choice;
487 *currentValueIt = std::move(choiceValue);
493 if (this->player1RepresentedByMatrix()) {
495 for (uint_fast64_t p1Group = 0; p1Group < this->getPlayer1Matrix().getRowGroupCount(); ++p1Group) {
496 uint_fast64_t firstRowInGroup = this->getPlayer1Matrix().getRowGroupIndices()[p1Group];
497 uint_fast64_t rowGroupSize = this->getPlayer1Matrix().getRowGroupIndices()[p1Group + 1] - firstRowInGroup;
498 uint_fast64_t currentChoice = player1Choices[p1Group];
499 ValueType currentValue = player2ChoiceValues[this->getPlayer1Matrix().getRow(firstRowInGroup + currentChoice).begin()->getColumn()];
500 for (uint_fast64_t p1Choice = 0; p1Choice < rowGroupSize; ++p1Choice) {
502 if (p1Choice == currentChoice) {
505 ValueType const& choiceValue = player2ChoiceValues[this->getPlayer1Matrix().getRow(firstRowInGroup + p1Choice).begin()->getColumn()];
506 if (valueImproved(player1Dir, comparator, currentValue, choiceValue)) {
507 schedulerImproved =
true;
508 player1Choices[p1Group] = p1Choice;
509 currentValue = choiceValue;
515 for (uint64_t player1State = 0; player1State < this->getPlayer1Grouping().size() - 1; ++player1State) {
516 uint64_t currentChoice = player1Choices[player1State];
517 ValueType currentValue = player2ChoiceValues[this->getPlayer1Grouping()[player1State] + currentChoice];
518 uint64_t numberOfPlayer2Successors = this->getPlayer1Grouping()[player1State + 1] - this->getPlayer1Grouping()[player1State];
519 for (uint64_t player2State = 0; player2State < numberOfPlayer2Successors; ++player2State) {
521 if (currentChoice == player2State) {
525 ValueType const& choiceValue = player2ChoiceValues[this->getPlayer1Grouping()[player1State] + player2State];
526 if (valueImproved(player1Dir, comparator, currentValue, choiceValue)) {
527 schedulerImproved =
true;
528 player1Choices[player1State] = player2State;
529 currentValue = choiceValue;
535 return schedulerImproved;
538template<
typename ValueType>
539void StandardGameSolver<ValueType>::getInducedMatrixVector(std::vector<ValueType>&, std::vector<ValueType>
const& b,
540 std::vector<uint_fast64_t>
const& player1Choices, std::vector<uint_fast64_t>
const& player2Choices,
541 storm::storage::SparseMatrix<ValueType>& inducedMatrix,
542 std::vector<ValueType>& inducedVector)
const {
545 std::vector<storm::storage::sparse::state_type> selectedRows;
546 if (this->player1RepresentedByMatrix()) {
548 selectedRows.reserve(this->getPlayer1Matrix().getRowGroupCount());
549 uint_fast64_t player1State = 0;
550 for (
auto const& player1Choice : player1Choices) {
551 auto const& player1Row = this->getPlayer1Matrix().getRow(player1State, player1Choice);
552 STORM_LOG_ASSERT(player1Row.getNumberOfEntries() == 1,
"It is assumed that rows of player one have one entry, but this is not the case.");
553 uint_fast64_t player2State = player1Row.begin()->getColumn();
554 selectedRows.push_back(player2Matrix.getRowGroupIndices()[player2State] + player2Choices[player2State]);
559 selectedRows.reserve(this->player2Matrix.getRowGroupCount());
560 for (uint64_t player1State = 0; player1State < this->getPlayer1Grouping().size() - 1; ++player1State) {
561 uint64_t player2State = this->getPlayer1Grouping()[player1State] + player1Choices[player1State];
562 selectedRows.emplace_back(player2Matrix.getRowGroupIndices()[player2State] + player2Choices[player2State]);
572template<
typename ValueType>
573bool StandardGameSolver<ValueType>::player1RepresentedByMatrix()
const {
574 return player1Matrix !=
nullptr;
577template<
typename ValueType>
578storm::storage::SparseMatrix<storm::storage::sparse::state_type>
const& StandardGameSolver<ValueType>::getPlayer1Matrix()
const {
579 STORM_LOG_ASSERT(player1RepresentedByMatrix(),
"Player 1 is represented by a matrix.");
580 return *player1Matrix;
583template<
typename ValueType>
584std::vector<uint64_t>
const& StandardGameSolver<ValueType>::getPlayer1Grouping()
const {
585 STORM_LOG_ASSERT(!player1RepresentedByMatrix(),
"Player 1 is represented by a matrix.");
586 return *player1Grouping;
589template<
typename ValueType>
590uint64_t StandardGameSolver<ValueType>::getNumberOfPlayer1States()
const {
591 if (this->player1RepresentedByMatrix()) {
592 return this->getPlayer1Matrix().getRowGroupCount();
594 return this->getPlayer1Grouping().size() - 1;
598template<
typename ValueType>
599uint64_t StandardGameSolver<ValueType>::getNumberOfPlayer2States()
const {
600 return this->player2Matrix.getRowGroupCount();
603template<
typename ValueType>
605 multiplierPlayer2Matrix.reset();
606 auxiliaryP2RowVector.reset();
607 auxiliaryP2RowGroupVector.reset();
608 auxiliaryP1RowGroupVector.reset();
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
uint64_t const & getMaximalNumberOfIterations() const
bool const & isMethodSetFromDefault() const
bool const & getRelativeTerminationCriterion() const
storm::solver::GameMethod const & getMethod() const
storm::solver::EquationSolverType const & getLinearEquationSolverType() const
GameSolverEnvironment & game()
bool isForceExact() const
bool isForceSoundness() const
std::pair< boost::optional< storm::RationalNumber >, boost::optional< bool > > getPrecisionOfLinearEquationSolver(storm::solver::EquationSolverType const &solverType) const
virtual void clearCache() const
bool isCachingEnabled() const
Retrieves whether some of the generated data during solver calls should be cached.
std::unique_ptr< Multiplier< ValueType, SolutionType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
void multiplyAndReduce(Environment const &env, OptimizationDirection const &dir, std::vector< SolutionType > const &x, std::vector< ValueType > const *b, std::vector< SolutionType > &result, UncertaintyResolutionMode const &uncertaintyResolutionMode=UncertaintyResolutionMode::Unset, std::vector< uint_fast64_t > *choices=nullptr) const
Performs a matrix-vector multiplication x' = A*x + b and then minimizes/maximizes over the row groups...
virtual void clearCache() const override
virtual bool solveGame(Environment const &env, OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector< ValueType > &x, std::vector< ValueType > const &b, std::vector< uint64_t > *player1Choices=nullptr, std::vector< uint64_t > *player2Choices=nullptr) const override
Solves the equation system defined by the game matrices.
virtual void repeatedMultiply(Environment const &env, OptimizationDirection player1Dir, OptimizationDirection player2Dir, std::vector< ValueType > &x, std::vector< ValueType > const *b, uint_fast64_t n=1) const override
Performs (repeated) matrix-vector multiplication with the given parameters, i.e.
StandardGameSolver(storm::storage::SparseMatrix< storm::storage::sparse::state_type > const &player1Matrix, storm::storage::SparseMatrix< ValueType > const &player2Matrix, std::unique_ptr< LinearEquationSolverFactory< ValueType > > &&linearEquationSolverFactory)
size_t size() const
Retrieves the number of bits this bit vector can store.
This class represents a number of consecutive rows of the matrix.
const_iterator end() const
Retrieves an iterator that points past the last entry of the rows.
index_type getNumberOfEntries() const
Retrieves the number of entries in the rows.
const_iterator begin() const
Retrieves an iterator that points to the beginning of the rows.
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.
SparseMatrix selectRowsFromRowIndexSequence(std::vector< index_type > const &rowIndexSequence, bool insertDiagonalEntries=true) const
Selects the rows that are given by the sequence of row indices, allowing to select rows arbitrarily o...
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.
bool isLess(ValueType const &value1, ValueType const &value2) const
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
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...
bool equalModuloPrecision(T const &val1, T const &val2, T const &precision, bool relativeError=true)
Compares the given elements and determines whether they are equal modulo the given precision.
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...
void reduceVectorMinOrMax(storm::solver::OptimizationDirection dir, std::vector< T > const &source, std::vector< T > &target, std::vector< uint_fast64_t > const &rowGrouping, std::vector< uint_fast64_t > *choices=nullptr)
Reduces the given source vector by selecting either the smallest or the largest out of each row group...
storm::storage::BitVector filterGreaterZero(std::vector< T > const &values)
Retrieves a bit vector containing all the indices for which the value at this position is greater tha...
TargetType convertNumber(SourceType const &number)
static const bool IsExact