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