39namespace modelchecker {
41template<
typename ModelType,
typename StateType>
43 : program(program.substituteConstantsFormulas()),
44 randomGenerator(
std::chrono::system_clock::now().time_since_epoch().count()),
45 comparator(
storm::settings::getModule<
storm::settings::modules::ExplorationSettings>().getPrecision()) {
49template<
typename ModelType,
typename StateType>
56template<
typename ModelType,
typename StateType>
58 return canHandleStatic(checkTask);
61template<
typename ModelType,
typename StateType>
68 "For nondeterministic systems, an optimization direction (min/max) must be given in the property.");
71 : storm::OptimizationDirection::Maximize);
76 std::map<std::string, storm::expressions::Expression> labelToExpressionMapping = program.getLabelToExpressionMapping();
78 conditionFormula.
toExpression(program.getManager(), labelToExpressionMapping),
79 targetFormula.
toExpression(program.getManager(), labelToExpressionMapping));
82 std::tuple<StateType, ValueType, ValueType> boundsForInitialState = performExploration(stateGeneration, explorationInformation);
83 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(std::get<0>(boundsForInitialState), std::get<1>(boundsForInitialState));
86template<
typename ModelType,
typename StateType>
92 "Currently only models with one initial state are supported by the exploration engine.");
99 StateActionStack stack;
103 bool convergenceCriterionMet =
false;
104 while (!convergenceCriterionMet) {
105 bool result = samplePathFromInitialState(stateGeneration, explorationInformation, stack, bounds, stats);
113 STORM_LOG_TRACE(
"Found terminal state, updating probabilities along path.");
114 updateProbabilityBoundsAlongSampledPath(stack, explorationInformation, bounds);
127 convergenceCriterionMet = comparator.isZero(difference);
131 performPrecomputation(stack, explorationInformation, bounds, stats);
140 return std::make_tuple(initialStateIndex, bounds.
getLowerBoundForState(initialStateIndex, explorationInformation),
144template<
typename ModelType,
typename StateType>
145bool SparseExplorationModelChecker<ModelType, StateType>::samplePathFromInitialState(StateGeneration<StateType, ValueType>& stateGeneration,
146 ExplorationInformation<StateType, ValueType>& explorationInformation,
147 StateActionStack& stack, Bounds<StateType, ValueType>& bounds,
148 Statistics<StateType, ValueType>& stats)
const {
150 stack.push_back(std::make_pair(stateGeneration.getFirstInitialState(), 0));
153 bool foundTerminalState =
false;
154 while (!foundTerminalState) {
155 StateType
const& currentStateId = stack.back().first;
156 STORM_LOG_TRACE(
"State on top of stack is: " << currentStateId <<
".");
159 auto unexploredIt = explorationInformation.findUnexploredState(currentStateId);
160 if (unexploredIt != explorationInformation.unexploredStatesEnd()) {
165 foundTerminalState = exploreState(stateGeneration, currentStateId, compressedState, explorationInformation, bounds, stats);
166 if (foundTerminalState) {
167 STORM_LOG_TRACE(
"Aborting sampling of path, because a terminal state was reached.");
169 explorationInformation.removeUnexploredState(unexploredIt);
172 if (explorationInformation.isTerminal(currentStateId)) {
173 STORM_LOG_TRACE(
"Found already explored terminal state: " << currentStateId <<
".");
174 foundTerminalState =
true;
179 stats.explorationStep();
182 if (!foundTerminalState) {
185 uint32_t chosenAction = sampleActionOfState(currentStateId, explorationInformation, bounds);
186 stack.back().second = chosenAction;
187 STORM_LOG_TRACE(
"Sampled action " << chosenAction <<
" in state " << currentStateId <<
".");
189 StateType successor = sampleSuccessorFromAction(chosenAction, explorationInformation, bounds);
190 STORM_LOG_TRACE(
"Sampled successor " << successor <<
" according to action " << chosenAction <<
" of state " << currentStateId <<
".");
193 stack.emplace_back(successor, 0);
196 if (explorationInformation.performPrecomputationExcessiveExplorationSteps(stats.explorationStepsSinceLastPrecomputation)) {
197 performPrecomputation(stack, explorationInformation, bounds, stats);
206 return foundTerminalState;
209template<
typename ModelType,
typename StateType>
210bool SparseExplorationModelChecker<ModelType, StateType>::exploreState(StateGeneration<StateType, ValueType>& stateGeneration, StateType
const& currentStateId,
212 ExplorationInformation<StateType, ValueType>& explorationInformation,
213 Bounds<StateType, ValueType>& bounds, Statistics<StateType, ValueType>& stats)
const {
214 bool isTerminalState =
false;
215 bool isTargetState =
false;
217 ++stats.numberOfExploredStates;
220 explorationInformation.assignStateToNextRowGroup(currentStateId);
221 STORM_LOG_TRACE(
"Assigning row group " << explorationInformation.getRowGroup(currentStateId) <<
" to state " << currentStateId <<
".");
225 bounds.initializeBoundsForNextState();
229 stateGeneration.load(currentState);
230 if (stateGeneration.isTargetState()) {
231 ++stats.numberOfTargetStates;
232 isTargetState =
true;
233 isTerminalState =
true;
234 }
else if (stateGeneration.isConditionState()) {
242 bool otherSuccessor =
false;
243 for (
auto const& choice : behavior) {
244 for (
auto const& entry : choice) {
245 if (entry.first != currentStateId) {
246 otherSuccessor =
true;
251 isTerminalState = !otherSuccessor;
255 if (!isTerminalState) {
257 StateType startAction = explorationInformation.getActionCount();
260 ActionType localAction = 0;
263 std::pair<ValueType, ValueType> stateBounds = getLowestBounds(explorationInformation.getOptimizationDirection());
265 for (
auto const& choice : behavior) {
266 for (
auto const& entry : choice) {
267 explorationInformation.getRowOfMatrix(startAction + localAction).emplace_back(entry.first, entry.second);
268 STORM_LOG_TRACE(
"Found transition " << currentStateId <<
"-[" << (startAction + localAction) <<
", " << entry.second <<
"]-> "
269 << entry.first <<
".");
272 std::pair<ValueType, ValueType> actionBounds = computeBoundsOfAction(startAction + localAction, explorationInformation, bounds);
273 bounds.initializeBoundsForNextAction(actionBounds);
274 stateBounds = combineBounds(explorationInformation.getOptimizationDirection(), stateBounds, actionBounds);
276 STORM_LOG_TRACE(
"Initializing bounds of action " << (startAction + localAction) <<
" to "
277 << bounds.getLowerBoundForAction(startAction + localAction) <<
" and "
278 << bounds.getUpperBoundForAction(startAction + localAction) <<
".");
284 explorationInformation.terminateCurrentRowGroup();
286 bounds.setBoundsForState(currentStateId, explorationInformation, stateBounds);
287 STORM_LOG_TRACE(
"Initializing bounds of state " << currentStateId <<
" to " << bounds.getLowerBoundForState(currentStateId, explorationInformation)
288 <<
" and " << bounds.getUpperBoundForState(currentStateId, explorationInformation) <<
".");
293 isTerminalState =
true;
296 if (isTerminalState) {
297 STORM_LOG_TRACE(
"State does not need to be explored, because it is " << (isTargetState ?
"a target state" :
"a rejecting terminal state") <<
".");
298 explorationInformation.addTerminalState(currentStateId);
301 bounds.setBoundsForState(currentStateId, explorationInformation,
302 std::make_pair(storm::utility::one<ValueType>(), storm::utility::one<ValueType>()));
303 bounds.initializeBoundsForNextAction(std::make_pair(storm::utility::one<ValueType>(), storm::utility::one<ValueType>()));
305 bounds.setBoundsForState(currentStateId, explorationInformation,
306 std::make_pair(storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>()));
307 bounds.initializeBoundsForNextAction(std::make_pair(storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>()));
311 explorationInformation.addActionsToMatrix(1);
314 explorationInformation.newRowGroup();
317 return isTerminalState;
320template<
typename ModelType,
typename StateType>
322 StateType
const& currentStateId, ExplorationInformation<StateType, ValueType>
const& explorationInformation, Bounds<StateType, ValueType>& bounds)
const {
324 std::vector<std::pair<ActionType, ValueType>> actionValues;
325 StateType rowGroup = explorationInformation.getRowGroup(currentStateId);
328 if (explorationInformation.onlyOneActionAvailable(rowGroup)) {
329 return explorationInformation.getStartRowOfGroup(rowGroup);
335 for (uint32_t row = explorationInformation.getStartRowOfGroup(rowGroup); row < explorationInformation.getStartRowOfGroup(rowGroup + 1); ++row) {
336 actionValues.push_back(std::make_pair(row, bounds.getBoundForAction(explorationInformation.getOptimizationDirection(), row)));
339 STORM_LOG_ASSERT(!actionValues.empty(),
"Values for actions must not be empty.");
342 if (explorationInformation.maximize()) {
343 std::sort(actionValues.begin(), actionValues.end(),
344 [](std::pair<ActionType, ValueType>
const& a, std::pair<ActionType, ValueType>
const& b) { return a.second > b.second; });
346 std::sort(actionValues.begin(), actionValues.end(),
347 [](std::pair<ActionType, ValueType>
const& a, std::pair<ActionType, ValueType>
const& b) { return a.second < b.second; });
351 auto end = ++actionValues.begin();
352 while (end != actionValues.end() && comparator.isEqual(actionValues.begin()->second, end->second)) {
357 std::uniform_int_distribution<ActionType> distribution(0, std::distance(actionValues.begin(), end) - 1);
358 return actionValues[distribution(randomGenerator)].first;
361template<
typename ModelType,
typename StateType>
362StateType SparseExplorationModelChecker<ModelType, StateType>::sampleSuccessorFromAction(
363 ActionType
const& chosenAction, ExplorationInformation<StateType, ValueType>
const& explorationInformation,
364 Bounds<StateType, ValueType>
const& bounds)
const {
365 std::vector<storm::storage::MatrixEntry<StateType, ValueType>>
const& row = explorationInformation.getRowOfMatrix(chosenAction);
366 if (row.size() == 1) {
367 return row.front().getColumn();
371 if (explorationInformation.useDifferenceProbabilitySumHeuristic() || explorationInformation.useProbabilityHeuristic()) {
372 std::vector<ValueType> probabilities(row.size());
373 if (explorationInformation.useDifferenceProbabilitySumHeuristic()) {
374 std::transform(row.begin(), row.end(), probabilities.begin(),
376 return entry.getValue() + bounds.getDifferenceOfStateBounds(entry.getColumn(), explorationInformation);
378 }
else if (explorationInformation.useProbabilityHeuristic()) {
379 std::transform(row.begin(), row.end(), probabilities.begin(),
384 std::discrete_distribution<StateType> distribution(probabilities.begin(), probabilities.end());
385 return row[distribution(randomGenerator)].getColumn();
387 STORM_LOG_ASSERT(explorationInformation.useUniformHeuristic(),
"Illegal next-state heuristic.");
388 std::uniform_int_distribution<ActionType> distribution(0, row.size() - 1);
389 return row[distribution(randomGenerator)].getColumn();
393template<
typename ModelType,
typename StateType>
394bool SparseExplorationModelChecker<ModelType, StateType>::performPrecomputation(StateActionStack
const& stack,
395 ExplorationInformation<StateType, ValueType>& explorationInformation,
396 Bounds<StateType, ValueType>& bounds,
397 Statistics<StateType, ValueType>& stats)
const {
398 ++stats.numberOfPrecomputations;
404 STORM_LOG_TRACE(
"Starting " << (explorationInformation.useLocalPrecomputation() ?
"local" :
"global") <<
" precomputation.");
410 std::vector<StateType> relevantStates;
411 if (explorationInformation.useLocalPrecomputation()) {
412 for (
auto const& stateActionPair : stack) {
413 if (explorationInformation.maximize() || !
storm::utility::isOne(bounds.getLowerBoundForState(stateActionPair.first, explorationInformation))) {
414 relevantStates.push_back(stateActionPair.first);
417 std::sort(relevantStates.begin(), relevantStates.end());
418 auto newEnd = std::unique(relevantStates.begin(), relevantStates.end());
419 relevantStates.resize(std::distance(relevantStates.begin(), newEnd));
421 for (StateType state = 0; state < explorationInformation.getNumberOfDiscoveredStates(); ++state) {
423 if (!explorationInformation.isUnexplored(state)) {
424 relevantStates.push_back(state);
428 StateType sink = relevantStates.size();
432 std::unordered_map<StateType, StateType> relevantStateToNewRowGroupMapping;
434 for (StateType index = 0; index < relevantStates.size(); ++index) {
435 relevantStateToNewRowGroupMapping.emplace(relevantStates[index], index);
436 if (
storm::utility::isOne(bounds.getLowerBoundForState(relevantStates[index], explorationInformation))) {
437 targetStates.set(index);
442 StateType currentRow = 0;
443 for (
auto const& state : relevantStates) {
444 builder.newRowGroup(currentRow);
445 StateType rowGroup = explorationInformation.getRowGroup(state);
446 for (
auto row = explorationInformation.getStartRowOfGroup(rowGroup); row < explorationInformation.getStartRowOfGroup(rowGroup + 1); ++row) {
447 ValueType unexpandedProbability = storm::utility::zero<ValueType>();
448 for (
auto const& entry : explorationInformation.getRowOfMatrix(row)) {
449 auto it = relevantStateToNewRowGroupMapping.find(entry.getColumn());
450 if (it != relevantStateToNewRowGroupMapping.end()) {
452 builder.addNextValue(currentRow, it->second, entry.getValue());
455 unexpandedProbability += entry.getValue();
458 if (unexpandedProbability != storm::utility::zero<ValueType>()) {
459 builder.addNextValue(currentRow, sink, unexpandedProbability);
465 builder.newRowGroup(currentRow);
466 builder.addNextValue(currentRow, sink, storm::utility::one<ValueType>());
474 if (explorationInformation.maximize()) {
480 targetStates.
set(sink,
true);
482 targetStates.set(sink,
false);
483 statesWithProbability1 =
487 ++stats.ecDetections;
488 STORM_LOG_TRACE(
"Successfully computed MEC decomposition. Found " << (mecDecomposition.size() > 1 ? (mecDecomposition.size() - 1) : 0) <<
" MEC(s).");
491 STORM_LOG_ASSERT(mecDecomposition.size() > 0,
"Expected at least one MEC (the trivial sink MEC).");
492 if (mecDecomposition.size() == 1) {
493 ++stats.failedEcDetections;
495 stats.totalNumberOfEcDetected += mecDecomposition.size() - 1;
498 for (
auto const& mec : mecDecomposition) {
500 if (mec.containsState(sink)) {
504 collapseMec(mec, relevantStates, relevantStatesMatrix, explorationInformation, bounds);
512 targetStates.set(sink,
true);
513 statesWithProbability0 =
515 targetStates.set(sink,
false);
516 statesWithProbability1 =
521 STORM_LOG_ASSERT((statesWithProbability0 & statesWithProbability1).empty(),
"States with probability 0 and 1 overlap.");
522 for (
auto state : statesWithProbability0) {
528 StateType originalState = relevantStates[state];
529 bounds.setUpperBoundForState(originalState, explorationInformation, storm::utility::zero<ValueType>());
530 explorationInformation.addTerminalState(originalState);
532 for (
auto state : statesWithProbability1) {
538 StateType originalState = relevantStates[state];
539 bounds.setLowerBoundForState(originalState, explorationInformation, storm::utility::one<ValueType>());
540 explorationInformation.addTerminalState(originalState);
545template<
typename ModelType,
typename StateType>
547 std::vector<StateType>
const& relevantStates,
549 ExplorationInformation<StateType, ValueType>& explorationInformation,
550 Bounds<StateType, ValueType>& bounds)
const {
551 bool containsTargetState =
false;
554 std::vector<ActionType> leavingActions;
555 for (
auto const& stateAndChoices : mec) {
557 StateType originalState = relevantStates[stateAndChoices.first];
558 StateType originalRowGroup = explorationInformation.getRowGroup(originalState);
561 if (!containsTargetState &&
storm::utility::isOne(bounds.getLowerBoundForRowGroup(originalRowGroup))) {
562 containsTargetState =
true;
566 auto includedChoicesIt = stateAndChoices.second.begin();
567 auto includedChoicesIte = stateAndChoices.second.end();
568 for (
auto action = explorationInformation.getStartRowOfGroup(originalRowGroup);
569 action < explorationInformation.getStartRowOfGroup(originalRowGroup + 1); ++action) {
570 if (includedChoicesIt != includedChoicesIte) {
572 << (*includedChoicesIt - relevantStatesMatrix.
getRowGroupIndices()[stateAndChoices.first]));
573 STORM_LOG_TRACE(
"Current (local) choice iterated is " << (action - explorationInformation.getStartRowOfGroup(originalRowGroup)));
574 if (action - explorationInformation.getStartRowOfGroup(originalRowGroup) !=
575 *includedChoicesIt - relevantStatesMatrix.
getRowGroupIndices()[stateAndChoices.first]) {
577 leavingActions.push_back(action);
583 STORM_LOG_TRACE(
"Choice leaves the EC, because there is no more choice staying in the EC.");
584 leavingActions.push_back(action);
591 if (!containsTargetState && !leavingActions.empty()) {
598 StateType nextRowGroup = explorationInformation.getNextRowGroup();
599 for (
auto const& stateAndChoices : mec) {
600 StateType originalState = relevantStates[stateAndChoices.first];
601 explorationInformation.assignStateToRowGroup(originalState, nextRowGroup);
604 bounds.initializeBoundsForNextState();
608 std::pair<ValueType, ValueType> stateBounds = getLowestBounds(explorationInformation.getOptimizationDirection());
609 for (
auto const& action : leavingActions) {
610 explorationInformation.moveActionToBackOfMatrix(action);
611 std::pair<ValueType, ValueType> actionBounds = bounds.getBoundsForAction(action);
612 bounds.initializeBoundsForNextAction(actionBounds);
613 stateBounds = combineBounds(explorationInformation.getOptimizationDirection(), stateBounds, actionBounds);
615 bounds.setBoundsForRowGroup(nextRowGroup, stateBounds);
618 explorationInformation.terminateCurrentRowGroup();
622template<
typename ModelType,
typename StateType>
623typename ModelType::ValueType SparseExplorationModelChecker<ModelType, StateType>::computeLowerBoundOfAction(
624 ActionType
const& action, ExplorationInformation<StateType, ValueType>
const& explorationInformation, Bounds<StateType, ValueType>
const& bounds)
const {
625 ValueType result = storm::utility::zero<ValueType>();
626 for (
auto const& element : explorationInformation.getRowOfMatrix(action)) {
627 result += element.getValue() * bounds.getLowerBoundForState(element.getColumn(), explorationInformation);
632template<
typename ModelType,
typename StateType>
633typename ModelType::ValueType SparseExplorationModelChecker<ModelType, StateType>::computeUpperBoundOfAction(
634 ActionType
const& action, ExplorationInformation<StateType, ValueType>
const& explorationInformation, Bounds<StateType, ValueType>
const& bounds)
const {
635 ValueType result = storm::utility::zero<ValueType>();
636 for (
auto const& element : explorationInformation.getRowOfMatrix(action)) {
637 result += element.getValue() * bounds.getUpperBoundForState(element.getColumn(), explorationInformation);
642template<
typename ModelType,
typename StateType>
643std::pair<typename ModelType::ValueType, typename ModelType::ValueType> SparseExplorationModelChecker<ModelType, StateType>::computeBoundsOfAction(
644 ActionType
const& action, ExplorationInformation<StateType, ValueType>
const& explorationInformation, Bounds<StateType, ValueType>
const& bounds)
const {
646 std::pair<ValueType, ValueType> result = std::make_pair(storm::utility::zero<ValueType>(), storm::utility::zero<ValueType>());
647 for (
auto const& element : explorationInformation.getRowOfMatrix(action)) {
648 result.first += element.getValue() * bounds.getLowerBoundForState(element.getColumn(), explorationInformation);
649 result.second += element.getValue() * bounds.getUpperBoundForState(element.getColumn(), explorationInformation);
654template<
typename ModelType,
typename StateType>
655std::pair<typename ModelType::ValueType, typename ModelType::ValueType> SparseExplorationModelChecker<ModelType, StateType>::computeBoundsOfState(
656 StateType
const& currentStateId, ExplorationInformation<StateType, ValueType>
const& explorationInformation,
657 Bounds<StateType, ValueType>
const& bounds)
const {
658 StateType group = explorationInformation.getRowGroup(currentStateId);
659 std::pair<ValueType, ValueType> result = getLowestBounds(explorationInformation.getOptimizationDirection());
660 for (ActionType action = explorationInformation.getStartRowOfGroup(group); action < explorationInformation.getStartRowOfGroup(group + 1); ++action) {
661 std::pair<ValueType, ValueType> actionValues = computeBoundsOfAction(action, explorationInformation, bounds);
662 result = combineBounds(explorationInformation.getOptimizationDirection(), result, actionValues);
667template<
typename ModelType,
typename StateType>
668void SparseExplorationModelChecker<ModelType, StateType>::updateProbabilityBoundsAlongSampledPath(
669 StateActionStack& stack, ExplorationInformation<StateType, ValueType>
const& explorationInformation, Bounds<StateType, ValueType>& bounds)
const {
671 while (!stack.empty()) {
672 updateProbabilityOfAction(stack.back().first, stack.back().second, explorationInformation, bounds);
677template<
typename ModelType,
typename StateType>
678void SparseExplorationModelChecker<ModelType, StateType>::updateProbabilityOfAction(StateType
const& state, ActionType
const& action,
679 ExplorationInformation<StateType, ValueType>
const& explorationInformation,
680 Bounds<StateType, ValueType>& bounds)
const {
682 std::pair<ValueType, ValueType> newBoundsForAction = computeBoundsOfAction(action, explorationInformation, bounds);
685 bounds.setBoundsForAction(action, newBoundsForAction);
688 if (explorationInformation.maximize()) {
689 bounds.setLowerBoundOfStateIfGreaterThanOld(state, explorationInformation, newBoundsForAction.first);
691 StateType rowGroup = explorationInformation.getRowGroup(state);
692 if (newBoundsForAction.second < bounds.getUpperBoundForRowGroup(rowGroup)) {
693 if (explorationInformation.getRowGroupSize(rowGroup) > 1) {
694 newBoundsForAction.second = std::max(newBoundsForAction.second, computeBoundOverAllOtherActions(storm::OptimizationDirection::Maximize, state,
695 action, explorationInformation, bounds));
698 bounds.setUpperBoundForRowGroup(rowGroup, newBoundsForAction.second);
701 bounds.setUpperBoundOfStateIfLessThanOld(state, explorationInformation, newBoundsForAction.second);
703 StateType rowGroup = explorationInformation.getRowGroup(state);
704 if (bounds.getLowerBoundForRowGroup(rowGroup) < newBoundsForAction.first) {
705 if (explorationInformation.getRowGroupSize(rowGroup) > 1) {
706 ValueType min = computeBoundOverAllOtherActions(storm::OptimizationDirection::Minimize, state, action, explorationInformation, bounds);
707 newBoundsForAction.first = std::min(newBoundsForAction.first, min);
710 bounds.setLowerBoundForRowGroup(rowGroup, newBoundsForAction.first);
715template<
typename ModelType,
typename StateType>
716typename ModelType::ValueType SparseExplorationModelChecker<ModelType, StateType>::computeBoundOverAllOtherActions(
718 ExplorationInformation<StateType, ValueType>
const& explorationInformation, Bounds<StateType, ValueType>
const& bounds)
const {
719 ValueType bound = getLowestBound(explorationInformation.getOptimizationDirection());
721 ActionType group = explorationInformation.getRowGroup(state);
722 for (
auto currentAction = explorationInformation.getStartRowOfGroup(group); currentAction < explorationInformation.getStartRowOfGroup(group + 1);
724 if (currentAction == action) {
728 if (direction == storm::OptimizationDirection::Maximize) {
729 bound = std::max(bound, computeUpperBoundOfAction(currentAction, explorationInformation, bounds));
731 bound = std::min(bound, computeLowerBoundOfAction(currentAction, explorationInformation, bounds));
737template<
typename ModelType,
typename StateType>
738std::pair<typename ModelType::ValueType, typename ModelType::ValueType> SparseExplorationModelChecker<ModelType, StateType>::getLowestBounds(
740 ValueType val = getLowestBound(direction);
741 return std::make_pair(val, val);
744template<
typename ModelType,
typename StateType>
745typename ModelType::ValueType SparseExplorationModelChecker<ModelType, StateType>::getLowestBound(
storm::OptimizationDirection const& direction)
const {
746 if (direction == storm::OptimizationDirection::Maximize) {
747 return storm::utility::zero<ValueType>();
749 return storm::utility::one<ValueType>();
753template<
typename ModelType,
typename StateType>
754std::pair<typename ModelType::ValueType, typename ModelType::ValueType> SparseExplorationModelChecker<ModelType, StateType>::combineBounds(
755 storm::OptimizationDirection const& direction, std::pair<ValueType, ValueType>
const& bounds1, std::pair<ValueType, ValueType>
const& bounds2)
const {
756 if (direction == storm::OptimizationDirection::Maximize) {
757 return std::make_pair(std::max(bounds1.first, bounds2.first), std::max(bounds1.second, bounds2.second));
759 return std::make_pair(std::min(bounds1.first, bounds2.first), std::min(bounds1.second, bounds2.second));
763template class SparseExplorationModelChecker<storm::models::sparse::Dtmc<double>, uint32_t>;
764template class SparseExplorationModelChecker<storm::models::sparse::Mdp<double>, uint32_t>;
std::size_t getNumberOfChoices() const
Retrieves the number of choices in the behavior.
bool isOptimizationDirectionSet() const
Retrieves whether an optimization direction was set.
FormulaType const & getFormula() const
Retrieves the formula from this task.
storm::OptimizationDirection const & getOptimizationDirection() const
Retrieves the optimization direction (if set).
bool isOnlyInitialStatesRelevantSet() const
Retrieves whether only the initial states are relevant in the computation.
virtual std::unique_ptr< CheckResult > computeUntilProbabilities(Environment const &env, CheckTask< storm::logic::UntilFormula, ValueType > const &checkTask) override
static bool canHandleStatic(CheckTask< storm::logic::Formula, ValueType > const &checkTask)
SparseExplorationModelChecker(storm::prism::Program const &program)
virtual bool canHandle(CheckTask< storm::logic::Formula, ValueType > const &checkTask) const override
ValueType getDifferenceOfStateBounds(StateType const &state, ExplorationInformation< StateType, ValueType > const &explorationInformation) const
ValueType getLowerBoundForState(StateType const &state, ExplorationInformation< StateType, ValueType > const &explorationInformation) const
ValueType getUpperBoundForState(StateType const &state, ExplorationInformation< StateType, ValueType > const &explorationInformation) const
std::size_t getNumberOfInitialStates() const
StateType getFirstInitialState() const
void computeInitialStates()
A bit vector that is internally represented as a vector of 64-bit values.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
This class represents the decomposition of a nondeterministic model into its maximal end components.
This class represents a maximal end-component of a nondeterministic model.
A class that can be used to build a sparse matrix by adding value by value.
A class that holds a possibly non-square matrix in the compressed row storage format.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
FragmentSpecification reachability()
SettingsType const & getModule()
Get module.
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
storm::storage::BitVector performProb0A(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 of satisfying phi until psi under at least one po...
storm::storage::BitVector performProb1E(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability 1 of satisfying phi until psi under at least one po...
bool isOne(ValueType const &a)
ValueType min(ValueType const &first, ValueType const &second)
std::size_t numberOfExploredStates
std::size_t pathsSampledSinceLastPrecomputation
void printToStream(std::ostream &out, ExplorationInformation< StateType, ValueType > const &explorationInformation) const
void updateMaxPathLength(std::size_t const ¤tPathLength)