26template<
typename ValueType,
typename SolutionType>
28 STORM_LOG_ASSERT(
static_cast<bool>(std::is_same_v<storm::Interval, ValueType>),
29 "Only for interval models");
32template<
typename ValueType,
typename SolutionType>
35 : linearEquationSolverFactory(
std::move(linearEquationSolverFactory)) {
39template<
typename ValueType,
typename SolutionType>
46template<
typename ValueType,
typename SolutionType>
53template<
typename ValueType,
typename SolutionType>
58 if (isExactMode && method != MinMaxMethod::PolicyIteration && method != MinMaxMethod::RationalSearch && method != MinMaxMethod::ViToPi) {
61 "Selecting 'Policy iteration' as the solution technique to guarantee exact results. If you want to override this, please explicitly specify a "
63 method = MinMaxMethod::PolicyIteration;
65 STORM_LOG_WARN(
"The selected solution method " <<
toString(method) <<
" does not guarantee exact results.");
67 }
else if (env.
solver().
isForceSoundness() && method != MinMaxMethod::SoundValueIteration && method != MinMaxMethod::IntervalIteration &&
68 method != MinMaxMethod::PolicyIteration && method != MinMaxMethod::RationalSearch && method != MinMaxMethod::OptimisticValueIteration) {
70 method = MinMaxMethod::OptimisticValueIteration;
74 <<
"' as the solution technique to guarantee sound results. If you want to override this, please explicitly specify a different method.");
76 STORM_LOG_WARN(
"The selected solution method does not guarantee sound results.");
79 STORM_LOG_THROW(method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch ||
80 method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::IntervalIteration ||
81 method == MinMaxMethod::OptimisticValueIteration || method == MinMaxMethod::ViToPi,
82 storm::exceptions::InvalidEnvironmentException,
"This solver does not support the selected method '" <<
toString(method) <<
"'.");
86template<
typename ValueType,
typename SolutionType>
88 std::vector<SolutionType>& x, std::vector<ValueType>
const& b)
const {
91 case MinMaxMethod::ValueIteration:
92 result = solveEquationsValueIteration(env, dir, x, b);
94 case MinMaxMethod::OptimisticValueIteration:
95 result = solveEquationsOptimisticValueIteration(env, dir, x, b);
97 case MinMaxMethod::PolicyIteration:
98 result = solveEquationsPolicyIteration(env, dir, x, b);
100 case MinMaxMethod::RationalSearch:
101 result = solveEquationsRationalSearch(env, dir, x, b);
103 case MinMaxMethod::IntervalIteration:
104 result = solveEquationsIntervalIteration(env, dir, x, b);
106 case MinMaxMethod::SoundValueIteration:
107 result = solveEquationsSoundValueIteration(env, dir, x, b);
109 case MinMaxMethod::ViToPi:
110 result = solveEquationsViToPi(env, dir, x, b);
113 STORM_LOG_THROW(
false, storm::exceptions::InvalidEnvironmentException,
"This solver does not implement the selected solution method");
119template<
typename ValueType,
typename SolutionType>
122 viOperator = std::make_shared<helper::ValueIterationOperator<ValueType, false, SolutionType>>();
123 viOperator->setMatrixBackwards(*this->A);
125 if (this->choiceFixedForRowGroup) {
127 assert(this->initialScheduler);
128 auto callback = [&](uint64_t groupIndex, uint64_t localRowIndex) {
129 return this->choiceFixedForRowGroup->get(groupIndex) && this->initialScheduler->at(groupIndex) != localRowIndex;
131 viOperator->setIgnoredRows(
true, callback);
135template<
typename ValueType,
typename SolutionType>
136void IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::extractScheduler(std::vector<SolutionType>& x, std::vector<ValueType>
const& b,
139 if (!this->schedulerChoices) {
140 this->schedulerChoices = std::vector<uint64_t>(x.size(), 0);
142 this->schedulerChoices->resize(x.size(), 0);
145 STORM_LOG_WARN_COND(viOperator,
"Expected VI operator to be initialized for scheduler extraction. Initializing now, but this is inefficient.");
150 schedHelper.computeScheduler(x, b, dir, *this->schedulerChoices, robust, updateX ? &x : nullptr);
153template<
typename ValueType,
typename SolutionType>
154bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::solveInducedEquationSystem(
155 Environment
const& env, std::unique_ptr<LinearEquationSolver<ValueType>>& linearEquationSolver, std::vector<uint64_t>
const& scheduler,
156 std::vector<SolutionType>& x, std::vector<ValueType>& subB, std::vector<ValueType>
const& originalB)
const {
157 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
158 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"We did not implement solving induced equation systems for interval-based models.");
162 STORM_LOG_ASSERT(subB.size() == x.size(),
"Sizes of subB and x do not coincide.");
163 STORM_LOG_ASSERT(this->linearEquationSolverFactory !=
nullptr,
"Wrong constructor was called.");
170 if (convertToEquationSystem) {
173 storm::utility::vector::selectVectorValues<ValueType>(subB, scheduler, this->A->getRowGroupIndices(), originalB);
176 if (!linearEquationSolver) {
178 linearEquationSolver = this->linearEquationSolverFactory->create(env, std::move(submatrix));
179 linearEquationSolver->setBoundsFromOtherSolver(*
this);
180 linearEquationSolver->setCachingEnabled(
true);
183 linearEquationSolver->setMatrix(std::move(submatrix));
186 return linearEquationSolver->solveEquations(env, x, subB);
190template<
typename ValueType,
typename SolutionType>
191bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::solveEquationsPolicyIteration(Environment
const& env,
OptimizationDirection dir,
192 std::vector<SolutionType>& x,
193 std::vector<ValueType>
const& b)
const {
194 std::vector<storm::storage::sparse::state_type> scheduler =
195 this->hasInitialScheduler() ? this->getInitialScheduler() :
std::vector<
storm::storage::sparse::
state_type>(this->A->getRowGroupCount());
196 return performPolicyIteration(env, dir, x, b, std::move(scheduler));
199template<
typename ValueType,
typename SolutionType>
200bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::performPolicyIteration(
201 Environment
const& env,
OptimizationDirection dir, std::vector<SolutionType>& x, std::vector<ValueType>
const& b,
202 std::vector<storm::storage::sparse::state_type>&& initialPolicy)
const {
203 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
204 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"We did not implement policy iteration for interval-based models.");
207 std::vector<storm::storage::sparse::state_type> scheduler = std::move(initialPolicy);
209 if (!auxiliaryRowGroupVector) {
210 auxiliaryRowGroupVector = std::make_unique<std::vector<ValueType>>(this->A->getRowGroupCount());
212 std::vector<ValueType>& subB = *auxiliaryRowGroupVector;
215 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver;
217 std::unique_ptr<storm::Environment> environmentOfSolverStorage;
218 auto precOfSolver = env.solver().getPrecisionOfLinearEquationSolver(env.solver().getLinearEquationSolverType());
220 bool changePrecision = precOfSolver.first && precOfSolver.first.get() > env.solver().minMax().getPrecision();
221 bool changeRelative = precOfSolver.second && !precOfSolver.second.get() && env.solver().minMax().getRelativeTerminationCriterion();
222 if (changePrecision || changeRelative) {
223 environmentOfSolverStorage = std::make_unique<storm::Environment>(env);
224 boost::optional<storm::RationalNumber> newPrecision;
225 boost::optional<bool> newRelative;
226 if (changePrecision) {
227 newPrecision = env.solver().minMax().getPrecision();
229 if (changeRelative) {
232 environmentOfSolverStorage->solver().setLinearEquationSolverPrecision(newPrecision, newRelative);
235 storm::Environment const& environmentOfSolver = environmentOfSolverStorage ? *environmentOfSolverStorage : env;
238 uint64_t iterations = 0;
239 this->startMeasureProgress();
242 solveInducedEquationSystem(environmentOfSolver, solver, scheduler, x, subB, b);
245 bool schedulerImproved =
false;
247 for (uint_fast64_t group = 0; group < this->A->getRowGroupCount(); ++group) {
248 if (!this->choiceFixedForRowGroup || !this->choiceFixedForRowGroup.get()[group]) {
250 uint_fast64_t currentChoice = scheduler[group];
251 for (uint_fast64_t choice = this->A->getRowGroupIndices()[group]; choice < this->A->getRowGroupIndices()[group + 1]; ++choice) {
253 if (choice - this->A->getRowGroupIndices()[group] == currentChoice) {
258 ValueType choiceValue = storm::utility::zero<ValueType>();
259 for (
auto const& entry : this->A->getRow(choice)) {
260 choiceValue += entry.getValue() * x[entry.getColumn()];
262 choiceValue += b[choice];
267 if (valueImproved(dir, x[group], choiceValue)) {
268 schedulerImproved =
true;
269 scheduler[group] = choice - this->A->getRowGroupIndices()[group];
270 x[group] = std::move(choiceValue);
277 if (!schedulerImproved) {
285 iterations, env.solver().minMax().getMaximalNumberOfIterations());
288 this->showProgressIterative(iterations);
292 this->reportStatus(status, iterations);
295 if (this->isTrackSchedulerSet()) {
296 this->schedulerChoices = std::move(scheduler);
299 if (!this->isCachingEnabled()) {
307template<
typename ValueType,
typename SolutionType>
308bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::valueImproved(
OptimizationDirection dir, ValueType
const& value1,
309 ValueType
const& value2)
const {
310 if (dir == OptimizationDirection::Minimize) {
311 return value2 < value1;
313 return value2 > value1;
317template<
typename ValueType,
typename SolutionType>
319 Environment const& env, boost::optional<storm::solver::OptimizationDirection>
const& direction,
bool const& hasInitialScheduler)
const {
323 bool needsLinEqSolver =
false;
324 needsLinEqSolver |= method == MinMaxMethod::PolicyIteration;
325 needsLinEqSolver |= method == MinMaxMethod::ValueIteration && (this->hasInitialScheduler() || hasInitialScheduler);
326 needsLinEqSolver |= method == MinMaxMethod::ViToPi;
329 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
330 STORM_LOG_ASSERT(!needsLinEqSolver,
"Intervals should not require a linear equation solver.");
332 }
else if (needsLinEqSolver) {
338 if (method == MinMaxMethod::ValueIteration) {
339 if (!this->hasUniqueSolution()) {
345 if (!direction || direction.get() == OptimizationDirection::Maximize) {
348 if (!direction || direction.get() == OptimizationDirection::Minimize) {
353 }
else if (method == MinMaxMethod::OptimisticValueIteration) {
355 if (!this->hasUniqueSolution()) {
360 }
else if (method == MinMaxMethod::IntervalIteration) {
362 if (!this->hasUniqueSolution()) {
366 }
else if (method == MinMaxMethod::RationalSearch) {
370 if (!this->hasUniqueSolution()) {
375 }
else if (method == MinMaxMethod::PolicyIteration) {
380 if (!this->hasNoEndComponents() && !this->hasInitialScheduler()) {
383 }
else if (method == MinMaxMethod::SoundValueIteration) {
384 if (!this->hasUniqueSolution()) {
388 }
else if (method == MinMaxMethod::ViToPi) {
390 if (!this->hasUniqueSolution()) {
394 STORM_LOG_THROW(
false, storm::exceptions::InvalidEnvironmentException,
"Unsupported technique for iterative MinMax linear equation solver.");
399template<
typename ValueType,
typename SolutionType>
401 ValueType result = storm::utility::zero<ValueType>();
402 auto oldValueIt = oldValues.begin();
403 for (
auto value : relevantValues) {
404 result = storm::utility::max<ValueType>(result, storm::utility::abs<ValueType>(allValues[value] - *oldValueIt));
410template<
typename ValueType,
typename SolutionType>
411ValueType
computeMaxAbsDiff(std::vector<ValueType>
const& allOldValues, std::vector<ValueType>
const& allNewValues,
413 ValueType result = storm::utility::zero<ValueType>();
414 for (
auto value : relevantValues) {
415 result = storm::utility::max<ValueType>(result, storm::utility::abs<ValueType>(allNewValues[value] - allOldValues[value]));
420template<
typename ValueType,
typename SolutionType>
422 std::vector<SolutionType>& x,
423 std::vector<ValueType>
const& b)
const {
424 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
425 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"We did not implement optimistic value iteration for interval-based models.");
430 x.assign(x.size(), storm::utility::zero<SolutionType>());
431 if (this->isTrackSchedulerSet()) {
432 this->schedulerChoices = std::vector<uint_fast64_t>(x.size(), 0);
439 helper::OptimisticValueIterationHelper<ValueType, false> oviHelper(viOperator);
441 std::optional<ValueType> lowerBound, upperBound;
442 if (this->hasLowerBound()) {
443 lowerBound = this->getLowerBound(
true);
445 if (this->hasUpperBound()) {
446 upperBound = this->getUpperBound(
true);
448 uint64_t numIterations{0};
449 auto oviCallback = [&](
SolverStatus const& current, std::vector<ValueType>
const& v) {
450 this->showProgressIterative(numIterations);
453 this->createLowerBoundsVector(x);
454 std::optional<ValueType> guessingFactor;
458 this->startMeasureProgress();
460 upperBound, oviCallback);
461 this->reportStatus(status, numIterations);
464 if (this->isTrackSchedulerSet()) {
465 this->extractScheduler(x, b, dir, this->isUncertaintyRobust());
468 if (!this->isCachingEnabled()) {
476template<
typename ValueType,
typename SolutionType>
477bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::solveEquationsValueIteration(Environment
const& env,
OptimizationDirection dir,
478 std::vector<SolutionType>& x,
479 std::vector<ValueType>
const& b)
const {
484 if (this->hasInitialScheduler()) {
485 if (!auxiliaryRowGroupVector) {
486 auxiliaryRowGroupVector = std::make_unique<std::vector<ValueType>>(this->A->getRowGroupCount());
489 std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> linEqSolver;
491 std::unique_ptr<storm::Environment> environmentOfSolverStorage;
492 auto precOfSolver = env.solver().getPrecisionOfLinearEquationSolver(env.solver().getLinearEquationSolverType());
494 bool changePrecision = precOfSolver.first && precOfSolver.first.get() > env.solver().minMax().getPrecision();
495 bool changeRelative = precOfSolver.second && !precOfSolver.second.get() && env.solver().minMax().getRelativeTerminationCriterion();
496 if (changePrecision || changeRelative) {
497 environmentOfSolverStorage = std::make_unique<storm::Environment>(env);
498 boost::optional<storm::RationalNumber> newPrecision;
499 boost::optional<bool> newRelative;
500 if (changePrecision) {
501 newPrecision = env.solver().minMax().getPrecision();
503 if (changeRelative) {
506 environmentOfSolverStorage->solver().setLinearEquationSolverPrecision(newPrecision, newRelative);
509 storm::Environment const& environmentOfSolver = environmentOfSolverStorage ? *environmentOfSolverStorage : env;
511 solveInducedEquationSystem(environmentOfSolver, linEqSolver, this->getInitialScheduler(), x, *auxiliaryRowGroupVector, b);
515 }
else if (!this->hasUniqueSolution()) {
517 this->createLowerBoundsVector(x);
520 this->createUpperBoundsVector(x);
523 }
else if (this->hasCustomTerminationCondition()) {
525 this->createLowerBoundsVector(x);
528 this->createUpperBoundsVector(x);
534 uint64_t numIterations{0};
536 this->showProgressIterative(numIterations);
537 return this->updateStatus(current, x, guarantee, numIterations, env.solver().minMax().getMaximalNumberOfIterations());
539 this->startMeasureProgress();
540 auto status = viHelper.VI(x, b, numIterations, env.solver().minMax().getRelativeTerminationCriterion(),
541 storm::utility::convertNumber<SolutionType>(env.solver().minMax().getPrecision()), dir, viCallback,
542 env.solver().minMax().getMultiplicationStyle(), this->isUncertaintyRobust());
543 this->reportStatus(status, numIterations);
546 if (this->isTrackSchedulerSet()) {
547 this->extractScheduler(x, b, dir, this->isUncertaintyRobust());
550 if (!this->isCachingEnabled()) {
557template<
typename ValueType,
typename SolutionType>
568template<
typename ValueType,
typename SolutionType>
570 std::vector<SolutionType>& x,
571 std::vector<ValueType>
const& b)
const {
572 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
573 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"We did not implement intervaliteration for interval-based models");
577 helper::IntervalIterationHelper<ValueType, false> iiHelper(viOperator);
579 auto lowerBoundsCallback = [&](std::vector<SolutionType>& vector) { this->createLowerBoundsVector(vector); };
580 auto upperBoundsCallback = [&](std::vector<SolutionType>& vector) { this->createUpperBoundsVector(vector); };
582 uint64_t numIterations{0};
583 auto iiCallback = [&](helper::IIData<ValueType>
const& data) {
584 this->showProgressIterative(numIterations);
585 bool terminateEarly = this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(data.x,
SolverGuarantee::LessOrEqual) &&
589 std::optional<storm::storage::BitVector> optionalRelevantValues;
590 if (this->hasRelevantValues()) {
591 optionalRelevantValues = this->getRelevantValues();
593 this->startMeasureProgress();
595 dir, iiCallback, optionalRelevantValues);
596 this->reportStatus(status, numIterations);
599 if (this->isTrackSchedulerSet()) {
600 this->extractScheduler(x, b, dir, this->isUncertaintyRobust());
603 if (!this->isCachingEnabled()) {
611template<
typename ValueType,
typename SolutionType>
612bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::solveEquationsSoundValueIteration(Environment
const& env,
OptimizationDirection dir,
613 std::vector<SolutionType>& x,
614 std::vector<ValueType>
const& b)
const {
615 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
616 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"SoundVI does not handle interval-based models");
620 assert(x.size() == this->A->getRowGroupCount());
622 std::optional<ValueType> lowerBound, upperBound;
623 if (this->hasLowerBound()) {
624 lowerBound = this->getLowerBound(
true);
626 if (this->hasUpperBound()) {
627 upperBound = this->getUpperBound(
true);
632 auto precision = storm::utility::convertNumber<ValueType>(env.solver().minMax().getPrecision());
633 uint64_t numIterations{0};
634 auto sviCallback = [&](
typename helper::SoundValueIterationHelper<ValueType, false>::SVIData
const& current) {
635 this->showProgressIterative(numIterations);
636 return this->updateStatus(current.status,
637 this->hasCustomTerminationCondition() && current.checkCustomTerminationCondition(this->getTerminationCondition()),
638 numIterations, env.solver().minMax().getMaximalNumberOfIterations());
640 this->startMeasureProgress();
641 helper::SoundValueIterationHelper<ValueType, false> sviHelper(viOperator);
642 std::optional<storm::storage::BitVector> optionalRelevantValues;
643 if (this->hasRelevantValues()) {
644 optionalRelevantValues = this->getRelevantValues();
646 auto status = sviHelper.SVI(x, b, numIterations, env.solver().minMax().getRelativeTerminationCriterion(), precision, dir, lowerBound, upperBound,
647 sviCallback, optionalRelevantValues);
650 if (this->isTrackSchedulerSet()) {
651 this->extractScheduler(x, b, dir, this->isUncertaintyRobust());
654 this->reportStatus(status, numIterations);
656 if (!this->isCachingEnabled()) {
664template<
typename ValueType,
typename SolutionType>
665bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::solveEquationsViToPi(Environment
const& env,
OptimizationDirection dir,
666 std::vector<SolutionType>& x, std::vector<ValueType>
const& b)
const {
667 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
668 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"ViToPi does not handle interval-based models");
672 std::vector<storm::storage::sparse::state_type> initialSched;
674 Environment viEnv = env;
675 viEnv.solver().minMax().setMethod(MinMaxMethod::ValueIteration);
676 viEnv.solver().setForceExact(
false);
677 viEnv.solver().setForceSoundness(
false);
678 auto impreciseSolver = GeneralMinMaxLinearEquationSolverFactory<double>().create(viEnv, this->A->template toValueType<double>());
679 impreciseSolver->setHasUniqueSolution(this->hasUniqueSolution());
680 impreciseSolver->setTrackScheduler(
true);
681 if (this->hasInitialScheduler()) {
682 auto initSched = this->getInitialScheduler();
683 impreciseSolver->setInitialScheduler(std::move(initSched));
685 auto impreciseSolverReq = impreciseSolver->getRequirements(viEnv, dir);
686 STORM_LOG_THROW(!impreciseSolverReq.hasEnabledCriticalRequirement(), storm::exceptions::UnmetRequirementException,
687 "The value-iteration based solver has an unmet requirement: " << impreciseSolverReq.getEnabledRequirementsAsString());
688 impreciseSolver->setRequirementsChecked(
true);
689 auto xVi = storm::utility::vector::convertNumericVector<double>(x);
690 auto bVi = storm::utility::vector::convertNumericVector<double>(b);
691 impreciseSolver->solveEquations(viEnv, dir, xVi, bVi);
692 initialSched = impreciseSolver->getSchedulerChoices();
694 STORM_LOG_INFO(
"Found initial policy using Value Iteration. Starting Policy iteration now.");
695 return performPolicyIteration(env, dir, x, b, std::move(initialSched));
698template<
typename ValueType,
typename SolutionType>
699bool IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>::solveEquationsRationalSearch(Environment
const& env,
OptimizationDirection dir,
700 std::vector<SolutionType>& x,
701 std::vector<ValueType>
const& b)
const {
702 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
703 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"Rational search does not handle interval-based models");
708 std::shared_ptr<helper::ValueIterationOperator<storm::RationalNumber, false>> exactOp;
709 std::shared_ptr<helper::ValueIterationOperator<double, false>> impreciseOp;
710 std::function<bool(uint64_t, uint64_t)> fixedChoicesCallback;
711 if (this->choiceFixedForRowGroup) {
713 assert(this->initialScheduler);
714 fixedChoicesCallback = [&](uint64_t groupIndex, uint64_t localRowIndex) {
715 return this->choiceFixedForRowGroup->get(groupIndex) && this->initialScheduler->at(groupIndex) != localRowIndex;
719 if constexpr (std::is_same_v<ValueType, storm::RationalNumber>) {
720 exactOp = viOperator;
721 impreciseOp = std::make_shared<helper::ValueIterationOperator<double, false>>();
722 impreciseOp->setMatrixBackwards(this->A->template toValueType<double>(), &this->A->getRowGroupIndices());
723 if (this->choiceFixedForRowGroup) {
724 impreciseOp->setIgnoredRows(
true, fixedChoicesCallback);
726 }
else if constexpr (std::is_same_v<ValueType, double>) {
727 impreciseOp = viOperator;
728 exactOp = std::make_shared<helper::ValueIterationOperator<storm::RationalNumber, false>>();
729 exactOp->setMatrixBackwards(this->A->template toValueType<storm::RationalNumber>(), &this->A->getRowGroupIndices());
730 if (this->choiceFixedForRowGroup) {
731 exactOp->setIgnoredRows(
true, fixedChoicesCallback);
736 uint64_t numIterations{0};
738 this->showProgressIterative(numIterations);
739 return this->updateStatus(current, x,
SolverGuarantee::None, numIterations, env.solver().minMax().getMaximalNumberOfIterations());
741 this->startMeasureProgress();
742 auto status = rsHelper.RS(x, b, numIterations, storm::utility::convertNumber<ValueType>(env.solver().minMax().getPrecision()), dir, rsCallback);
744 this->reportStatus(status, numIterations);
747 if (this->isTrackSchedulerSet()) {
748 this->extractScheduler(x, b, dir, this->isUncertaintyRobust());
751 if (!this->isCachingEnabled()) {
759template<
typename ValueType,
typename SolutionType>
761 auxiliaryRowGroupVector.reset();
SolverEnvironment & solver()
uint64_t const & getMaximalNumberOfIterations() const
storm::RationalNumber const & getPrecision() const
bool const & isMethodSetFromDefault() const
storm::solver::MinMaxMethod const & getMethod() const
bool isForceRequireUnique() const
bool const & getRelativeTerminationCriterion() const
std::optional< storm::RationalNumber > const & getUpperBoundGuessingFactor() const
OviSolverEnvironment const & ovi() const
MinMaxSolverEnvironment & minMax()
bool isForceExact() const
bool isForceSoundness() const
IterativeMinMaxLinearEquationSolver()
virtual void clearCache() const override
Clears the currently cached data that has been stored during previous calls of the solver.
virtual bool internalSolveEquations(Environment const &env, OptimizationDirection dir, std::vector< SolutionType > &x, std::vector< ValueType > const &b) const override
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.
virtual void clearCache() const
Clears the currently cached data that has been stored during previous calls of the solver.
MinMaxLinearEquationSolverRequirements & requireBounds(bool critical=true)
MinMaxLinearEquationSolverRequirements & requireUniqueSolution(bool critical=true)
MinMaxLinearEquationSolverRequirements & requireLowerBounds(bool critical=true)
MinMaxLinearEquationSolverRequirements & requireValidInitialScheduler(bool critical=true)
MinMaxLinearEquationSolverRequirements & requireUpperBounds(bool critical=true)
Implements rational search.
Helper class to extract optimal scheduler choices from a MinMax equation system solution.
A bit vector that is internally represented as a vector of 64-bit values.
A class that holds a possibly non-square matrix in the compressed row storage format.
void convertToEquationSystem()
Transforms the matrix into an equation system.
SparseMatrix selectRowsFromRowGroups(std::vector< index_type > const &rowGroupToRowIndexMapping, bool insertDiagonalEntries=true) const
Selects exactly one row from each row group of this matrix and returns the resulting matrix.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
bool constexpr maximize(OptimizationDirection d)
void preserveOldRelevantValues(std::vector< ValueType > const &allValues, storm::storage::BitVector const &relevantValues, std::vector< ValueType > &oldValues)
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
ValueType computeMaxAbsDiff(std::vector< ValueType > const &allValues, storm::storage::BitVector const &relevantValues, std::vector< ValueType > const &oldValues)
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...
bool hasNonZeroEntry(std::vector< T > const &v)