Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ParameterRegion.cpp
Go to the documentation of this file.
2
3#include <limits>
4
10
11namespace storm {
12namespace storage {
13
14template<typename ParametricType>
19template<typename ParametricType>
20ParameterRegion<ParametricType>::ParameterRegion(Valuation const& lowerBoundaries, Valuation const& upperBoundaries)
21 : lowerBoundaries(lowerBoundaries), upperBoundaries(upperBoundaries) {
22 init();
23}
24
25template<typename ParametricType>
27 : lowerBoundaries(lowerBoundaries), upperBoundaries(upperBoundaries) {
28 init();
31template<typename ParametricType>
33 // check whether both mappings map the same variables, check that lower boundary <= upper boundary, and pre-compute the set of variables
34 for (auto const& variableWithLowerBoundary : this->lowerBoundaries) {
35 auto variableWithUpperBoundary = this->upperBoundaries.find(variableWithLowerBoundary.first);
36 STORM_LOG_THROW((variableWithUpperBoundary != upperBoundaries.end()), storm::exceptions::InvalidArgumentException,
37 "Could not create region. No upper boundary specified for Variable " << variableWithLowerBoundary.first);
38 STORM_LOG_THROW((variableWithLowerBoundary.second <= variableWithUpperBoundary->second), storm::exceptions::InvalidArgumentException,
39 "Could not create region. The lower boundary for " << variableWithLowerBoundary.first << " is larger then the upper boundary");
40 this->variables.insert(variableWithLowerBoundary.first);
41 this->sortedOnDifference.insert({variableWithLowerBoundary.second - variableWithUpperBoundary->second, variableWithLowerBoundary.first});
42 }
43 for (auto const& variableWithBoundary : this->upperBoundaries) {
44 STORM_LOG_THROW((this->variables.find(variableWithBoundary.first) != this->variables.end()), storm::exceptions::InvalidArgumentException,
45 "Could not create region. No lower boundary specified for Variable " << variableWithBoundary.first);
46 }
47 this->splitThreshold = variables.size();
48}
50template<typename ParametricType>
51std::set<typename ParameterRegion<ParametricType>::VariableType> const& ParameterRegion<ParametricType>::getVariables() const {
52 return this->variables;
53}
55template<typename ParametricType>
56std::multimap<typename ParameterRegion<ParametricType>::CoefficientType, typename ParameterRegion<ParametricType>::VariableType> const&
58 return this->sortedOnDifference;
60
61template<typename ParametricType>
63 auto const& result = lowerBoundaries.find(variable);
64 STORM_LOG_THROW(result != lowerBoundaries.end(), storm::exceptions::InvalidArgumentException,
65 "Tried to find a lower boundary for variable " << variable << " which is not specified by this region");
66 return (*result).second;
67}
68
69template<typename ParametricType>
71 for (auto itr = lowerBoundaries.begin(); itr != lowerBoundaries.end(); ++itr) {
72 if (itr->first.name().compare(varName) == 0) {
73 return (*itr).second;
74 }
75 }
76 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException,
77 "Tried to find a lower boundary for variableName " << varName << " which is not specified by this region");
78}
79
80template<typename ParametricType>
82 auto const& result = upperBoundaries.find(variable);
83 STORM_LOG_THROW(result != upperBoundaries.end(), storm::exceptions::InvalidArgumentException,
84 "Tried to find an upper boundary for variable " << variable << " which is not specified by this region");
85 return (*result).second;
86}
88template<typename ParametricType>
90 for (auto itr = upperBoundaries.begin(); itr != upperBoundaries.end(); ++itr) {
91 if (itr->first.name().compare(varName) == 0) {
92 return (*itr).second;
93 }
94 }
95 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException,
96 "Tried to find an upper boundary for variableName " << varName << " which is not specified by this region");
97}
98
99template<typename ParametricType>
101 return getUpperBoundary(variable) - getLowerBoundary(variable);
102}
103
104template<typename ParametricType>
106 return getUpperBoundary(varName) - getLowerBoundary(varName);
107}
108
109template<typename ParametricType>
111 return (getLowerBoundary(variable) + getUpperBoundary(variable)) / 2;
112}
113
114template<typename ParametricType>
116 return (getLowerBoundary(varName) + getUpperBoundary(varName)) / 2;
117}
118
119template<typename ParametricType>
123
124template<typename ParametricType>
128
129template<typename ParametricType>
130std::vector<typename ParameterRegion<ParametricType>::Valuation> ParameterRegion<ParametricType>::getVerticesOfRegion(
131 std::set<VariableType> const& consideredVariables) const {
132 std::size_t const numOfVariables = consideredVariables.size();
133 STORM_LOG_THROW(numOfVariables <= std::numeric_limits<std::size_t>::digits, storm::exceptions::OutOfRangeException,
134 "Number of variables " << numOfVariables << " is too high.");
135 std::size_t const numOfVertices = std::pow(2, numOfVariables);
136 std::vector<Valuation> resultingVector(numOfVertices);
137
138 for (uint_fast64_t vertexId = 0; vertexId < numOfVertices; ++vertexId) {
139 // interprete vertexId as a bit sequence
140 // the consideredVariables.size() least significant bits of vertex will always represent the next vertex
141 //(00...0 = lower boundaries for all variables, 11...1 = upper boundaries for all variables)
142 uint_fast64_t variableIndex = 0;
143
144 for (auto variable : consideredVariables) {
145 if ((vertexId >> variableIndex) % 2 == 0) {
146 resultingVector[vertexId].insert(std::pair<VariableType, CoefficientType>(variable, getLowerBoundary(variable)));
147 } else {
148 resultingVector[vertexId].insert(std::pair<VariableType, CoefficientType>(variable, getUpperBoundary(variable)));
149 }
150 ++variableIndex;
151 }
152 }
153 return resultingVector;
154}
155
156template<typename ParametricType>
158 return this->getLowerBoundaries();
159}
160
161template<typename ParametricType>
163 Valuation result;
164 for (auto const& variable : this->variables) {
165 result.emplace(variable, getCenter(variable));
166 }
167 return result;
168}
169
170template<typename ParametricType>
172 CoefficientType result = storm::utility::one<CoefficientType>();
173 for (auto const& variable : this->variables) {
174 if (this->getUpperBoundary(variable) != this->getLowerBoundary(variable)) {
175 result *= (this->getUpperBoundary(variable) - this->getLowerBoundary(variable));
176 } else {
177 // HACK to get regions with zero area to work correctly
178 // (It's a hack but it's a harmless one for now, as regions with zero area do not exist without discrete parameters)
179 // This area represents half of the area of the region
180 result /= utility::convertNumber<CoefficientType>(2);
181 }
182 }
183 return result;
184}
185
186template<typename ParametricType>
188 for (auto const& variable : this->variables) {
189 STORM_LOG_ASSERT(point.count(variable) > 0,
190 "Tried to check if a point is in a region, but the point does not contain a value for variable " << variable);
191 auto pointEntry = point.find(variable)->second;
192 if (pointEntry < this->getLowerBoundary(variable) || pointEntry > this->getUpperBoundary(variable)) {
193 return false;
194 }
195 }
196 return true;
197}
198
199template<typename ParametricType>
200void ParameterRegion<ParametricType>::split(Valuation const& splittingPoint, std::vector<ParameterRegion<ParametricType>>& regionVector) const {
201 return split(splittingPoint, regionVector, variables, {});
202}
203
204template<typename ParametricType>
205void ParameterRegion<ParametricType>::split(Valuation const& splittingPoint, std::vector<storm::storage::ParameterRegion<ParametricType>>& regionVector,
206 const std::set<VariableType>& consideredVariables, const std::set<VariableType>& discreteVariables) const {
207 std::set<VariableType> vertexVariables = consideredVariables;
208 // Remove the discrete variables that are already unit from the considered
209 // variables set, so we don't split them again
210 for (auto const& var : discreteVariables) {
211 if (this->getDifference(var) == storm::utility::zero<CoefficientType>()) {
212 vertexVariables.erase(var);
213 }
214 }
215
216 auto vertices = getVerticesOfRegion(vertexVariables);
217
218 for (auto const& vertex : vertices) {
219 // The resulting subregion is the smallest region containing vertex and splittingPoint.
220 Valuation subLower, subUpper;
221 for (auto variableBound : this->lowerBoundaries) {
222 VariableType variable = variableBound.first;
223 auto vertexEntry = vertex.find(variable);
224 if (vertexEntry != vertex.end()) {
225 if (discreteVariables.find(variable) != discreteVariables.end()) {
226 // As this parameter is discrete, we set this parameter to the vertex entry (splitting point does not matter)
227 // e.g. we split the region p in [0,1], q in [0,1] at center with q being discrete
228 // then we get the regions [0,0.5]x[0,1] and [0.5,1]x[0,1]
229 subLower.insert(typename Valuation::value_type(variable, vertexEntry->second));
230 subUpper.insert(typename Valuation::value_type(variable, vertexEntry->second));
231 } else {
232 auto splittingPointEntry = splittingPoint.find(variable);
233 subLower.insert(typename Valuation::value_type(variable, std::min(vertexEntry->second, splittingPointEntry->second)));
234 subUpper.insert(typename Valuation::value_type(variable, std::max(vertexEntry->second, splittingPointEntry->second)));
235 }
236 } else {
237 subLower.insert(typename Valuation::value_type(variable, getLowerBoundary(variable)));
238 subUpper.insert(typename Valuation::value_type(variable, getUpperBoundary(variable)));
239 }
240 }
241
242 ParameterRegion<ParametricType> subRegion(std::move(subLower), std::move(subUpper));
243
244 if (!storm::utility::isZero(subRegion.area())) {
245 regionVector.push_back(std::move(subRegion));
246 }
247 }
248}
249
250template<typename ParametricType>
251std::string ParameterRegion<ParametricType>::toString(bool boundariesAsDouble) const {
252 std::stringstream regionstringstream;
253 if (boundariesAsDouble) {
254 for (auto var : this->getVariables()) {
255 regionstringstream << storm::utility::convertNumber<double>(this->getLowerBoundary(var));
256 regionstringstream << "<=";
257 regionstringstream << var;
258 regionstringstream << "<=";
259 regionstringstream << storm::utility::convertNumber<double>(this->getUpperBoundary(var));
260 regionstringstream << ",";
261 }
262 } else {
263 for (auto var : this->getVariables()) {
264 regionstringstream << this->getLowerBoundary(var);
265 regionstringstream << "<=";
266 regionstringstream << var;
267 regionstringstream << "<=";
268 regionstringstream << this->getUpperBoundary(var);
269 regionstringstream << ",";
270 }
271 }
272 std::string regionstring = regionstringstream.str();
273 // the last comma should actually be a semicolon
274 regionstring = regionstring.substr(0, regionstring.length() - 1) + ";";
275 return regionstring;
276}
277
278template<typename ParametricType>
280 auto varsRegion = getVariables();
281 auto varsSubRegion = subRegion.getVariables();
282 for (auto var : varsRegion) {
283 if (std::find(varsSubRegion.begin(), varsSubRegion.end(), var) != varsSubRegion.end()) {
284 if (getLowerBoundary(var) > subRegion.getLowerBoundary(var) || getUpperBoundary(var) < getUpperBoundary(var)) {
285 return false;
286 }
287 } else {
288 return false;
289 }
290 }
291 return true;
292}
293
294template<typename ParametricType>
297 auto val = this->getCenterPoint();
298 for (auto monResEntry : monRes.getMonotonicityResult()) {
299 if (monRes.isDoneForVar(monResEntry.first)) {
301 val[monResEntry.first] = storm::solver::minimize(dir) ? getLowerBoundary(monResEntry.first) : getUpperBoundary(monResEntry.first);
303 val[monResEntry.first] = storm::solver::maximize(dir) ? getLowerBoundary(monResEntry.first) : getUpperBoundary(monResEntry.first);
304 }
305 }
306 }
307 return val;
308}
309
310template<typename ParametricType>
312 std::set<VariableType> const& monIncrParameters,
313 std::set<VariableType> const& monDecrParameters) const {
314 auto val = this->getCenterPoint();
315 for (auto var : monIncrParameters) {
316 val[var] = storm::solver::minimize(dir) ? getLowerBoundary(var) : getUpperBoundary(var);
317 }
318 for (auto var : monDecrParameters) {
319 val[var] = storm::solver::maximize(dir) ? getLowerBoundary(var) : getUpperBoundary(var);
320 }
321
322 return val;
323}
324
325template<typename ParametricType>
329
330template<typename ParametricType>
332 parentBound = bound;
333}
334
335template<typename ParametricType>
336std::ostream& operator<<(std::ostream& out, ParameterRegion<ParametricType> const& region) {
337 out << region.toString();
338 return out;
339}
340
341#ifdef STORM_HAVE_CARL
342template class ParameterRegion<storm::RationalFunction>;
343template std::ostream& operator<<(std::ostream& out, ParameterRegion<storm::RationalFunction> const& region);
344#endif
345
346} // namespace storage
347} // namespace storm
std::map< VariableType, Monotonicity > const & getMonotonicityResult() const
Returns the results so far.
storm::utility::parametric::CoefficientType< ParametricType >::type CoefficientType
std::set< VariableType > const & getVariables() const
Valuation getCenterPoint() const
Returns the center point of this region.
CoefficientType area() const
Returns the area of this region.
void setBoundParent(CoefficientType bound)
std::string toString(bool boundariesAsDouble=false) const
storm::utility::parametric::Valuation< ParametricType > Valuation
Valuation const & getLowerBoundaries() const
CoefficientType getDifference(const std::string varName) const
storm::utility::parametric::VariableType< ParametricType >::type VariableType
Valuation getPoint(storm::solver::OptimizationDirection dir, storm::analysis::MonotonicityResult< VariableType > &monRes) const
bool contains(Valuation const &point) const
Returns whether the given point is in this region.
CoefficientType const & getLowerBoundary(VariableType const &variable) const
void split(Valuation const &splittingPoint, std::vector< ParameterRegion< ParametricType > > &regionVector) const
Splits the region at the given point and inserts the resulting subregions at the end of the given vec...
bool isSubRegion(ParameterRegion< ParametricType > region)
CoefficientType const & getUpperBoundary(VariableType const &variable) const
Valuation getSomePoint() const
Returns some point that lies within this region.
CoefficientType getCenter(const std::string varName) const
Valuation const & getUpperBoundaries() const
std::multimap< CoefficientType, VariableType > const & getVariablesSorted() const
std::vector< Valuation > getVerticesOfRegion(std::set< VariableType > const &consideredVariables) const
Returns a vector of all possible combinations of lower and upper bounds of the given variables.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool constexpr maximize(OptimizationDirection d)
bool constexpr minimize(OptimizationDirection d)
std::set< storm::RationalFunctionVariable > getVariables(SparseMatrix< storm::RationalFunction > const &matrix)
bool isZero(ValueType const &a)
Definition constants.cpp:38