Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SolutionBounds.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cstdint>
5#include <optional>
6#include <type_traits>
7#include <vector>
8
12
13namespace storm::solver {
14
20template<typename ValueType>
22 std::optional<std::vector<ValueType>> lower;
23 std::optional<std::vector<ValueType>> upper;
24
28 bool hasLower() const {
29 return lower.has_value();
30 }
31
35 bool hasUpper() const {
36 return upper.has_value();
37 }
38
42 bool hasAny() const {
43 return hasLower() || hasUpper();
44 }
45
49 bool encloses(std::vector<ValueType> const& values) const {
50 auto const isBoundedBy = [&values](std::optional<std::vector<ValueType>> const& bound, bool fromBelow) {
51 if (!bound.has_value()) {
52 return true;
53 }
54 if (bound->size() != values.size()) {
55 return false;
56 }
57 for (uint64_t i = 0; i < values.size(); ++i) {
58 if (fromBelow ? (*bound)[i] > values[i] : (*bound)[i] < values[i]) {
59 return false;
60 }
61 }
62 return true;
63 };
64 return isBoundedBy(lower, true) && isBoundedBy(upper, false);
65 }
66
70 bool isExact() const {
71 return hasLower() && hasUpper() && *lower == *upper;
72 }
73
77 bool isWithinPrecision(std::vector<ValueType> const& values, ValueType const& precision, bool relative) const {
78 if (!hasLower() || !hasUpper()) {
79 return false;
80 }
81 STORM_LOG_THROW(lower->size() == values.size() && upper->size() == values.size(), storm::exceptions::InvalidArgumentException,
82 "The given values do not match the size of the bounds.");
83 ValueType const zero = storm::utility::zero<ValueType>();
84 for (uint64_t i = 0; i < values.size(); ++i) {
85 ValueType const& low = (*lower)[i];
86 ValueType const& up = (*upper)[i];
87 ValueType allowed = precision;
88 if (relative) {
89 // The enclosed value is at least as far from zero as the bound closer to it, unless the two
90 // straddle zero, where only coinciding bounds say anything.
91 allowed = (low <= zero && up >= zero) ? zero : precision * std::min(storm::utility::abs<ValueType>(low), storm::utility::abs<ValueType>(up));
92 }
93 // Negated, so that a distance that is not a number is rejected.
94 if (!(values[i] - low <= allowed) || !(up - values[i] <= allowed)) {
95 return false;
96 }
97 }
98 return true;
99 }
100
104 void setExact(std::vector<ValueType> const& values) {
105 lower = values;
106 upper = values;
107 }
108
113 auto const oneMinus = [](ValueType const& value) { return storm::utility::one<ValueType>() - value; };
114 if (hasLower()) {
115 std::ranges::transform(*lower, lower->begin(), oneMinus);
116 }
117 if (hasUpper()) {
118 std::ranges::transform(*upper, upper->begin(), oneMinus);
119 }
120 std::swap(lower, upper);
121 }
122
127 template<typename Function>
128 auto transform(Function const& function) const {
130 if (hasLower()) {
131 result.lower = function(*lower);
132 }
133 if (hasUpper()) {
134 result.upper = function(*upper);
135 }
136 return result;
137 }
138
143 void widenTo(std::vector<ValueType> const& values) {
144 if (hasLower()) {
145 std::ranges::transform(*lower, values, lower->begin(), [](ValueType const& bound, ValueType const& value) { return std::min(bound, value); });
146 }
147 if (hasUpper()) {
148 std::ranges::transform(*upper, values, upper->begin(), [](ValueType const& bound, ValueType const& value) { return std::max(bound, value); });
149 }
150 }
151
155 void clear() {
156 lower = std::nullopt;
157 upper = std::nullopt;
158 }
159};
160
161} // namespace storm::solver
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:39
ValueType abs(ValueType const &number)
ValueType zero()
Definition constants.cpp:26
ValueType one()
Definition constants.cpp:21
Sound lower and upper bounds on a solution vector.
bool hasAny() const
Returns true if at least one of the bounds is set.
std::optional< std::vector< ValueType > > lower
bool hasUpper() const
Returns true if the upper bound is set.
auto transform(Function const &function) const
Applies the given function to whichever of the bounds are set, e.g.
bool hasLower() const
Returns true if the lower bound is set.
std::optional< std::vector< ValueType > > upper
void widenTo(std::vector< ValueType > const &values)
Widens whichever bounds are set until they enclose the given values.
void invertProbabilityBounds()
Turns bounds on a probability p into bounds on 1-p, i.e.
void clear()
Clears both bounds.
bool isWithinPrecision(std::vector< ValueType > const &values, ValueType const &precision, bool relative) const
Returns true if both bounds are set and neither is further from its value than the given precision al...
bool encloses(std::vector< ValueType > const &values) const
Returns true if every one of the given values lies within the bounds that are set.
bool isExact() const
Returns true if both bounds are set and coincide.
void setExact(std::vector< ValueType > const &values)
Sets both bounds to the given values, i.e.