Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
NondeterministicBeliefTracker.cpp
Go to the documentation of this file.
1
8
9namespace storm {
10namespace generator {
11
12template<typename ValueType>
14 numberActionsPerObservation = std::vector<uint64_t>(pomdp.getNrObservations(), 0);
15 statePerObservationAndOffset = std::vector<std::vector<uint64_t>>(pomdp.getNrObservations(), std::vector<uint64_t>());
16 for (uint64_t state = 0; state < pomdp.getNumberOfStates(); ++state) {
17 numberActionsPerObservation[pomdp.getObservation(state)] = pomdp.getNumberOfChoices(state);
18 statePerObservationAndOffset[pomdp.getObservation(state)].push_back(state);
19 observationOffsetId.push_back(statePerObservationAndOffset[pomdp.getObservation(state)].size() - 1);
20 }
21}
22
23template<typename ValueType>
24uint32_t BeliefStateManager<ValueType>::getObservation(uint64_t state) const {
25 return pomdp.getObservation(state);
26}
27
28template<typename ValueType>
30 return pomdp.getNumberOfStates();
31}
32
33template<typename ValueType>
34uint64_t BeliefStateManager<ValueType>::getActionsForObservation(uint32_t observation) const {
35 return numberActionsPerObservation[observation];
36}
37
38template<typename ValueType>
39ValueType BeliefStateManager<ValueType>::getRisk(uint64_t state) const {
40 return riskPerState.at(state);
41}
42
43template<typename ValueType>
47
48template<typename ValueType>
49void BeliefStateManager<ValueType>::setRiskPerState(std::vector<ValueType> const& risk) {
50 riskPerState = risk;
51}
52
53template<typename ValueType>
55 beliefIdCounter++;
56 return beliefIdCounter;
57}
58
59template<typename ValueType>
61 STORM_LOG_ASSERT(state < observationOffsetId.size(), "State " << state << " not a state id");
62 return observationOffsetId[state];
63}
64
65template<typename ValueType>
67 STORM_LOG_ASSERT(observation < observationOffsetId.size(), "Observation " << observation << " not an observation id");
68 return statePerObservationAndOffset[observation].size();
69}
70
71template<typename ValueType>
72uint64_t BeliefStateManager<ValueType>::getState(uint32_t obs, uint64_t offset) const {
73 STORM_LOG_ASSERT(obs < statePerObservationAndOffset.size(), "Obs " << obs << " not a known observatoin");
74 STORM_LOG_ASSERT(offset < statePerObservationAndOffset[obs].size(), "Offset " << offset << " too high for observation " << obs);
75 return statePerObservationAndOffset[obs][offset];
76}
77
78template<typename ValueType>
80 : manager(manager), belief(), id(0), prevId(0) {
81 id = manager->getFreshId();
82 belief[state] = storm::utility::one<ValueType>();
83 risk = manager->getRisk(state);
84}
85
86template<typename ValueType>
87SparseBeliefState<ValueType>::SparseBeliefState(std::shared_ptr<BeliefStateManager<ValueType>> const& manager, std::map<uint64_t, ValueType> const& belief,
88 std::size_t hash, ValueType const& risk, uint64_t prevId)
89 : manager(manager), belief(belief), prestoredhash(hash), risk(risk), id(0), prevId(prevId) {
90 id = manager->getFreshId();
91}
92
93template<typename ValueType>
94ValueType SparseBeliefState<ValueType>::get(uint64_t state) const {
95 return belief.at(state);
96}
97
98template<typename ValueType>
100 return risk;
101}
102
103template<typename ValueType>
104std::size_t SparseBeliefState<ValueType>::hash() const noexcept {
105 return prestoredhash;
106}
107
108template<typename ValueType>
110 return !belief.empty();
111}
112
113template<typename ValueType>
115 std::stringstream sstr;
116 sstr << "id: " << id << "; ";
117 bool first = true;
118 for (auto const& beliefentry : belief) {
119 if (!first) {
120 sstr << ", ";
121 } else {
122 first = false;
123 }
124 sstr << beliefentry.first << " : " << beliefentry.second;
125 }
126 sstr << " (from " << prevId << ")";
127 return sstr.str();
128}
129
130template<typename ValueType>
132 if (lhs.hash() != rhs.hash()) {
133 return false;
134 }
135 if (lhs.belief.size() != rhs.belief.size()) {
136 return false;
137 }
138 storm::utility::ConstantsComparator<ValueType> cmp(storm::utility::convertNumber<ValueType>(0.00001), true);
139 auto lhsIt = lhs.belief.begin();
140 auto rhsIt = rhs.belief.begin();
141 while (lhsIt != lhs.belief.end()) {
142 if (lhsIt->first != rhsIt->first || !cmp.isEqual(lhsIt->second, rhsIt->second)) {
143 return false;
144 }
145 ++lhsIt;
146 ++rhsIt;
147 }
148 return true;
149 // return std::equal(lhs.belief.begin(), lhs.belief.end(), rhs.belief.begin());
150}
151
152template<typename ValueType>
153void SparseBeliefState<ValueType>::update(uint32_t newObservation, std::unordered_set<SparseBeliefState<ValueType>>& previousBeliefs) const {
154 updateHelper({{}}, {storm::utility::zero<ValueType>()}, belief.begin(), newObservation, previousBeliefs);
155}
156
157template<typename ValueType>
159 return manager->getNumberOfStates();
160}
161
162template<typename ValueType>
163std::map<uint64_t, ValueType> const& SparseBeliefState<ValueType>::getBeliefMap() const {
164 return belief;
165}
166
167template<typename ValueType>
169 for (auto const& entry : belief) {
170 support.set(entry.first, true);
171 }
172}
173
174template<typename ValueType>
175void SparseBeliefState<ValueType>::updateHelper(std::vector<std::map<uint64_t, ValueType>> const& partialBeliefs, std::vector<ValueType> const& sums,
176 typename std::map<uint64_t, ValueType>::const_iterator nextStateIt, uint32_t newObservation,
177 std::unordered_set<SparseBeliefState<ValueType>>& previousBeliefs) const {
178 if (nextStateIt == belief.end()) {
179 for (uint64_t i = 0; i < partialBeliefs.size(); ++i) {
180 auto const& partialBelief = partialBeliefs[i];
181 auto const& sum = sums[i];
182 if (storm::utility::isZero(sum)) {
183 continue;
184 }
185 std::size_t newHash = 0;
186 ValueType risk = storm::utility::zero<ValueType>();
187 std::map<uint64_t, ValueType> finalBelief;
188 for (auto& entry : partialBelief) {
189 assert(!storm::utility::isZero(sum));
190 finalBelief[entry.first] = entry.second / sum;
191 // boost::hash_combine(newHash, std::hash<ValueType>()(entry.second));
192 boost::hash_combine(newHash, entry.first);
193 risk += entry.second / sum * manager->getRisk(entry.first);
194 }
195 previousBeliefs.insert(SparseBeliefState<ValueType>(manager, finalBelief, newHash, risk, id));
196 }
197 } else {
198 uint64_t state = nextStateIt->first;
199 auto newNextStateIt = nextStateIt;
200 newNextStateIt++;
201 std::vector<std::map<uint64_t, ValueType>> newPartialBeliefs;
202 std::vector<ValueType> newSums;
203 for (uint64_t i = 0; i < partialBeliefs.size(); ++i) {
204 for (auto row = manager->getPomdp().getNondeterministicChoiceIndices()[state];
205 row < manager->getPomdp().getNondeterministicChoiceIndices()[state + 1]; ++row) {
206 std::map<uint64_t, ValueType> newPartialBelief = partialBeliefs[i];
207 ValueType newSum = sums[i];
208 for (auto const& transition : manager->getPomdp().getTransitionMatrix().getRow(row)) {
209 if (newObservation != manager->getPomdp().getObservation(transition.getColumn())) {
210 continue;
211 }
212
213 if (newPartialBelief.count(transition.getColumn()) == 0) {
214 newPartialBelief[transition.getColumn()] = transition.getValue() * nextStateIt->second;
215 } else {
216 newPartialBelief[transition.getColumn()] += transition.getValue() * nextStateIt->second;
217 }
218 newSum += transition.getValue() * nextStateIt->second;
219 }
220 newPartialBeliefs.push_back(newPartialBelief);
221 newSums.push_back(newSum);
222 }
223 }
224 updateHelper(newPartialBeliefs, newSums, newNextStateIt, newObservation, previousBeliefs);
225 }
226}
227
228template<typename ValueType>
230 if (lhs.hash() != rhs.hash()) {
231 return false;
232 }
233 if (lhs.observation != rhs.observation) {
234 return false;
235 }
237 auto lhsIt = lhs.belief.begin();
238 auto rhsIt = rhs.belief.begin();
239 while (lhsIt != lhs.belief.end()) {
240 if (!cmp.isEqual(*lhsIt, *rhsIt)) {
241 return false;
242 }
243 ++lhsIt;
244 ++rhsIt;
245 }
246 return true;
247 // return std::equal(lhs.belief.begin(), lhs.belief.end(), rhs.belief.begin());
248}
249
250template<typename ValueType>
252 : manager(manager), belief(manager->numberOfStatesPerObservation(manager->getObservation(state))) {
253 observation = manager->getObservation(state);
254 belief[manager->getObservationOffset(state)] = storm::utility::one<ValueType>();
255}
256
257template<typename ValueType>
259 std::vector<ValueType> const& belief, std::size_t newHash, ValueType const& risk,
260 uint64_t prevId)
261 : manager(manager), belief(belief), observation(observation), prestoredhash(newHash), risk(risk), id(manager->getFreshId()), prevId(prevId) {
262 // Intentionally left empty.
263}
264
265template<typename ValueType>
266void ObservationDenseBeliefState<ValueType>::update(uint32_t newObservation, std::unordered_set<ObservationDenseBeliefState>& previousBeliefs) const {
267 updateHelper({{}}, {storm::utility::zero<ValueType>()}, 0, newObservation, previousBeliefs);
268}
269
270template<typename ValueType>
271void ObservationDenseBeliefState<ValueType>::updateHelper(std::vector<std::map<uint64_t, ValueType>> const& partialBeliefs, std::vector<ValueType> const& sums,
272 uint64_t currentEntry, uint32_t newObservation,
273 std::unordered_set<ObservationDenseBeliefState<ValueType>>& previousBeliefs) const {
274 while (currentEntry != belief.size() && storm::utility::isZero(belief[currentEntry])) {
275 currentEntry++;
276 }
277 if (currentEntry == belief.size()) {
278 for (uint64_t i = 0; i < partialBeliefs.size(); ++i) {
279 auto const& partialBelief = partialBeliefs[i];
280 auto const& sum = sums[i];
281 if (storm::utility::isZero(sum)) {
282 continue;
283 }
284 std::size_t newHash = 0;
285 ValueType risk = storm::utility::zero<ValueType>();
286 std::vector<ValueType> finalBelief(manager->numberOfStatesPerObservation(observation), storm::utility::zero<ValueType>());
287 for (auto& entry : partialBelief) {
288 assert(!storm::utility::isZero(sum));
289 finalBelief[manager->getObservationOffset(entry.first)] = (entry.second / sum);
290 // boost::hash_combine(newHash, std::hash<ValueType>()(entry.second));
291 boost::hash_combine(newHash, entry.first);
292 risk += entry.second / sum * manager->getRisk(entry.first);
293 }
294 previousBeliefs.insert(ObservationDenseBeliefState<ValueType>(manager, newObservation, finalBelief, newHash, risk, id));
295 }
296 } else {
297 uint64_t state = manager->getState(observation, currentEntry);
298 uint64_t nextEntry = currentEntry + 1;
299 std::vector<std::map<uint64_t, ValueType>> newPartialBeliefs;
300 std::vector<ValueType> newSums;
301 for (uint64_t i = 0; i < partialBeliefs.size(); ++i) {
302 for (auto row = manager->getPomdp().getNondeterministicChoiceIndices()[state];
303 row < manager->getPomdp().getNondeterministicChoiceIndices()[state + 1]; ++row) {
304 std::map<uint64_t, ValueType> newPartialBelief = partialBeliefs[i];
305 ValueType newSum = sums[i];
306 for (auto const& transition : manager->getPomdp().getTransitionMatrix().getRow(row)) {
307 if (newObservation != manager->getPomdp().getObservation(transition.getColumn())) {
308 continue;
309 }
310
311 if (newPartialBelief.count(transition.getColumn()) == 0) {
312 newPartialBelief[transition.getColumn()] = transition.getValue() * belief[currentEntry];
313 } else {
314 newPartialBelief[transition.getColumn()] += transition.getValue() * belief[currentEntry];
315 }
316 newSum += transition.getValue() * belief[currentEntry];
317 }
318 newPartialBeliefs.push_back(newPartialBelief);
319 newSums.push_back(newSum);
320 }
321 }
322 updateHelper(newPartialBeliefs, newSums, nextEntry, newObservation, previousBeliefs);
323 }
324}
325
326template<typename ValueType>
328 return prestoredhash;
329}
330
331template<typename ValueType>
332ValueType ObservationDenseBeliefState<ValueType>::get(uint64_t state) const {
333 if (manager->getObservation(state) != state) {
334 return storm::utility::zero<ValueType>();
335 }
336 return belief[manager->getObservationOffset(state)];
337}
338
339template<typename ValueType>
341 return risk;
342}
343
344template<typename ValueType>
346 return belief.size();
347}
348
349template<typename ValueType>
353
354template<typename ValueType>
356 std::stringstream sstr;
357 sstr << "id: " << id << "; ";
358 bool first = true;
359 uint64_t i = 0;
360 for (auto const& beliefentry : belief) {
361 if (!storm::utility::isZero(beliefentry)) {
362 if (!first) {
363 sstr << ", ";
364 } else {
365 first = false;
366 }
367
368 sstr << manager->getState(observation, i) << " : " << beliefentry;
369 }
370 i++;
371 }
372 sstr << " (from " << prevId << ")";
373 return sstr.str();
374}
375
376template<typename ValueType, typename BeliefState>
379 : pomdp(pomdp), manager(std::make_shared<BeliefStateManager<ValueType>>(pomdp)), beliefs(), options(options) {
380 //
381}
382
383template<typename ValueType, typename BeliefState>
385 bool hit = false;
386 for (auto state : pomdp.getInitialStates()) {
387 if (observation == pomdp.getObservation(state)) {
388 hit = true;
389 beliefs.emplace(manager, state);
390 }
391 }
392 lastObservation = observation;
393 return hit;
394}
395
396template<typename ValueType, typename BeliefState>
398 STORM_LOG_THROW(!beliefs.empty(), storm::exceptions::InvalidOperationException, "Cannot track without a belief (need to reset).");
399 std::unordered_set<BeliefState> newBeliefs;
400 storm::utility::Stopwatch trackTimer(true);
401 for (auto const& belief : beliefs) {
402 belief.update(newObservation, newBeliefs);
403 if (options.trackTimeOut > 0 && static_cast<uint64_t>(trackTimer.getTimeInMilliseconds()) > options.trackTimeOut) {
404 return false;
405 }
406 }
407 beliefs = newBeliefs;
408 lastObservation = newObservation;
409 return !beliefs.empty();
410}
411
412template<typename ValueType, typename BeliefState>
414 STORM_LOG_THROW(!beliefs.empty(), storm::exceptions::InvalidOperationException, "Risk is only defined for beliefs (run reset() first).");
415 ValueType result = beliefs.begin()->getRisk();
416 if (max) {
417 for (auto const& belief : beliefs) {
418 if (belief.getRisk() > result) {
419 result = belief.getRisk();
420 }
421 }
422 } else {
423 for (auto const& belief : beliefs) {
424 if (belief.getRisk() < result) {
425 result = belief.getRisk();
426 }
427 }
428 }
429 return result;
430}
431
432template<typename ValueType, typename BeliefState>
434 manager->setRiskPerState(risk);
435}
436
437template<typename ValueType, typename BeliefState>
439 return beliefs;
440}
441
442template<typename ValueType, typename BeliefState>
446
447template<typename ValueType, typename BeliefState>
449 return beliefs.size();
450}
451
452template<typename ValueType, typename BeliefState>
454 storm::storage::BitVector support(beliefs.begin()->getSupportSize());
455 for (auto const& belief : beliefs) {
456 belief.setSupport(support);
457 }
458 return support.getNumberOfSetBits();
459}
460
461//
462template<typename ValueType, typename BeliefState>
464 reductionTimedOut = false;
465 std::shared_ptr<storm::utility::solver::SmtSolverFactory> solverFactory = std::make_shared<storm::utility::solver::Z3SmtSolverFactory>();
466 storm::storage::geometry::ReduceVertexCloud<ValueType> rvc(solverFactory, options.wiggle, options.timeOut);
467 std::vector<std::map<uint64_t, ValueType>> points;
468 std::vector<typename std::unordered_set<BeliefState>::iterator> iterators;
469 for (auto it = beliefs.begin(); it != beliefs.end(); ++it) {
470 // TODO get rid of the getBeliefMap function.
471 points.push_back(it->getBeliefMap());
472 iterators.push_back(it);
473 }
474 auto res = rvc.eliminate(points, pomdp.getNumberOfStates());
475 storm::storage::BitVector eliminate = ~res.first;
476 if (res.second) {
477 reductionTimedOut = true;
478 }
479
480 auto selectedIterators = storm::utility::vector::filterVector(iterators, eliminate);
481 for (auto iter : selectedIterators) {
482 beliefs.erase(iter);
483 }
484 return eliminate.getNumberOfSetBits();
485}
486
487template<typename ValueType, typename BeliefState>
489 return reductionTimedOut;
490}
491
492template class SparseBeliefState<double>;
495// template class ObservationDenseBeliefState<double>;
496// template bool operator==(ObservationDenseBeliefState<double> const&, ObservationDenseBeliefState<double> const&);
497// template class NondeterministicBeliefTracker<double, ObservationDenseBeliefState<double>>;
498
502
503} // namespace generator
504} // namespace storm
This class keeps track of common information of a set of beliefs.
BeliefStateManager(storm::models::sparse::Pomdp< ValueType > const &pomdp)
storm::models::sparse::Pomdp< ValueType > const & getPomdp() const
uint64_t getState(uint32_t obs, uint64_t offset) const
uint64_t numberOfStatesPerObservation(uint32_t observation) const
void setRiskPerState(std::vector< ValueType > const &risk)
uint64_t getActionsForObservation(uint32_t observation) const
This tracker implements state estimation for POMDPs.
std::unordered_set< BeliefState > const & getCurrentBeliefs() const
Provides access to the current beliefs.
NondeterministicBeliefTracker(storm::models::sparse::Pomdp< ValueType > const &pomdp, typename NondeterministicBeliefTracker< ValueType, BeliefState >::Options options=Options())
uint64_t reduce()
Apply reductions to the belief state.
ValueType getCurrentRisk(bool max=true)
What is the (worst-case/best-case) risk over all beliefs.
void setRisk(std::vector< ValueType > const &risk)
Sets the state-risk to use for all beliefs.
uint64_t getCurrentDimension() const
What is the dimension of the current set of beliefs, i.e., what is the number of states we could poss...
uint32_t getCurrentObservation() const
What was the last obervation that we made?
bool hasTimedOut() const
Did we time out during the computation?
bool reset(uint32_t observation)
Start with a new trace.
uint64_t getNumberOfBeliefs() const
How many beliefs are we currently tracking?
bool track(uint64_t newObservation)
Extend the observed trace with the new observation.
ObservationDenseBeliefState stores beliefs in a dense format (per observation).
ObservationDenseBeliefState(std::shared_ptr< BeliefStateManager< ValueType > > const &manager, uint64_t state)
void update(uint32_t newObservation, std::unordered_set< ObservationDenseBeliefState > &previousBeliefs) const
SparseBeliefState stores beliefs in a sparse format.
void setSupport(storm::storage::BitVector &) const
void update(uint32_t newObservation, std::unordered_set< SparseBeliefState > &previousBeliefs) const
Update the belief using the new observation.
std::map< uint64_t, ValueType > const & getBeliefMap() const
ValueType get(uint64_t state) const
Get the estimate to be in the given state.
ValueType getRisk() const
Get the weighted risk.
SparseBeliefState(std::shared_ptr< BeliefStateManager< ValueType > > const &manager, uint64_t state)
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:162
uint_fast64_t getNumberOfChoices(uint_fast64_t state) const
This class represents a partially observable Markov decision process.
Definition Pomdp.h:15
uint64_t getNrObservations() const
Definition Pomdp.cpp:68
uint32_t getObservation(uint64_t state) const
Definition Pomdp.cpp:63
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
std::pair< storm::storage::BitVector, bool > eliminate(std::vector< std::map< uint64_t, ValueType > > const &input, uint64_t maxdimension)
bool isEqual(ValueType const &value1, ValueType const &value2) const
A class that provides convenience operations to display run times.
Definition Stopwatch.h:14
MilisecondType getTimeInMilliseconds() const
Gets the measured time in milliseconds.
Definition Stopwatch.cpp:21
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SFTBDDChecker::ValueType ValueType
bool operator==(SparseBeliefState< ValueType > const &lhs, SparseBeliefState< ValueType > const &rhs)
SettingsManager const & manager()
Retrieves the settings manager.
void setNonzeroIndices(std::vector< T > const &vec, storm::storage::BitVector &bv)
Definition vector.h:111
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
Definition vector.h:1213
bool isZero(ValueType const &a)
Definition constants.cpp:41
LabParser.cpp.
Definition cli.cpp:18