38 for (uint64_t currentState : initialStates) {
39 for (
auto const& successor : transitionMatrix.
getRowGroup(currentState)) {
41 result.set(successor.getColumn());
50 bool useStepBound, uint_fast64_t maximalSteps, boost::optional<storm::storage::BitVector>
const& choiceFilter) {
56 std::vector<uint_fast64_t> stack;
57 stack.reserve(initialStates.
size());
58 for (
auto state : initialStates) {
59 if (constraintStates.
get(state)) {
60 stack.push_back(state);
65 std::vector<uint_fast64_t> stepStack;
66 std::vector<uint_fast64_t> remainingSteps;
68 stepStack.reserve(numberOfStates);
69 stepStack.insert(stepStack.begin(), stack.size(), maximalSteps);
70 remainingSteps.resize(numberOfStates);
71 for (
auto state : stack) {
72 remainingSteps[state] = maximalSteps;
77 uint_fast64_t currentState = 0, currentStepBound = 0;
78 while (!stack.empty()) {
79 currentState = stack.back();
83 currentStepBound = stepStack.back();
86 if (currentStepBound == 0) {
93 row = choiceFilter->getNextSetIndex(row);
96 while (row < rowGroupEnd) {
97 for (
auto const& successor : transitionMatrix.
getRow(row)) {
101 (!reachableStates.
get(successor.getColumn()) || (useStepBound && remainingSteps[successor.getColumn()] < currentStepBound - 1))) {
104 if (targetStates.
get(successor.getColumn())) {
105 reachableStates.
set(successor.getColumn());
106 }
else if (constraintStates.
get(successor.getColumn())) {
110 remainingSteps[successor.getColumn()] = currentStepBound - 1;
111 stepStack.push_back(currentStepBound - 1);
113 reachableStates.
set(successor.getColumn());
114 stack.push_back(successor.getColumn());
120 row = choiceFilter->getNextSetIndex(row);
125 return reachableStates;
135 for (
auto const& scc : decomposition) {
136 result.
set(*scc.begin());
147 unexploredStates = subsystem.
get();
148 acyclicStates = ~subsystem.
get();
153 std::vector<uint64_t> dfsStack;
155 dfsStack.push_back(start);
156 while (!dfsStack.empty()) {
157 uint64_t state = dfsStack.back();
158 if (unexploredStates.
get(state)) {
159 unexploredStates.
set(state,
false);
160 for (
auto const& entry : transitionMatrix.
getRowGroup(state)) {
162 if (unexploredStates.
get(entry.getColumn())) {
163 dfsStack.push_back(entry.getColumn());
165 if (!acyclicStates.
get(entry.getColumn())) {
173 acyclicStates.
set(state,
true);
192 uint_fast64_t state = 0;
193 for (
auto choice : choices) {
200 if (subsystem.
get(state)) {
201 bool choiceStaysInSubsys =
true;
202 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
203 if (!subsystem.
get(entry.getColumn())) {
204 choiceStaysInSubsys =
false;
208 if (choiceStaysInSubsys) {
209 statesWithChoice.
set(state,
true);
225 statesWithChoice &= candidateStates;
227 for (
auto state : statesWithChoice) {
230 bool choiceStaysInCandidateSet =
true;
231 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
232 if (!candidateStates.
get(entry.getColumn())) {
233 choiceStaysInCandidateSet =
false;
237 if (choiceStaysInCandidateSet) {
238 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
239 choiceTargets.
set(entry.getColumn(),
true);
249 while (!candidateStates.
empty()) {
251 statesWithChoice &= candidateStates;
252 for (
auto state : statesWithChoice) {
253 bool stateHasChoice =
false;
256 bool choiceStaysInCandidateSet =
true;
257 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
258 if (!candidateStates.
get(entry.getColumn())) {
259 choiceStaysInCandidateSet =
false;
263 if (choiceStaysInCandidateSet) {
264 stateHasChoice =
true;
268 if (!stateHasChoice) {
269 statesWithChoice.
set(state,
false);
275 backwardTransitions, candidateStates, statesWithChoice);
278 if (newCandidates == candidateStates) {
279 assert(!candidateStates.
empty());
282 candidateStates = std::move(newCandidates);
289 boost::optional<storm::storage::BitVector>
const& subsystem) {
292 std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> stateQueue;
297 for (
auto initialState : initialStates) {
298 stateQueue.emplace_back(initialState, 0);
299 statesInQueue.
set(initialState);
303 while (currentPosition < stateQueue.size()) {
304 std::pair<storm::storage::sparse::state_type, std::size_t>
const& stateDistancePair = stateQueue[currentPosition];
305 distances[stateDistancePair.first] = stateDistancePair.second;
307 for (
auto const& successorEntry : transitionMatrix.
getRowGroup(stateDistancePair.first)) {
308 if (!statesInQueue.
get(successorEntry.getColumn())) {
309 if (!subsystem || subsystem.get()[successorEntry.getColumn()]) {
310 stateQueue.emplace_back(successorEntry.getColumn(), stateDistancePair.second + 1);
311 statesInQueue.
set(successorEntry.getColumn());
325 uint_fast64_t numberOfStates = phiStates.
size();
329 statesWithProbabilityGreater0 |= psiStates;
332 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
335 std::vector<uint_fast64_t> stepStack;
336 std::vector<uint_fast64_t> remainingSteps;
338 stepStack.reserve(numberOfStates);
340 remainingSteps.resize(numberOfStates);
341 for (
auto state : psiStates) {
342 remainingSteps[state] = maximalSteps;
347 uint_fast64_t currentState, currentStepBound;
348 while (!stack.empty()) {
349 currentState = stack.back();
353 currentStepBound = stepStack.back();
354 stepStack.pop_back();
355 if (currentStepBound == 0) {
361 entryIte = backwardTransitions.
end(currentState);
362 entryIt != entryIte; ++entryIt) {
363 if (phiStates[entryIt->getColumn()] &&
364 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
365 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
370 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
371 stepStack.push_back(currentStepBound - 1);
373 stack.push_back(entryIt->getColumn());
379 return statesWithProbabilityGreater0;
387 return statesWithProbability1;
396 return statesWithProbability1;
403 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
406 result.second =
performProb1(backwardTransitions, phiStates, psiStates, result.first);
407 result.first.complement();
415 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
417 result.second =
performProb1(backwardTransitions, phiStates, psiStates, result.first);
418 result.first.complement();
422template<storm::dd::DdType Type,
typename ValueType>
425 boost::optional<uint_fast64_t>
const& stepBound) {
431 uint_fast64_t iterations = 0;
432 while (lastIterationStates != statesWithProbabilityGreater0) {
433 if (stepBound && iterations >= stepBound.get()) {
437 lastIterationStates = statesWithProbabilityGreater0;
438 statesWithProbabilityGreater0 =
440 statesWithProbabilityGreater0 &= phiStates;
441 statesWithProbabilityGreater0 |= lastIterationStates;
445 return statesWithProbabilityGreater0;
448template<storm::dd::DdType Type,
typename ValueType>
455 return statesWithProbability1;
458template<storm::dd::DdType Type,
typename ValueType>
462 return performProb1(model, transitionMatrix, phiStates, psiStates, statesWithProbabilityGreater0);
465template<storm::dd::DdType Type,
typename ValueType>
477template<storm::dd::DdType Type,
typename ValueType>
489template<
typename T,
typename SchedulerValueType>
492 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
494 for (
auto state : states) {
495 [[maybe_unused]]
bool setValue{
false};
497 if (rowFilter && !rowFilter->get(choice)) {
500 auto const row = transitionMatrix.
getRow(choice);
501 bool const allSuccessorsInStates = std::all_of(row.begin(), row.end(), [&states](
auto const& entry) { return states.get(entry.getColumn()); });
502 if (allSuccessorsInStates) {
504 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
510 STORM_LOG_ASSERT(setValue,
"Expected that at least one action for state " << state <<
" stays within the selected state");
514template<
typename T,
typename SchedulerValueType>
517 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
519 for (
auto state : states) {
520 [[maybe_unused]]
bool setValue =
false;
521 for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) {
522 bool oneSuccessorInStates =
false;
523 for (
auto const& element : transitionMatrix.
getRow(choice)) {
524 if (states.
get(element.getColumn())) {
525 oneSuccessorInStates =
true;
529 if (oneSuccessorInStates) {
531 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
537 STORM_LOG_ASSERT(setValue,
"Expected that at least one action for state " << state <<
" leads with positive probability to the selected state");
541template<
typename T,
typename SchedulerValueType>
547 std::vector<uint_fast64_t> stack;
549 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
550 uint_fast64_t currentState = 0;
552 while (!stack.empty()) {
553 currentState = stack.back();
557 predecessorEntryIte = backwardTransitions.
end(currentState);
558 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
559 uint_fast64_t
const& predecessor = predecessorEntryIt->getColumn();
560 if (phiStates.
get(predecessor) && !currentStates.
get(predecessor)) {
563 bool foundValidChoice =
false;
566 if (rowFilter && !rowFilter->get(row)) {
570 successorEntryIte = transitionMatrix.
end(row);
571 successorEntryIt != successorEntryIte; ++successorEntryIt) {
572 if (currentStates.
get(successorEntryIt->getColumn())) {
573 foundValidChoice =
true;
577 if (foundValidChoice) {
581 currentStates.
set(predecessor,
true);
582 stack.push_back(predecessor);
586 STORM_LOG_INFO_COND(foundValidChoice,
"Could not find a valid choice for ProbGreater0E state " << predecessor <<
".");
592template<
typename T,
typename SchedulerValueType>
598template<
typename T,
typename SchedulerValueType>
608 auto remainingStates = rewInfStates & ~trapStates;
609 if (!remainingStates.empty()) {
614template<
typename T,
typename SchedulerValueType>
618 boost::optional<storm::storage::BitVector>
const& rowFilter) {
620 for (
auto psiState : psiStates) {
622 if (!scheduler.
getChoice(psiState, memState).isDefined()) {
623 scheduler.
setChoice(0, psiState, memState);
629 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
630 std::vector<uint_fast64_t> stack;
632 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
633 uint_fast64_t currentState = 0;
635 while (!stack.empty()) {
636 currentState = stack.back();
640 predecessorEntryIte = backwardTransitions.
end(currentState);
641 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
642 if (phiStates.
get(predecessorEntryIt->getColumn()) && !currentStates.
get(predecessorEntryIt->getColumn())) {
645 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
646 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
647 if (!rowFilter || rowFilter.get().get(row)) {
648 bool allSuccessorsInProb1EStates =
true;
649 bool hasSuccessorInCurrentStates =
false;
651 successorEntryIte = transitionMatrix.
end(row);
652 successorEntryIt != successorEntryIte; ++successorEntryIt) {
653 if (!prob1EStates.
get(successorEntryIt->getColumn())) {
654 allSuccessorsInProb1EStates =
false;
656 }
else if (currentStates.
get(successorEntryIt->getColumn())) {
657 hasSuccessorInCurrentStates =
true;
663 if (allSuccessorsInProb1EStates && hasSuccessorInCurrentStates) {
665 scheduler.
setChoice(row - nondeterministicChoiceIndices[predecessorEntryIt->getColumn()], predecessorEntryIt->getColumn(),
668 currentStates.
set(predecessorEntryIt->getColumn(),
true);
669 stack.push_back(predecessorEntryIt->getColumn());
682 size_t numberOfStates = phiStates.
size();
688 statesWithProbabilityGreater0 |= psiStates;
691 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
694 std::vector<uint_fast64_t> stepStack;
695 std::vector<uint_fast64_t> remainingSteps;
697 stepStack.reserve(numberOfStates);
699 remainingSteps.resize(numberOfStates);
700 for (
auto state : psiStates) {
701 remainingSteps[state] = maximalSteps;
706 uint_fast64_t currentState, currentStepBound;
707 while (!stack.empty()) {
708 currentState = stack.back();
712 currentStepBound = stepStack.back();
713 stepStack.pop_back();
714 if (currentStepBound == 0) {
720 entryIte = backwardTransitions.
end(currentState);
721 entryIt != entryIte; ++entryIt) {
722 if (phiStates.
get(entryIt->getColumn()) &&
723 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
727 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
728 stepStack.push_back(currentStepBound - 1);
730 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
731 stack.push_back(entryIt->getColumn());
736 return statesWithProbabilityGreater0;
744 return statesWithProbability0;
749 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
752 size_t numberOfStates = phiStates.
size();
756 std::vector<uint_fast64_t> stack;
757 stack.reserve(numberOfStates);
761 uint_fast64_t currentState;
765 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
767 while (!stack.empty()) {
768 currentState = stack.back();
772 predecessorEntryIte = backwardTransitions.
end(currentState);
773 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
774 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
777 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
778 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
779 if (!choiceConstraint || choiceConstraint.get().get(row)) {
780 bool allSuccessorsInCurrentStates =
true;
781 bool hasNextStateSuccessor =
false;
783 successorEntryIte = transitionMatrix.
end(row);
784 successorEntryIt != successorEntryIte; ++successorEntryIt) {
785 if (!currentStates.
get(successorEntryIt->getColumn())) {
786 allSuccessorsInCurrentStates =
false;
788 }
else if (nextStates.
get(successorEntryIt->getColumn())) {
789 hasNextStateSuccessor =
true;
796 if (allSuccessorsInCurrentStates && hasNextStateSuccessor) {
797 nextStates.
set(predecessorEntryIt->getColumn(),
true);
798 stack.push_back(predecessorEntryIt->getColumn());
808 if (currentStates == nextStates) {
811 currentStates = std::move(nextStates);
815 return currentStates;
818template<
typename T,
typename RM>
827 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
831 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
833 result.first =
performProb0A(backwardTransitions, phiStates, psiStates);
835 result.second =
performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
839template<
typename T,
typename RM>
849 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
852 boost::optional<storm::storage::BitVector>
const& choiceConstraint) {
853 size_t numberOfStates = phiStates.
size();
859 statesWithProbabilityGreater0 |= psiStates;
862 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
865 std::vector<uint_fast64_t> stepStack;
866 std::vector<uint_fast64_t> remainingSteps;
868 stepStack.reserve(numberOfStates);
870 remainingSteps.resize(numberOfStates);
871 for (
auto state : psiStates) {
872 remainingSteps[state] = maximalSteps;
877 uint_fast64_t currentState, currentStepBound;
878 while (!stack.empty()) {
879 currentState = stack.back();
883 currentStepBound = stepStack.back();
884 stepStack.pop_back();
885 if (currentStepBound == 0) {
891 predecessorEntryIte = backwardTransitions.
end(currentState);
892 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
893 if (phiStates.
get(predecessorEntryIt->getColumn())) {
894 if (!statesWithProbabilityGreater0.
get(predecessorEntryIt->getColumn())) {
900 uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
901 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
902 if (!choiceConstraint || choiceConstraint->getNextSetIndex(row) < endOfGroup) {
903 bool addToStatesWithProbabilityGreater0 =
true;
904 for (; row < endOfGroup; ++row) {
905 if (!choiceConstraint || choiceConstraint->get(row)) {
906 bool hasAtLeastOneSuccessorWithProbabilityGreater0 =
false;
908 successorEntryIte = transitionMatrix.
end(row);
909 successorEntryIt != successorEntryIte; ++successorEntryIt) {
910 if (statesWithProbabilityGreater0.
get(successorEntryIt->getColumn())) {
911 hasAtLeastOneSuccessorWithProbabilityGreater0 =
true;
916 if (!hasAtLeastOneSuccessorWithProbabilityGreater0) {
917 addToStatesWithProbabilityGreater0 =
false;
924 if (addToStatesWithProbabilityGreater0) {
928 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
929 stepStack.push_back(currentStepBound - 1);
931 statesWithProbabilityGreater0.
set(predecessorEntryIt->getColumn(),
true);
932 stack.push_back(predecessorEntryIt->getColumn());
936 }
else if (useStepBound && remainingSteps[predecessorEntryIt->getColumn()] < currentStepBound - 1) {
939 bool predecessorIsValid =
true;
940 if (choiceConstraint) {
941 predecessorIsValid =
false;
942 uint_fast64_t row = choiceConstraint->getNextSetIndex(nondeterministicChoiceIndices[predecessorEntryIt->getColumn()]);
943 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
944 for (; row < endOfGroup && !predecessorIsValid; row = choiceConstraint->getNextSetIndex(row + 1)) {
945 for (
auto const& entry : transitionMatrix.
getRow(row)) {
946 if (entry.getColumn() == currentState) {
947 predecessorIsValid =
true;
953 if (predecessorIsValid) {
954 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
955 stepStack.push_back(currentStepBound - 1);
956 stack.push_back(predecessorEntryIt->getColumn());
963 return statesWithProbabilityGreater0;
966template<
typename T,
typename RM>
973 return statesWithProbability0;
978 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
982 performProbGreater0A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
984 return statesWithProbability0;
987template<
typename T,
typename RM>
996 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
999 size_t numberOfStates = phiStates.
size();
1003 std::vector<uint_fast64_t> stack;
1004 stack.reserve(numberOfStates);
1008 uint_fast64_t currentState;
1012 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1014 while (!stack.empty()) {
1015 currentState = stack.back();
1019 predecessorEntryIte = backwardTransitions.
end(currentState);
1020 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
1021 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
1025 bool addToStatesWithProbability1 =
true;
1026 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
1027 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
1028 bool hasAtLeastOneSuccessorWithProbability1 =
false;
1030 successorEntryIte = transitionMatrix.
end(row);
1031 successorEntryIt != successorEntryIte; ++successorEntryIt) {
1032 if (!currentStates.
get(successorEntryIt->getColumn())) {
1033 addToStatesWithProbability1 =
false;
1034 goto afterCheckLoop;
1036 if (nextStates.
get(successorEntryIt->getColumn())) {
1037 hasAtLeastOneSuccessorWithProbability1 =
true;
1041 if (!hasAtLeastOneSuccessorWithProbability1) {
1042 addToStatesWithProbability1 =
false;
1051 if (addToStatesWithProbability1) {
1052 nextStates.
set(predecessorEntryIt->getColumn(),
true);
1053 stack.push_back(predecessorEntryIt->getColumn());
1060 if (currentStates == nextStates) {
1063 currentStates = std::move(nextStates);
1066 return currentStates;
1071 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1075 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
1076 result.first =
performProb0E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
1080 result.second =
performProb0A(backwardTransitions, ~psiStates, result.first);
1084template<
typename T,
typename RM>
1092template<storm::dd::DdType Type,
typename ValueType>
1102 while (!frontier.
isZero()) {
1106 scheduler = scheduler || (frontier && statesAndChoicesWithProbabilityGreater0E).existsAbstractRepresentative(model.
getNondeterminismVariables());
1107 statesWithProbabilityGreater0E |= frontier;
1113template<storm::dd::DdType Type,
typename ValueType>
1123 while (lastIterationStates != statesWithProbabilityGreater0E) {
1124 lastIterationStates = statesWithProbabilityGreater0E;
1125 statesWithProbabilityGreater0E =
1127 statesWithProbabilityGreater0E &= phiStates;
1128 statesWithProbabilityGreater0E |= lastIterationStates;
1131 return statesWithProbabilityGreater0E;
1134template<storm::dd::DdType Type,
typename ValueType>
1140template<storm::dd::DdType Type,
typename ValueType>
1149 while (lastIterationStates != statesWithProbabilityGreater0A) {
1150 lastIterationStates = statesWithProbabilityGreater0A;
1151 statesWithProbabilityGreater0A =
1155 statesWithProbabilityGreater0A &= phiStates;
1156 statesWithProbabilityGreater0A |= psiStates;
1159 return statesWithProbabilityGreater0A;
1162template<storm::dd::DdType Type,
typename ValueType>
1168template<storm::dd::DdType Type,
typename ValueType>
1176 while (lastIterationStates != statesWithProbability1A) {
1177 lastIterationStates = statesWithProbability1A;
1179 statesWithProbability1A = transitionMatrix.
implies(statesWithProbability1A).universalAbstract(model.
getColumnVariables());
1182 statesWithProbability1A &= statesWithProbabilityGreater0A;
1183 statesWithProbability1A |= psiStates;
1186 return statesWithProbability1A;
1189template<storm::dd::DdType Type,
typename ValueType>
1197 bool outerLoopDone =
false;
1198 while (!outerLoopDone) {
1201 bool innerLoopDone =
false;
1202 while (!innerLoopDone) {
1210 temporary &= phiStates;
1211 temporary |= psiStates;
1213 if (innerStates == temporary) {
1214 innerLoopDone =
true;
1216 innerStates = temporary;
1220 if (statesWithProbability1E == innerStates) {
1221 outerLoopDone =
true;
1223 statesWithProbability1E = innerStates;
1227 return statesWithProbability1E;
1230template<storm::dd::DdType Type,
typename ValueType>
1240 bool innerLoopDone =
false;
1241 while (!innerLoopDone) {
1247 temporary &= temporary2;
1248 temporary &= phiStates;
1254 temporary |= psiStates;
1256 if (innerStates == temporary) {
1257 innerLoopDone =
true;
1259 innerStates = temporary;
1266template<storm::dd::DdType Type,
typename ValueType>
1272template<storm::dd::DdType Type,
typename ValueType>
1277 result.first =
performProb0A(model, transitionMatrix, phiStates, psiStates);
1282template<storm::dd::DdType Type,
typename ValueType>
1288template<storm::dd::DdType Type,
typename ValueType>
1293 result.first =
performProb0E(model, transitionMatrix, phiStates, psiStates);
1298template<
typename ValueType>
1307 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
1310 uint_fast64_t currentState;
1311 while (!stack.empty()) {
1312 currentState = stack.back();
1316 for (
auto const& player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1317 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1319 bool addPlayer2State =
false;
1320 if (player2Direction == OptimizationDirection::Minimize) {
1321 bool allChoicesHavePlayer1State =
true;
1324 bool choiceHasPlayer1State =
false;
1325 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1327 choiceHasPlayer1State =
true;
1331 if (!choiceHasPlayer1State) {
1332 allChoicesHavePlayer1State =
false;
1335 if (allChoicesHavePlayer1State) {
1336 addPlayer2State =
true;
1339 addPlayer2State =
true;
1342 if (addPlayer2State) {
1347 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1350 bool addPlayer1State =
false;
1351 if (player1Direction == OptimizationDirection::Minimize) {
1352 bool allPlayer2Successors =
true;
1353 for (uint64_t player2State = player1Groups[player1Predecessor]; player2State < player1Groups[player1Predecessor + 1];
1356 allPlayer2Successors =
false;
1360 if (allPlayer2Successors) {
1361 addPlayer1State =
true;
1364 addPlayer1State =
true;
1367 if (addPlayer1State) {
1369 stack.emplace_back(player1Predecessor);
1384 if (player1Direction == storm::OptimizationDirection::Minimize) {
1386 [[maybe_unused]]
bool foundProb0Successor =
false;
1387 uint64_t player2State;
1388 for (player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1390 foundProb0Successor =
true;
1394 STORM_LOG_ASSERT(foundProb0Successor,
"Expected at least one state 2 successor with probability 0.");
1406 if (player2Direction == storm::OptimizationDirection::Minimize) {
1408 [[maybe_unused]]
bool foundProb0SuccessorDistribution =
false;
1412 bool distributionHasOnlyProb0Successors =
true;
1413 for (
auto const& player1SuccessorEntry : transitionMatrix.
getRow(row)) {
1415 distributionHasOnlyProb0Successors =
false;
1419 if (distributionHasOnlyProb0Successors) {
1420 foundProb0SuccessorDistribution =
true;
1425 STORM_LOG_ASSERT(foundProb0SuccessorDistribution,
"Expected at least one distribution with only successors with probability 0.");
1437template<storm::dd::DdType Type,
typename ValueType>
1451 if (player2Strategy == OptimizationDirection::Minimize) {
1456 player2States |= tmp;
1458 if (player1Strategy == OptimizationDirection::Minimize) {
1465 tmp |= player1States;
1467 if (tmp == player1States) {
1471 player1States = tmp;
1477 std::set<storm::expressions::Variable> variablesToAbstract(model.
getColumnVariables());
1479 player2States = !player2States && transitionMatrix.
existsAbstract(variablesToAbstract);
1488 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1489 if (producePlayer2Strategy) {
1494 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1495 if (producePlayer1Strategy) {
1497 onlyProb0Successors = (player1States && onlyProb0Successors).existsAbstract(model.
getPlayer2Variables());
1500 player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.
getPlayer1Variables());
1506template<
typename ValueType>
1512 boost::optional<storm::storage::BitVector>
const& player1Candidates) {
1515 if (player1Candidates) {
1522 bool produceStrategiesInIteration =
false;
1525 std::vector<uint_fast64_t> stack;
1526 bool maybeStatesDone =
false;
1527 while (!maybeStatesDone || produceStrategiesInIteration) {
1532 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1535 uint_fast64_t currentState;
1536 while (!stack.empty()) {
1537 currentState = stack.back();
1540 for (
auto player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1541 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1542 if (!player2Solution.
get(player2PredecessorEntry.getColumn())) {
1543 bool addPlayer2State = player2Direction == storm::OptimizationDirection::Minimize ? true :
false;
1546 for (uint64_t row = validChoice; row < transitionMatrix.
getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1547 bool choiceHasSolutionSuccessor =
false;
1548 bool choiceStaysInMaybeStates =
true;
1549 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1550 if (player1Solution.
get(entry.getColumn())) {
1551 choiceHasSolutionSuccessor =
true;
1554 choiceStaysInMaybeStates =
false;
1559 if (choiceHasSolutionSuccessor && choiceStaysInMaybeStates) {
1560 if (player2Direction == storm::OptimizationDirection::Maximize) {
1562 addPlayer2State =
true;
1565 }
else if (player2Direction == storm::OptimizationDirection::Minimize) {
1566 addPlayer2State =
false;
1571 if (addPlayer2State) {
1572 player2Solution.
set(player2Predecessor);
1573 if (produceStrategiesInIteration) {
1579 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1581 if (!player1Solution.
get(player1Predecessor)) {
1582 bool addPlayer1State = player1Direction == storm::OptimizationDirection::Minimize ? true :
false;
1584 validChoice = player1Groups[player1Predecessor];
1585 for (uint64_t player2Successor = validChoice; player2Successor < player1Groups[player1Predecessor + 1]; ++player2Successor) {
1586 if (player2Solution.
get(player2Successor)) {
1587 if (player1Direction == storm::OptimizationDirection::Maximize) {
1588 validChoice = player2Successor;
1589 addPlayer1State =
true;
1592 }
else if (player1Direction == storm::OptimizationDirection::Minimize) {
1593 addPlayer1State =
false;
1598 if (addPlayer1State) {
1599 player1Solution.
set(player1Predecessor);
1601 if (produceStrategiesInIteration) {
1605 stack.emplace_back(player1Predecessor);
1614 maybeStatesDone =
true;
1619 produceStrategiesInIteration = !produceStrategiesInIteration && strategyPair;
1629template<storm::dd::DdType Type,
typename ValueType>
1637 if (player1Candidates) {
1638 maybePlayer1States &= player1Candidates.get();
1645 bool produceStrategiesInIteration =
false;
1646 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1647 boost::optional<storm::dd::Bdd<Type>> consideredPlayer1States;
1648 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1649 boost::optional<storm::dd::Bdd<Type>> consideredPlayer2States;
1651 bool maybeStatesDone =
false;
1652 while (!maybeStatesDone || produceStrategiesInIteration) {
1653 bool solutionStatesDone =
false;
1656 if (produceStrategiesInIteration) {
1657 if (player1Strategy == storm::OptimizationDirection::Maximize) {
1658 player1StrategyBdd = model.
getManager().getBddZero();
1659 consideredPlayer1States = model.
getManager().getBddZero();
1661 if (player2Strategy == storm::OptimizationDirection::Maximize) {
1662 player2StrategyBdd = model.
getManager().getBddZero();
1663 consideredPlayer2States = model.
getManager().getBddZero();
1669 while (!solutionStatesDone) {
1682 storm::dd::Bdd<Type> valid = phiStates && distributionsStayingInMaybe && distributionsWithProb1Successor;
1686 if (player2Strategy == OptimizationDirection::Minimize) {
1689 if (produceStrategiesInIteration) {
1696 if (produceStrategiesInIteration) {
1697 consideredPlayer2States.get() |= valid;
1701 player2Solution |= valid;
1704 if (player1Strategy == OptimizationDirection::Minimize) {
1707 if (produceStrategiesInIteration) {
1714 if (produceStrategiesInIteration) {
1715 consideredPlayer1States.get() |= valid;
1725 if (valid == player1Solution) {
1726 solutionStatesDone =
true;
1728 player1Solution = valid;
1734 if (player1Solution == maybePlayer1States) {
1735 maybePlayer2States = player2Solution;
1736 maybeStatesDone =
true;
1740 produceStrategiesInIteration = !produceStrategiesInIteration && ((producePlayer1Strategy && player1Strategy == OptimizationDirection::Maximize) ||
1741 (producePlayer2Strategy && player2Strategy == OptimizationDirection::Maximize));
1745 maybePlayer1States = player1Solution;
1753 bool strategiesToCompute = (producePlayer1Strategy && !player1StrategyBdd) || (producePlayer2Strategy && !player2StrategyBdd);
1754 if (strategiesToCompute) {
1756 if (producePlayer2Strategy && !player2StrategyBdd) {
1759 if (producePlayer1Strategy && !player1StrategyBdd) {
1760 relevantStates = (maybePlayer1States && relevantStates).existsAbstract(model.
getPlayer2Variables());
1770 std::vector<uint_fast64_t>& recursionStack,
1773 if (!visitedStates.
get(state)) {
1774 recursionStack.push_back(state);
1775 iteratorRecursionStack.push_back(matrix.
begin(state));
1777 recursionStepForward:
1778 while (!recursionStack.empty()) {
1779 uint_fast64_t currentState = recursionStack.back();
1782 visitedStates.
set(currentState,
true);
1784 recursionStepBackward:
1785 for (; successorIterator != matrix.
end(currentState); ++successorIterator) {
1786 if (!visitedStates.
get(successorIterator->getColumn())) {
1788 recursionStack.push_back(successorIterator->getColumn());
1791 iteratorRecursionStack.push_back(matrix.
begin(successorIterator->getColumn()));
1793 goto recursionStepForward;
1797 topologicalSort.push_back(currentState);
1801 recursionStack.pop_back();
1802 iteratorRecursionStack.pop_back();
1807 if (recursionStack.size() > 0) {
1808 currentState = recursionStack.back();
1809 successorIterator = iteratorRecursionStack.back();
1811 goto recursionStepBackward;
1821 std::vector<uint_fast64_t> stateQueue;
1823 std::vector<uint_fast64_t> result;
1828 for (
auto const& state : firstStates) {
1829 stateQueue.push_back(state);
1830 result[count] = state;
1835 while (!stateQueue.empty()) {
1836 auto state = stateQueue.back();
1837 stateQueue.pop_back();
1838 seenStates.
set(state);
1839 for (
auto const& successorEntry : matrix.
getRowGroup(state)) {
1840 auto succ = successorEntry.geColumn();
1841 if (!seenStates[succ]) {
1842 result[count] = succ;
1844 stateQueue.insert(stateQueue.begin(), succ);
1855 throw storm::exceptions::InvalidArgumentException() <<
"Provided matrix is required to be square.";
1858 uint_fast64_t numberOfStates = matrix.
getRowCount();
1861 std::vector<uint_fast64_t> topologicalSort;
1862 topologicalSort.reserve(numberOfStates);
1865 std::vector<uint_fast64_t> recursionStack;
1867 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator> iteratorRecursionStack;
1868 iteratorRecursionStack.reserve(numberOfStates);
1872 for (
auto const state : firstStates) {
1873 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1875 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
1876 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1879 return topologicalSort;
1885 boost::optional<storm::storage::BitVector>
const& choiceFilter);
1896 boost::optional<storm::storage::BitVector>
const& subsystem);
1900 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1919 boost::optional<storm::storage::BitVector>
const& rowFilter);
1930 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
1934 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1940 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1943 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1950 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1960 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1963 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
1964 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1969#ifdef STORM_HAVE_CARL
1975 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1982#ifdef STORM_HAVE_CARL
1988 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1993 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2001#ifdef STORM_HAVE_CARL
2002template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2018 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2023#ifdef STORM_HAVE_CARL
2027 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2032 boost::optional<storm::storage::BitVector>
const& subsystem);
2043 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2052template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2056template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2064 boost::optional<storm::storage::BitVector>
const& rowFilter);
2076 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2080 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2086 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2089 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2095template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2100template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2105 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2108 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2109 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2116 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2121 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2125template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2130template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2135 std::vector<uint64_t>
const& player1RowGrouping,
2142 std::vector<uint64_t>
const& player1RowGrouping,
2147 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2150 std::vector<uint64_t>
const& firstStates);
2160 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2175 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2206 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2210 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2216 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2219 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2225template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2230template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2235 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2238 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2239 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2246 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2251 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2255template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2260template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2265 std::vector<uint64_t>
const& player1RowGrouping,
2272 std::vector<uint64_t>
const& player1RowGrouping,
2277 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2285 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2290 boost::optional<storm::storage::BitVector>
const& subsystem);
2301 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2310template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2314template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2323 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2327 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2333 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2336 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2342template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2347template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2352 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2355 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2356 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2362 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2370 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2374template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2379template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2384 std::vector<uint64_t>
const& firstStates);
2393 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2492 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2576 bool producePlayer2Strategy);