Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
NextStateGenerator.cpp
Go to the documentation of this file.
2
13
14namespace storm {
15namespace generator {
16
17template<typename ValueType, typename StateType>
19 : func(f) {
20 // Intentionally left empty
21}
22
23template<typename ValueType, typename StateType>
25 uint64_t actionIndex) {
26 auto val = generator.currentStateToSimpleValuation();
27 bool res = func(val, actionIndex);
28 return res;
29}
30
31template<typename ValueType, typename StateType>
33 VariableInformation const& variableInformation, NextStateGeneratorOptions const& options,
34 std::shared_ptr<ActionMask<ValueType, StateType>> const& mask)
35 : options(options),
36 expressionManager(expressionManager.getSharedPointer()),
37 variableInformation(variableInformation),
38 evaluator(nullptr),
39 state(nullptr),
40 comparator(storm::utility::convertNumber<ValueType>(options.getStochasticTolerance())),
41 actionMask(mask) {
43}
44
45template<typename ValueType, typename StateType>
47 NextStateGeneratorOptions const& options,
48 std::shared_ptr<ActionMask<ValueType, StateType>> const& mask)
49 : options(options),
50 expressionManager(expressionManager.getSharedPointer()),
51 variableInformation(),
52 evaluator(nullptr),
53 state(nullptr),
54 comparator(storm::utility::convertNumber<ValueType>(options.getStochasticTolerance())),
55 actionMask(mask) {}
56
57template<typename ValueType, typename StateType>
59
60template<typename ValueType, typename StateType>
64
65template<typename ValueType, typename StateType>
67 return variableInformation.getTotalBitOffset(true);
68}
69
70template<typename ValueType, typename StateType>
72 if (variableInformation.hasOutOfBoundsBit()) {
73 outOfBoundsState = createOutOfBoundsState(variableInformation);
74 }
75 if (options.isAddOverlappingGuardLabelSet()) {
76 overlappingGuardStates = std::vector<uint64_t>();
77 }
79
80template<typename ValueType, typename StateType>
83 for (auto const& v : variableInformation.locationVariables) {
84 result.addVariable(v.variable);
85 }
86 for (auto const& v : variableInformation.booleanVariables) {
87 result.addVariable(v.variable);
88 }
89 for (auto const& v : variableInformation.integerVariables) {
90 result.addVariable(v.variable);
91 }
92 return result;
93}
94
95template<typename ValueType, typename StateType>
98 for (auto const& v : variableInformation.booleanVariables) {
99 if (v.observable) {
100 result.addVariable(v.variable);
102 }
103 for (auto const& v : variableInformation.integerVariables) {
104 if (v.observable) {
105 result.addVariable(v.variable);
106 }
107 }
108 for (auto const& l : variableInformation.observationLabels) {
109 result.addObservationLabel(l.name);
110 }
111 return result;
112}
113
114template<typename ValueType, typename StateType>
116 // Since almost all subsequent operations are based on the evaluator, we load the state into it now.
117 unpackStateIntoEvaluator(state, variableInformation, *evaluator);
119 // Also, we need to store a pointer to the state itself, because we need to be able to access it when expanding it.
120 this->state = &state;
122
123template<typename ValueType, typename StateType>
125 if (expression.isTrue()) {
126 return true;
127 }
128 return evaluator->asBool(expression);
129}
131template<typename ValueType, typename StateType>
135
136template<typename ValueType, typename StateType>
138 storm::storage::sparse::StateValuationsBuilder& valuationsBuilder) const {
139 std::vector<bool> booleanValues;
140 booleanValues.reserve(variableInformation.booleanVariables.size());
141 std::vector<int64_t> integerValues;
142 integerValues.reserve(variableInformation.locationVariables.size() + variableInformation.integerVariables.size());
143 extractVariableValues(*this->state, variableInformation, integerValues, booleanValues, integerValues);
144 valuationsBuilder.addState(currentStateIndex, std::move(booleanValues), std::move(integerValues));
145}
146
147template<typename ValueType, typename StateType>
149 storm::storage::sparse::StateValuationsBuilder valuationsBuilder = initializeObservationValuationsBuilder();
150 for (auto const& observationEntry : observabilityMap) {
151 std::vector<bool> booleanValues;
152 booleanValues.reserve(variableInformation.booleanVariables.size()); // TODO: use number of observable boolean variables
153 std::vector<int64_t> integerValues;
154 integerValues.reserve(variableInformation.locationVariables.size() +
155 variableInformation.integerVariables.size()); // TODO: use number of observable integer variables
156 std::vector<int64_t> observationLabelValues;
157 observationLabelValues.reserve(variableInformation.observationLabels.size());
158 expressions::SimpleValuation val = unpackStateIntoValuation(observationEntry.first, variableInformation, *expressionManager);
159 for (auto const& v : variableInformation.booleanVariables) {
160 if (v.observable) {
161 booleanValues.push_back(val.getBooleanValue(v.variable));
162 }
163 }
164 for (auto const& v : variableInformation.integerVariables) {
165 if (v.observable) {
166 integerValues.push_back(val.getIntegerValue(v.variable));
168 }
169 for (uint64_t labelStart = variableInformation.getTotalBitOffset(true); labelStart < observationEntry.first.size(); labelStart += 64) {
170 observationLabelValues.push_back(observationEntry.first.getAsInt(labelStart, 64));
171 }
172 valuationsBuilder.addState(observationEntry.second, std::move(booleanValues), std::move(integerValues), {}, std::move(observationLabelValues));
173 }
174 return valuationsBuilder.build();
175}
177template<typename ValueType, typename StateType>
179 storm::storage::sparse::StateStorage<StateType> const& stateStorage, std::vector<StateType> const& initialStateIndices,
180 std::vector<StateType> const& deadlockStateIndices, std::vector<StateType> const& unexploredStateIndices,
181 std::vector<std::pair<std::string, storm::expressions::Expression>> labelsAndExpressions) {
182 labelsAndExpressions.insert(labelsAndExpressions.end(), this->options.getExpressionLabels().begin(), this->options.getExpressionLabels().end());
183
184 // Make the labels unique.
185 std::sort(labelsAndExpressions.begin(), labelsAndExpressions.end(),
186 [](std::pair<std::string, storm::expressions::Expression> const& a, std::pair<std::string, storm::expressions::Expression> const& b) {
187 return a.first < b.first;
188 });
189 auto it = std::unique(labelsAndExpressions.begin(), labelsAndExpressions.end(),
190 [](std::pair<std::string, storm::expressions::Expression> const& a, std::pair<std::string, storm::expressions::Expression> const& b) {
191 return a.first == b.first;
192 });
193 labelsAndExpressions.resize(std::distance(labelsAndExpressions.begin(), it));
194
195 // Prepare result.
197
198 // Initialize labeling.
199 for (auto const& label : labelsAndExpressions) {
200 result.addLabel(label.first);
201 }
202
203 auto const& states = stateStorage.stateToId;
204 for (auto const& stateIndexPair : states) {
205 unpackStateIntoEvaluator(stateIndexPair.first, variableInformation, *this->evaluator);
206 unpackTransientVariableValuesIntoEvaluator(stateIndexPair.first, *this->evaluator);
207
208 for (auto const& label : labelsAndExpressions) {
209 // Add label to state, if the corresponding expression is true.
210 if (evaluator->asBool(label.second)) {
211 result.addLabelToState(label.first, stateIndexPair.second);
212 }
213 }
214 }
215
216 auto addSpecialLabel = [&result](std::string const& label, auto const& indices) {
217 if (!result.containsLabel(label)) {
218 result.addLabel(label);
219 for (auto index : indices) {
220 result.addLabelToState(label, index);
221 }
222 }
223 };
224 addSpecialLabel("init", initialStateIndices);
225 addSpecialLabel("deadlock", deadlockStateIndices);
226 if (!unexploredStateIndices.empty()) {
227 addSpecialLabel("unexplored", unexploredStateIndices);
228 }
229 if (this->options.isAddOverlappingGuardLabelSet()) {
230 STORM_LOG_THROW(!result.containsLabel("overlap_guards"), storm::exceptions::WrongFormatException,
231 "Label 'overlap_guards' is reserved when adding overlapping guard labels");
232 addSpecialLabel("overlap_guards", overlappingGuardStates.get());
233 }
234 if (this->options.isAddOutOfBoundsStateSet() && stateStorage.stateToId.contains(outOfBoundsState)) {
235 STORM_LOG_THROW(!result.containsLabel("out_of_bounds"), storm::exceptions::WrongFormatException,
236 "Label 'out_of_bounds' is reserved when adding out of bounds states.");
237 addSpecialLabel("out_of_bounds", std::vector{stateStorage.stateToId.getValue(outOfBoundsState)});
238 }
239
240 return result;
241}
242
243template<typename ValueType, typename StateType>
245 return label == "init" || label == "deadlock" || label == "unexplored" || label == "overlap_guards" || label == "out_of_bounds";
246}
247
248template<typename ValueType, typename StateType>
251 // Intentionally left empty.
252 // This method should be overwritten in case there are transient variables (e.g. JANI).
253}
254
255template<typename ValueType, typename StateType>
257 // If the model we build is a Markov Automaton, we postprocess the choices to sum all Markovian choices
258 // and make the Markovian choice the very first one (if there is any).
259 bool foundPreviousMarkovianChoice = false;
260 if (this->getModelType() == ModelType::MA) {
261 uint64_t numberOfChoicesToDelete = 0;
262
263 for (uint_fast64_t index = 0; index + numberOfChoicesToDelete < result.getNumberOfChoices();) {
264 Choice<ValueType>& choice = result.getChoices()[index];
265
266 if (choice.isMarkovian()) {
267 if (foundPreviousMarkovianChoice) {
268 // If there was a previous Markovian choice, we need to sum them. Note that we can assume
269 // that the previous Markovian choice is the very first one in the choices vector.
270 result.getChoices().front().add(choice);
271
272 // Swap the choice to the end to indicate it can be removed (if it's not already there).
273 if (index != result.getNumberOfChoices() - 1 - numberOfChoicesToDelete) {
274 choice = std::move(result.getChoices()[result.getNumberOfChoices() - 1 - numberOfChoicesToDelete]);
275 }
276 ++numberOfChoicesToDelete;
277 } else {
278 // If there is no previous Markovian choice, just move the Markovian choice to the front.
279 if (index != 0) {
280 std::swap(result.getChoices().front(), choice);
281 }
282 foundPreviousMarkovianChoice = true;
283 ++index;
284 }
285 } else {
286 ++index;
287 }
288 }
289
290 // Finally remove the choices that were added to other Markovian choices.
291 if (numberOfChoicesToDelete > 0) {
292 result.getChoices().resize(result.getChoices().size() - numberOfChoicesToDelete);
293 }
294 }
295}
296
297template<typename ValueType, typename StateType>
299 return toString(state, variableInformation);
300}
301
302template<typename ValueType, typename StateType>
304 storm::json<BaseValueType> result = unpackStateIntoJson<BaseValueType>(*state, variableInformation, onlyObservable);
305 extendStateInformation(result);
306 return result;
307}
308
309template<typename ValueType, typename StateType>
313
314template<typename ValueType, typename StateType>
318
319template<typename ValueType, typename StateType>
320std::shared_ptr<storm::storage::sparse::ChoiceOrigins> NextStateGenerator<ValueType, StateType>::generateChoiceOrigins(
321 std::vector<boost::any>& /*dataForChoiceOrigins*/) const {
322 STORM_LOG_ERROR_COND(!options.isBuildChoiceOriginsSet(), "Generating choice origins is not supported for the considered model format.");
323 return nullptr;
324}
325
326template<typename ValueType, typename StateType>
328 if (this->mask.size() == 0) {
329 this->mask = computeObservabilityMask(variableInformation);
330 }
331 uint32_t classId = unpackStateToObservabilityClass(state, evaluateObservationLabels(state), observabilityMap, mask);
332 return classId;
333}
334
335template<typename ValueType, typename StateType>
336std::map<std::string, storm::storage::PlayerIndex> NextStateGenerator<ValueType, StateType>::getPlayerNameToIndexMap() const {
337 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Generating player mappings is not supported for this model input format");
338}
339
340template<typename ValueType, typename StateType>
341void NextStateGenerator<ValueType, StateType>::remapStateIds(std::function<StateType(StateType const&)> const& /*remapping*/) {
342 if (overlappingGuardStates != boost::none) {
343 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException,
344 "Remapping of Ids during model building is not supported for overlapping guard statements.");
345 }
346 // Nothing to be done.
347}
348
349template class ActionMask<double>;
351template class NextStateGenerator<double>;
352
356
360
361template class ActionMask<storm::Interval>;
364} // namespace generator
365} // namespace storm
bool isTrue() const
Checks if the expression is equal to the boolean literal true.
This class is responsible for managing a set of typed variables and all expressions using these varia...
A simple implementation of the valuation interface.
virtual int_fast64_t getIntegerValue(Variable const &integerVariable) const override
Retrieves the value of the given integer variable.
virtual bool getBooleanValue(Variable const &booleanVariable) const override
Retrieves the value of the given boolean variable.
Action masks are arguments you can give to the state generator that limit which states are generated.
virtual std::shared_ptr< storm::storage::sparse::ChoiceOrigins > generateChoiceOrigins(std::vector< boost::any > &dataForChoiceOrigins) const
NextStateGenerator(storm::expressions::ExpressionManager const &expressionManager, VariableInformation const &variableInformation, NextStateGeneratorOptions const &options, std::shared_ptr< ActionMask< ValueType, StateType > > const &=nullptr)
virtual std::map< std::string, storm::storage::PlayerIndex > getPlayerNameToIndexMap() const
virtual storm::storage::sparse::StateValuations makeObservationValuation() const
Adds the valuation for the currently loaded state.
bool isSpecialLabel(std::string const &label) const
Checks if the input label has a special purpose (e.g.
void initializeSpecialStates()
Initializes the out-of-bounds state and states with overlapping guards.
std::string stateToString(CompressedState const &state) const
virtual storm::storage::sparse::StateValuationsBuilder initializeStateValuationsBuilder() const
Initializes a builder for state valuations by adding the appropriate variables.
void postprocess(StateBehavior< ValueType, StateType > &result)
uint32_t observabilityClass(CompressedState const &state) const
virtual void extendStateInformation(storm::json< BaseValueType > &stateInfo) const
NextStateGeneratorOptions const & getOptions() const
storm::expressions::SimpleValuation currentStateToSimpleValuation() const
storm::json< ValueType > currentStateToJson(bool onlyObservable=false) const
void load(CompressedState const &state)
virtual storm::storage::sparse::StateValuationsBuilder initializeObservationValuationsBuilder() const
bool satisfies(storm::expressions::Expression const &expression) const
virtual void addStateValuation(storm::storage::sparse::state_type const &currentStateIndex, storm::storage::sparse::StateValuationsBuilder &valuationsBuilder) const
Adds the valuation for the currently loaded state to the given builder.
void remapStateIds(std::function< StateType(StateType const &)> const &remapping)
Performs a remapping of all values stored by applying the given remapping.
VariableInformation const & getVariableInformation() const
virtual void unpackTransientVariableValuesIntoEvaluator(CompressedState const &state, storm::expressions::ExpressionEvaluator< BaseValueType > &evaluator) const
Sets the values of all transient variables in the current state to the given evaluator.
virtual storm::models::sparse::StateLabeling label(storm::storage::sparse::StateStorage< StateType > const &stateStorage, std::vector< StateType > const &initialStateIndices={}, std::vector< StateType > const &deadlockStateIndices={}, std::vector< StateType > const &unexploredStateIndices={})=0
std::vector< Choice< ValueType, StateType > > const & getChoices() const
Retrieves the vector of choices.
std::size_t getNumberOfChoices() const
Retrieves the number of choices in the behavior.
A particular instance of the action mask that uses a callback function to evaluate whether an action ...
StateValuationFunctionMask(std::function< bool(storm::expressions::SimpleValuation const &, uint64_t)> const &f)
bool query(storm::generator::NextStateGenerator< ValueType, StateType > const &generator, uint64_t actionIndex) override
This method is called to check whether an action should be expanded.
void addLabel(std::string const &label)
Adds a new label to the labelings.
bool containsLabel(std::string const &label) const
Checks whether a label is registered within this labeling.
This class manages the labeling of the state space with a number of (atomic) labels.
void addLabelToState(std::string const &label, storm::storage::sparse::state_type state)
Adds a label to a given state.
ValueType getValue(storm::storage::BitVector const &key) const
Retrieves the value associated with the given key (if any).
bool contains(storm::storage::BitVector const &key) const
Checks if the given key is already contained in the map.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void addState(storm::storage::sparse::state_type const &state, std::vector< bool > &&booleanValues={}, std::vector< int64_t > &&integerValues={})
Adds a new state.
void addObservationLabel(std::string const &label)
StateValuations build()
Creates the finalized state valuations object.
void addVariable(storm::expressions::Variable const &variable)
Adds a new variable to keep track of for the state valuations.
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:52
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void unpackStateIntoEvaluator(CompressedState const &state, VariableInformation const &variableInformation, storm::expressions::ExpressionEvaluator< ValueType > &evaluator)
Unpacks the compressed state into the evaluator.
storm::expressions::SimpleValuation unpackStateIntoValuation(CompressedState const &state, VariableInformation const &variableInformation, storm::expressions::ExpressionManager const &manager)
Converts the compressed state into an explicit representation in the form of a valuation.
void extractVariableValues(CompressedState const &state, VariableInformation const &variableInformation, std::vector< int64_t > &locationValues, std::vector< bool > &booleanValues, std::vector< int64_t > &integerValues)
Appends the values of the given variables in the given state to the corresponding result vectors.
uint32_t unpackStateToObservabilityClass(CompressedState const &state, storm::storage::BitVector const &observationVector, std::unordered_map< storm::storage::BitVector, uint32_t > &observabilityMap, storm::storage::BitVector const &mask)
std::string toString(CompressedState const &state, VariableInformation const &variableInformation)
Returns a (human readable) string representation of the variable valuation encoded by the given state...
CompressedState createOutOfBoundsState(VariableInformation const &varInfo, bool roundTo64Bit)
storm::storage::BitVector computeObservabilityMask(VariableInformation const &variableInformation)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
Definition JsonForward.h:10
bool isMarkovian() const
Retrieves whether the choice is Markovian.
Definition Choice.cpp:179
storm::storage::BitVectorHashMap< StateType > stateToId