Browse Source

cleanup

tempestpy_adaptions
Sebastian Junges 4 years ago
parent
commit
32c88825e2
  1. 6
      CHANGELOG.md
  2. 45
      src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp
  3. 86
      src/storm-pomdp/generator/NondeterministicBeliefTracker.h
  4. 25
      src/storm-pomdp/transformer/ObservationTraceUnfolder.h

6
CHANGELOG.md

@ -8,6 +8,12 @@ The releases of major and minor versions contain an overview of changes since th
Version 1.6.x Version 1.6.x
------------- -------------
## Version 1.6.3 (20xx/xx)
- Simulator supports exact arithmetic
- `storm-pomdp`: States can be labelled with values for observable predicates
- `storm-pomdp`: (Only API) Track state estimates
- `storm-pomdp`: (Only API) Reduce computation of state estimates to computation on unrolled MDP
## Version 1.6.2 (2020/09) ## Version 1.6.2 (2020/09)
- Prism program simplification improved. - Prism program simplification improved.
- Revamped implementation of long-run-average algorithms, including scheduler export for LRA properties on Markov automata. - Revamped implementation of long-run-average algorithms, including scheduler export for LRA properties on Markov automata.

45
src/storm-pomdp/generator/NondeterministicBeliefTracker.cpp

@ -153,48 +153,12 @@ namespace storm {
//return std::equal(lhs.belief.begin(), lhs.belief.end(), rhs.belief.begin()); //return std::equal(lhs.belief.begin(), lhs.belief.end(), rhs.belief.begin());
} }
template<typename ValueType>
SparseBeliefState<ValueType> SparseBeliefState<ValueType>::update(uint64_t action, uint32_t observation) const {
std::map<uint64_t, ValueType> newBelief;
ValueType sum = storm::utility::zero<ValueType>();
for (auto const& beliefentry : belief) {
assert(manager->getPomdp().getNumberOfChoices(beliefentry.first) > action);
auto row = manager->getPomdp().getNondeterministicChoiceIndices()[beliefentry.first] + action;
for (auto const& transition : manager->getPomdp().getTransitionMatrix().getRow(row)) {
if (observation != manager->getPomdp().getObservation(transition.getColumn())) {
continue;
}
if (newBelief.count(transition.getColumn()) == 0) {
newBelief[transition.getColumn()] = transition.getValue() * beliefentry.second;
} else {
newBelief[transition.getColumn()] += transition.getValue() * beliefentry.second;
}
sum += transition.getValue() * beliefentry.second;
}
}
std::size_t newHash = 0;
ValueType risk = storm::utility::zero<ValueType>();
for(auto& entry : newBelief) {
assert(!storm::utility::isZero(sum));
entry.second /= sum;
//boost::hash_combine(newHash, std::hash<ValueType>()(entry.second));
boost::hash_combine(newHash, entry.first);
risk += entry.second * manager->getRisk(entry.first);
}
return SparseBeliefState<ValueType>(manager, newBelief, newHash, risk, id);
}
template<typename ValueType> template<typename ValueType>
void SparseBeliefState<ValueType>::update(uint32_t newObservation, std::unordered_set<SparseBeliefState<ValueType>>& previousBeliefs) const { void SparseBeliefState<ValueType>::update(uint32_t newObservation, std::unordered_set<SparseBeliefState<ValueType>>& previousBeliefs) const {
updateHelper({{}}, {storm::utility::zero<ValueType>()}, belief.begin(), newObservation, previousBeliefs); updateHelper({{}}, {storm::utility::zero<ValueType>()}, belief.begin(), newObservation, previousBeliefs);
} }
template<typename ValueType>
Eigen::Matrix<ValueType, Eigen::Dynamic, 1> SparseBeliefState<ValueType>::toEigenVector(storm::storage::BitVector const& support) const {
assert(false);
}
template<typename ValueType> template<typename ValueType>
uint64_t SparseBeliefState<ValueType>::getSupportSize() const { uint64_t SparseBeliefState<ValueType>::getSupportSize() const {
return manager->getNumberOfStates(); return manager->getNumberOfStates();
@ -385,11 +349,6 @@ namespace storm {
return risk; return risk;
} }
template<typename ValueType>
Eigen::Matrix<ValueType, Eigen::Dynamic, 1> ObservationDenseBeliefState<ValueType>::toEigenVector(storm::storage::BitVector const& support) const {
return storm::adapters::EigenAdapter::toEigenVector(storm::utility::vector::filterVector(belief, support));
}
template<typename ValueType> template<typename ValueType>
uint64_t ObservationDenseBeliefState<ValueType>::getSupportSize() const { uint64_t ObservationDenseBeliefState<ValueType>::getSupportSize() const {
return belief.size(); return belief.size();
@ -398,8 +357,6 @@ namespace storm {
template<typename ValueType> template<typename ValueType>
void ObservationDenseBeliefState<ValueType>::setSupport(storm::storage::BitVector& support) const { void ObservationDenseBeliefState<ValueType>::setSupport(storm::storage::BitVector& support) const {
storm::utility::vector::setNonzeroIndices(belief, support); storm::utility::vector::setNonzeroIndices(belief, support);
std::cout << "Belief is " << storm::utility::vector::toString(belief) << std::endl;
std::cout << "Support is now " << support << std::endl;
} }
@ -450,7 +407,6 @@ namespace storm {
bool NondeterministicBeliefTracker<ValueType, BeliefState>::track(uint64_t newObservation) { bool NondeterministicBeliefTracker<ValueType, BeliefState>::track(uint64_t newObservation) {
STORM_LOG_THROW(!beliefs.empty(), storm::exceptions::InvalidOperationException, "Cannot track without a belief (need to reset)."); STORM_LOG_THROW(!beliefs.empty(), storm::exceptions::InvalidOperationException, "Cannot track without a belief (need to reset).");
std::unordered_set<BeliefState> newBeliefs; std::unordered_set<BeliefState> newBeliefs;
//for (uint64_t action = 0; action < manager->getActionsForObservation(lastObservation); ++action) {
storm::utility::Stopwatch trackTimer(true); storm::utility::Stopwatch trackTimer(true);
for (auto const& belief : beliefs) { for (auto const& belief : beliefs) {
belief.update(newObservation, newBeliefs); belief.update(newObservation, newBeliefs);
@ -458,7 +414,6 @@ namespace storm {
return false; return false;
} }
} }
//}
beliefs = newBeliefs; beliefs = newBeliefs;
lastObservation = newObservation; lastObservation = newObservation;
return !beliefs.empty(); return !beliefs.empty();

86
src/storm-pomdp/generator/NondeterministicBeliefTracker.h

@ -1,9 +1,12 @@
#pragma once #pragma once
#include "storm/models/sparse/Pomdp.h" #include "storm/models/sparse/Pomdp.h"
#include "storm/adapters/EigenAdapter.h"
namespace storm { namespace storm {
namespace generator { namespace generator {
/**
* This class keeps track of common information of a set of beliefs.
* It also keeps a reference to the POMDP. The manager is referenced by all beliefs.
*/
template<typename ValueType> template<typename ValueType>
class BeliefStateManager { class BeliefStateManager {
public: public:
@ -28,22 +31,41 @@ namespace storm {
std::vector<std::vector<uint64_t>> statePerObservationAndOffset; std::vector<std::vector<uint64_t>> statePerObservationAndOffset;
}; };
template<typename ValueType> template<typename ValueType>
class SparseBeliefState; class SparseBeliefState;
template<typename ValueType> template<typename ValueType>
bool operator==(SparseBeliefState<ValueType> const& lhs, SparseBeliefState<ValueType> const& rhs); bool operator==(SparseBeliefState<ValueType> const& lhs, SparseBeliefState<ValueType> const& rhs);
/**
* SparseBeliefState stores beliefs in a sparse format.
*/
template<typename ValueType> template<typename ValueType>
class SparseBeliefState { class SparseBeliefState {
public: public:
SparseBeliefState(std::shared_ptr<BeliefStateManager<ValueType>> const& manager, uint64_t state); SparseBeliefState(std::shared_ptr<BeliefStateManager<ValueType>> const& manager, uint64_t state);
SparseBeliefState update(uint64_t action, uint32_t observation) const;
/**
* Update the belief using the new observation
* @param newObservation
* @param previousBeliefs put the new belief in this set
*/
void update(uint32_t newObservation, std::unordered_set<SparseBeliefState>& previousBeliefs) const; void update(uint32_t newObservation, std::unordered_set<SparseBeliefState>& previousBeliefs) const;
std::size_t hash() const noexcept; std::size_t hash() const noexcept;
/**
* Get the estimate to be in the given state
* @param state
* @return
*/
ValueType get(uint64_t state) const; ValueType get(uint64_t state) const;
/**
* Get the weighted risk
* @return
*/
ValueType getRisk() const; ValueType getRisk() const;
// Various getters
std::string toString() const; std::string toString() const;
bool isValid() const; bool isValid() const;
Eigen::Matrix<ValueType, Eigen::Dynamic, 1> toEigenVector(storm::storage::BitVector const& support) const;
uint64_t getSupportSize() const; uint64_t getSupportSize() const;
void setSupport(storm::storage::BitVector&) const; void setSupport(storm::storage::BitVector&) const;
std::map<uint64_t, ValueType> const& getBeliefMap() const; std::map<uint64_t, ValueType> const& getBeliefMap() const;
@ -61,7 +83,9 @@ namespace storm {
uint64_t prevId; uint64_t prevId;
}; };
/**
* ObservationDenseBeliefState stores beliefs in a dense format (per observation).
*/
template<typename ValueType> template<typename ValueType>
class ObservationDenseBeliefState; class ObservationDenseBeliefState;
template<typename ValueType> template<typename ValueType>
@ -76,7 +100,6 @@ namespace storm {
ValueType get(uint64_t state) const; ValueType get(uint64_t state) const;
ValueType getRisk() const; ValueType getRisk() const;
std::string toString() const; std::string toString() const;
Eigen::Matrix<ValueType, Eigen::Dynamic, 1> toEigenVector(storm::storage::BitVector const& support) const;
uint64_t getSupportSize() const; uint64_t getSupportSize() const;
void setSupport(storm::storage::BitVector&) const; void setSupport(storm::storage::BitVector&) const;
friend bool operator==<>(ObservationDenseBeliefState<ValueType> const& lhs, ObservationDenseBeliefState<ValueType> const& rhs); friend bool operator==<>(ObservationDenseBeliefState<ValueType> const& lhs, ObservationDenseBeliefState<ValueType> const& rhs);
@ -93,10 +116,15 @@ namespace storm {
uint64_t prevId; uint64_t prevId;
}; };
/**
* This tracker implements state estimation for POMDPs.
* This corresponds to forward filtering in Junges, Torfah, Seshia.
*
* @tparam ValueType How are probabilities stored
* @tparam BeliefState What format to use for beliefs
*/
template<typename ValueType, typename BeliefState> template<typename ValueType, typename BeliefState>
class NondeterministicBeliefTracker { class NondeterministicBeliefTracker {
public: public:
struct Options { struct Options {
uint64_t trackTimeOut = 0; uint64_t trackTimeOut = 0;
@ -104,15 +132,59 @@ namespace storm {
ValueType wiggle; // tolerance, anything above 0 means that we are incomplete. ValueType wiggle; // tolerance, anything above 0 means that we are incomplete.
}; };
NondeterministicBeliefTracker(storm::models::sparse::Pomdp<ValueType> const& pomdp, typename NondeterministicBeliefTracker<ValueType, BeliefState>::Options options = Options()); NondeterministicBeliefTracker(storm::models::sparse::Pomdp<ValueType> const& pomdp, typename NondeterministicBeliefTracker<ValueType, BeliefState>::Options options = Options());
/**
* Start with a new trace.
* @param observation The initial observation to start with.
* @return
*/
bool reset(uint32_t observation); bool reset(uint32_t observation);
/**
* Extend the observed trace with the new observation
* @param newObservation
* @return
*/
bool track(uint64_t newObservation); bool track(uint64_t newObservation);
/**
* Provides access to the current beliefs.
* @return
*/
std::unordered_set<BeliefState> const& getCurrentBeliefs() const; std::unordered_set<BeliefState> const& getCurrentBeliefs() const;
/**
* What was the last obervation that we made?
* @return
*/
uint32_t getCurrentObservation() const; uint32_t getCurrentObservation() const;
/**
* How many beliefs are we currently tracking?
* @return
*/
uint64_t getNumberOfBeliefs() const; uint64_t getNumberOfBeliefs() const;
/**
* What is the (worst-case/best-case) risk over all beliefs
* @param max Should we take the max or the min?
* @return
*/
ValueType getCurrentRisk(bool max=true); ValueType getCurrentRisk(bool max=true);
/**
* Sets the state-risk to use for all beliefs.
* @param risk
*/
void setRisk(std::vector<ValueType> const& risk); void setRisk(std::vector<ValueType> const& risk);
/**
* What is the dimension of the current set of beliefs, i.e.,
* what is the number of states we could possibly be in?
* @return
*/
uint64_t getCurrentDimension() const; uint64_t getCurrentDimension() const;
/**
* Apply reductions to the belief state
* @return
*/
uint64_t reduce(); uint64_t reduce();
/**
* Did we time out during the computation?
* @return
*/
bool hasTimedOut() const; bool hasTimedOut() const;
private: private:

25
src/storm-pomdp/transformer/ObservationTraceUnfolder.h

@ -2,13 +2,38 @@
namespace storm { namespace storm {
namespace pomdp { namespace pomdp {
/**
* Observation-trace unrolling to allow model checking for monitoring.
* This approach is outlined in Junges, Hazem, Seshia -- Runtime Monitoring for Markov Decision Processes
* @tparam ValueType ValueType for probabilities
*/
template<typename ValueType> template<typename ValueType>
class ObservationTraceUnfolder { class ObservationTraceUnfolder {
public: public:
/**
* Initialize
* @param model the MDP with state-based observations
* @param risk the state risk
* @param exprManager an Expression Manager
*/
ObservationTraceUnfolder(storm::models::sparse::Pomdp<ValueType> const& model, std::vector<ValueType> const& risk, std::shared_ptr<storm::expressions::ExpressionManager>& exprManager); ObservationTraceUnfolder(storm::models::sparse::Pomdp<ValueType> const& model, std::vector<ValueType> const& risk, std::shared_ptr<storm::expressions::ExpressionManager>& exprManager);
/**
* Transform in one shot
* @param observations
* @return
*/
std::shared_ptr<storm::models::sparse::Mdp<ValueType>> transform(std::vector<uint32_t> const& observations); std::shared_ptr<storm::models::sparse::Mdp<ValueType>> transform(std::vector<uint32_t> const& observations);
/**
* Transform incrementaly
* @param observation
* @return
*/
std::shared_ptr<storm::models::sparse::Mdp<ValueType>> extend(uint32_t observation); std::shared_ptr<storm::models::sparse::Mdp<ValueType>> extend(uint32_t observation);
/**
* When using the incremental approach, reset the observations made so far.
* @param observation The new initial observation
*/
void reset(uint32_t observation); void reset(uint32_t observation);
private: private:
storm::models::sparse::Pomdp<ValueType> const& model; storm::models::sparse::Pomdp<ValueType> const& model;

Loading…
Cancel
Save