Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
MinMaxLinearEquationSolver.cpp
Go to the documentation of this file.
2
3#include <memory>
4
17
18namespace storm::solver {
19
20template<typename ValueType, typename SolutionType>
23 trackScheduler(false),
24 uniqueSolution(false),
25 noEndComponents(false),
26 cachingEnabled(false),
27 requirementsChecked(false),
28 uncertaintyResolutionMode(UncertaintyResolutionMode::Unset) {
29 // Intentionally left empty.
30}
31
32template<typename ValueType, typename SolutionType>
36
37template<typename ValueType, typename SolutionType>
39 std::vector<ValueType> const& b) const {
41 "The requirements of the solver have not been marked as checked. Please provide the appropriate check or mark the requirements "
42 "as checked (if applicable).");
43 // A reused solver must not report bounds that a previous call computed.
44 this->clearSolutionBounds();
45 bool const result = internalSolveEquations(env, d, x, b);
46 if (result) {
48 }
49 return result;
50}
51
52template<typename ValueType, typename SolutionType>
54 std::vector<ValueType> const& b) const {
55 STORM_LOG_THROW(isSet(this->direction), storm::exceptions::IllegalFunctionCallException, "Optimization direction not set.");
56 STORM_LOG_THROW(isSet(this->uncertaintyResolutionMode) || !storm::IsIntervalType<ValueType>, storm::exceptions::IllegalFunctionCallException,
57 "Uncertainty resolution mode not set.");
58 solveEquations(env, convert(this->direction), x, b);
59}
60
61template<typename ValueType, typename SolutionType>
65
66template<typename ValueType, typename SolutionType>
69}
70
71template<typename ValueType, typename SolutionType>
73 uniqueSolution = value;
74}
75
76template<typename ValueType, typename SolutionType>
78 return uniqueSolution || noEndComponents;
79}
80
81template<typename ValueType, typename SolutionType>
83 noEndComponents = value;
84}
85
86template<typename ValueType, typename SolutionType>
90
91template<typename ValueType, typename SolutionType>
93 this->trackScheduler = trackScheduler;
94 if (!this->trackScheduler) {
95 schedulerChoices = boost::none;
96 }
97}
98
99template<typename ValueType, typename SolutionType>
101 return this->trackScheduler;
102}
104template<typename ValueType, typename SolutionType>
109template<typename ValueType, typename SolutionType>
111 STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve scheduler, because none was generated.");
113 uint_fast64_t state = 0;
114 for (auto const& schedulerChoice : schedulerChoices.get()) {
115 result.setChoice(schedulerChoice, state);
116 ++state;
117 }
118 return result;
120
121template<typename ValueType, typename SolutionType>
123 STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve scheduler choices, because they were not generated.");
124 return schedulerChoices.get();
125}
126
127template<typename ValueType, typename SolutionType>
129 STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException,
130 "Cannot retrieve robust index into scheduler choices, because they were not generated.");
131 return robustSchedulerIndex.get();
132}
133
134template<typename ValueType, typename SolutionType>
136 if (cachingEnabled && !value) {
137 // caching will be turned off. Hence we clear the cache at this point
138 clearCache();
140 cachingEnabled = value;
141}
142
143template<typename ValueType, typename SolutionType>
145 return cachingEnabled;
146}
147
148template<typename ValueType, typename SolutionType>
150 // Intentionally left empty.
151}
152
153template<typename ValueType, typename SolutionType>
155 initialScheduler = std::move(choices);
156}
157
158template<typename ValueType, typename SolutionType>
160 return static_cast<bool>(initialScheduler);
161}
162
163template<typename ValueType, typename SolutionType>
165 return initialScheduler.get();
166}
167
168template<typename ValueType, typename SolutionType>
170 Environment const&, boost::optional<storm::solver::OptimizationDirection> const& direction, bool const& hasInitialScheduler) const {
172}
173
174template<typename ValueType, typename SolutionType>
176 this->requirementsChecked = value;
177}
178
179template<typename ValueType, typename SolutionType>
181 return requirementsChecked;
182}
183
184template<typename ValueType, typename SolutionType>
186 STORM_LOG_ASSERT(this->hasInitialScheduler(), "Expecting an initial scheduler to be set before setting the states for which the choices are fixed.");
187 this->choiceFixedForRowGroup = std::move(schedulerFixedForRowGroup);
188}
190template<typename ValueType, typename SolutionType>
192 // Intentionally left empty
193}
195template<typename ValueType, typename SolutionType>
197 this->requirementsChecked = value;
198}
199
200template<typename ValueType, typename SolutionType>
202 return this->requirementsChecked;
203}
204
205template<typename ValueType, typename SolutionType>
207 this->uncertaintyResolutionMode = uncertaintyResolutionMode;
208}
209
210template<typename ValueType, typename SolutionType>
214
215template<typename ValueType, typename SolutionType>
217 Environment const& env, bool hasUniqueSolution, bool hasNoEndComponents, boost::optional<storm::solver::OptimizationDirection> const& direction,
218 bool hasInitialScheduler, bool trackScheduler) const {
219 // Create dummy solver and ask it for requirements.
220 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = this->create(env);
221 solver->setTrackScheduler(trackScheduler);
222 solver->setHasUniqueSolution(hasUniqueSolution);
223 solver->setHasNoEndComponents(hasNoEndComponents);
224 return solver->getRequirements(env, direction, hasInitialScheduler);
225}
226
227template<typename ValueType, typename SolutionType>
228std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> MinMaxLinearEquationSolverFactory<ValueType, SolutionType>::create(
229 Environment const& env, storm::storage::SparseMatrix<ValueType> const& matrix) const {
230 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = this->create(env);
231 solver->setMatrix(matrix);
232 return solver;
233}
234
235template<typename ValueType, typename SolutionType>
236std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> MinMaxLinearEquationSolverFactory<ValueType, SolutionType>::create(
237 Environment const& env, storm::storage::SparseMatrix<ValueType>&& matrix) const {
238 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = this->create(env);
239 solver->setMatrix(std::move(matrix));
240 return solver;
241}
242
243template<typename ValueType, typename SolutionType>
245 : MinMaxLinearEquationSolverFactory<ValueType, SolutionType>() {
246 // Intentionally left empty.
247}
248
249template<typename ValueType, typename SolutionType>
250std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> GeneralMinMaxLinearEquationSolverFactory<ValueType, SolutionType>::create(
251 Environment const& env) const {
252 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> result;
253 // TODO some minmax linear equation solvers only support SolutionType == ValueType.
255 if (method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch ||
256 method == MinMaxMethod::IntervalIteration || method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::OptimisticValueIteration ||
257 method == MinMaxMethod::GuessingValueIteration || method == MinMaxMethod::ViToPi) {
258 result = std::make_unique<IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>>(
259 std::make_unique<GeneralLinearEquationSolverFactory<SolutionType>>());
260 } else if (method == MinMaxMethod::Topological) {
262 STORM_LOG_ERROR("Topological method not implemented for ValueType==Interval.");
263 } else {
264 result = std::make_unique<TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>>();
265 }
266 } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) {
267 if constexpr (storm::IsIntervalType<ValueType>) {
268 STORM_LOG_ERROR("LP method not implemented for ValueType==Interval.");
269 } else {
270 result = std::make_unique<LpMinMaxLinearEquationSolver<ValueType>>(storm::utility::solver::getLpSolverFactory<ValueType>(env));
271 }
272 } else if (method == MinMaxMethod::Acyclic) {
273 if constexpr (storm::IsIntervalType<ValueType>) {
274 STORM_LOG_ERROR("Acyclic method not implemented for ValueType==Interval");
275 } else {
276 result = std::make_unique<AcyclicMinMaxLinearEquationSolver<ValueType>>();
277 }
278 } else {
279 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unsupported technique.");
280 }
281 result->setRequirementsChecked(this->isRequirementsCheckedSet());
282 result->setShowProgress(env.solver().isVerboseSet(), env.solver().getShowProgressDelay());
283 return result;
284}
285
286template<>
287std::unique_ptr<MinMaxLinearEquationSolver<storm::RationalNumber>> GeneralMinMaxLinearEquationSolverFactory<storm::RationalNumber>::create(
288 Environment const& env) const {
289 std::unique_ptr<MinMaxLinearEquationSolver<storm::RationalNumber>> result;
290 auto method = getMethod(env);
291 if (method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch ||
292 method == MinMaxMethod::IntervalIteration || method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::OptimisticValueIteration ||
293 method == MinMaxMethod::GuessingValueIteration || method == MinMaxMethod::ViToPi) {
294 result = std::make_unique<IterativeMinMaxLinearEquationSolver<storm::RationalNumber>>(
295 std::make_unique<GeneralLinearEquationSolverFactory<storm::RationalNumber>>());
296 } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) {
297 result = std::make_unique<LpMinMaxLinearEquationSolver<storm::RationalNumber>>(storm::utility::solver::getLpSolverFactory<storm::RationalNumber>(env));
298 } else if (method == MinMaxMethod::Acyclic) {
299 result = std::make_unique<AcyclicMinMaxLinearEquationSolver<storm::RationalNumber>>();
300 } else if (method == MinMaxMethod::Topological) {
301 result = std::make_unique<TopologicalMinMaxLinearEquationSolver<storm::RationalNumber>>();
302 } else {
303 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unsupported technique.");
304 }
305 result->setRequirementsChecked(this->isRequirementsCheckedSet());
306 result->setShowProgress(env.solver().isVerboseSet(), env.solver().getShowProgressDelay());
307 return result;
308}
309
310template<typename ValueType, typename SolutionType>
312 // Default to robust value iteration in case of interval models.
313 auto method = env.solver().minMax().getMethod();
314 if (storm::IsIntervalType<ValueType> && method != MinMaxMethod::ValueIteration) {
315 STORM_LOG_WARN("Selected method is not supported for this solver and interval models, switching to robust value iteration.");
316 method = MinMaxMethod::ValueIteration;
317 }
318 return method;
319}
320
322
325
329
333
337} // namespace storm::solver
SolverEnvironment & solver()
storm::solver::MinMaxMethod const & getMethod() const
MinMaxSolverEnvironment & minMax()
uint64_t getShowProgressDelay() const
void finalizeSolutionBounds(std::vector< ValueType > const &x) 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.
std::unique_ptr< MinMaxLinearEquationSolver< ValueType, SolutionType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix) const
A class representing the interface that all min-max linear equation solvers shall implement.
virtual void setSchedulerFixedForRowGroup(storm::storage::BitVector &&schedulerFixedForRowGroup)
Sets the states for which the choices are fixed.
void unsetOptimizationDirection()
Unsets the optimization direction to use for calls to methods that do not explicitly provide one.
storm::storage::Scheduler< ValueType > computeScheduler() const
Retrieves the generated scheduler.
void setHasUniqueSolution(bool value=true)
Sets whether the solution to the min max equation system is known to be unique.
bool solveEquations(Environment const &env, OptimizationDirection d, std::vector< SolutionType > &x, std::vector< ValueType > const &b) const
Solves the equation system x = min/max(A*x + b) given by the parameters.
virtual void clearCache() const
Clears the currently cached data that has been stored during previous calls of the solver.
void setOptimizationDirection(OptimizationDirection direction)
Sets an optimization direction to use for calls to methods that do not explicitly provide one.
MinMaxLinearEquationSolver(OptimizationDirectionSetting direction=OptimizationDirectionSetting::Unset)
OptimizationDirectionSetting direction
The optimization direction to use for calls to functions that do not provide it explicitly....
void setInitialScheduler(std::vector< uint_fast64_t > &&choices)
Sets a valid initial scheduler that is required by some solvers (see requirements of solvers).
bool hasScheduler() const
Retrieves whether the solver generated a scheduler.
std::vector< uint_fast64_t > const & getSchedulerChoices() const
Retrieves the generated (deterministic) choices of the optimal scheduler.
std::vector< uint_fast64_t > const & getInitialScheduler() const
Retrieves the initial scheduler if one was set.
bool trackScheduler
Whether we generate a scheduler during solving.
void setRequirementsChecked(bool value=true)
Notifies the solver that the requirements for solving equations have been checked.
bool hasUniqueSolution() const
Retrieves whether the solution to the min max equation system is assumed to be unique.
virtual MinMaxLinearEquationSolverRequirements getRequirements(Environment const &env, boost::optional< storm::solver::OptimizationDirection > const &direction=boost::none, bool const &hasInitialScheduler=false) const
Retrieves the requirements of this solver for solving equations with the current settings.
boost::optional< storm::storage::BitVector > choiceFixedForRowGroup
void setHasNoEndComponents(bool value=true)
Sets whether the min max equation system is known to not have any end components.
std::vector< uint_fast64_t > const & getRobustSchedulerIndex() const
Retrieves the generated robust index into the scheduler.
void setUncertaintyResolutionMode(UncertaintyResolutionMode uncertaintyResolutionMode)
Sets how the uncertainty should be resolved.
UncertaintyResolutionMode getUncertaintyResolutionMode() const
Retrieves the mode indicating how the uncertainty should be resolved.
bool isTrackSchedulerSet() const
Retrieves whether this solver is set to generate schedulers.
bool hasNoEndComponents() const
Retrieves whether the min max equation system is known to not have any end components.
virtual bool internalSolveEquations(Environment const &env, OptimizationDirection d, std::vector< ValueType > &x, std::vector< ValueType > const &b) const=0
void setCachingEnabled(bool value)
Sets whether some of the generated data during solver calls should be cached.
bool isCachingEnabled() const
Retrieves whether some of the generated data during solver calls should be cached.
bool hasInitialScheduler() const
Returns true iff an initial scheduler is set.
void setTrackScheduler(bool trackScheduler=true)
Sets whether schedulers are generated when solving equation systems.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
This class defines which action is chosen in a particular state of a non-deterministic model.
Definition Scheduler.h:18
void setChoice(SchedulerChoice< ValueType > const &choice, uint_fast64_t modelState, uint_fast64_t memoryState=0)
Sets the choice defined by the scheduler for the given state.
Definition Scheduler.cpp:38
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_WARN(message)
Definition logging.h:35
#define STORM_LOG_ERROR(message)
Definition logging.h:36
#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
OptimizationDirection convert(OptimizationDirectionSetting s)
bool isSet(OptimizationDirectionSetting s)
std::unique_ptr< LpSolverFactory< ValueType > > getLpSolverFactory(storm::Environment const &env, storm::solver::LpSolverTypeSelection solvType)
Definition solver.cpp:114
constexpr bool IsIntervalType
Helper to check if a type is an interval.