Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
WinningRegion.cpp
Go to the documentation of this file.
2
3#include <boost/algorithm/string.hpp>
4#include <iostream>
5
8#include "storm/io/file.h"
12
13namespace storm {
14namespace pomdp {
15WinningRegion::WinningRegion(std::vector<uint64_t> const& observationSizes) : observationSizes(observationSizes) {
16 for (uint64_t i = 0; i < observationSizes.size(); ++i) {
17 winningRegion.push_back(std::vector<storm::storage::BitVector>());
18 }
19}
20
21void WinningRegion::setObservationIsWinning(uint64_t observation) {
22 winningRegion[observation] = {storm::storage::BitVector(observationSizes[observation], true)};
23}
24
25void WinningRegion::addTargetStates(uint64_t observation, storm::storage::BitVector const& offsets) {
26 assert(!offsets.empty());
27 if (winningRegion[observation].empty()) {
28 winningRegion[observation].push_back(offsets);
29 return;
30 }
31 std::vector<storm::storage::BitVector> newWinningSupport = std::vector<storm::storage::BitVector>();
32
33 for (auto const& support : winningRegion[observation]) {
34 newWinningSupport.push_back(support | offsets);
35 }
36 // TODO it may be worthwhile to check whether something changed. If nothing changed, there is no need for the next routine.
37 // TODO the following code is bit naive.
38 winningRegion[observation].clear(); // This prevents some overhead.
39 for (auto const& newWinning : newWinningSupport) {
40 update(observation, newWinning);
41 }
42}
43
44bool WinningRegion::update(uint64_t observation, storm::storage::BitVector const& winning) {
45 std::vector<storm::storage::BitVector> newWinningSupport = std::vector<storm::storage::BitVector>();
46 bool changed = false;
47 for (auto const& support : winningRegion[observation]) {
48 if (winning.isSubsetOf(support)) {
49 // This new winning support is already covered.
50 return false;
51 }
52 if (support.isSubsetOf(winning)) {
53 // This new winning support extends the previous support, thus the previous support is now spurious
54 changed = true;
55 } else {
56 newWinningSupport.push_back(support);
57 }
58 }
59
60 // only if changed.
61 if (changed) {
62 newWinningSupport.push_back(winning);
63 winningRegion[observation] = newWinningSupport;
64 } else {
65 winningRegion[observation].push_back(winning);
66 }
67 return true;
68}
69
70bool WinningRegion::query(uint64_t observation, storm::storage::BitVector const& currently) const {
71 for (storm::storage::BitVector winning : winningRegion[observation]) {
72 if (currently.isSubsetOf(winning)) {
73 return true;
74 }
75 }
76 return false;
77}
78
79storm::expressions::Expression WinningRegion::extensionExpression(uint64_t observation, std::vector<storm::expressions::Expression>& varsForStates) const {
80 std::vector<storm::expressions::Expression> expressionForEntry;
81
82 for (auto const& winningForObservation : winningRegion[observation]) {
83 if (winningForObservation.full()) {
84 assert(winningRegion[observation].size() == 1);
85 return varsForStates.front().getManager().boolean(false);
86 }
87 std::vector<storm::expressions::Expression> subexpr;
88 std::vector<storm::expressions::Expression> leftHandSides;
89 assert(varsForStates.size() == winningForObservation.size());
90 for (uint64_t i = 0; i < varsForStates.size(); ++i) {
91 if (winningForObservation.get(i)) {
92 leftHandSides.push_back(varsForStates[i]);
93 } else {
94 subexpr.push_back(varsForStates[i]);
95 }
96 }
98 for (auto const& lhs : leftHandSides) {
99 expressionForEntry.push_back(storm::expressions::implies(lhs, rightHandSide));
100 }
101 expressionForEntry.push_back(storm::expressions::disjunction(varsForStates));
102 }
103 return storm::expressions::conjunction(expressionForEntry);
104}
105
111bool WinningRegion::observationIsWinning(uint64_t observation) const {
112 return winningRegion[observation].size() == 1 && winningRegion[observation].front().full();
113}
114
116 uint64_t observation = 0;
117 std::vector<uint64_t> winningObservations;
118 std::vector<uint64_t> loosingObservations;
119
120 for (auto const& winningSupport : winningRegion) {
121 if (observationIsWinning(observation)) {
122 winningObservations.push_back(observation);
123 } else if (winningRegion[observation].empty()) {
124 loosingObservations.push_back(observation);
125 } else {
126 std::cout << "***** observation" << observation << '\n';
127 for (auto const& support : winningSupport) {
128 std::cout << " " << support;
129 }
130 std::cout << '\n';
131 }
132 observation++;
133 }
134 std::cout << "and " << winningObservations.size() << " winning observations: (";
135 for (auto const& obs : winningObservations) {
136 std::cout << obs << " ";
137 }
138 std::cout << ") and " << loosingObservations.size() << " loosing observations: (";
139 for (auto const& obs : loosingObservations) {
140 std::cout << obs << " ";
141 }
142}
143
149 assert(winningRegion.size() == observationSizes.size());
150 return observationSizes.size();
151}
152
154 for (auto const& ob : winningRegion) {
155 if (!ob.empty()) {
156 return false;
157 }
158 }
159 return true;
160}
161
162std::vector<storm::storage::BitVector> const& WinningRegion::getWinningSetsPerObservation(uint64_t observation) const {
163 assert(observation < getNumberOfObservations());
164 return winningRegion[observation];
165}
166
167storm::RationalNumber WinningRegion::beliefSupportStates() const {
168 storm::RationalNumber total = 0;
169 storm::RationalNumber two = storm::utility::convertNumber<storm::RationalNumber>(2);
170 for (auto const& size : observationSizes) {
171 total += carl::pow(two, size) - 1;
172 }
173 return total;
174}
175
176std::pair<storm::RationalNumber, storm::RationalNumber> count(std::vector<storm::storage::BitVector> const& origSets,
177 std::vector<storm::storage::BitVector> const& intersects,
178 std::vector<storm::storage::BitVector> const& intersectsInfo, storm::RationalNumber val,
179 bool plus, uint64_t remdepth) {
180 assert(intersects.size() == intersectsInfo.size());
181 storm::RationalNumber newVal = val;
182 storm::RationalNumber two = storm::utility::convertNumber<storm::RationalNumber>(2);
183 for (uint64_t i = 0; i < intersects.size(); ++i) {
184 if (plus) {
185 newVal += carl::pow(two, intersects[i].getNumberOfSetBits());
186 } else {
187 newVal -= carl::pow(two, intersects[i].getNumberOfSetBits());
188 }
189 }
190
191 storm::RationalNumber diff = val - newVal;
192 storm::RationalNumber max = storm::utility::max(val, newVal);
193
194 diff = storm::utility::abs(diff);
195 if (remdepth == 0 || 20 * diff < max) {
196 if (plus) {
197 return std::make_pair(val, newVal);
198 } else {
199 return std::make_pair(newVal, val);
200 }
201 } else {
202 storm::RationalNumber skipped = 0;
203 uint64_t upperBoundElements = origSets.size() * intersects.size();
204 STORM_LOG_DEBUG("Upper bound on number of elements to be considered " << upperBoundElements);
205 STORM_LOG_DEBUG("Value " << val << " newVal " << newVal);
206 uint64_t oom = 0;
207 uint64_t critoom = 0;
208 storm::RationalNumber n = 1;
209 while (n < max) {
210 oom += 1;
211 n = n * 2;
212 }
213 STORM_LOG_DEBUG("Order of magnitude = " << oom);
214
215 critoom = oom - static_cast<uint64_t>(floor(log2(upperBoundElements)));
216
217 STORM_LOG_DEBUG("Crit Order of magnitude = " << critoom);
218
219 uint64_t intersectSetSkip = critoom - static_cast<uint64_t>(floor(log2(origSets.size())));
220
221 std::vector<storm::storage::BitVector> useIntersects;
222 std::vector<storm::storage::BitVector> useInfo;
223 for (uint64_t i = 0; i < intersects.size(); ++i) {
224 if (upperBoundElements > 10000 && intersects[i].getNumberOfSetBits() < intersectSetSkip - 3) {
225 skipped += (carl::pow(two, intersects[i].getNumberOfSetBits()) * origSets.size());
226 STORM_LOG_DEBUG("Skipped " << skipped);
227 } else {
228 useIntersects.push_back(intersects[i]);
229 useInfo.push_back(intersectsInfo[i]);
230 }
231 }
232
233 uint64_t origSetSkip = critoom - static_cast<uint64_t>(floor(log2(useIntersects.size())));
234 STORM_LOG_DEBUG("OrigSkip= " << origSetSkip);
235
236 std::vector<storm::storage::BitVector> newIntersects;
237 std::vector<storm::storage::BitVector> newInfo;
238
239 for (uint64_t i = 0; i < origSets.size(); ++i) {
240 if (upperBoundElements > 20000 && origSets[i].getNumberOfSetBits() < origSetSkip - 3) {
241 skipped += (carl::pow(two, origSets[i].getNumberOfSetBits()) * useIntersects.size());
242 STORM_LOG_DEBUG("Skipped " << skipped);
243 continue;
244 }
245 for (uint64_t j = 0; j < useIntersects.size(); ++j) {
246 if (useInfo[j].get(i)) {
247 continue;
248 }
249 storm::storage::BitVector newinf = useInfo[j];
250 newinf.set(i);
251 if (newinf == useInfo[j]) {
252 continue;
253 }
254 bool exists = false;
255 for (auto const& entry : newInfo) {
256 if (entry == newinf) {
257 exists = true;
258 break;
259 }
260 }
261 if (!exists) {
262 newInfo.push_back(newinf);
263 newIntersects.push_back(origSets[i] & useIntersects[j]);
264 }
265 }
266 }
267
268 auto res = count(origSets, newIntersects, newInfo, newVal, !plus, remdepth - 1);
269 if (plus) {
270 storm::RationalNumber tmp = res.first - skipped;
271 return std::make_pair(storm::utility::max(tmp, val), res.second);
272 } else {
273 storm::RationalNumber tmp = res.second + skipped;
274 return std::make_pair(res.first, storm::utility::min(tmp, val));
275 }
276 }
277}
278
279std::pair<storm::RationalNumber, storm::RationalNumber> WinningRegion::computeNrWinningBeliefs() const {
280 storm::RationalNumber upper = 0;
281 storm::RationalNumber lower = 0;
282 storm::RationalNumber two = storm::utility::convertNumber<storm::RationalNumber>(2);
283 for (auto const& winningSets : winningRegion) {
284 storm::RationalNumber totalForObs = 0;
285 storm::RationalNumber two = storm::utility::convertNumber<storm::RationalNumber>(2);
286
287 std::vector<storm::storage::BitVector> info; // which intersections are part of this
288 for (uint64_t i = 0; i < winningSets.size(); ++i) {
289 storm::storage::BitVector entry(winningSets.size());
290 entry.set(i);
291 info.push_back(entry);
292 }
293 auto res = count(winningSets, winningSets, info, totalForObs, true, 40);
294 lower += res.first;
295 upper += res.second;
296 }
297 if (lower > 0) {
298 lower -= 1;
299 upper -= 1;
300 }
301 return std::make_pair(lower, upper);
302}
303
305 uint64_t result = 0;
306 for (uint64_t i = 0; i < getNumberOfObservations(); ++i) {
307 result += winningRegion[i].size() * observationSizes[i];
308 }
309 return result;
310}
311
312void WinningRegion::storeToFile(std::string const& path, std::string const& preamble, bool append) const {
313 std::ofstream file;
314 storm::io::openFile(path, file, append);
315 file << ":preamble\n";
316 file << preamble << '\n';
317 file << ":winningregion\n";
318 bool firstLine = true;
319 for (auto const& i : observationSizes) {
320 if (!firstLine) {
321 file << " ";
322 } else {
323 firstLine = false;
324 }
325 file << i;
326 }
327 file << '\n';
328 for (auto const& obsWr : winningRegion) {
329 for (auto const& bv : obsWr) {
330 bv.store(file);
331 file << ";";
332 }
333 file << '\n';
334 }
336}
337
338std::pair<WinningRegion, std::string> WinningRegion::loadFromFile(std::string const& path) {
339 std::ifstream file;
340 std::vector<uint64_t> observationSizes;
341 storm::io::openFile(path, file);
342 std::string line;
343 uint64_t state = 0; // 0 = expect preamble
344 uint64_t observation = 0;
345 WinningRegion wr({1});
346 std::stringstream preamblestream;
347 while (storm::io::getline(file, line)) {
348 if (boost::starts_with(line, "#")) {
349 continue;
350 }
351 if (state == 0) {
352 STORM_LOG_THROW(line == ":preamble", storm::exceptions::WrongFormatException, "Expected to see :preamble");
353 state = 1; // state = 1: preamble
354 } else if (state == 1) {
355 if (line == ":winningregion") {
356 state = 2; // get sizes
357 } else {
358 preamblestream << line << '\n';
359 }
360 } else if (state == 2) {
361 std::vector<std::string> entries;
362 boost::split(entries, line, boost::is_space());
363 std::vector<uint64_t> observationSizes;
364 for (auto const& entry : entries) {
365 observationSizes.push_back(std::stoul(entry));
366 }
367 wr = WinningRegion(observationSizes);
368 state = 3;
369 } else if (state == 3) {
370 std::vector<std::string> entries;
371 boost::split(entries, line, boost::is_any_of(";"));
372 entries.pop_back();
373 for (std::string const& bvString : entries) {
374 wr.update(observation, storm::storage::BitVector::load(bvString));
375 }
376 ++observation;
377 }
378 }
380 return {wr, preamblestream.str()};
381}
382
383} // namespace pomdp
384} // namespace storm
static std::pair< WinningRegion, std::string > loadFromFile(std::string const &path)
std::pair< storm::RationalNumber, storm::RationalNumber > computeNrWinningBeliefs() const
bool update(uint64_t observation, storm::storage::BitVector const &winning)
void addTargetStates(uint64_t observation, storm::storage::BitVector const &offsets)
WinningRegion(std::vector< uint64_t > const &observationSizes={})
std::vector< storm::storage::BitVector > const & getWinningSetsPerObservation(uint64_t observation) const
uint64_t getNumberOfObservations() const
How many different observations are there?
storm::RationalNumber beliefSupportStates() const
storm::expressions::Expression extensionExpression(uint64_t observation, std::vector< storm::expressions::Expression > &varsForStates) const
bool query(uint64_t observation, storm::storage::BitVector const &currently) const
bool observationIsWinning(uint64_t observation) const
If we observe this observation, do we surely win?
void setObservationIsWinning(uint64_t observation)
void storeToFile(std::string const &path, std::string const &preamble="", bool append=false) const
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
static BitVector load(std::string const &description)
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
Expression conjunction(std::vector< storm::expressions::Expression > const &expressions)
Expression disjunction(std::vector< storm::expressions::Expression > const &expressions)
Expression implies(Expression const &first, Expression const &second)
std::basic_istream< CharT, Traits > & getline(std::basic_istream< CharT, Traits > &input, std::basic_string< CharT, Traits, Allocator > &str)
Overloaded getline function which handles different types of newline ( and \r).
Definition file.h:80
void closeFile(std::ofstream &stream)
Close the given file after writing.
Definition file.h:47
void openFile(std::string const &filepath, std::ofstream &filestream, bool append=false, bool silent=false)
Open the given file for writing.
Definition file.h:18
std::pair< storm::RationalNumber, storm::RationalNumber > count(std::vector< storm::storage::BitVector > const &origSets, std::vector< storm::storage::BitVector > const &intersects, std::vector< storm::storage::BitVector > const &intersectsInfo, storm::RationalNumber val, bool plus, uint64_t remdepth)
ValueType max(ValueType const &first, ValueType const &second)
ValueType min(ValueType const &first, ValueType const &second)
ValueType abs(ValueType const &number)