Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
ObservationTraceUnfolder.cpp
Go to the documentation of this file.
2
6
7#undef _VERBOSE_OBSERVATION_UNFOLDING
8
9namespace storm {
10namespace pomdp {
11template<typename ValueType>
13 std::shared_ptr<storm::expressions::ExpressionManager>& exprManager)
14 : model(model), risk(risk), exprManager(exprManager) {
15 statesPerObservation = std::vector<storm::storage::BitVector>(model.getNrObservations() + 1, storm::storage::BitVector(model.getNumberOfStates()));
16 for (uint64_t state = 0; state < model.getNumberOfStates(); ++state) {
17 statesPerObservation[model.getObservation(state)].set(state, true);
18 }
19 svvar = exprManager->declareFreshIntegerVariable(false, "_s");
20}
21
22template<typename ValueType>
23std::shared_ptr<storm::models::sparse::Mdp<ValueType>> ObservationTraceUnfolder<ValueType>::transform(const std::vector<uint32_t>& observations) {
24 std::vector<uint32_t> modifiedObservations = observations;
25 // First observation should be special.
26 // This just makes the algorithm simpler because we do not treat the first step as a special case later.
27 modifiedObservations[0] = model.getNrObservations();
28
29 storm::storage::BitVector initialStates = model.getInitialStates();
30 storm::storage::BitVector actualInitialStates = initialStates;
31 for (uint64_t state : initialStates) {
32 if (model.getObservation(state) != observations[0]) {
33 actualInitialStates.set(state, false);
34 }
35 }
36 STORM_LOG_THROW(actualInitialStates.getNumberOfSetBits() == 1, storm::exceptions::InvalidArgumentException,
37 "Must have unique initial state matching the observation");
38 //
39 statesPerObservation[model.getNrObservations()] = actualInitialStates;
40
41#ifdef _VERBOSE_OBSERVATION_UNFOLDING
42 std::cout << "build valution builder..\n";
43#endif
45 svbuilder.addVariable(svvar);
46
47 std::map<uint64_t, uint64_t> unfoldedToOld;
48 std::map<uint64_t, uint64_t> unfoldedToOldNextStep;
49 std::map<uint64_t, uint64_t> oldToUnfolded;
50
51#ifdef _VERBOSE_OBSERVATION_UNFOLDING
52 std::cout << "start buildiing matrix...\n";
53#endif
54
55 // Add this initial state state:
56 unfoldedToOldNextStep[0] = actualInitialStates.getNextSetIndex(0);
57
58 storm::storage::SparseMatrixBuilder<ValueType> transitionMatrixBuilder(0, 0, 0, true, true);
59 uint64_t newStateIndex = 1;
60 uint64_t newRowGroupStart = 0;
61 uint64_t newRowCount = 0;
62 // Notice that we are going to use a special last step
63
64 for (uint64_t step = 0; step < observations.size() - 1; ++step) {
65 oldToUnfolded.clear();
66 unfoldedToOld = unfoldedToOldNextStep;
67 unfoldedToOldNextStep.clear();
68
69 for (auto const& unfoldedToOldEntry : unfoldedToOld) {
70 transitionMatrixBuilder.newRowGroup(newRowGroupStart);
71#ifdef _VERBOSE_OBSERVATION_UNFOLDING
72 std::cout << "\tconsider new state " << unfoldedToOldEntry.first << '\n';
73#endif
74 assert(step == 0 || newRowCount == transitionMatrixBuilder.getLastRow() + 1);
75 svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast<int64_t>(unfoldedToOldEntry.second)});
76 uint64_t oldRowIndexStart = model.getNondeterministicChoiceIndices()[unfoldedToOldEntry.second];
77 uint64_t oldRowIndexEnd = model.getNondeterministicChoiceIndices()[unfoldedToOldEntry.second + 1];
78
79 for (uint64_t oldRowIndex = oldRowIndexStart; oldRowIndex != oldRowIndexEnd; oldRowIndex++) {
80#ifdef _VERBOSE_OBSERVATION_UNFOLDING
81 std::cout << "\t\tconsider old action " << oldRowIndex << '\n';
82 std::cout << "\t\tconsider new row nr " << newRowCount << '\n';
83#endif
84
85 ValueType resetProb = storm::utility::zero<ValueType>();
86 // We first find the reset probability
87 for (auto const& oldRowEntry : model.getTransitionMatrix().getRow(oldRowIndex)) {
88 if (model.getObservation(oldRowEntry.getColumn()) != observations[step + 1]) {
89 resetProb += oldRowEntry.getValue();
90 }
91 }
92#ifdef _VERBOSE_OBSERVATION_UNFOLDING
93 std::cout << "\t\t\t add reset with probability " << resetProb << '\n';
94#endif
95
96 // Add the resets
97 if (resetProb != storm::utility::zero<ValueType>()) {
98 transitionMatrixBuilder.addNextValue(newRowCount, 0, resetProb);
99 }
100#ifdef _VERBOSE_OBSERVATION_UNFOLDING
101 std::cout << "\t\t\t add other transitions...\n";
102#endif
103
104 // Now, we build the outgoing transitions.
105 for (auto const& oldRowEntry : model.getTransitionMatrix().getRow(oldRowIndex)) {
106 if (model.getObservation(oldRowEntry.getColumn()) != observations[step + 1]) {
107 continue; // already handled.
108 }
109 uint64_t column = 0;
110
111 auto entryIt = oldToUnfolded.find(oldRowEntry.getColumn());
112 if (entryIt == oldToUnfolded.end()) {
113 column = newStateIndex;
114 oldToUnfolded[oldRowEntry.getColumn()] = column;
115 unfoldedToOldNextStep[column] = oldRowEntry.getColumn();
116 newStateIndex++;
117 } else {
118 column = entryIt->second;
119 }
120#ifdef _VERBOSE_OBSERVATION_UNFOLDING
121 std::cout << "\t\t\t\t transition to " << column << "with probability " << oldRowEntry.getValue() << '\n';
122#endif
123 transitionMatrixBuilder.addNextValue(newRowCount, column, oldRowEntry.getValue());
124 }
125 newRowCount++;
126 }
127
128 newRowGroupStart = transitionMatrixBuilder.getLastRow() + 1;
129 }
130 }
131 // Now, take care of the last step.
132 uint64_t sinkState = newStateIndex;
133 uint64_t targetState = newStateIndex + 1;
134 for (auto const& unfoldedToOldEntry : unfoldedToOldNextStep) {
135 svbuilder.addState(unfoldedToOldEntry.first, {}, {static_cast<int64_t>(unfoldedToOldEntry.second)});
136
137 transitionMatrixBuilder.newRowGroup(newRowGroupStart);
138 STORM_LOG_ASSERT(risk.size() > unfoldedToOldEntry.second, "Must be a state");
139 STORM_LOG_ASSERT(!storm::utility::isBetween(storm::utility::zero<ValueType>(), risk[unfoldedToOldEntry.second], storm::utility::one<ValueType>()),
140 "Risk must be a probability");
141 // std::cout << "risk is" << risk[unfoldedToOldEntry.second] << '\n';
142 if (!storm::utility::isOne(risk[unfoldedToOldEntry.second])) {
143 transitionMatrixBuilder.addNextValue(newRowGroupStart, sinkState, storm::utility::one<ValueType>() - risk[unfoldedToOldEntry.second]);
144 }
145 if (!storm::utility::isZero(risk[unfoldedToOldEntry.second])) {
146 transitionMatrixBuilder.addNextValue(newRowGroupStart, targetState, risk[unfoldedToOldEntry.second]);
147 }
148 newRowGroupStart++;
149 }
150 // sink state
151 transitionMatrixBuilder.newRowGroup(newRowGroupStart);
152 transitionMatrixBuilder.addNextValue(newRowGroupStart, sinkState, storm::utility::one<ValueType>());
153 svbuilder.addState(sinkState, {}, {-1});
154
155 newRowGroupStart++;
156 transitionMatrixBuilder.newRowGroup(newRowGroupStart);
157 // target state
158 transitionMatrixBuilder.addNextValue(newRowGroupStart, targetState, storm::utility::one<ValueType>());
159 svbuilder.addState(targetState, {}, {-1});
160#ifdef _VERBOSE_OBSERVATION_UNFOLDING
161 std::cout << "build matrix...\n";
162#endif
163
165 components.transitionMatrix = transitionMatrixBuilder.build();
166#ifdef _VERBOSE_OBSERVATION_UNFOLDING
167 std::cout << components.transitionMatrix << '\n';
168#endif
169 STORM_LOG_ASSERT(components.transitionMatrix.getRowGroupCount() == targetState + 1,
170 "Expect row group count (" << components.transitionMatrix.getRowGroupCount() << ") one more as target state index " << targetState << ")");
171
172 storm::models::sparse::StateLabeling labeling(components.transitionMatrix.getRowGroupCount());
173 labeling.addLabel("_goal");
174 labeling.addLabelToState("_goal", targetState);
175 labeling.addLabel("init");
176 labeling.addLabelToState("init", 0);
177 components.stateLabeling = labeling;
178 components.stateValuations = svbuilder.build();
179 return std::make_shared<storm::models::sparse::Mdp<ValueType>>(std::move(components));
180}
181
182template<typename ValueType>
183std::shared_ptr<storm::models::sparse::Mdp<ValueType>> ObservationTraceUnfolder<ValueType>::extend(uint32_t observation) {
184 traceSoFar.push_back(observation);
185 return transform(traceSoFar);
186}
187
188template<typename ValueType>
190 traceSoFar = {observation};
191}
192
196} // namespace pomdp
197} // namespace storm
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:164
This class represents a partially observable Markov decision process.
Definition Pomdp.h:13
uint64_t getNrObservations() const
Definition Pomdp.cpp:70
uint32_t getObservation(uint64_t state) const
Definition Pomdp.cpp:65
This class manages the labeling of the state space with a number of (atomic) labels.
Observation-trace unrolling to allow model checking for monitoring.
ObservationTraceUnfolder(storm::models::sparse::Pomdp< ValueType > const &model, std::vector< ValueType > const &risk, std::shared_ptr< storm::expressions::ExpressionManager > &exprManager)
Initialize.
std::shared_ptr< storm::models::sparse::Mdp< ValueType > > transform(std::vector< uint32_t > const &observations)
Transform in one shot.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
uint64_t getNextSetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
A class that can be used to build a sparse matrix by adding value by value.
index_type getLastRow() const
Retrieves the most recently used row.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
void addState(storm::storage::sparse::state_type const &state, std::vector< bool > &&booleanValues={}, std::vector< int64_t > &&integerValues={})
Adds a new state.
void addVariable(storm::expressions::Variable const &variable)
Adds a new variable to keep track of for the state valuations.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool isOne(ValueType const &a)
Definition constants.cpp:34
bool isBetween(ValueType const &a, ValueType const &b, ValueType const &c, bool strict)
Compare whether a <= b <= c or a < b < c, based on the strictness parameter.
Definition constants.cpp:82
bool isZero(ValueType const &a)
Definition constants.cpp:39
std::optional< storm::storage::sparse::StateValuations > stateValuations
storm::storage::SparseMatrix< ValueType > transitionMatrix
storm::models::sparse::StateLabeling stateLabeling