Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
PrismNextStateGenerator.cpp
Go to the documentation of this file.
2
3#include <boost/any.hpp>
4#include <boost/container/flat_map.hpp>
5
9
12
14
16
24
26
27namespace storm {
28namespace generator {
30template<typename ValueType, typename StateType>
32 std::shared_ptr<ActionMask<ValueType, StateType>> const& mask)
33 : PrismNextStateGenerator<ValueType, StateType>(program.substituteConstantsFormulas(), options, mask, false) {
34 // Intentionally left empty.
36
37template<typename ValueType, typename StateType>
39 std::shared_ptr<ActionMask<ValueType, StateType>> const& mask, bool)
40 : NextStateGenerator<ValueType, StateType>(program.getManager(), options, mask), program(program), rewardModels(), hasStateActionRewards(false) {
41 STORM_LOG_TRACE("Creating next-state generator for PRISM program: " << program);
42 STORM_LOG_THROW(!this->program.specifiesSystemComposition(), storm::exceptions::WrongFormatException,
43 "The explicit next-state generator currently does not support custom system compositions.");
45 // Only after checking validity of the program, we initialize the variable information.
46 this->checkValid();
47 this->variableInformation = VariableInformation(program, options.getReservedBitsForUnboundedVariables(), options.isAddOutOfBoundsStateSet());
48 this->initializeSpecialStates();
50 // Create a proper evaluator.
51 this->evaluator = std::make_unique<storm::expressions::ExpressionEvaluator<ValueType>>(program.getManager());
52
53 if (this->options.isBuildAllRewardModelsSet()) {
54 for (auto const& rewardModel : this->program.getRewardModels()) {
55 rewardModels.push_back(rewardModel);
56 }
57 } else {
58 // Extract the reward models from the program based on the names we were given.
59 for (auto const& rewardModelName : this->options.getRewardModelNames()) {
60 if (this->program.hasRewardModel(rewardModelName)) {
61 rewardModels.push_back(this->program.getRewardModel(rewardModelName));
62 } else {
63 STORM_LOG_THROW(rewardModelName.empty(), storm::exceptions::InvalidArgumentException,
64 "Cannot build unknown reward model '" << rewardModelName << "'.");
65 STORM_LOG_THROW(this->program.getNumberOfRewardModels() == 1, storm::exceptions::InvalidArgumentException,
66 "Reference to standard reward model is ambiguous.");
67 }
68 }
69
70 // If no reward model was yet added, but there was one that was given in the options, we try to build the
71 // standard reward model.
72 if (rewardModels.empty() && !this->options.getRewardModelNames().empty()) {
73 rewardModels.push_back(this->program.getRewardModel(0));
74 }
75 }
76
77 // Determine whether any reward model has state action rewards.
78 for (auto const& rewardModel : rewardModels) {
79 hasStateActionRewards |= rewardModel.get().hasStateActionRewards();
80 }
81
82 // If there are terminal states we need to handle, we now need to translate all labels to expressions.
83 if (this->options.hasTerminalStates()) {
84 for (auto const& expressionOrLabelAndBool : this->options.getTerminalStates()) {
85 if (expressionOrLabelAndBool.first.isExpression()) {
86 this->terminalStates.push_back(std::make_pair(expressionOrLabelAndBool.first.getExpression(), expressionOrLabelAndBool.second));
87 } else {
88 if (program.hasLabel(expressionOrLabelAndBool.first.getLabel())) {
89 this->terminalStates.push_back(
90 std::make_pair(this->program.getLabelExpression(expressionOrLabelAndBool.first.getLabel()), expressionOrLabelAndBool.second));
91 } else {
92 // If the label is not present in the program and is not a special one, we raise an error.
93 STORM_LOG_THROW(this->isSpecialLabel(expressionOrLabelAndBool.first.getLabel()), storm::exceptions::InvalidArgumentException,
94 "Terminal states refer to illegal label '" << expressionOrLabelAndBool.first.getLabel() << "'.");
95 }
96 }
97 }
98 }
99
101 moduleIndexToPlayerIndexMap = program.buildModuleIndexToPlayerIndexMap();
102 actionIndexToPlayerIndexMap = program.buildActionIndexToPlayerIndexMap();
103 }
104}
105
106template<typename ValueType, typename StateType>
108 // We can handle all valid prism programs (except for PTAs)
110}
111
112template<typename ValueType, typename StateType>
114 // If the program still contains undefined constants and we are not in a parametric setting, assemble an appropriate error message.
115#ifdef STORM_HAVE_CARL
116 if (!std::is_same<ValueType, storm::RationalFunction>::value && program.hasUndefinedConstants()) {
117#else
118 if (program.hasUndefinedConstants()) {
119#endif
120 std::vector<std::reference_wrapper<storm::prism::Constant const>> undefinedConstants = program.getUndefinedConstants();
121 std::stringstream stream;
122 bool printComma = false;
123 for (auto const& constant : undefinedConstants) {
124 if (printComma) {
125 stream << ", ";
126 } else {
127 printComma = true;
128 }
129 stream << constant.get().getName() << " (" << constant.get().getType() << ")";
130 }
131 stream << ".";
132 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException, "Program still contains these undefined constants: " + stream.str());
133 }
134#ifdef STORM_HAVE_CARL
135 else if (std::is_same<ValueType, storm::RationalFunction>::value && !program.undefinedConstantsAreGraphPreserving()) {
136 auto undef = program.getUndefinedConstantsAsString();
137 STORM_LOG_THROW(false, storm::exceptions::InvalidArgumentException,
138 "The program contains undefined constants that appear in some places other than update probabilities and reward value expressions, "
139 "which is not admitted. Undefined constants are: "
140 << undef);
141 }
142#endif
143}
144
145template<typename ValueType, typename StateType>
147 switch (program.getModelType()) {
149 return ModelType::DTMC;
151 return ModelType::CTMC;
153 return ModelType::MDP;
155 return ModelType::MA;
157 return ModelType::POMDP;
159 return ModelType::SMG;
160 default:
161 STORM_LOG_THROW(false, storm::exceptions::WrongFormatException, "Invalid model type.");
162 }
163}
164
165template<typename ValueType, typename StateType>
169
170template<typename ValueType, typename StateType>
174
175template<typename ValueType, typename StateType>
179
180template<typename ValueType, typename StateType>
182 std::vector<StateType> initialStateIndices;
183
184 // If all states are initial, we can simplify the enumeration substantially.
185 if (program.hasInitialConstruct() && program.getInitialStatesExpression().isTrue()) {
186 // Create vectors holding all possible values
187 std::vector<std::vector<uint64_t>> allValues;
188 for (auto const& intVar : this->variableInformation.integerVariables) {
189 STORM_LOG_ASSERT(intVar.lowerBound <= intVar.upperBound, "Expecting variable with non-empty set of possible values.");
190 // The value of integer variables is shifted so that 0 is always the smallest possible value
191 allValues.push_back(storm::utility::vector::buildVectorForRange<uint64_t>(static_cast<uint64_t>(0), intVar.upperBound + 1 - intVar.lowerBound));
192 }
193 uint64_t intEndIndex = allValues.size();
194 // For boolean variables we consider the values 0 and 1.
195 allValues.resize(allValues.size() + this->variableInformation.booleanVariables.size(),
196 std::vector<uint64_t>({static_cast<uint64_t>(0), static_cast<uint64_t>(1)}));
197
198 std::vector<std::vector<uint64_t>::const_iterator> its;
199 std::vector<std::vector<uint64_t>::const_iterator> ites;
200 for (auto const& valVec : allValues) {
201 its.push_back(valVec.cbegin());
202 ites.push_back(valVec.cend());
203 }
204
205 // Now create an initial state for each combination of values
206 CompressedState initialState(this->variableInformation.getTotalBitOffset(true));
208 its, ites,
209 [this, &initialState, &intEndIndex](uint64_t index, uint64_t value) {
210 // Set the value for the variable corresponding to the given index
211 if (index < intEndIndex) {
212 // Integer variable
213 auto const& intVar = this->variableInformation.integerVariables[index];
214 initialState.setFromInt(intVar.bitOffset, intVar.bitWidth, value);
215 } else {
216 // Boolean variable
217 STORM_LOG_ASSERT(index - intEndIndex < this->variableInformation.booleanVariables.size(), "Unexpected index");
218 auto const& boolVar = this->variableInformation.booleanVariables[index - intEndIndex];
219 STORM_LOG_ASSERT(value <= 1u, "Unexpected value for boolean variable.");
220 initialState.set(boolVar.bitOffset, static_cast<bool>(value));
221 }
222 },
223 [&stateToIdCallback, &initialStateIndices, &initialState]() {
224 // Register initial state.
225 StateType id = stateToIdCallback(initialState);
226 initialStateIndices.push_back(id);
227 return true; // Keep on exploring
228 });
229 STORM_LOG_DEBUG("Enumerated " << initialStateIndices.size() << " initial states using brute force enumeration.");
230 } else {
231 // Prepare an SMT solver to enumerate all initial states.
233 std::unique_ptr<storm::solver::SmtSolver> solver = factory.create(program.getManager());
234
235 std::vector<storm::expressions::Expression> rangeExpressions = program.getAllRangeExpressions();
236 for (auto const& expression : rangeExpressions) {
237 solver->add(expression);
238 }
239 solver->add(program.getInitialStatesExpression());
240
241 // Proceed ss long as the solver can still enumerate initial states.
242 while (solver->check() == storm::solver::SmtSolver::CheckResult::Sat) {
243 // Create fresh state.
244 CompressedState initialState(this->variableInformation.getTotalBitOffset(true));
245
246 // Read variable assignment from the solution of the solver. Also, create an expression we can use to
247 // prevent the variable assignment from being enumerated again.
248 storm::expressions::Expression blockingExpression;
249 std::shared_ptr<storm::solver::SmtSolver::ModelReference> model = solver->getModel();
250 for (auto const& booleanVariable : this->variableInformation.booleanVariables) {
251 bool variableValue = model->getBooleanValue(booleanVariable.variable);
252 storm::expressions::Expression localBlockingExpression = variableValue ? !booleanVariable.variable : booleanVariable.variable;
253 blockingExpression = blockingExpression.isInitialized() ? blockingExpression || localBlockingExpression : localBlockingExpression;
254 initialState.set(booleanVariable.bitOffset, variableValue);
255 }
256 for (auto const& integerVariable : this->variableInformation.integerVariables) {
257 int_fast64_t variableValue = model->getIntegerValue(integerVariable.variable);
258 storm::expressions::Expression localBlockingExpression = integerVariable.variable != model->getManager().integer(variableValue);
259 blockingExpression = blockingExpression.isInitialized() ? blockingExpression || localBlockingExpression : localBlockingExpression;
260 initialState.setFromInt(integerVariable.bitOffset, integerVariable.bitWidth,
261 static_cast<uint_fast64_t>(variableValue - integerVariable.lowerBound));
262 }
263
264 // Register initial state and return it.
265 StateType id = stateToIdCallback(initialState);
266 initialStateIndices.push_back(id);
267
268 // Block the current initial state to search for the next one.
269 if (!blockingExpression.isInitialized()) {
270 break;
271 }
272 solver->add(blockingExpression);
273 }
274
275 STORM_LOG_DEBUG("Enumerated " << initialStateIndices.size() << " initial states using SMT solving.");
276 }
277
278 return initialStateIndices;
279}
280
281template<typename ValueType, typename StateType>
283 // Prepare the result, in case we return early.
285
286 // First, construct the state rewards, as we may return early if there are no choices later and we already
287 // need the state rewards then.
288 for (auto const& rewardModel : rewardModels) {
289 ValueType stateRewardValue = storm::utility::zero<ValueType>();
290 if (rewardModel.get().hasStateRewards()) {
291 for (auto const& stateReward : rewardModel.get().getStateRewards()) {
292 if (this->evaluator->asBool(stateReward.getStatePredicateExpression())) {
293 stateRewardValue += ValueType(this->evaluator->asRational(stateReward.getRewardValueExpression()));
294 }
295 }
296 }
297 result.addStateReward(stateRewardValue);
298 }
299
300 // If a terminal expression was set, we must not expand this state
301 if (!this->terminalStates.empty()) {
302 for (auto const& expressionBool : this->terminalStates) {
303 if (this->evaluator->asBool(expressionBool.first) == expressionBool.second) {
304 if (!isPartiallyObservable()) {
305 // If the model is not partially observable, return.
306 return result;
307 } else {
308 // for partially observable models, we need to add self-loops for all enabled actions.
309 result.setExpanded();
310 std::vector<Choice<ValueType>> allChoices = getSelfLoopsForAllActions(*this->state, stateToIdCallback);
311 if (allChoices.size() != 0) {
312 for (auto& choice : allChoices) {
313 result.addChoice(std::move(choice));
314 }
315
316 this->postprocess(result);
317 }
318 return result;
319 }
320 }
321 }
322 }
323
324 // Get all choices for the state.
325 result.setExpanded();
326
327 std::vector<Choice<ValueType>> allChoices;
328 if (this->getOptions().isApplyMaximalProgressAssumptionSet()) {
329 // First explore only edges without a rate
330 allChoices = getAsynchronousChoices(*this->state, stateToIdCallback, CommandFilter::Probabilistic);
331 addSynchronousChoices(allChoices, *this->state, stateToIdCallback, CommandFilter::Probabilistic);
332 if (allChoices.empty()) {
333 // Expand the Markovian edges if there are no probabilistic ones.
334 allChoices = getAsynchronousChoices(*this->state, stateToIdCallback, CommandFilter::Markovian);
335 addSynchronousChoices(allChoices, *this->state, stateToIdCallback, CommandFilter::Markovian);
336 }
337 } else {
338 allChoices = getAsynchronousChoices(*this->state, stateToIdCallback);
339 addSynchronousChoices(allChoices, *this->state, stateToIdCallback);
340 }
341
342 std::size_t totalNumberOfChoices = allChoices.size();
343
344 // If there is not a single choice, we return immediately, because the state has no behavior (other than
345 // the state reward).
346 if (totalNumberOfChoices == 0) {
347 return result;
348 }
349
350 // If the model is a deterministic model, we need to fuse the choices into one.
351 if (this->isDeterministicModel() && totalNumberOfChoices > 1) {
352 Choice<ValueType> globalChoice;
353
354 if (this->options.isAddOverlappingGuardLabelSet()) {
355 this->overlappingGuardStates->push_back(stateToIdCallback(*this->state));
356 }
357
358 // For CTMCs, we need to keep track of the total exit rate to scale the action rewards later. For DTMCs
359 // this is equal to the number of choices, which is why we initialize it like this here.
360 ValueType totalExitRate = this->isDiscreteTimeModel() ? static_cast<ValueType>(totalNumberOfChoices) : storm::utility::zero<ValueType>();
361
362 // Iterate over all choices and combine the probabilities/rates into one choice.
363 for (auto const& choice : allChoices) {
364 for (auto const& stateProbabilityPair : choice) {
365 if (this->isDiscreteTimeModel()) {
366 globalChoice.addProbability(stateProbabilityPair.first, stateProbabilityPair.second / totalNumberOfChoices);
367 } else {
368 globalChoice.addProbability(stateProbabilityPair.first, stateProbabilityPair.second);
369 }
370 }
371
372 if (hasStateActionRewards && !this->isDiscreteTimeModel()) {
373 totalExitRate += choice.getTotalMass();
374 }
375
376 if (this->options.isBuildChoiceLabelsSet() && choice.hasLabels()) {
377 globalChoice.addLabels(choice.getLabels());
378 }
379
380 if (this->options.isBuildChoiceOriginsSet() && choice.hasOriginData()) {
381 globalChoice.addOriginData(choice.getOriginData());
382 }
383 }
384
385 // Now construct the state-action reward for all selected reward models.
386 for (auto const& rewardModel : rewardModels) {
387 ValueType stateActionRewardValue = storm::utility::zero<ValueType>();
388 if (rewardModel.get().hasStateActionRewards()) {
389 for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) {
390 for (auto const& choice : allChoices) {
391 if (stateActionReward.getActionIndex() == choice.getActionIndex() &&
392 this->evaluator->asBool(stateActionReward.getStatePredicateExpression())) {
393 stateActionRewardValue +=
394 ValueType(this->evaluator->asRational(stateActionReward.getRewardValueExpression())) * choice.getTotalMass();
395 }
396 }
397 }
398 }
399 if (hasStateActionRewards) {
400 globalChoice.addReward(stateActionRewardValue / totalExitRate);
401 }
402 }
403
404 // Move the newly fused choice in place.
405 allChoices.clear();
406 allChoices.push_back(std::move(globalChoice));
407 }
408
409 // For SMG we check whether the state has a unique player
410 if (program.getModelType() == storm::prism::Program::ModelType::SMG && allChoices.size() > 1) {
411 auto choiceIt = allChoices.begin();
412 STORM_LOG_ASSERT(choiceIt->hasPlayerIndex(),
413 "State '" << this->stateToString(*this->state)
414 << "' features a choice without player index."); // This should have been catched while creating the choice already
415 storm::storage::PlayerIndex statePlayerIndex = choiceIt->getPlayerIndex();
417 "State '" << this->stateToString(*this->state)
418 << "' features a choice with invalid player index."); // This should have been catched while creating the choice already
419 for (++choiceIt; choiceIt != allChoices.end(); ++choiceIt) {
420 STORM_LOG_ASSERT(choiceIt->hasPlayerIndex(),
421 "State '" << this->stateToString(*this->state)
422 << "' features a choice without player index."); // This should have been catched while creating the choice already
423 STORM_LOG_ASSERT(choiceIt->getPlayerIndex() != storm::storage::INVALID_PLAYER_INDEX,
424 "State '" << this->stateToString(*this->state)
425 << "' features a choice with invalid player index."); // This should have been catched while creating the choice already
426 STORM_LOG_THROW(statePlayerIndex == choiceIt->getPlayerIndex(), storm::exceptions::WrongFormatException,
427 "The player for state '" << this->stateToString(*this->state) << "' is not unique. At least one choice is owned by player '"
428 << statePlayerIndex << "' while another is owned by player '" << choiceIt->getPlayerIndex() << "'.");
429 }
430 }
431
432 // Move all remaining choices in place.
433 for (auto& choice : allChoices) {
434 result.addChoice(std::move(choice));
435 }
436
437 this->postprocess(result);
438
439 return result;
440}
441
442template<typename ValueType, typename StateType>
446
447template<typename ValueType, typename StateType>
449 CompressedState newState(state);
450
451 // NOTE: the following process assumes that the assignments of the update are ordered in such a way that the
452 // assignments to boolean variables precede the assignments to all integer variables and that within the
453 // types, the assignments to variables are ordered (in ascending order) by the expression variables.
454 // This is guaranteed for PRISM models, by sorting the assignments as soon as an update is created.
455
456 auto assignmentIt = update.getAssignments().begin();
457 auto assignmentIte = update.getAssignments().end();
458
459 // Iterate over all boolean assignments and carry them out.
460 auto boolIt = this->variableInformation.booleanVariables.begin();
461 for (; assignmentIt != assignmentIte && assignmentIt->getExpression().hasBooleanType(); ++assignmentIt) {
462 while (assignmentIt->getVariable() != boolIt->variable) {
463 ++boolIt;
464 }
465 newState.set(boolIt->bitOffset, this->evaluator->asBool(assignmentIt->getExpression()));
466 }
467
468 // Iterate over all integer assignments and carry them out.
469 auto integerIt = this->variableInformation.integerVariables.begin();
470 for (; assignmentIt != assignmentIte && assignmentIt->getExpression().hasIntegerType(); ++assignmentIt) {
471 while (assignmentIt->getVariable() != integerIt->variable) {
472 ++integerIt;
473 }
474 int_fast64_t assignedValue = this->evaluator->asInt(assignmentIt->getExpression());
475 if (this->options.isAddOutOfBoundsStateSet()) {
476 if (assignedValue < integerIt->lowerBound || assignedValue > integerIt->upperBound) {
477 return this->outOfBoundsState;
478 }
479 } else if (integerIt->forceOutOfBoundsCheck || this->options.isExplorationChecksSet()) {
480 STORM_LOG_THROW(assignedValue >= integerIt->lowerBound, storm::exceptions::WrongFormatException,
481 "The update " << update << " leads to an out-of-bounds value (" << assignedValue << ") for the variable '"
482 << assignmentIt->getVariableName() << "'.");
483 STORM_LOG_THROW(assignedValue <= integerIt->upperBound, storm::exceptions::WrongFormatException,
484 "The update " << update << " leads to an out-of-bounds value (" << assignedValue << ") for the variable '"
485 << assignmentIt->getVariableName() << "'.");
486 }
487 newState.setFromInt(integerIt->bitOffset, integerIt->bitWidth, assignedValue - integerIt->lowerBound);
488 STORM_LOG_ASSERT(static_cast<int_fast64_t>(newState.getAsInt(integerIt->bitOffset, integerIt->bitWidth)) + integerIt->lowerBound == assignedValue,
489 "Writing to the bit vector bucket failed (read " << newState.getAsInt(integerIt->bitOffset, integerIt->bitWidth) << " but wrote "
490 << assignedValue << ").");
491 }
492
493 // Check that we processed all assignments.
494 STORM_LOG_ASSERT(assignmentIt == assignmentIte, "Not all assignments were consumed.");
495
496 return newState;
497}
498
501 typename std::set<uint_fast64_t>::const_iterator currentCommandIndexIt)
503 // Intentionally left empty
504 }
506 std::set<uint_fast64_t> const* commandIndicesPtr;
507 typename std::set<uint_fast64_t>::const_iterator currentCommandIndexIt;
508};
509
510template<typename ValueType, typename StateType>
511boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>>
512PrismNextStateGenerator<ValueType, StateType>::getActiveCommandsByActionIndex(uint_fast64_t const& actionIndex, CommandFilter const& commandFilter) {
513 // First check whether there is at least one enabled command at each module
514 // This avoids evaluating unnecessarily many guards.
515 // If we find one module without an enabled command, we return boost::none.
516 // At the same time, we store pointers to the relevant modules, the relevant command sets and the first enabled command within each set.
517
518 // Iterate over all modules.
519 std::vector<ActiveCommandData> activeCommands;
520 for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
521 storm::prism::Module const& module = program.getModule(i);
522
523 // If the module has no command labeled with the given action, we can skip this module.
524 if (!module.hasActionIndex(actionIndex)) {
525 continue;
526 }
527
528 std::set<uint_fast64_t> const& commandIndices = module.getCommandIndicesByActionIndex(actionIndex);
529
530 // If the module contains the action, but there is no command in the module that is labeled with
531 // this action, we don't have any feasible command combinations.
532 if (commandIndices.empty()) {
533 return boost::none;
534 }
535
536 // Look up commands by their indices and check if the guard evaluates to true in the given state.
537 bool hasOneEnabledCommand = false;
538 for (auto commandIndexIt = commandIndices.begin(), commandIndexIte = commandIndices.end(); commandIndexIt != commandIndexIte; ++commandIndexIt) {
539 storm::prism::Command const& command = module.getCommand(*commandIndexIt);
540 if (!isCommandPotentiallySynchronizing(command)) {
541 continue;
542 }
543 if (commandFilter != CommandFilter::All) {
544 STORM_LOG_ASSERT(commandFilter == CommandFilter::Markovian || commandFilter == CommandFilter::Probabilistic, "Unexpected command filter.");
545 if ((commandFilter == CommandFilter::Markovian) != command.isMarkovian()) {
546 continue;
547 }
548 }
549 if (this->evaluator->asBool(command.getGuardExpression())) {
550 // Found the first enabled command for this module.
551 hasOneEnabledCommand = true;
552 activeCommands.emplace_back(&module, &commandIndices, commandIndexIt);
553 break;
554 }
555 }
556
557 if (!hasOneEnabledCommand) {
558 return boost::none;
559 }
560 }
561
562 // If we reach this point, there has to be at least one active command for each relevant module.
563 std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>> result;
564
565 // Iterate over all command sets.
566 for (auto const& activeCommand : activeCommands) {
567 std::vector<std::reference_wrapper<storm::prism::Command const>> commands;
568
569 auto commandIndexIt = activeCommand.currentCommandIndexIt;
570 // The command at the current position is already known to be enabled
571 commands.push_back(activeCommand.modulePtr->getCommand(*commandIndexIt));
572
573 // Look up commands by their indices and add them if the guard evaluates to true in the given state.
574 auto commandIndexIte = activeCommand.commandIndicesPtr->end();
575 for (++commandIndexIt; commandIndexIt != commandIndexIte; ++commandIndexIt) {
576 storm::prism::Command const& command = activeCommand.modulePtr->getCommand(*commandIndexIt);
577 if (commandFilter != CommandFilter::All) {
578 STORM_LOG_ASSERT(commandFilter == CommandFilter::Markovian || commandFilter == CommandFilter::Probabilistic, "Unexpected command filter.");
579 if ((commandFilter == CommandFilter::Markovian) != command.isMarkovian()) {
580 continue;
581 }
582 }
583 if (this->evaluator->asBool(command.getGuardExpression())) {
584 commands.push_back(command);
585 }
586 }
587
588 result.push_back(std::move(commands));
589 }
590
591 STORM_LOG_ASSERT(!result.empty(), "Expected non-empty list.");
592 return result;
593}
594
595template<typename ValueType, typename StateType>
596std::vector<Choice<ValueType>> PrismNextStateGenerator<ValueType, StateType>::getAsynchronousChoices(CompressedState const& state,
597 StateToIdCallback stateToIdCallback,
598 CommandFilter const& commandFilter) {
599 std::vector<Choice<ValueType>> result;
600
601 // Iterate over all modules.
602 for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
603 storm::prism::Module const& module = program.getModule(i);
604
605 // Iterate over all commands.
606 for (uint_fast64_t j = 0; j < module.getNumberOfCommands(); ++j) {
607 storm::prism::Command const& command = module.getCommand(j);
608
609 // Only consider commands that are not possibly synchronizing.
610 if (isCommandPotentiallySynchronizing(command))
611 continue;
612
613 if (commandFilter != CommandFilter::All) {
614 STORM_LOG_ASSERT(commandFilter == CommandFilter::Markovian || commandFilter == CommandFilter::Probabilistic, "Unexpected command filter.");
615 if ((commandFilter == CommandFilter::Markovian) != command.isMarkovian()) {
616 continue;
617 }
618 }
619 if (this->actionMask != nullptr) {
620 if (!this->actionMask->query(*this, command.getActionIndex())) {
621 continue;
622 }
623 }
624
625 // Skip the command, if it is not enabled.
626 if (!this->evaluator->asBool(command.getGuardExpression())) {
627 continue;
628 }
629
630 result.push_back(Choice<ValueType>(command.getActionIndex(), command.isMarkovian()));
631 Choice<ValueType>& choice = result.back();
632
633 // Remember the choice origin only if we were asked to.
634 if (this->options.isBuildChoiceOriginsSet()) {
635 CommandSet commandIndex{command.getGlobalIndex()};
636 choice.addOriginData(boost::any(std::move(commandIndex)));
637 }
638
639 // Iterate over all updates of the current command.
640 ValueType probabilitySum = storm::utility::zero<ValueType>();
641 for (uint_fast64_t k = 0; k < command.getNumberOfUpdates(); ++k) {
642 storm::prism::Update const& update = command.getUpdate(k);
643
644 ValueType probability = this->evaluator->asRational(update.getLikelihoodExpression());
645 if (probability != storm::utility::zero<ValueType>()) {
646 // Obtain target state index and add it to the list of known states. If it has not yet been
647 // seen, we also add it to the set of states that have yet to be explored.
648 StateType stateIndex = stateToIdCallback(applyUpdate(state, update));
649
650 // Update the choice by adding the probability/target state to it.
651 choice.addProbability(stateIndex, probability);
652 if (this->options.isExplorationChecksSet()) {
653 probabilitySum += probability;
654 }
655 }
656 }
657
658 // Create the state-action reward for the newly created choice.
659 for (auto const& rewardModel : rewardModels) {
660 ValueType stateActionRewardValue = storm::utility::zero<ValueType>();
661 if (rewardModel.get().hasStateActionRewards()) {
662 for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) {
663 if (stateActionReward.getActionIndex() == choice.getActionIndex() &&
664 this->evaluator->asBool(stateActionReward.getStatePredicateExpression())) {
665 stateActionRewardValue += ValueType(this->evaluator->asRational(stateActionReward.getRewardValueExpression()));
666 }
667 }
668 }
669 choice.addReward(stateActionRewardValue);
670 }
671
672 if (this->options.isBuildChoiceLabelsSet() && command.isLabeled()) {
673 choice.addLabel(program.getActionName(command.getActionIndex()));
674 }
675
677 if (command.getActionIndex() == 0) {
678 // Unlabeled command
679 auto const playerOfModule = moduleIndexToPlayerIndexMap.at(i);
680 STORM_LOG_THROW(playerOfModule != storm::storage::INVALID_PLAYER_INDEX, storm::exceptions::WrongFormatException,
681 "Module " << module.getName() << " is not owned by any player but has at least one enabled, unlabeled command.");
682 choice.setPlayerIndex(playerOfModule);
683 } else {
684 // Labelled command (that happens to not synchronize with another command
685 auto const playerOfAction = actionIndexToPlayerIndexMap.at(command.getActionIndex());
686 STORM_LOG_THROW(playerOfAction != storm::storage::INVALID_PLAYER_INDEX, storm::exceptions::WrongFormatException,
687 "Command with action label '" << program.getActionName(command.getActionIndex()) << "' is not owned by any player.");
688 choice.setPlayerIndex(playerOfAction);
689 }
690 }
691
692 if (this->options.isExplorationChecksSet()) {
693 // Check that the resulting distribution is in fact a distribution.
694 STORM_LOG_THROW(!program.isDiscreteTimeModel() || this->comparator.isOne(probabilitySum), storm::exceptions::WrongFormatException,
695 "Probabilities do not sum to one for command '" << command << "' (actually sum to " << probabilitySum << ").");
696 }
697 }
698 }
699
700 return result;
701}
702
703template<typename ValueType, typename StateType>
704std::vector<Choice<ValueType>> PrismNextStateGenerator<ValueType, StateType>::getSelfLoopsForAllActions(CompressedState const& state,
705 StateToIdCallback stateToIdCallback,
706 CommandFilter const& commandFilter) {
707 std::vector<Choice<ValueType>> result;
708
709 // Asynchronous actions
710 // Iterate over all modules.
711 for (uint_fast64_t i = 0; i < program.getNumberOfModules(); ++i) {
712 storm::prism::Module const& module = program.getModule(i);
713
714 // Iterate over all commands.
715 for (uint_fast64_t j = 0; j < module.getNumberOfCommands(); ++j) {
716 storm::prism::Command const& command = module.getCommand(j);
717
718 // Only consider commands that are not possibly synchronizing.
719 if (isCommandPotentiallySynchronizing(command))
720 continue;
721
722 if (this->actionMask != nullptr) {
723 if (!this->actionMask->query(*this, command.getActionIndex())) {
724 continue;
725 }
726 }
727
728 // Skip the command, if it is not enabled.
729 if (!this->evaluator->asBool(command.getGuardExpression())) {
730 continue;
731 }
732
733 result.push_back(Choice<ValueType>(command.getActionIndex(), command.isMarkovian()));
734 Choice<ValueType>& choice = result.back();
735
736 // Remember the choice origin only if we were asked to.
737 if (this->options.isBuildChoiceOriginsSet()) {
738 CommandSet commandIndex{command.getGlobalIndex()};
739 choice.addOriginData(boost::any(std::move(commandIndex)));
740 }
741 choice.addProbability(stateToIdCallback(*this->state), storm::utility::one<ValueType>());
742
743 // Create the state-action reward for the newly created choice.
744 for (auto const& rewardModel : rewardModels) {
745 ValueType stateActionRewardValue = storm::utility::zero<ValueType>();
746 if (rewardModel.get().hasStateActionRewards()) {
747 for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) {
748 if (stateActionReward.getActionIndex() == choice.getActionIndex() &&
749 this->evaluator->asBool(stateActionReward.getStatePredicateExpression())) {
750 stateActionRewardValue += ValueType(this->evaluator->asRational(stateActionReward.getRewardValueExpression()));
751 }
752 }
753 }
754 choice.addReward(stateActionRewardValue);
755 }
756
757 if (this->options.isBuildChoiceLabelsSet() && command.isLabeled()) {
758 choice.addLabel(program.getActionName(command.getActionIndex()));
759 }
760 }
761 }
762
763 // Synchronizing actions
764 for (uint_fast64_t actionIndex : program.getSynchronizingActionIndices()) {
765 if (this->actionMask != nullptr) {
766 if (!this->actionMask->query(*this, actionIndex)) {
767 continue;
768 }
769 }
770 boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> optionalActiveCommandLists =
771 getActiveCommandsByActionIndex(actionIndex, commandFilter);
772
773 // Only process this action label, if there is at least one feasible solution.
774 if (optionalActiveCommandLists) {
775 std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>> const& activeCommandList = optionalActiveCommandLists.get();
776 std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>::const_iterator> iteratorList(activeCommandList.size());
777
778 // Initialize the list of iterators.
779 for (size_t i = 0; i < activeCommandList.size(); ++i) {
780 iteratorList[i] = activeCommandList[i].cbegin();
781 }
782
783 // As long as there is one feasible combination of commands, keep on expanding it.
784 bool done = false;
785 while (!done) {
786 // At this point, we applied all commands of the current command combination and newTargetStates
787 // contains all target states and their respective probabilities. That means we are now ready to
788 // add the choice to the list of transitions.
789 result.push_back(Choice<ValueType>(actionIndex));
790
791 // Now create the actual distribution.
792 Choice<ValueType>& choice = result.back();
793
794 // Remember the choice label and origins only if we were asked to.
795 if (this->options.isBuildChoiceLabelsSet()) {
796 choice.addLabel(program.getActionName(actionIndex));
797 }
798 if (this->options.isBuildChoiceOriginsSet()) {
799 CommandSet commandIndices;
800 for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) {
801 commandIndices.insert(iteratorList[i]->get().getGlobalIndex());
802 }
803 choice.addOriginData(boost::any(std::move(commandIndices)));
804 }
805 choice.addProbability(stateToIdCallback(*this->state), storm::utility::one<ValueType>());
806
807 // Create the state-action reward for the newly created choice.
808 for (auto const& rewardModel : rewardModels) {
809 ValueType stateActionRewardValue = storm::utility::zero<ValueType>();
810 if (rewardModel.get().hasStateActionRewards()) {
811 for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) {
812 if (stateActionReward.getActionIndex() == choice.getActionIndex() &&
813 this->evaluator->asBool(stateActionReward.getStatePredicateExpression())) {
814 stateActionRewardValue += ValueType(this->evaluator->asRational(stateActionReward.getRewardValueExpression()));
815 }
816 }
817 }
818 choice.addReward(stateActionRewardValue);
819 }
820
821 // Now, check whether there is one more command combination to consider.
822 bool movedIterator = false;
823 for (int_fast64_t j = iteratorList.size() - 1; !movedIterator && j >= 0; --j) {
824 ++iteratorList[j];
825 if (iteratorList[j] != activeCommandList[j].end()) {
826 movedIterator = true;
827 } else {
828 // Reset the iterator to the beginning of the list.
829 iteratorList[j] = activeCommandList[j].begin();
830 }
831 }
832
833 done = !movedIterator;
834 }
835 }
836 }
837
838 return result;
839}
840
841template<typename ValueType, typename StateType>
842void PrismNextStateGenerator<ValueType, StateType>::generateSynchronizedDistribution(
843 storm::storage::BitVector const& state, ValueType const& probability, uint64_t position,
844 std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>::const_iterator> const& iteratorList,
845 storm::generator::Distribution<StateType, ValueType>& distribution, StateToIdCallback stateToIdCallback) {
846 if (storm::utility::isZero<ValueType>(probability)) {
847 return;
848 }
849
850 if (position >= iteratorList.size()) {
851 StateType id = stateToIdCallback(state);
852 distribution.add(id, probability);
853 } else {
854 storm::prism::Command const& command = *iteratorList[position];
855 for (uint_fast64_t j = 0; j < command.getNumberOfUpdates(); ++j) {
856 storm::prism::Update const& update = command.getUpdate(j);
857 generateSynchronizedDistribution(applyUpdate(state, update), probability * this->evaluator->asRational(update.getLikelihoodExpression()),
858 position + 1, iteratorList, distribution, stateToIdCallback);
859 }
860 }
861}
862
863template<typename ValueType, typename StateType>
864void PrismNextStateGenerator<ValueType, StateType>::addSynchronousChoices(std::vector<Choice<ValueType>>& choices, CompressedState const& state,
865 StateToIdCallback stateToIdCallback, CommandFilter const& commandFilter) {
866 for (uint_fast64_t actionIndex : program.getSynchronizingActionIndices()) {
867 if (this->actionMask != nullptr) {
868 if (!this->actionMask->query(*this, actionIndex)) {
869 continue;
870 }
871 }
872 boost::optional<std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>>> optionalActiveCommandLists =
873 getActiveCommandsByActionIndex(actionIndex, commandFilter);
874
875 // Only process this action label, if there is at least one feasible solution.
876 if (optionalActiveCommandLists) {
877 std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>> const& activeCommandList = optionalActiveCommandLists.get();
878 std::vector<std::vector<std::reference_wrapper<storm::prism::Command const>>::const_iterator> iteratorList(activeCommandList.size());
879
880 // Initialize the list of iterators.
881 for (size_t i = 0; i < activeCommandList.size(); ++i) {
882 iteratorList[i] = activeCommandList[i].cbegin();
883 }
884
886
887 // As long as there is one feasible combination of commands, keep on expanding it.
888 bool done = false;
889 while (!done) {
890 distribution.clear();
891 generateSynchronizedDistribution(state, storm::utility::one<ValueType>(), 0, iteratorList, distribution, stateToIdCallback);
892 distribution.compress();
893
894 // At this point, we applied all commands of the current command combination and newTargetStates
895 // contains all target states and their respective probabilities. That means we are now ready to
896 // add the choice to the list of transitions.
897 choices.push_back(Choice<ValueType>(actionIndex));
898
899 // Now create the actual distribution.
900 Choice<ValueType>& choice = choices.back();
901
903 storm::storage::PlayerIndex const& playerOfAction = actionIndexToPlayerIndexMap.at(actionIndex);
904 STORM_LOG_THROW(playerOfAction != storm::storage::INVALID_PLAYER_INDEX, storm::exceptions::WrongFormatException,
905 "Action " << program.getActionName(actionIndex)
906 << " is not owned by any player but has at least one enabled, unlabeled (synchronized) command.");
907 choice.setPlayerIndex(playerOfAction);
908 }
909
910 // Remember the choice label and origins only if we were asked to.
911 if (this->options.isBuildChoiceLabelsSet()) {
912 choice.addLabel(program.getActionName(actionIndex));
913 }
914 if (this->options.isBuildChoiceOriginsSet()) {
915 CommandSet commandIndices;
916 for (uint_fast64_t i = 0; i < iteratorList.size(); ++i) {
917 commandIndices.insert(iteratorList[i]->get().getGlobalIndex());
918 }
919 choice.addOriginData(boost::any(std::move(commandIndices)));
920 }
921
922 // Add the probabilities/rates to the newly created choice.
923 ValueType probabilitySum = storm::utility::zero<ValueType>();
924 choice.reserve(std::distance(distribution.begin(), distribution.end()));
925 for (auto const& stateProbability : distribution) {
926 choice.addProbability(stateProbability.getState(), stateProbability.getValue());
927 if (this->options.isExplorationChecksSet()) {
928 probabilitySum += stateProbability.getValue();
929 }
930 }
931
932 if (this->options.isExplorationChecksSet()) {
933 // Check that the resulting distribution is in fact a distribution.
934 STORM_LOG_THROW(!program.isDiscreteTimeModel() || !this->comparator.isConstant(probabilitySum) || this->comparator.isOne(probabilitySum),
935 storm::exceptions::WrongFormatException,
936 "Sum of update probabilities do not some to one for some command (actually sum to " << probabilitySum << ").");
937 }
938
939 // Create the state-action reward for the newly created choice.
940 for (auto const& rewardModel : rewardModels) {
941 ValueType stateActionRewardValue = storm::utility::zero<ValueType>();
942 if (rewardModel.get().hasStateActionRewards()) {
943 for (auto const& stateActionReward : rewardModel.get().getStateActionRewards()) {
944 if (stateActionReward.getActionIndex() == choice.getActionIndex() &&
945 this->evaluator->asBool(stateActionReward.getStatePredicateExpression())) {
946 stateActionRewardValue += ValueType(this->evaluator->asRational(stateActionReward.getRewardValueExpression()));
947 }
948 }
949 }
950 choice.addReward(stateActionRewardValue);
951 }
952
953 // Now, check whether there is one more command combination to consider.
954 bool movedIterator = false;
955 for (int_fast64_t j = iteratorList.size() - 1; !movedIterator && j >= 0; --j) {
956 ++iteratorList[j];
957 if (iteratorList[j] != activeCommandList[j].end()) {
958 movedIterator = true;
959 } else {
960 // Reset the iterator to the beginning of the list.
961 iteratorList[j] = activeCommandList[j].begin();
962 }
963 }
964
965 done = !movedIterator;
966 }
967 }
968 }
969}
970
971template<typename ValueType, typename StateType>
972std::map<std::string, storm::storage::PlayerIndex> PrismNextStateGenerator<ValueType, StateType>::getPlayerNameToIndexMap() const {
973 return program.getPlayerNameToIndexMapping();
974}
975
976template<typename ValueType, typename StateType>
978 std::vector<StateType> const& initialStateIndices,
979 std::vector<StateType> const& deadlockStateIndices,
980 std::vector<StateType> const& unexploredStateIndices) {
981 // Gather a vector of labels and their expressions.
982 std::vector<std::pair<std::string, storm::expressions::Expression>> labels;
983 if (this->options.isBuildAllLabelsSet()) {
984 for (auto const& label : program.getLabels()) {
985 labels.push_back(std::make_pair(label.getName(), label.getStatePredicateExpression()));
986 }
987 } else {
988 for (auto const& labelName : this->options.getLabelNames()) {
989 if (program.hasLabel(labelName)) {
990 labels.push_back(std::make_pair(labelName, program.getLabelExpression(labelName)));
991 } else {
992 STORM_LOG_THROW(this->isSpecialLabel(labelName), storm::exceptions::InvalidArgumentException,
993 "Cannot build labeling for unknown label '" << labelName << "'.");
994 }
995 }
996 }
997
998 return NextStateGenerator<ValueType, StateType>::label(stateStorage, initialStateIndices, deadlockStateIndices, unexploredStateIndices, labels);
999}
1000
1001template<typename ValueType, typename StateType>
1003 // TODO consider to avoid reloading by computing these bitvectors in an earlier build stage
1005
1006 if (program.getNumberOfObservationLabels() == 0) {
1007 return result;
1008 }
1009 unpackStateIntoEvaluator(state, this->variableInformation, *this->evaluator);
1010 for (uint64_t i = 0; i < program.getNumberOfObservationLabels(); ++i) {
1011 result.setFromInt(64 * i, 64, this->evaluator->asInt(program.getObservationLabels()[i].getStatePredicateExpression()));
1012 }
1013 return result;
1014}
1015
1016template<typename ValueType, typename StateType>
1017void PrismNextStateGenerator<ValueType, StateType>::extendStateInformation(storm::json<ValueType>& result) const {
1018 for (uint64_t i = 0; i < program.getNumberOfObservationLabels(); ++i) {
1019 result[program.getObservationLabels()[i].getName()] = this->evaluator->asInt(program.getObservationLabels()[i].getStatePredicateExpression());
1020 }
1021}
1022
1023template<typename ValueType, typename StateType>
1025 return rewardModels.size();
1026}
1027
1028template<typename ValueType, typename StateType>
1030 storm::prism::RewardModel const& rewardModel = rewardModels[index].get();
1031 return storm::builder::RewardModelInformation(rewardModel.getName(), rewardModel.hasStateRewards(), rewardModel.hasStateActionRewards(),
1032 rewardModel.hasTransitionRewards());
1033}
1034
1035template<typename ValueType, typename StateType>
1036std::shared_ptr<storm::storage::sparse::ChoiceOrigins> PrismNextStateGenerator<ValueType, StateType>::generateChoiceOrigins(
1037 std::vector<boost::any>& dataForChoiceOrigins) const {
1038 if (!this->getOptions().isBuildChoiceOriginsSet()) {
1039 return nullptr;
1040 }
1041
1042 std::vector<uint_fast64_t> identifiers;
1043 identifiers.reserve(dataForChoiceOrigins.size());
1044
1045 std::map<CommandSet, uint_fast64_t> commandSetToIdentifierMap;
1046 // The empty commandset (i.e., the choices without origin) always has to get identifier getIdentifierForChoicesWithNoOrigin() -- which is assumed to be 0
1047 STORM_LOG_ASSERT(storm::storage::sparse::ChoiceOrigins::getIdentifierForChoicesWithNoOrigin() == 0, "The no origin identifier is assumed to be zero");
1048 commandSetToIdentifierMap.insert(std::make_pair(CommandSet(), 0));
1049 uint_fast64_t currentIdentifier = 1;
1050 for (boost::any& originData : dataForChoiceOrigins) {
1051 STORM_LOG_ASSERT(originData.empty() || boost::any_cast<CommandSet>(&originData) != nullptr,
1052 "Origin data has unexpected type: " << originData.type().name() << ".");
1053
1054 CommandSet currentCommandSet = originData.empty() ? CommandSet() : boost::any_cast<CommandSet>(std::move(originData));
1055 auto insertionRes = commandSetToIdentifierMap.insert(std::make_pair(std::move(currentCommandSet), currentIdentifier));
1056 identifiers.push_back(insertionRes.first->second);
1057 if (insertionRes.second) {
1058 ++currentIdentifier;
1059 }
1060 }
1061
1062 std::vector<CommandSet> identifierToCommandSetMapping(currentIdentifier);
1063 for (auto const& setIdPair : commandSetToIdentifierMap) {
1064 identifierToCommandSetMapping[setIdPair.second] = setIdPair.first;
1065 }
1066
1067 return std::make_shared<storm::storage::sparse::PrismChoiceOrigins>(std::make_shared<storm::prism::Program>(program), std::move(identifiers),
1068 std::move(identifierToCommandSetMapping));
1069}
1070
1071template<typename ValueType, typename StateType>
1073 return program.getPossiblySynchronizingCommands().get(command.getGlobalIndex());
1074}
1075
1076template class PrismNextStateGenerator<double>;
1077
1078#ifdef STORM_HAVE_CARL
1079template class PrismNextStateGenerator<storm::RationalNumber>;
1080template class PrismNextStateGenerator<storm::RationalFunction>;
1081#endif
1082} // namespace generator
1083} // namespace storm
uint64_t getReservedBitsForUnboundedVariables() const
std::set< std::string > const & getLabelNames() const
Which labels are built.
ExpressionManager const & getManager() const
Retrieves the manager responsible for this expression.
bool isTrue() const
Checks if the expression is equal to the boolean literal true.
bool isInitialized() const
Checks whether the object encapsulates a base-expression.
Expression integer(int_fast64_t value) const
Creates an expression that characterizes the given integer literal.
Action masks are arguments you can give to the state generator that limit which states are generated.
void clear()
Clears this distribution.
ContainerType::iterator begin()
Access to iterators over the entries of the distribution.
void compress()
Compresses the internal storage by summing the values of entries which agree on the index.
ContainerType::iterator end()
void add(DistributionEntry< IndexType, ValueType > const &entry)
Adds the given entry to the distribution.
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
storm::storage::FlatSet< uint_fast64_t > CommandSet
virtual std::vector< StateType > getInitialStates(StateToIdCallback const &stateToIdCallback) override
NextStateGenerator< ValueType, StateType >::StateToIdCallback StateToIdCallback
virtual StateBehavior< ValueType, StateType > expand(StateToIdCallback const &stateToIdCallback) override
virtual ModelType getModelType() const override
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={}) override
PrismNextStateGenerator(storm::prism::Program const &program, NextStateGeneratorOptions const &options=NextStateGeneratorOptions(), std::shared_ptr< ActionMask< ValueType, StateType > > const &=nullptr)
virtual std::size_t getNumberOfRewardModels() const override
virtual std::shared_ptr< storm::storage::sparse::ChoiceOrigins > generateChoiceOrigins(std::vector< boost::any > &dataForChoiceOrigins) const override
static bool canHandle(storm::prism::Program const &program)
A quick check to detect whether the given model is not supported.
bool evaluateBooleanExpressionInCurrentState(storm::expressions::Expression const &) const
virtual std::map< std::string, storm::storage::PlayerIndex > getPlayerNameToIndexMap() const override
virtual storm::builder::RewardModelInformation getRewardModelInformation(uint64_t const &index) const override
void addChoice(Choice< ValueType, StateType > &&choice)
Adds the given choice to the behavior of the state.
void addStateReward(ValueType const &stateReward)
Adds the given state reward to the behavior of the state.
void setExpanded(bool newValue=true)
Sets whether the state was expanded.
This class manages the labeling of the state space with a number of (atomic) labels.
bool isLabeled() const
Retrieves whether the command possesses a synchronization label.
Definition Command.cpp:82
std::size_t getNumberOfUpdates() const
Retrieves the number of updates associated with this command.
Definition Command.cpp:39
storm::prism::Update const & getUpdate(uint_fast64_t index) const
Retrieves a reference to the update with the given index.
Definition Command.cpp:43
storm::expressions::Expression const & getGuardExpression() const
Retrieves a reference to the guard of the command.
Definition Command.cpp:35
uint_fast64_t getActionIndex() const
Retrieves the action index of this command.
Definition Command.cpp:19
bool isMarkovian() const
Retrieves whether the command is a Markovian command, i.e.
Definition Command.cpp:23
uint_fast64_t getGlobalIndex() const
Retrieves the global index of the command, that is, a unique index over all modules.
Definition Command.cpp:56
ModelType getModelType() const
Retrieves the model type of the model.
Definition Program.cpp:247
std::vector< storm::expressions::Expression > getAllRangeExpressions() const
Retrieves a list of expressions that characterize the legal ranges of all variables.
Definition Program.cpp:512
std::vector< RewardModel > const & getRewardModels() const
Retrieves the reward models of the program.
Definition Program.cpp:808
RewardModel const & getRewardModel(std::string const &rewardModelName) const
Retrieves the reward model with the given name.
Definition Program.cpp:816
std::vector< std::reference_wrapper< Constant const > > getUndefinedConstants() const
Retrieves the undefined constants in the program.
Definition Program.cpp:368
bool isPartiallyObservable() const
Retrieves whether the model has restricted observability.
Definition Program.cpp:259
std::string const & getActionName(uint_fast64_t actionIndex) const
Retrieves the action name of the given action index.
Definition Program.cpp:742
bool isDiscreteTimeModel() const
Retrieves whether the model is a discrete-time model, i.e.
Definition Program.cpp:251
storm::expressions::Expression const & getLabelExpression(std::string const &label) const
Retrieves the expression associated with the given label, if it exists.
Definition Program.cpp:847
std::vector< ObservationLabel > const & getObservationLabels() const
Retrieves all observation labels that are defined by this program.
Definition Program.cpp:900
std::map< uint_fast64_t, storm::storage::PlayerIndex > buildActionIndexToPlayerIndexMap() const
Retrieves a vector whose i'th entry corresponds to the player controlling action with index i.
Definition Program.cpp:590
bool isDeterministicModel() const
Retrieves whether the model is one without nondeterministic choices, i.e.
Definition Program.cpp:255
bool undefinedConstantsAreGraphPreserving() const
Checks that undefined constants (parameters) of the model preserve the graph of the underlying model.
Definition Program.cpp:294
std::size_t getNumberOfRewardModels() const
Retrieves the number of reward models in the program.
Definition Program.cpp:812
std::size_t getNumberOfObservationLabels() const
Retrieves the number of observation labels in the program.
Definition Program.cpp:904
std::map< std::string, storm::storage::PlayerIndex > const & getPlayerNameToIndexMapping() const
Definition Program.cpp:574
storm::expressions::ExpressionManager & getManager() const
Retrieves the manager responsible for the expressions of this program.
Definition Program.cpp:2359
bool hasLabel(std::string const &labelName) const
Checks whether the program has a label with the given name.
Definition Program.cpp:828
std::vector< storm::storage::PlayerIndex > buildModuleIndexToPlayerIndexMap() const
Retrieves a vector whose i'th entry corresponds to the player controlling module i.
Definition Program.cpp:578
std::string getUndefinedConstantsAsString() const
Retrieves the undefined constants in the program as a comma-separated string.
Definition Program.cpp:378
storm::expressions::Expression getInitialStatesExpression() const
Retrieves an expression characterizing the initial states.
Definition Program.cpp:662
std::size_t getNumberOfModules() const
Retrieves the number of modules in the program.
Definition Program.cpp:611
bool hasInitialConstruct() const
Retrieves whether the program specifies an initial construct.
Definition Program.cpp:645
bool hasUndefinedConstants() const
Retrieves whether there are undefined constants of any type in the program.
Definition Program.cpp:285
bool specifiesSystemComposition() const
Retrieves whether the program specifies a system composition in terms of process algebra operations o...
Definition Program.cpp:710
std::vector< Label > const & getLabels() const
Retrieves all labels that are defined by the probabilitic program.
Definition Program.cpp:833
storm::storage::BitVector const & getPossiblySynchronizingCommands() const
Compute the (labelled) commands in the program that may be synchronizing.
Definition Program.cpp:908
bool hasRewardModel() const
Retrieves whether the program has reward models.
Definition Program.cpp:799
bool hasStateRewards() const
Retrieves whether there are any state rewards.
bool hasTransitionRewards() const
Retrieves whether there are any transition rewards.
std::string const & getName() const
Retrieves the name of the reward model.
bool hasStateActionRewards() const
Retrieves whether there are any state-action rewards.
std::vector< storm::prism::Assignment > const & getAssignments() const
Retrieves a reference to the map of variable names to their respective assignments.
Definition Update.cpp:44
storm::expressions::Expression const & getLikelihoodExpression() const
Retrieves the expression for the likelihood of this update.
Definition Update.cpp:36
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
void setFromInt(uint_fast64_t bitIndex, uint_fast64_t numberOfBits, uint64_t value)
Sets the selected number of lowermost bits of the provided value at the given bit index.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
static uint_fast64_t getIdentifierForChoicesWithNoOrigin()
virtual std::unique_ptr< storm::solver::SmtSolver > create(storm::expressions::ExpressionManager &manager) const
Creates a new SMT solver instance.
Definition solver.cpp:124
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SFTBDDChecker::ValueType ValueType
void unpackStateIntoEvaluator(CompressedState const &state, VariableInformation const &variableInformation, storm::expressions::ExpressionEvaluator< ValueType > &evaluator)
Unpacks the compressed state into the evaluator.
storm::storage::BitVector CompressedState
PlayerIndex const INVALID_PLAYER_INDEX
Definition PlayerIndex.h:8
uint64_t PlayerIndex
Definition PlayerIndex.h:7
void forEach(std::vector< IteratorType > const &its, std::vector< IteratorType > const &ites, std::function< void(uint64_t, decltype(*std::declval< IteratorType >()))> const &setValueCallback, std::function< bool()> const &newCombinationCallback)
LabParser.cpp.
Definition cli.cpp:18
nlohmann::basic_json< std::map, std::vector, std::string, bool, int64_t, uint64_t, ValueType > json
Definition JsonForward.h:10
ActiveCommandData(storm::prism::Module const *modulePtr, std::set< uint_fast64_t > const *commandIndicesPtr, typename std::set< uint_fast64_t >::const_iterator currentCommandIndexIt)
std::set< uint_fast64_t >::const_iterator currentCommandIndexIt
std::set< uint_fast64_t > const * commandIndicesPtr
void addOriginData(boost::any const &data)
Adds the given data that specifies the origin of this choice w.r.t.
Definition Choice.cpp:116
void addLabels(std::set< std::string > const &labels)
Adds the given label set to the labels associated with this choice.
Definition Choice.cpp:82
void addProbability(StateType const &state, ValueType const &value)
Adds the given probability value to the given state in the underlying distribution.
Definition Choice.cpp:158
void addReward(ValueType const &value)
Adds the given value to the reward associated with this choice.
Definition Choice.cpp:164