Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
AbstractEquationSolver.cpp
Go to the documentation of this file.
2
13
14namespace storm {
15namespace solver {
16
17template<typename ValueType>
23
24template<typename ValueType>
26 this->terminationCondition = std::move(terminationCondition);
27}
28
29template<typename ValueType>
31 this->terminationCondition = nullptr;
32}
33
34template<typename ValueType>
36 return static_cast<bool>(this->terminationCondition);
37}
38
39template<typename ValueType>
43
44template<typename ValueType>
45std::unique_ptr<TerminationCondition<ValueType>> const& AbstractEquationSolver<ValueType>::getTerminationConditionPointer() const {
46 return terminationCondition;
47}
48
49template<typename ValueType>
50bool AbstractEquationSolver<ValueType>::terminateNow(std::vector<ValueType> const& values, SolverGuarantee const& guarantee) const {
51 if (!this->hasCustomTerminationCondition()) {
52 return false;
53 }
54
55 return this->getTerminationCondition().terminateNow(values, guarantee);
56}
57
58template<typename ValueType>
60 return static_cast<bool>(relevantValues);
61}
62
63template<typename ValueType>
67
68template<typename ValueType>
69boost::optional<storm::storage::BitVector> const& AbstractEquationSolver<ValueType>::getOptionalRelevantValues() const {
70 return relevantValues;
71}
72
73template<typename ValueType>
75 this->relevantValues = std::move(relevantValues);
76}
77
78template<typename ValueType>
80 this->relevantValues = relevantValues;
81}
82
83template<typename ValueType>
85 relevantValues = boost::none;
86}
87
88template<typename ValueType>
90 if (type == BoundType::Any) {
91 return static_cast<bool>(lowerBound) || static_cast<bool>(lowerBounds);
92 } else if (type == BoundType::Global) {
93 return static_cast<bool>(lowerBound);
94 } else if (type == BoundType::Local) {
95 return static_cast<bool>(lowerBounds);
96 }
97 return false;
98}
99
100template<typename ValueType>
102 if (type == BoundType::Any) {
103 return static_cast<bool>(upperBound) || static_cast<bool>(upperBounds);
104 } else if (type == BoundType::Global) {
105 return static_cast<bool>(upperBound);
106 } else if (type == BoundType::Local) {
107 return static_cast<bool>(upperBounds);
108 }
109 return false;
110}
111
112template<typename ValueType>
114 lowerBound = value;
115}
116
117template<typename ValueType>
119 upperBound = value;
120}
121
122template<typename ValueType>
123void AbstractEquationSolver<ValueType>::setBounds(ValueType const& lower, ValueType const& upper) {
124 setLowerBound(lower);
125 setUpperBound(upper);
126}
127
128template<typename ValueType>
130 return lowerBound.get();
131}
132
133template<typename ValueType>
134ValueType const& AbstractEquationSolver<ValueType>::getLowerBound(uint64_t const& index) const {
135 if (lowerBounds) {
136 STORM_LOG_ASSERT(index < lowerBounds->size(), "Invalid row index " << index << " for vector of size " << lowerBounds->size());
137 if (lowerBound) {
138 return std::max(lowerBound.get(), lowerBounds.get()[index]);
139 } else {
140 return lowerBounds.get()[index];
141 }
142 } else {
143 STORM_LOG_ASSERT(lowerBound, "Lower bound requested but was not specified before.");
144 return lowerBound.get();
145 }
146}
147
148template<typename ValueType>
149ValueType AbstractEquationSolver<ValueType>::getLowerBound(bool convertLocalBounds) const {
150 if (lowerBound) {
151 return lowerBound.get();
152 } else if (convertLocalBounds) {
153 return *std::min_element(lowerBounds->begin(), lowerBounds->end());
154 }
155 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "No lower bound available but some was requested.");
156 return ValueType();
157}
158
159template<typename ValueType>
161 return upperBound.get();
162}
163
164template<typename ValueType>
165ValueType const& AbstractEquationSolver<ValueType>::getUpperBound(uint64_t const& index) const {
166 if (upperBounds) {
167 STORM_LOG_ASSERT(index < upperBounds->size(), "Invalid row index " << index << " for vector of size " << upperBounds->size());
168 if (upperBound) {
169 return std::min(upperBound.get(), upperBounds.get()[index]);
170 } else {
171 return upperBounds.get()[index];
172 }
173 } else {
174 STORM_LOG_ASSERT(upperBound, "Upper bound requested but was not specified before.");
175 return upperBound.get();
176 }
177}
178
179template<typename ValueType>
180ValueType AbstractEquationSolver<ValueType>::getUpperBound(bool convertLocalBounds) const {
181 if (upperBound) {
182 return upperBound.get();
183 } else if (convertLocalBounds) {
184 return *std::max_element(upperBounds->begin(), upperBounds->end());
185 }
186 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "No upper bound available but some was requested.");
187 return ValueType();
188}
189
190template<typename ValueType>
191std::vector<ValueType> const& AbstractEquationSolver<ValueType>::getLowerBounds() const {
192 return lowerBounds.get();
193}
194
195template<typename ValueType>
196std::vector<ValueType> const& AbstractEquationSolver<ValueType>::getUpperBounds() const {
197 return upperBounds.get();
198}
199
200template<typename ValueType>
201void AbstractEquationSolver<ValueType>::setLowerBounds(std::vector<ValueType> const& values) {
202 lowerBounds = values;
203}
204
205template<typename ValueType>
206void AbstractEquationSolver<ValueType>::setLowerBounds(std::vector<ValueType>&& values) {
207 lowerBounds = std::move(values);
208}
209
210template<typename ValueType>
211void AbstractEquationSolver<ValueType>::setUpperBounds(std::vector<ValueType> const& values) {
212 upperBounds = values;
213}
214
215template<typename ValueType>
216void AbstractEquationSolver<ValueType>::setUpperBounds(std::vector<ValueType>&& values) {
217 upperBounds = std::move(values);
218}
219
220template<typename ValueType>
221void AbstractEquationSolver<ValueType>::setBounds(std::vector<ValueType> const& lower, std::vector<ValueType> const& upper) {
222 setLowerBounds(lower);
223 setUpperBounds(upper);
224}
225
226template<typename ValueType>
228 if (other.hasLowerBound(BoundType::Global)) {
229 this->setLowerBound(other.getLowerBound());
230 }
231 if (other.hasLowerBound(BoundType::Local)) {
232 this->setLowerBounds(other.getLowerBounds());
233 }
234 if (other.hasUpperBound(BoundType::Global)) {
235 this->setUpperBound(other.getUpperBound());
236 }
237 if (other.hasUpperBound(BoundType::Local)) {
238 this->setUpperBounds(other.getUpperBounds());
239 }
240}
241
242template<typename ValueType>
244 lowerBound = boost::none;
245 upperBound = boost::none;
246 lowerBounds = boost::none;
247 upperBounds = boost::none;
248}
249
250template<typename ValueType>
251void AbstractEquationSolver<ValueType>::createLowerBoundsVector(std::vector<ValueType>& lowerBoundsVector) const {
252 if (this->hasLowerBound(BoundType::Local)) {
253 lowerBoundsVector = this->getLowerBounds();
254 } else {
255 ValueType lowerBound = this->hasLowerBound(BoundType::Global) ? this->getLowerBound() : storm::utility::zero<ValueType>();
256 for (auto& e : lowerBoundsVector) {
257 e = lowerBound;
258 }
259 }
260}
261
262template<typename ValueType>
263void AbstractEquationSolver<ValueType>::createUpperBoundsVector(std::vector<ValueType>& upperBoundsVector) const {
264 STORM_LOG_ASSERT(this->hasUpperBound(), "Expecting upper bound(s).");
265 if (this->hasUpperBound(BoundType::Global)) {
266 upperBoundsVector.assign(upperBoundsVector.size(), this->getUpperBound());
267 } else {
268 upperBoundsVector.assign(this->getUpperBounds().begin(), this->getUpperBounds().end());
269 }
270}
271
272template<typename ValueType>
273void AbstractEquationSolver<ValueType>::createUpperBoundsVector(std::unique_ptr<std::vector<ValueType>>& upperBoundsVector, uint64_t length) const {
274 STORM_LOG_ASSERT(this->hasUpperBound(), "Expecting upper bound(s).");
275 if (!upperBoundsVector) {
276 if (this->hasUpperBound(BoundType::Local)) {
277 STORM_LOG_ASSERT(length == this->getUpperBounds().size(), "Mismatching sizes.");
278 upperBoundsVector = std::make_unique<std::vector<ValueType>>(this->getUpperBounds());
279 } else {
280 upperBoundsVector = std::make_unique<std::vector<ValueType>>(length, this->getUpperBound());
281 }
282 } else {
283 createUpperBoundsVector(*upperBoundsVector);
284 }
285}
286
287template<typename ValueType>
289 return this->progressMeasurement.is_initialized();
290}
291
292template<typename ValueType>
294 STORM_LOG_ASSERT(this->isShowProgressSet(), "Tried to get the progress message delay but progress is not shown.");
295 return this->progressMeasurement->getShowProgressDelay();
296}
297
298template<typename ValueType>
299void AbstractEquationSolver<ValueType>::startMeasureProgress(uint64_t startingIteration) const {
300 if (this->isShowProgressSet()) {
301 this->progressMeasurement->startNewMeasurement(startingIteration);
302 }
303}
304
305template<typename ValueType>
306void AbstractEquationSolver<ValueType>::showProgressIterative(uint64_t iteration, boost::optional<uint64_t> const& bound) const {
307 if (this->isShowProgressSet()) {
308 if (bound) {
309 this->progressMeasurement->setMaxCount(bound.get());
310 }
311 this->progressMeasurement->updateProgress(iteration);
312 }
313}
314
315template<typename ValueType>
316void AbstractEquationSolver<ValueType>::reportStatus(SolverStatus status, boost::optional<uint64_t> const& iterations) const {
317 if (iterations) {
318 switch (status) {
320 STORM_LOG_TRACE("Iterative solver converged after " << iterations.get() << " iterations.");
321 break;
323 STORM_LOG_TRACE("Iterative solver terminated early after " << iterations.get() << " iterations.");
324 break;
326 STORM_LOG_WARN("Iterative solver did not converge after " << iterations.get() << " iterations.");
327 break;
329 STORM_LOG_WARN("Iterative solver was aborted after " << iterations.get() << " iterations.");
330 break;
331 default:
332 STORM_LOG_THROW(false, storm::exceptions::InvalidStateException, "Iterative solver terminated unexpectedly.");
333 }
334 } else {
335 switch (status) {
337 STORM_LOG_TRACE("Solver converged.");
338 break;
340 STORM_LOG_TRACE("Solver terminated early.");
341 break;
343 STORM_LOG_ASSERT(false, "Non-iterative solver should not exceed maximal number of iterations.");
344 STORM_LOG_WARN("Solver did not converge.");
345 break;
347 STORM_LOG_WARN("Solver was aborted.");
348 break;
349 default:
350 STORM_LOG_THROW(false, storm::exceptions::InvalidStateException, "Solver terminated unexpectedly.");
351 }
352 }
353}
354
355template<typename ValueType>
356SolverStatus AbstractEquationSolver<ValueType>::updateStatus(SolverStatus status, bool earlyTermination, uint64_t iterations,
357 uint64_t maximalNumberOfIterations) const {
358 if (status != SolverStatus::Converged) {
359 if (earlyTermination) {
361 } else if (iterations >= maximalNumberOfIterations) {
364 status = SolverStatus::Aborted;
365 }
366 }
367 return status;
368}
369
370template<typename ValueType>
371SolverStatus AbstractEquationSolver<ValueType>::updateStatus(SolverStatus status, std::vector<ValueType> const& x, SolverGuarantee const& guarantee,
372 uint64_t iterations, uint64_t maximalNumberOfIterations) const {
373 return this->updateStatus(status, this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(x, guarantee), iterations,
374 maximalNumberOfIterations);
375}
376
377template class AbstractEquationSolver<double>;
378
379#ifdef STORM_HAVE_CARL
382#endif
383
384} // namespace solver
385} // namespace storm
uint64_t getShowProgressDelay() const
Retrieves the delay between progress emissions.
void clearRelevantValues()
Removes the values of interest (if there were any).
void setUpperBound(ValueType const &value)
Sets an upper bound for the solution that can potentially be used by the solver.
void createLowerBoundsVector(std::vector< ValueType > &lowerBoundsVector) const
std::vector< ValueType > const & getLowerBounds() const
Retrieves a vector containing the lower bounds (if there are any).
bool hasUpperBound(BoundType const &type=BoundType::Any) const
Retrieves whether this solver has an upper bound.
bool hasLowerBound(BoundType const &type=BoundType::Any) const
Retrieves whether this solver has a lower bound.
void showProgressIterative(uint64_t iterations, boost::optional< uint64_t > const &bound=boost::none) const
Shows progress if this solver is asked to do so.
storm::storage::BitVector const & getRelevantValues() const
Retrieves the relevant values (if there are any).
std::unique_ptr< TerminationCondition< ValueType > > const & getTerminationConditionPointer() const
void setLowerBound(ValueType const &value)
Sets a lower bound for the solution that can potentially be used by the solver.
ValueType const & getUpperBound() const
Retrieves the upper bound (if there is any).
void setUpperBounds(std::vector< ValueType > const &values)
Sets upper bounds for the solution that can potentially be used by the solver.
void setRelevantValues(storm::storage::BitVector &&valuesOfInterest)
Sets the relevant values.
bool terminateNow(std::vector< ValueType > const &values, SolverGuarantee const &guarantee) const
Checks whether the solver can terminate wrt.
void setBounds(ValueType const &lower, ValueType const &upper)
Sets bounds for the solution that can potentially be used by the solver.
void startMeasureProgress(uint64_t startingIteration=0) const
Starts to measure progress.
void createUpperBoundsVector(std::vector< ValueType > &upperBoundsVector) const
void setBoundsFromOtherSolver(AbstractEquationSolver< ValueType > const &other)
void resetTerminationCondition()
Removes a previously set custom termination condition.
std::vector< ValueType > const & getUpperBounds() const
Retrieves a vector containing the upper bounds (if there are any).
bool isShowProgressSet() const
Retrieves whether progress is to be shown.
void clearBounds()
Removes all specified solution bounds.
TerminationCondition< ValueType > const & getTerminationCondition() const
Retrieves the custom termination condition (if any was set).
bool hasRelevantValues() const
Retrieves whether this solver has particularly relevant values.
bool hasCustomTerminationCondition() const
Retrieves whether a custom termination condition has been set.
boost::optional< storm::storage::BitVector > const & getOptionalRelevantValues() const
ValueType const & getLowerBound() const
Retrieves the lower bound (if there is any).
void setTerminationCondition(std::unique_ptr< TerminationCondition< ValueType > > terminationCondition)
Sets a custom termination condition that is used together with the regular termination condition of t...
SolverStatus updateStatus(SolverStatus status, std::vector< ValueType > const &x, SolverGuarantee const &guarantee, uint64_t iterations, uint64_t maximalNumberOfIterations) const
Update the status of the solver with respect to convergence, early termination, abortion,...
void reportStatus(SolverStatus status, boost::optional< uint64_t > const &iterations=boost::none) const
Report the current status of the solver.
void setLowerBounds(std::vector< ValueType > const &values)
Sets lower bounds for the solution that can potentially be used by the solver.
virtual bool terminateNow(std::vector< ValueType > const &currentValues, SolverGuarantee const &guarantee=SolverGuarantee::None) const
Retrieves whether the guarantee provided by the solver for the current result is sufficient to termin...
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
A class that provides convenience operations to display run times.
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SettingsType const & getModule()
Get module.
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
LabParser.cpp.
Definition cli.cpp:18