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