Storm 1.13.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ExplicitQuantitativeCheckResult.cpp
Go to the documentation of this file.
1#include "storm/adapters/RationalNumberAdapter.h" // Must come first. TODO: fix
2
4
15
16namespace storm {
17namespace modelchecker {
18template<typename ValueType>
22
23template<typename ValueType>
25 // Intentionally left empty.
26}
27
28template<typename ValueType>
30 // Intentionally left empty.
31}
32
33template<typename ValueType>
35 : values(map_type()) {
36 boost::get<map_type>(values).emplace(state, value);
37}
38
39template<typename ValueType>
41 // Intentionally left empty.
42}
43
44template<typename ValueType>
46 // Intentionally left empty.
47}
48
49template<typename ValueType>
50ExplicitQuantitativeCheckResult<ValueType>::ExplicitQuantitativeCheckResult(boost::variant<vector_type, map_type> const& values,
51 std::optional<std::shared_ptr<storm::storage::Scheduler<ValueType>>> scheduler)
52 : values(values), scheduler(scheduler) {
53 // Intentionally left empty.
54}
55
56template<typename ValueType>
58 std::optional<std::shared_ptr<storm::storage::Scheduler<ValueType>>> scheduler)
59 : values(std::move(values)), scheduler(scheduler) {
60 // Intentionally left empty.
61}
62
63template<typename ValueType>
65 if (other.isResultForAllStates()) {
66 storm::storage::BitVector const& bvValues = other.getTruthValuesVector();
67
68 vector_type newVector;
69 newVector.reserve(bvValues.size());
70 for (std::size_t i = 0, n = bvValues.size(); i < n; i++) {
71 newVector.push_back(bvValues.get(i) ? storm::utility::one<ValueType>() : storm::utility::zero<ValueType>());
72 }
73
74 values = newVector;
75 } else {
77
78 map_type newMap;
79 for (auto const& e : bitMap) {
80 newMap[e.first] = e.second ? storm::utility::one<ValueType>() : storm::utility::zero<ValueType>();
81 }
82
83 values = newMap;
84 }
85}
86
87template<typename ValueType>
88std::unique_ptr<CheckResult> ExplicitQuantitativeCheckResult<ValueType>::clone() const {
89 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(this->values, this->scheduler);
90}
91
92template<typename ValueType>
96
97template<typename ValueType>
101
102template<typename ValueType>
104 return boost::get<map_type>(values);
105}
106
107template<typename ValueType>
109 STORM_LOG_THROW(filter.isExplicitQualitativeCheckResult(), storm::exceptions::InvalidOperationException,
110 "Cannot filter explicit check result with non-explicit filter.");
111 STORM_LOG_THROW(filter.isResultForAllStates(), storm::exceptions::InvalidOperationException, "Cannot filter check result with non-complete filter.");
112 STORM_LOG_THROW(filter.hasValueType<ValueType>(), storm::exceptions::InvalidOperationException, "Filter has unexpected value type.");
114 typename ExplicitQualitativeCheckResult<ValueType>::vector_type const& filterTruthValues = explicitFilter.getTruthValuesVector();
115
116 if (this->isResultForAllStates()) {
117 map_type newMap;
118
119 for (auto element : filterTruthValues) {
120 STORM_LOG_THROW(element < this->getValueVector().size(), storm::exceptions::InvalidAccessException, "Invalid index in results.");
121 newMap.emplace(element, this->getValueVector()[element]);
122 }
123 this->values = newMap;
124 } else {
125 map_type const& map = boost::get<map_type>(values);
126
127 map_type newMap;
128 for (auto const& element : map) {
129 if (filterTruthValues.get(element.first)) {
130 newMap.insert(element);
131 }
132 }
133
134 STORM_LOG_THROW(newMap.size() == filterTruthValues.getNumberOfSetBits(), storm::exceptions::InvalidOperationException,
135 "The check result fails to contain some results referred to by the filter.");
136
137 this->values = newMap;
138 }
139}
140
141template<typename ValueType>
143 STORM_LOG_THROW(!values.empty(), storm::exceptions::InvalidOperationException, "Minimum of empty set is not defined.");
144
145 if (this->isResultForAllStates()) {
146 return storm::utility::minimum(boost::get<vector_type>(values));
147 } else {
148 return storm::utility::minimum(boost::get<map_type>(values));
149 }
150}
151
152template<typename ValueType>
154 STORM_LOG_THROW(!values.empty(), storm::exceptions::InvalidOperationException, "Minimum of empty set is not defined.");
155
156 if (this->isResultForAllStates()) {
157 return storm::utility::maximum(boost::get<vector_type>(values));
158 } else {
159 return storm::utility::maximum(boost::get<map_type>(values));
160 }
161}
162
163template<typename ValueType>
164std::pair<ValueType, ValueType> ExplicitQuantitativeCheckResult<ValueType>::getMinMax() const {
165 STORM_LOG_THROW(!values.empty(), storm::exceptions::InvalidOperationException, "Minimum/maximum of empty set is not defined.");
166
167 if (this->isResultForAllStates()) {
168 return storm::utility::minmax(boost::get<vector_type>(values));
169 } else {
170 return storm::utility::minmax(boost::get<map_type>(values));
171 }
172}
173
174template<typename ValueType>
176 STORM_LOG_THROW(!values.empty(), storm::exceptions::InvalidOperationException, "Sum of empty set is not defined");
177
179 if (this->isResultForAllStates()) {
180 for (auto& element : boost::get<vector_type>(values)) {
181 STORM_LOG_THROW(element != storm::utility::infinity<ValueType>(), storm::exceptions::InvalidOperationException,
182 "Cannot compute the sum of values containing infinity.");
183 sum += element;
184 }
185 } else {
186 for (auto& element : boost::get<map_type>(values)) {
187 STORM_LOG_THROW(element.second != storm::utility::infinity<ValueType>(), storm::exceptions::InvalidOperationException,
188 "Cannot compute the sum of values containing infinity.");
189 sum += element.second;
190 }
191 }
192 return sum;
193}
194
195template<typename ValueType>
197 STORM_LOG_THROW(!values.empty(), storm::exceptions::InvalidOperationException, "Average of empty set is not defined");
198
200 if (this->isResultForAllStates()) {
201 for (auto& element : boost::get<vector_type>(values)) {
202 STORM_LOG_THROW(element != storm::utility::infinity<ValueType>(), storm::exceptions::InvalidOperationException,
203 "Cannot compute the average of values containing infinity.");
204 sum += element;
205 }
206 return sum / boost::get<vector_type>(values).size();
207 } else {
208 for (auto& element : boost::get<map_type>(values)) {
209 STORM_LOG_THROW(element.second != storm::utility::infinity<ValueType>(), storm::exceptions::InvalidOperationException,
210 "Cannot compute the average of values containing infinity.");
211 sum += element.second;
212 }
213 return sum / boost::get<map_type>(values).size();
214 }
215}
216
217template<typename ValueType>
219 return static_cast<bool>(scheduler);
220}
221
222template<typename ValueType>
224 this->scheduler = std::move(scheduler);
225}
226
227template<typename ValueType>
229 STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler.");
230 return *scheduler.value();
231}
232
233template<typename ValueType>
235 STORM_LOG_THROW(this->hasScheduler(), storm::exceptions::InvalidOperationException, "Unable to retrieve non-existing scheduler.");
236 return *scheduler.value();
237}
238
239template<typename ValueType>
240void print(std::ostream& out, ValueType const& value) {
242 out << "inf";
243 } else {
244 out << value;
245 if (std::is_same<ValueType, storm::RationalNumber>::value) {
246 out << " (approx. " << storm::utility::convertNumber<double>(value) << ")";
247 }
248 }
249}
250
251template<typename ValueType>
252void printRange(std::ostream& out, ValueType const& min, ValueType const& max) {
253 out << "[";
255 out << "inf";
256 } else {
257 out << min;
258 }
259 out << ", ";
261 out << "inf";
262 } else {
263 out << max;
264 }
265 out << "]";
266 if (std::is_same<ValueType, storm::RationalNumber>::value) {
267 out << " (approx. [";
269 out << "inf";
270 } else {
271 out << storm::utility::convertNumber<double>(min);
272 }
273 out << ", ";
275 out << "inf";
276 } else {
277 out << storm::utility::convertNumber<double>(max);
278 }
279 out << "])";
280 }
281 out << " (range)";
282}
283
284template<typename ValueType>
285std::ostream& ExplicitQuantitativeCheckResult<ValueType>::writeToStream(std::ostream& out) const {
286 bool minMaxSupported = std::is_same<ValueType, double>::value || std::is_same<ValueType, storm::RationalNumber>::value;
287 bool printAsRange = false;
288
289 if (this->isResultForAllStates()) {
290 vector_type const& valuesAsVector = boost::get<vector_type>(values);
291 if (valuesAsVector.size() >= 10 && minMaxSupported) {
292 printAsRange = true;
293 } else {
294 out << "{";
295 bool first = true;
296 for (auto const& element : valuesAsVector) {
297 if (!first) {
298 out << ", ";
299 } else {
300 first = false;
301 }
302 print(out, element);
303 }
304 out << "}";
305 }
306 } else {
307 map_type const& valuesAsMap = boost::get<map_type>(values);
308 if (valuesAsMap.size() >= 10 && minMaxSupported) {
309 printAsRange = true;
310 } else {
311 if (valuesAsMap.size() == 1) {
312 print(out, valuesAsMap.begin()->second);
313 } else {
314 out << "{";
315 bool first = true;
316 for (auto const& element : valuesAsMap) {
317 if (!first) {
318 out << ", ";
319 } else {
320 first = false;
321 }
322 print(out, element.second);
323 }
324 out << "}";
325 }
326 }
327 }
328
329 if (printAsRange) {
330 std::pair<ValueType, ValueType> minmax = this->getMinMax();
331 printRange(out, minmax.first, minmax.second);
332 }
333
334 return out;
335}
336
337template<typename ValueType>
339 ValueType const& bound) const {
340 if (this->isResultForAllStates()) {
341 vector_type const& valuesAsVector = boost::get<vector_type>(values);
342 storm::storage::BitVector result(valuesAsVector.size());
343 switch (comparisonType) {
345 for (uint_fast64_t index = 0; index < valuesAsVector.size(); ++index) {
346 if (valuesAsVector[index] < bound) {
347 result.set(index);
348 }
349 }
350 break;
352 for (uint_fast64_t index = 0; index < valuesAsVector.size(); ++index) {
353 if (valuesAsVector[index] <= bound) {
354 result.set(index);
355 }
356 }
357 break;
359 for (uint_fast64_t index = 0; index < valuesAsVector.size(); ++index) {
360 if (valuesAsVector[index] > bound) {
361 result.set(index);
362 }
363 }
364 break;
366 for (uint_fast64_t index = 0; index < valuesAsVector.size(); ++index) {
367 if (valuesAsVector[index] >= bound) {
368 result.set(index);
369 }
370 }
371 break;
372 }
373 return std::unique_ptr<CheckResult>(new ExplicitQualitativeCheckResult<ValueType>(std::move(result), std::move(scheduler)));
374 } else {
375 map_type const& valuesAsMap = boost::get<map_type>(values);
376 std::map<storm::storage::sparse::state_type, bool> result;
377 switch (comparisonType) {
379 for (auto const& element : valuesAsMap) {
380 result[element.first] = element.second < bound;
381 }
382 break;
384 for (auto const& element : valuesAsMap) {
385 result[element.first] = element.second <= bound;
386 }
387 break;
389 for (auto const& element : valuesAsMap) {
390 result[element.first] = element.second > bound;
391 }
392 break;
394 for (auto const& element : valuesAsMap) {
395 result[element.first] = element.second >= bound;
396 }
397 break;
398 }
399 return std::unique_ptr<CheckResult>(new ExplicitQualitativeCheckResult<ValueType>(std::move(result), std::move(scheduler)));
400 }
401}
402
403template<>
405 storm::RationalFunction const& bound) const {
406 // Since it is not possible to compare rational functions against bounds, we simply call the base class method.
407 return QuantitativeCheckResult::compareAgainstBound(comparisonType, bound);
408}
409
410template<typename ValueType>
412 if (this->isResultForAllStates()) {
413 return boost::get<vector_type>(values)[state];
414 } else {
415 return boost::get<map_type>(values)[state];
416 }
417}
418
419template<typename ValueType>
421 if (this->isResultForAllStates()) {
422 return boost::get<vector_type>(values)[state];
423 } else {
424 map_type const& valuesAsMap = boost::get<map_type>(values);
425 auto const& keyValuePair = valuesAsMap.find(state);
426 STORM_LOG_THROW(keyValuePair != valuesAsMap.end(), storm::exceptions::InvalidOperationException, "Unknown key '" << state << "'.");
427 return keyValuePair->second;
428 }
429}
430
431template<typename ValueType>
435
436template<typename ValueType>
438 return values.which() == 0;
439}
440
441template<typename ValueType>
445
446template<typename ValueType>
448 if (this->isResultForAllStates()) {
449 for (auto& element : boost::get<vector_type>(values)) {
450 element = storm::utility::one<ValueType>() - element;
451 }
452 } else {
453 for (auto& element : boost::get<map_type>(values)) {
454 element.second = storm::utility::one<ValueType>() - element.second;
455 }
456 }
457}
458
459template<typename ValueType>
460void insertJsonEntry(storm::json<ValueType>& json, uint64_t const& id, ValueType const& value,
461 std::optional<storm::storage::sparse::StateValuations> const& stateValuations = std::nullopt,
462 std::optional<storm::models::sparse::StateLabeling> const& stateLabels = std::nullopt) {
463 typename storm::json<ValueType> entry;
464 if (stateValuations) {
465 entry["s"] = stateValuations->template toJson<ValueType>(id);
466 } else {
467 entry["s"] = id;
468 }
469 entry["v"] = value;
470 if (stateLabels) {
471 auto labs = stateLabels->getLabelsOfState(id);
472 entry["l"] = labs;
473 }
474 json.push_back(std::move(entry));
475}
476
477template<typename ValueType>
478storm::json<ValueType> ExplicitQuantitativeCheckResult<ValueType>::toJson(std::optional<storm::storage::sparse::StateValuations> const& stateValuations,
479 std::optional<storm::models::sparse::StateLabeling> const& stateLabels) const {
481 if (this->isResultForAllStates()) {
482 vector_type const& valuesAsVector = boost::get<vector_type>(values);
483 for (uint64_t state = 0; state < valuesAsVector.size(); ++state) {
484 insertJsonEntry(result, state, valuesAsVector[state], stateValuations, stateLabels);
485 }
486 } else {
487 map_type const& valuesAsMap = boost::get<map_type>(values);
488 for (auto const& stateValue : valuesAsMap) {
489 insertJsonEntry(result, stateValue.first, stateValue.second, stateValuations, stateLabels);
490 }
491 }
492 return result;
493}
494
495template<>
497 std::optional<storm::storage::sparse::StateValuations> const&, std::optional<storm::models::sparse::StateLabeling> const&) const {
498 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Export of Check results is not supported for Rational Functions.");
499}
500
504} // namespace modelchecker
505} // namespace storm
ExplicitQualitativeCheckResult< ValueType > & asExplicitQualitativeCheckResult()
std::map< storm::storage::sparse::state_type, bool > map_type
virtual std::ostream & writeToStream(std::ostream &out) const override
virtual std::unique_ptr< CheckResult > clone() const override
storm::storage::Scheduler< ValueType > const & getScheduler() const
std::map< storm::storage::sparse::state_type, ValueType > map_type
ValueType & operator[](storm::storage::sparse::state_type state)
storm::json< ValueType > toJson(std::optional< storm::storage::sparse::StateValuations > const &stateValuations=std::nullopt, std::optional< storm::models::sparse::StateLabeling > const &stateLabels=std::nullopt) const
virtual std::pair< ValueType, ValueType > getMinMax() const
virtual void filter(QualitativeCheckResult const &filter) override
Filters the current result wrt.
void setScheduler(std::unique_ptr< storm::storage::Scheduler< ValueType > > &&scheduler)
virtual std::unique_ptr< CheckResult > compareAgainstBound(storm::logic::ComparisonType comparisonType, ValueType const &bound) const override
virtual std::unique_ptr< CheckResult > compareAgainstBound(storm::logic::ComparisonType comparisonType, ValueType const &bound) const
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
This class defines which action is chosen in a particular state of a non-deterministic model.
Definition Scheduler.h:18
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void print(std::ostream &out, ValueType const &value)
void printRange(std::ostream &out, ValueType const &min, ValueType const &max)
void insertJsonEntry(storm::json< JsonRationalType > &json, uint64_t const &id, bool value, std::optional< storm::storage::sparse::StateValuations > const &stateValuations=std::nullopt, std::optional< storm::models::sparse::StateLabeling > const &stateLabels=std::nullopt)
ValueType minimum(std::vector< ValueType > const &values)
ValueType zero()
Definition constants.cpp:24
ValueType infinity()
Definition constants.cpp:29
std::pair< ValueType, ValueType > minmax(std::vector< ValueType > const &values)
ValueType one()
Definition constants.cpp:19
ValueType maximum(std::vector< ValueType > const &values)
TargetType convertNumber(SourceType const &number)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
Definition JsonForward.h:10
carl::RationalFunction< Polynomial, true > RationalFunction