Storm 1.11.1.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>
22 : direction(direction),
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 {
40 STORM_LOG_WARN_COND_DEBUG(this->isRequirementsCheckedSet(),
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 return internalSolveEquations(env, d, x, b);
44}
45
46template<typename ValueType, typename SolutionType>
48 std::vector<ValueType> const& b) const {
49 STORM_LOG_THROW(isSet(this->direction), storm::exceptions::IllegalFunctionCallException, "Optimization direction not set.");
50 STORM_LOG_THROW(isSet(this->uncertaintyResolutionMode) || !storm::IsIntervalType<ValueType>, storm::exceptions::IllegalFunctionCallException,
51 "Uncertainty resolution mode not set.");
52 solveEquations(env, convert(this->direction), x, b);
53}
54
55template<typename ValueType, typename SolutionType>
59
60template<typename ValueType, typename SolutionType>
64
65template<typename ValueType, typename SolutionType>
69
70template<typename ValueType, typename SolutionType>
72 return uniqueSolution || noEndComponents;
74
75template<typename ValueType, typename SolutionType>
79
80template<typename ValueType, typename SolutionType>
84
85template<typename ValueType, typename SolutionType>
87 this->trackScheduler = trackScheduler;
88 if (!this->trackScheduler) {
89 schedulerChoices = boost::none;
90 }
91}
92
93template<typename ValueType, typename SolutionType>
95 return this->trackScheduler;
96}
97
98template<typename ValueType, typename SolutionType>
100 return static_cast<bool>(schedulerChoices);
101}
102
103template<typename ValueType, typename SolutionType>
105 STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve scheduler, because none was generated.");
106 storm::storage::Scheduler<ValueType> result(schedulerChoices->size());
107 uint_fast64_t state = 0;
108 for (auto const& schedulerChoice : schedulerChoices.get()) {
109 result.setChoice(schedulerChoice, state);
110 ++state;
111 }
112 return result;
114
115template<typename ValueType, typename SolutionType>
117 STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException, "Cannot retrieve scheduler choices, because they were not generated.");
118 return schedulerChoices.get();
120
121template<typename ValueType, typename SolutionType>
123 STORM_LOG_THROW(hasScheduler(), storm::exceptions::IllegalFunctionCallException,
124 "Cannot retrieve robust index into scheduler choices, because they were not generated.");
125 return robustSchedulerIndex.get();
126}
127
128template<typename ValueType, typename SolutionType>
130 if (cachingEnabled && !value) {
131 // caching will be turned off. Hence we clear the cache at this point
132 clearCache();
133 }
134 cachingEnabled = value;
135}
136
137template<typename ValueType, typename SolutionType>
139 return cachingEnabled;
140}
141
142template<typename ValueType, typename SolutionType>
144 // Intentionally left empty.
145}
146
147template<typename ValueType, typename SolutionType>
149 initialScheduler = std::move(choices);
151
152template<typename ValueType, typename SolutionType>
154 return static_cast<bool>(initialScheduler);
156
157template<typename ValueType, typename SolutionType>
159 return initialScheduler.get();
161
162template<typename ValueType, typename SolutionType>
164 Environment const&, boost::optional<storm::solver::OptimizationDirection> const& direction, bool const& hasInitialScheduler) const {
166}
167
168template<typename ValueType, typename SolutionType>
170 this->requirementsChecked = value;
171}
172
173template<typename ValueType, typename SolutionType>
175 return requirementsChecked;
176}
177
178template<typename ValueType, typename SolutionType>
180 STORM_LOG_ASSERT(this->hasInitialScheduler(), "Expecting an initial scheduler to be set before setting the states for which the choices are fixed");
181 this->choiceFixedForRowGroup = std::move(schedulerFixedForRowGroup);
182}
183
184template<typename ValueType, typename SolutionType>
186 // Intentionally left empty
187}
188
189template<typename ValueType, typename SolutionType>
191 this->requirementsChecked = value;
192}
193
194template<typename ValueType, typename SolutionType>
196 return this->requirementsChecked;
197}
198
199template<typename ValueType, typename SolutionType>
201 this->uncertaintyResolutionMode = uncertaintyResolutionMode;
202}
203
204template<typename ValueType, typename SolutionType>
208
209template<typename ValueType, typename SolutionType>
211 Environment const& env, bool hasUniqueSolution, bool hasNoEndComponents, boost::optional<storm::solver::OptimizationDirection> const& direction,
212 bool hasInitialScheduler, bool trackScheduler) const {
213 // Create dummy solver and ask it for requirements.
214 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = this->create(env);
215 solver->setTrackScheduler(trackScheduler);
216 solver->setHasUniqueSolution(hasUniqueSolution);
217 solver->setHasNoEndComponents(hasNoEndComponents);
218 return solver->getRequirements(env, direction, hasInitialScheduler);
219}
220
221template<typename ValueType, typename SolutionType>
222std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> MinMaxLinearEquationSolverFactory<ValueType, SolutionType>::create(
223 Environment const& env, storm::storage::SparseMatrix<ValueType> const& matrix) const {
224 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = this->create(env);
225 solver->setMatrix(matrix);
226 return solver;
227}
228
229template<typename ValueType, typename SolutionType>
230std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> MinMaxLinearEquationSolverFactory<ValueType, SolutionType>::create(
231 Environment const& env, storm::storage::SparseMatrix<ValueType>&& matrix) const {
232 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> solver = this->create(env);
233 solver->setMatrix(std::move(matrix));
234 return solver;
235}
236
237template<typename ValueType, typename SolutionType>
242
243template<typename ValueType, typename SolutionType>
244std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> GeneralMinMaxLinearEquationSolverFactory<ValueType, SolutionType>::create(
245 Environment const& env) const {
246 std::unique_ptr<MinMaxLinearEquationSolver<ValueType, SolutionType>> result;
247 // TODO some minmax linear equation solvers only support SolutionType == ValueType.
249 if (method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch ||
250 method == MinMaxMethod::IntervalIteration || method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::OptimisticValueIteration ||
251 method == MinMaxMethod::GuessingValueIteration || method == MinMaxMethod::ViToPi) {
252 result = std::make_unique<IterativeMinMaxLinearEquationSolver<ValueType, SolutionType>>(
253 std::make_unique<GeneralLinearEquationSolverFactory<SolutionType>>());
254 } else if (method == MinMaxMethod::Topological) {
255 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
256 STORM_LOG_ERROR("Topological method not implemented for ValueType==Interval.");
257 } else {
258 result = std::make_unique<TopologicalMinMaxLinearEquationSolver<ValueType, SolutionType>>();
259 }
260 } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) {
261 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
262 STORM_LOG_ERROR("LP method not implemented for ValueType==Interval.");
263 } else {
264 result = std::make_unique<LpMinMaxLinearEquationSolver<ValueType>>(storm::utility::solver::getLpSolverFactory<ValueType>());
265 }
266 } else if (method == MinMaxMethod::Acyclic) {
267 if constexpr (std::is_same_v<ValueType, storm::Interval>) {
268 STORM_LOG_ERROR("Acyclic method not implemented for ValueType==Interval");
269 } else {
270 result = std::make_unique<AcyclicMinMaxLinearEquationSolver<ValueType>>();
271 }
272 } else {
273 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unsupported technique.");
274 }
275 result->setRequirementsChecked(this->isRequirementsCheckedSet());
276 return result;
277}
278
279template<>
280std::unique_ptr<MinMaxLinearEquationSolver<storm::RationalNumber>> GeneralMinMaxLinearEquationSolverFactory<storm::RationalNumber>::create(
281 Environment const& env) const {
282 std::unique_ptr<MinMaxLinearEquationSolver<storm::RationalNumber>> result;
283 auto method = getMethod(env);
284 if (method == MinMaxMethod::ValueIteration || method == MinMaxMethod::PolicyIteration || method == MinMaxMethod::RationalSearch ||
285 method == MinMaxMethod::IntervalIteration || method == MinMaxMethod::SoundValueIteration || method == MinMaxMethod::OptimisticValueIteration ||
286 method == MinMaxMethod::GuessingValueIteration || method == MinMaxMethod::ViToPi) {
287 result = std::make_unique<IterativeMinMaxLinearEquationSolver<storm::RationalNumber>>(
288 std::make_unique<GeneralLinearEquationSolverFactory<storm::RationalNumber>>());
289 } else if (method == MinMaxMethod::LinearProgramming || method == MinMaxMethod::ViToLp) {
290 result = std::make_unique<LpMinMaxLinearEquationSolver<storm::RationalNumber>>(storm::utility::solver::getLpSolverFactory<storm::RationalNumber>());
291 } else if (method == MinMaxMethod::Acyclic) {
292 result = std::make_unique<AcyclicMinMaxLinearEquationSolver<storm::RationalNumber>>();
293 } else if (method == MinMaxMethod::Topological) {
294 result = std::make_unique<TopologicalMinMaxLinearEquationSolver<storm::RationalNumber>>();
295 } else {
296 STORM_LOG_THROW(false, storm::exceptions::InvalidSettingsException, "Unsupported technique.");
297 }
298 result->setRequirementsChecked(this->isRequirementsCheckedSet());
299 return result;
300}
301
302template<typename ValueType, typename SolutionType>
304 // Default to robust value iteration in case of interval models.
305 auto method = env.solver().minMax().getMethod();
306 if (storm::IsIntervalType<ValueType> && method != MinMaxMethod::ValueIteration) {
307 STORM_LOG_WARN("Selected method is not supported for this solver and interval models, switching to robust value iteration.");
308 method = MinMaxMethod::ValueIteration;
309 }
310 return method;
311}
312
314
317
321
325} // namespace storm::solver
SolverEnvironment & solver()
storm::solver::MinMaxMethod const & getMethod() const
MinMaxSolverEnvironment & minMax()
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)
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.
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.
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.
void setCachingEnabled(bool value)
Sets whether some of the generated data during solver calls should be cached.
bool isRequirementsCheckedSet() const
Retrieves whether the solver is aware that the requirements were checked.
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:25
#define STORM_LOG_ERROR(message)
Definition logging.h:26
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_LOG_WARN_COND_DEBUG(cond, message)
Definition macros.h:18
OptimizationDirection convert(OptimizationDirectionSetting s)
bool isSet(OptimizationDirectionSetting s)