Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
NextStateGenerator.cpp
Go to the documentation of this file.
2
17
18namespace storm {
19namespace generator {
20
21template<typename ValueType, typename StateType>
23 : func(f) {
24 // Intentionally left empty
25}
26
27template<typename ValueType, typename StateType>
29 uint64_t actionIndex) {
30 auto val = generator.currentStateToSimpleValuation();
31 bool res = func(val, actionIndex);
32 return res;
33}
34
35template<typename ValueType, typename StateType>
49
50template<typename ValueType, typename StateType>
53 std::shared_ptr<ActionMask<ValueType, StateType>> const& mask)
55 expressionManager(expressionManager.getSharedPointer()),
57 evaluator(nullptr),
58 state(nullptr),
59 comparator(storm::NumberTraits<ValueType>::IsExact ? storm::utility::zero<ValueType>()
60 : storm::utility::convertNumber<ValueType>(options.getStochasticTolerance())),
62
63template<typename ValueType, typename StateType>
65
66template<typename ValueType, typename StateType>
70
71template<typename ValueType, typename StateType>
73 return variableInformation.getTotalBitOffset(true);
74}
75
76template<typename ValueType, typename StateType>
78 if (variableInformation.hasOutOfBoundsBit()) {
80 }
81 if (options.isAddOverlappingGuardLabelSet()) {
82 overlappingGuardStates = std::vector<uint64_t>();
83 }
84}
85
86template<typename ValueType, typename StateType>
89 if (variableInformation.hasOutOfBoundsBit()) {
90 builder.addBooleanVariable(variableInformation.outOfBoundsBit->variable);
91 }
92 for (auto const& v : variableInformation.locationVariables) {
93 builder.addIntegerVariable(v.variable, 0, v.highestValue);
94 }
95 for (auto const& v : variableInformation.booleanVariables) {
96 builder.addBooleanVariable(v.variable);
97 }
98 for (auto const& v : variableInformation.integerVariables) {
99 builder.addIntegerVariable(v.variable, v.lowerBound, v.upperBound);
100 }
102}
104template<typename ValueType, typename StateType>
107 for (auto const& v : variableInformation.booleanVariables) {
108 if (v.observable) {
109 builder.addBooleanVariable(v.variable);
112 for (auto const& v : variableInformation.integerVariables) {
113 if (v.observable) {
114 builder.addIntegerVariable(v.variable, v.lowerBound, v.upperBound);
116 }
117 for (auto const& l : variableInformation.observationLabels) {
118 if (l.variable.hasBooleanType()) {
119 builder.addBooleanVariable(l.variable);
120 } else {
121 STORM_LOG_ASSERT(l.variable.hasIntegerType(), "Observation label " << l.variable.getName() << " has neither boolean nor integer type.");
122 builder.addIntegerVariable(l.variable, std::numeric_limits<int64_t>::min(), std::numeric_limits<int64_t>::max());
123 }
125 storm::storage::sparse::Valuations res(builder.buildClassDescription(), expressionManager, observabilityMap.size());
126 return res;
127}
128
129template<typename ValueType, typename StateType>
131 // Since almost all subsequent operations are based on the evaluator, we load the state into it now.
134 // Also, we need to store a pointer to the state itself, because we need to be able to access it when expanding it.
135 this->state = &state;
136}
137
138template<typename ValueType, typename StateType>
140 if (expression.isTrue()) {
141 return true;
142 }
143 return evaluator->asBool(expression);
144}
145
146template<typename ValueType, typename StateType>
150
151template<typename ValueType, typename StateType>
156
157template<typename ValueType, typename StateType>
160 for (auto const& observationEntry : observabilityMap) {
161 unpackObservationClassIntoValuations(observationEntry.first, observationEntry.second, variableInformation, valuations.getStorage());
162 }
163 return valuations;
165
166template<typename ValueType, typename StateType>
168 storm::storage::sparse::StateStorage<StateType> const& stateStorage, std::vector<StateType> const& initialStateIndices,
169 std::vector<StateType> const& deadlockStateIndices, std::vector<StateType> const& unexploredStateIndices,
170 std::vector<std::pair<std::string, storm::expressions::Expression>> labelsAndExpressions) {
171 labelsAndExpressions.insert(labelsAndExpressions.end(), this->options.getExpressionLabels().begin(), this->options.getExpressionLabels().end());
172
173 // Make the labels unique.
174 std::sort(labelsAndExpressions.begin(), labelsAndExpressions.end(),
175 [](std::pair<std::string, storm::expressions::Expression> const& a, std::pair<std::string, storm::expressions::Expression> const& b) {
176 return a.first < b.first;
177 });
178 auto it = std::unique(labelsAndExpressions.begin(), labelsAndExpressions.end(),
179 [](std::pair<std::string, storm::expressions::Expression> const& a, std::pair<std::string, storm::expressions::Expression> const& b) {
180 return a.first == b.first;
181 });
182 labelsAndExpressions.resize(std::distance(labelsAndExpressions.begin(), it));
183
184 // Prepare result.
186
187 // Initialize labeling.
188 for (auto const& label : labelsAndExpressions) {
189 result.addLabel(label.first);
190 }
191
192 auto const& states = stateStorage.stateToId;
193 for (auto const& stateIndexPair : states) {
194 unpackStateIntoEvaluator(stateIndexPair.first, variableInformation, *this->evaluator);
195 unpackTransientVariableValuesIntoEvaluator(stateIndexPair.first, *this->evaluator);
196
197 for (auto const& label : labelsAndExpressions) {
198 // Add label to state, if the corresponding expression is true.
199 if (evaluator->asBool(label.second)) {
200 result.addLabelToState(label.first, stateIndexPair.second);
201 }
202 }
203 }
204
205 auto addSpecialLabel = [&result](std::string const& label, auto const& indices) {
206 if (!result.containsLabel(label)) {
207 result.addLabel(label);
208 for (auto index : indices) {
209 result.addLabelToState(label, index);
210 }
211 }
212 };
213 addSpecialLabel("init", initialStateIndices);
214 addSpecialLabel("deadlock", deadlockStateIndices);
215 if (!unexploredStateIndices.empty()) {
216 addSpecialLabel("unexplored", unexploredStateIndices);
217 }
218 if (this->options.isAddOverlappingGuardLabelSet()) {
219 STORM_LOG_THROW(!result.containsLabel("overlap_guards"), storm::exceptions::WrongFormatException,
220 "Label 'overlap_guards' is reserved when adding overlapping guard labels.");
221 addSpecialLabel("overlap_guards", overlappingGuardStates.get());
222 }
223 if (this->options.isAddOutOfBoundsStateSet() && stateStorage.stateToId.contains(outOfBoundsState)) {
224 STORM_LOG_THROW(!result.containsLabel("out_of_bounds"), storm::exceptions::WrongFormatException,
225 "Label 'out_of_bounds' is reserved when adding out of bounds states.");
226 addSpecialLabel("out_of_bounds", std::vector{stateStorage.stateToId.getValue(outOfBoundsState)});
227 }
228
229 return result;
230}
231
232template<typename ValueType, typename StateType>
234 return label == "init" || label == "deadlock" || label == "unexplored" || label == "overlap_guards" || label == "out_of_bounds";
235}
236
237template<typename ValueType, typename StateType>
240 // Intentionally left empty.
241 // This method should be overwritten in case there are transient variables (e.g. JANI).
242}
243
244template<typename ValueType, typename StateType>
246 // If the model we build is a Markov Automaton, we postprocess the choices to sum all Markovian choices
247 // and make the Markovian choice the very first one (if there is any).
248 bool foundPreviousMarkovianChoice = false;
249 if (this->getModelType() == ModelType::MA) {
250 uint64_t numberOfChoicesToDelete = 0;
251
252 for (uint_fast64_t index = 0; index + numberOfChoicesToDelete < result.getNumberOfChoices();) {
253 Choice<ValueType>& choice = result.getChoices()[index];
254
255 if (choice.isMarkovian()) {
256 if (foundPreviousMarkovianChoice) {
257 // If there was a previous Markovian choice, we need to sum them. Note that we can assume
258 // that the previous Markovian choice is the very first one in the choices vector.
259 result.getChoices().front().add(choice);
260
261 // Swap the choice to the end to indicate it can be removed (if it's not already there).
262 if (index != result.getNumberOfChoices() - 1 - numberOfChoicesToDelete) {
263 choice = std::move(result.getChoices()[result.getNumberOfChoices() - 1 - numberOfChoicesToDelete]);
264 }
265 ++numberOfChoicesToDelete;
266 } else {
267 // If there is no previous Markovian choice, just move the Markovian choice to the front.
268 if (index != 0) {
269 std::swap(result.getChoices().front(), choice);
270 }
271 foundPreviousMarkovianChoice = true;
272 ++index;
273 }
274 } else {
275 ++index;
276 }
277 }
278
279 // Finally remove the choices that were added to other Markovian choices.
280 if (numberOfChoicesToDelete > 0) {
281 result.getChoices().resize(result.getChoices().size() - numberOfChoicesToDelete);
282 }
283 }
284}
285
286template<typename ValueType, typename StateType>
290
291template<typename ValueType, typename StateType>
297
298template<typename ValueType, typename StateType>
302
303template<typename ValueType, typename StateType>
307
308template<typename ValueType, typename StateType>
309std::shared_ptr<storm::storage::sparse::ChoiceOrigins> NextStateGenerator<ValueType, StateType>::generateChoiceOrigins(
310 std::vector<boost::any>& /*dataForChoiceOrigins*/) const {
311 STORM_LOG_ERROR_COND(!options.isBuildChoiceOriginsSet(), "Generating choice origins is not supported for the considered model format.");
312 return nullptr;
313}
314
315template<typename ValueType, typename StateType>
323
324template<typename ValueType, typename StateType>
325std::map<std::string, storm::storage::PlayerIndex> NextStateGenerator<ValueType, StateType>::getPlayerNameToIndexMap() const {
326 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "Generating player mappings is not supported for this model input format.");
327}
328
329template<typename ValueType, typename StateType>
330void NextStateGenerator<ValueType, StateType>::remapStateIds(std::function<StateType(StateType const&)> const& /*remapping*/) {
331 STORM_LOG_THROW(overlappingGuardStates == boost::none, storm::exceptions::NotImplementedException,
332 "Remapping of Ids during model building is not supported for overlapping guard statements.");
333 // Nothing to be done.
334}
335
336template class ActionMask<double>;
338template class NextStateGenerator<double>;
339
343
347
348template class ActionMask<storm::Interval>;
351
355} // namespace generator
356} // 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.
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
std::shared_ptr< storm::expressions::ExpressionManager const > expressionManager
The expression manager used for evaluating expressions.
bool isSpecialLabel(std::string const &label) const
Checks if the input label has a special purpose (e.g.
std::unique_ptr< storm::expressions::ExpressionEvaluator< BaseValueType > > evaluator
An evaluator used to evaluate expressions.
std::shared_ptr< ActionMask< ValueType, StateType > > actionMask
virtual storm::storage::BitVector evaluateObservationLabels(CompressedState const &state) const =0
void initializeSpecialStates()
Initializes the out-of-bounds state and states with overlapping guards.
std::string stateToString(CompressedState const &state) const
virtual storm::storage::sparse::Valuations initializeStateValuations() const
Initializes state valuations by adding the appropriate variables.
storm::utility::ConstantsComparator< ValueType > comparator
A comparator used to approximately compare constants, e.g., whether they sum to one....
void postprocess(StateBehavior< ValueType, StateType > &result)
boost::optional< std::vector< uint64_t > > overlappingGuardStates
A map that stores the indices of states with overlapping guards.
CompressedState const * state
The currently loaded state.
uint32_t observabilityClass(CompressedState const &state) const
virtual void extendStateInformation(storm::json< BaseValueType > &stateInfo) const
virtual ModelType getModelType() const =0
virtual storm::storage::sparse::Valuations initializeObservationValuations() const
NextStateGeneratorOptions const & getOptions() const
storm::expressions::SimpleValuation currentStateToSimpleValuation() const
CompressedState outOfBoundsState
A state that encodes the outOfBoundsState.
storm::storage::BitVector mask
The mask to compute the observability class (Constructed upon first use).
virtual void addStateValuation(storm::storage::sparse::state_type const &currentStateIndex, storm::storage::sparse::Valuations &valuations) const
Adds the valuation for the currently loaded state to the given builder.
storm::json< ValueType > currentStateToJson(bool onlyObservable=false) const
void load(CompressedState const &state)
bool satisfies(storm::expressions::Expression const &expression) const
std::unordered_map< storm::storage::BitVector, uint32_t > observabilityMap
NextStateGeneratorOptions options
The options to be used for next-state generation.
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 storm::storage::sparse::Valuations makeObservationValuation() const
Adds the valuation for the currently loaded state.
virtual void unpackTransientVariableValuesIntoEvaluator(CompressedState const &state, storm::expressions::ExpressionEvaluator< BaseValueType > &evaluator) const
VariableInformation variableInformation
Information about how the variables are packed.
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
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.
Helper to incrementally build a ValuationClassDescription, i.e.
Provides access to valuations of variables for a set of entities (e.g.
Definition Valuations.h:28
ValuationsStorage const & getStorage() const
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:50
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:28
void unpackStateIntoEvaluator(CompressedState const &state, VariableInformation const &variableInformation, storm::expressions::ExpressionEvaluator< ValueType > &evaluator)
Unpacks the compressed state into the evaluator.
void unpackStateAppendToValuations(CompressedState const &state, VariableInformation const &variableInformation, storm::storage::sparse::ValuationsStorage &valuations)
Appends the values of the variables in the given state to the valuations object.
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.
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 CompressedState
storm::builder::BuilderOptions NextStateGeneratorOptions
void unpackObservationClassIntoValuations(CompressedState const &observationClass, uint64_t const observationClassIndex, VariableInformation const &variableInformation, storm::storage::sparse::ValuationsStorage &valuations)
Sets the values of observable variables and observation expressions to the given observationClassInde...
storm::storage::BitVector computeObservabilityMask(VariableInformation const &variableInformation)
storm::json< ValueType > unpackStateIntoJson(CompressedState const &state, VariableInformation const &variableInformation, bool onlyObservable)
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
Definition JsonForward.h:11
bool isMarkovian() const
Retrieves whether the choice is Markovian.
Definition Choice.cpp:179
storm::storage::BitVectorHashMap< StateType > stateToId