Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
BinaryPomdpTransformer.cpp
Go to the documentation of this file.
2
3#include <queue>
4
9
10namespace storm {
11namespace transformer {
12
13template<typename ValueType>
15 // Intentionally left empty
16}
17
18template<typename ValueType>
20 bool keepStateValuations) const {
21 auto data = transformTransitions(pomdp, transformSimple);
23 components.stateLabeling = transformStateLabeling(pomdp, data);
24 for (auto const& rewModel : pomdp.getRewardModels()) {
25 components.rewardModels.emplace(rewModel.first, transformRewardModel(pomdp, rewModel.second, data));
26 }
27 components.transitionMatrix = std::move(data.simpleMatrix);
28 components.observabilityClasses = std::move(data.simpleObservations);
29 if (keepStateValuations && pomdp.hasStateValuations()) {
30 components.stateValuations = pomdp.getStateValuations().blowup(data.simpleStateToOriginalState);
31 }
33 result.transformedPomdp = std::make_shared<storm::models::sparse::Pomdp<ValueType>>(std::move(components), true);
34 result.transformedStateToOriginalStateMap = data.simpleStateToOriginalState;
35 return result;
36}
37
43
44 uint64_t origState;
45 uint64_t firstRow;
46 uint64_t endRow;
49
50 uint64_t size() const {
51 return endRow - firstRow;
52 }
53
54 std::vector<BinaryPomdpTransformerRowGroup> split() const {
55 assert(size() > 1);
56 uint64_t midRow = firstRow + size() / 2;
57 std::vector<BinaryPomdpTransformerRowGroup> res;
58 res.emplace_back(origState, firstRow, midRow, origStateObservation);
60 newAuxStateId.resize(auxStateId.size() + 1, false);
61 res.back().auxStateId = newAuxStateId;
62 res.emplace_back(origState, midRow, endRow, origStateObservation);
63 newAuxStateId.set(auxStateId.size(), true);
64 res.back().auxStateId = newAuxStateId;
65 return res;
66 }
67};
68
72 return lhs.auxStateId < rhs.auxStateId;
73 } else {
75 }
76 }
77};
78
79template<typename ValueType>
80typename BinaryPomdpTransformer<ValueType>::TransformationData BinaryPomdpTransformer<ValueType>::transformTransitions(
81 storm::models::sparse::Pomdp<ValueType> const& pomdp, bool transformSimple) const {
82 auto const& matrix = pomdp.getTransitionMatrix();
83
84 // Initialize a FIFO Queue that stores the start and the end of each row group
85 std::queue<BinaryPomdpTransformerRowGroup> queue;
86 for (uint64_t state = 0; state < matrix.getRowGroupCount(); ++state) {
87 queue.emplace(state, matrix.getRowGroupIndices()[state], matrix.getRowGroupIndices()[state + 1], pomdp.getObservation(state));
88 }
89
90 std::vector<uint32_t> newObservations;
91 std::map<BinaryPomdpTransformerRowGroup, uint32_t, BinaryPomdpTransformerRowGroupCompare> observationMap;
92 storm::storage::SparseMatrixBuilder<ValueType> builder(0, 0, 0, true, true);
93 uint64_t currRow = 0;
94 std::vector<uint64_t> origRowToSimpleRowMap(pomdp.getNumberOfChoices(), std::numeric_limits<uint64_t>::max());
95 uint64_t currAuxState = queue.size();
96 std::vector<uint64_t> origStates;
97
98 while (!queue.empty()) {
99 auto group = std::move(queue.front());
100 queue.pop();
101
102 // Get the observation
103 uint64_t newObservation = observationMap.insert(std::make_pair(group, observationMap.size())).first->second;
104 newObservations.push_back(newObservation);
105
106 // Add matrix entries
107 builder.newRowGroup(currRow);
108 if (group.size() == 1) {
109 // Insert the row directly
110 for (auto const& entry : matrix.getRow(group.firstRow)) {
111 builder.addNextValue(currRow, entry.getColumn(), entry.getValue());
112 }
113 origRowToSimpleRowMap[group.firstRow] = currRow;
114 ++currRow;
115 } else if (group.size() > 1) {
116 // Split the row group into two equally large parts
117 for (auto& splittedGroup : group.split()) {
118 // Check whether we can insert the row now or whether an auxiliary state is needed
119 if (splittedGroup.size() == 1 && (!transformSimple || matrix.getRow(splittedGroup.firstRow).getNumberOfEntries() < 2)) {
120 for (auto const& entry : matrix.getRow(splittedGroup.firstRow)) {
121 builder.addNextValue(currRow, entry.getColumn(), entry.getValue());
122 }
123 origRowToSimpleRowMap[splittedGroup.firstRow] = currRow;
124 ++currRow;
125 } else {
126 queue.push(std::move(splittedGroup));
127 builder.addNextValue(currRow, currAuxState, storm::utility::one<ValueType>());
128 ++currAuxState;
129 ++currRow;
130 }
131 }
132 }
133 // Nothing to be done if group has size zero
134 origStates.push_back(group.origState);
135 }
136
137 TransformationData result;
138 result.simpleMatrix = builder.build(currRow, currAuxState, currAuxState);
139 result.simpleObservations = std::move(newObservations);
140 result.originalToSimpleChoiceMap = std::move(origRowToSimpleRowMap);
141 result.simpleStateToOriginalState = std::move(origStates);
142 return result;
143}
144
145template<typename ValueType>
146storm::models::sparse::StateLabeling BinaryPomdpTransformer<ValueType>::transformStateLabeling(storm::models::sparse::Pomdp<ValueType> const& pomdp,
147 TransformationData const& data) const {
148 storm::models::sparse::StateLabeling labeling(data.simpleMatrix.getRowGroupCount());
149 for (auto const& labelName : pomdp.getStateLabeling().getLabels()) {
150 storm::storage::BitVector newStates = pomdp.getStateLabeling().getStates(labelName);
151 newStates.resize(data.simpleMatrix.getRowGroupCount(), false);
152 if (labelName != "init") {
153 for (uint64_t newState = pomdp.getNumberOfStates(); newState < data.simpleMatrix.getRowGroupCount(); ++newState) {
154 newStates.set(newState, newStates[data.simpleStateToOriginalState[newState]]);
155 }
156 }
157 labeling.addLabel(labelName, std::move(newStates));
158 }
159 return labeling;
160}
161
162template<typename ValueType>
163storm::models::sparse::StandardRewardModel<ValueType> BinaryPomdpTransformer<ValueType>::transformRewardModel(
165 TransformationData const& data) const {
166 std::optional<std::vector<ValueType>> stateRewards, actionRewards;
167 if (rewardModel.hasStateRewards()) {
168 stateRewards = rewardModel.getStateRewardVector();
169 stateRewards.value().resize(data.simpleMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
170 }
171 if (rewardModel.hasStateActionRewards()) {
172 actionRewards = std::vector<ValueType>(data.simpleMatrix.getRowCount(), storm::utility::zero<ValueType>());
173 for (uint64_t pomdpChoice = 0; pomdpChoice < pomdp.getNumberOfChoices(); ++pomdpChoice) {
174 STORM_LOG_ASSERT(data.originalToSimpleChoiceMap[pomdpChoice] < data.simpleMatrix.getRowCount(), "Invalid entry in map for choice " << pomdpChoice);
175 actionRewards.value()[data.originalToSimpleChoiceMap[pomdpChoice]] = rewardModel.getStateActionReward(pomdpChoice);
176 }
177 }
178 STORM_LOG_THROW(!rewardModel.hasTransitionRewards(), storm::exceptions::NotSupportedException, "Transition rewards are currently not supported.");
179 return storm::models::sparse::StandardRewardModel<ValueType>(std::move(stateRewards), std::move(actionRewards));
180}
181
182template class BinaryPomdpTransformer<storm::RationalNumber>;
183
184template class BinaryPomdpTransformer<double>;
185template class BinaryPomdpTransformer<storm::RationalFunction>;
186} // namespace transformer
187} // namespace storm
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:199
std::unordered_map< std::string, RewardModelType > const & getRewardModels() const
Retrieves the reward models.
Definition Model.cpp:691
bool hasStateValuations() const
Retrieves whether this model was build with state valuations.
Definition Model.cpp:351
storm::storage::sparse::StateValuations const & getStateValuations() const
Retrieves the valuations of the states of the model.
Definition Model.cpp:356
storm::models::sparse::StateLabeling const & getStateLabeling() const
Returns the state labeling associated with this model.
Definition Model.cpp:321
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:164
uint_fast64_t getNumberOfChoices(uint_fast64_t state) const
This class represents a partially observable Markov decision process.
Definition Pomdp.h:13
uint32_t getObservation(uint64_t state) const
Definition Pomdp.cpp:65
bool hasTransitionRewards() const
Retrieves whether the reward model has transition rewards.
std::vector< ValueType > const & getStateRewardVector() const
Retrieves the state rewards of the reward model.
ValueType const & getStateActionReward(uint_fast64_t choiceIndex) const
Retrieves the state-action reward for the given choice.
bool hasStateRewards() const
Retrieves whether the reward model has state rewards.
bool hasStateActionRewards() const
Retrieves whether the reward model has state-action rewards.
This class manages the labeling of the state space with a number of (atomic) labels.
storm::storage::BitVector const & getStates(std::string const &label) const
Returns the labeling of states associated with the given label.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
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.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
A class that can be used to build a sparse matrix by adding value by value.
StateValuations blowup(std::vector< uint64_t > const &mapNewToOld) const
PomdpTransformationResult< ValueType > transform(storm::models::sparse::Pomdp< ValueType > const &pomdp, bool transformSimple, bool keepStateValuations=false) const
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
RewardModelType transformRewardModel(RewardModelType const &originalRewardModel, storm::storage::BitVector const &subsystem, storm::storage::BitVector const &subsystemActions, bool makeRowGroupingTrivial)
std::optional< storm::storage::sparse::StateValuations > stateValuations
std::unordered_map< std::string, RewardModelType > rewardModels
storm::storage::SparseMatrix< ValueType > transitionMatrix
storm::models::sparse::StateLabeling stateLabeling
std::optional< std::vector< uint32_t > > observabilityClasses
bool operator()(BinaryPomdpTransformerRowGroup const &lhs, BinaryPomdpTransformerRowGroup const &rhs) const
BinaryPomdpTransformerRowGroup(uint64_t origState, uint64_t firstRow, uint64_t endRow, uint32_t origStateObservation)
std::vector< BinaryPomdpTransformerRowGroup > split() const
std::shared_ptr< storm::models::sparse::Pomdp< ValueType > > transformedPomdp