Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
AbstractEquationSolver.cpp
Go to the documentation of this file.
2
11
12namespace storm {
13namespace solver {
14
15template<typename ValueType>
17 if (storm::settings::getModule<storm::settings::modules::GeneralSettings>().isVerboseSet()) {
18 this->progressMeasurement = storm::utility::ProgressMeasurement("iterations");
19 }
20}
21
22template<typename ValueType>
24 this->terminationCondition = std::move(terminationCondition);
25}
26
27template<typename ValueType>
29 this->terminationCondition = nullptr;
30}
31
32template<typename ValueType>
34 return static_cast<bool>(this->terminationCondition);
35}
36
37template<typename ValueType>
41
42template<typename ValueType>
43std::unique_ptr<TerminationCondition<ValueType>> const& AbstractEquationSolver<ValueType>::getTerminationConditionPointer() const {
44 return terminationCondition;
45}
46
47template<typename ValueType>
48bool AbstractEquationSolver<ValueType>::terminateNow(std::vector<ValueType> const& values, SolverGuarantee const& guarantee) const {
49 if (!this->hasCustomTerminationCondition()) {
50 return false;
51 }
52
53 return this->getTerminationCondition().terminateNow(values, guarantee);
54}
55
56template<typename ValueType>
58 return static_cast<bool>(relevantValues);
59}
60
61template<typename ValueType>
65
66template<typename ValueType>
67boost::optional<storm::storage::BitVector> const& AbstractEquationSolver<ValueType>::getOptionalRelevantValues() const {
68 return relevantValues;
69}
70
71template<typename ValueType>
73 this->relevantValues = std::move(relevantValues);
74}
75
76template<typename ValueType>
78 this->relevantValues = relevantValues;
79}
80
81template<typename ValueType>
83 relevantValues = boost::none;
84}
85
86template<typename ValueType>
88 if (type == BoundType::Any) {
89 return static_cast<bool>(lowerBound) || static_cast<bool>(lowerBounds);
90 } else if (type == BoundType::Global) {
91 return static_cast<bool>(lowerBound);
92 } else if (type == BoundType::Local) {
93 return static_cast<bool>(lowerBounds);
94 }
95 return false;
96}
97
98template<typename ValueType>
100 if (type == BoundType::Any) {
101 return static_cast<bool>(upperBound) || static_cast<bool>(upperBounds);
102 } else if (type == BoundType::Global) {
103 return static_cast<bool>(upperBound);
104 } else if (type == BoundType::Local) {
105 return static_cast<bool>(upperBounds);
106 }
107 return false;
108}
109
110template<typename ValueType>
112 lowerBound = value;
113}
114
115template<typename ValueType>
117 upperBound = value;
118}
119
120template<typename ValueType>
121void AbstractEquationSolver<ValueType>::setBounds(ValueType const& lower, ValueType const& upper) {
122 setLowerBound(lower);
123 setUpperBound(upper);
124}
125
126template<typename ValueType>
128 return lowerBound.get();
129}
130
131template<typename ValueType>
132ValueType const& AbstractEquationSolver<ValueType>::getLowerBound(uint64_t const& index) const {
133 if (lowerBounds) {
134 STORM_LOG_ASSERT(index < lowerBounds->size(), "Invalid row index " << index << " for vector of size " << lowerBounds->size());
135 if (lowerBound) {
136 return std::max(lowerBound.get(), lowerBounds.get()[index]);
137 } else {
138 return lowerBounds.get()[index];
139 }
140 } else {
141 STORM_LOG_ASSERT(lowerBound, "Lower bound requested but was not specified before.");
142 return lowerBound.get();
143 }
144}
145
146template<typename ValueType>
147ValueType AbstractEquationSolver<ValueType>::getLowerBound(bool convertLocalBounds) const {
148 if (lowerBound) {
149 return lowerBound.get();
150 } else if (convertLocalBounds) {
151 return *std::min_element(lowerBounds->begin(), lowerBounds->end());
152 }
153 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "No lower bound available but some was requested.");
154 return ValueType();
155}
156
157template<typename ValueType>
159 return upperBound.get();
160}
161
162template<typename ValueType>
163ValueType const& AbstractEquationSolver<ValueType>::getUpperBound(uint64_t const& index) const {
164 if (upperBounds) {
165 STORM_LOG_ASSERT(index < upperBounds->size(), "Invalid row index " << index << " for vector of size " << upperBounds->size());
166 if (upperBound) {
167 return std::min(upperBound.get(), upperBounds.get()[index]);
168 } else {
169 return upperBounds.get()[index];
170 }
171 } else {
172 STORM_LOG_ASSERT(upperBound, "Upper bound requested but was not specified before.");
173 return upperBound.get();
174 }
175}
176
177template<typename ValueType>
178ValueType AbstractEquationSolver<ValueType>::getUpperBound(bool convertLocalBounds) const {
179 if (upperBound) {
180 return upperBound.get();
181 } else if (convertLocalBounds) {
182 return *std::max_element(upperBounds->begin(), upperBounds->end());
183 }
184 STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "No upper bound available but some was requested.");
185 return ValueType();
186}
187
188template<typename ValueType>
189std::vector<ValueType> const& AbstractEquationSolver<ValueType>::getLowerBounds() const {
190 return lowerBounds.get();
191}
192
193template<typename ValueType>
194std::vector<ValueType> const& AbstractEquationSolver<ValueType>::getUpperBounds() const {
195 return upperBounds.get();
196}
197
198template<typename ValueType>
199void AbstractEquationSolver<ValueType>::setLowerBounds(std::vector<ValueType> const& values) {
200 lowerBounds = values;
201}
202
203template<typename ValueType>
204void AbstractEquationSolver<ValueType>::setLowerBounds(std::vector<ValueType>&& values) {
205 lowerBounds = std::move(values);
206}
207
208template<typename ValueType>
209void AbstractEquationSolver<ValueType>::setUpperBounds(std::vector<ValueType> const& values) {
210 upperBounds = values;
211}
212
213template<typename ValueType>
214void AbstractEquationSolver<ValueType>::setUpperBounds(std::vector<ValueType>&& values) {
215 upperBounds = std::move(values);
216}
217
218template<typename ValueType>
219void AbstractEquationSolver<ValueType>::setBounds(std::vector<ValueType> const& lower, std::vector<ValueType> const& upper) {
220 setLowerBounds(lower);
221 setUpperBounds(upper);
222}
223
224template<typename ValueType>
226 if (other.hasLowerBound(BoundType::Global)) {
227 this->setLowerBound(other.getLowerBound());
228 }
229 if (other.hasLowerBound(BoundType::Local)) {
230 this->setLowerBounds(other.getLowerBounds());
231 }
232 if (other.hasUpperBound(BoundType::Global)) {
233 this->setUpperBound(other.getUpperBound());
234 }
235 if (other.hasUpperBound(BoundType::Local)) {
236 this->setUpperBounds(other.getUpperBounds());
237 }
238}
239
240template<typename ValueType>
242 lowerBound = boost::none;
243 upperBound = boost::none;
244 lowerBounds = boost::none;
245 upperBounds = boost::none;
246}
247
248template<typename ValueType>
249void AbstractEquationSolver<ValueType>::createLowerBoundsVector(std::vector<ValueType>& lowerBoundsVector) const {
250 if (this->hasLowerBound(BoundType::Local)) {
251 lowerBoundsVector = this->getLowerBounds();
252 } else {
253 ValueType lowerBound = this->hasLowerBound(BoundType::Global) ? this->getLowerBound() : storm::utility::zero<ValueType>();
254 for (auto& e : lowerBoundsVector) {
255 e = lowerBound;
256 }
257 }
258}
259
260template<typename ValueType>
261void AbstractEquationSolver<ValueType>::createUpperBoundsVector(std::vector<ValueType>& upperBoundsVector) const {
262 STORM_LOG_ASSERT(this->hasUpperBound(), "Expecting upper bound(s).");
263 if (this->hasUpperBound(BoundType::Global)) {
264 upperBoundsVector.assign(upperBoundsVector.size(), this->getUpperBound());
265 } else {
266 upperBoundsVector.assign(this->getUpperBounds().begin(), this->getUpperBounds().end());
267 }
268}
269
270template<typename ValueType>
271void AbstractEquationSolver<ValueType>::createUpperBoundsVector(std::unique_ptr<std::vector<ValueType>>& upperBoundsVector, uint64_t length) const {
272 STORM_LOG_ASSERT(this->hasUpperBound(), "Expecting upper bound(s).");
273 if (!upperBoundsVector) {
274 if (this->hasUpperBound(BoundType::Local)) {
275 STORM_LOG_ASSERT(length == this->getUpperBounds().size(), "Mismatching sizes.");
276 upperBoundsVector = std::make_unique<std::vector<ValueType>>(this->getUpperBounds());
277 } else {
278 upperBoundsVector = std::make_unique<std::vector<ValueType>>(length, this->getUpperBound());
279 }
280 } else {
281 createUpperBoundsVector(*upperBoundsVector);
282 }
283}
284
285template<typename ValueType>
287 return this->progressMeasurement.is_initialized();
288}
289
290template<typename ValueType>
292 STORM_LOG_ASSERT(this->isShowProgressSet(), "Tried to get the progress message delay but progress is not shown.");
293 return this->progressMeasurement->getShowProgressDelay();
294}
295
296template<typename ValueType>
297void AbstractEquationSolver<ValueType>::startMeasureProgress(uint64_t startingIteration) const {
298 if (this->isShowProgressSet()) {
299 this->progressMeasurement->startNewMeasurement(startingIteration);
300 }
301}
302
303template<typename ValueType>
304void AbstractEquationSolver<ValueType>::showProgressIterative(uint64_t iteration, boost::optional<uint64_t> const& bound) const {
305 if (this->isShowProgressSet()) {
306 if (bound) {
307 this->progressMeasurement->setMaxCount(bound.get());
308 }
309 this->progressMeasurement->updateProgress(iteration);
310 }
311}
312
313template<typename ValueType>
314void AbstractEquationSolver<ValueType>::reportStatus(SolverStatus status, boost::optional<uint64_t> const& iterations) const {
315 if (iterations) {
316 switch (status) {
318 STORM_LOG_TRACE("Iterative solver converged after " << iterations.get() << " iterations.");
319 break;
321 STORM_LOG_TRACE("Iterative solver terminated early after " << iterations.get() << " iterations.");
322 break;
324 STORM_LOG_WARN("Iterative solver did not converge after " << iterations.get() << " iterations.");
325 break;
327 STORM_LOG_WARN("Iterative solver was aborted after " << iterations.get() << " iterations.");
328 break;
329 default:
330 STORM_LOG_THROW(false, storm::exceptions::InvalidStateException, "Iterative solver terminated unexpectedly.");
331 }
332 } else {
333 switch (status) {
335 STORM_LOG_TRACE("Solver converged.");
336 break;
338 STORM_LOG_TRACE("Solver terminated early.");
339 break;
341 STORM_LOG_ASSERT(false, "Non-iterative solver should not exceed maximal number of iterations.");
342 STORM_LOG_WARN("Solver did not converge.");
343 break;
345 STORM_LOG_WARN("Solver was aborted.");
346 break;
347 default:
348 STORM_LOG_THROW(false, storm::exceptions::InvalidStateException, "Solver terminated unexpectedly.");
349 }
350 }
351}
352
353template<typename ValueType>
354SolverStatus AbstractEquationSolver<ValueType>::updateStatus(SolverStatus status, bool earlyTermination, uint64_t iterations,
355 uint64_t maximalNumberOfIterations) const {
356 if (status != SolverStatus::Converged) {
357 if (earlyTermination) {
359 } else if (iterations >= maximalNumberOfIterations) {
362 status = SolverStatus::Aborted;
363 }
364 }
365 return status;
366}
367
368template<typename ValueType>
369SolverStatus AbstractEquationSolver<ValueType>::updateStatus(SolverStatus status, std::vector<ValueType> const& x, SolverGuarantee const& guarantee,
370 uint64_t iterations, uint64_t maximalNumberOfIterations) const {
371 return this->updateStatus(status, this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(x, guarantee), iterations,
372 maximalNumberOfIterations);
373}
374
375template class AbstractEquationSolver<double>;
376
379
380} // namespace solver
381} // 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:16
bool get(uint64_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:25
#define STORM_LOG_TRACE(message)
Definition logging.h:12
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool isTerminate()
Check whether the program should terminate (due to some abort signal).