37 for (uint64_t currentState : initialStates) {
38 for (
auto const& successor : transitionMatrix.
getRowGroup(currentState)) {
40 result.set(successor.getColumn());
49 bool useStepBound, uint_fast64_t maximalSteps, boost::optional<storm::storage::BitVector>
const& choiceFilter) {
55 std::vector<uint_fast64_t> stack;
56 stack.reserve(initialStates.
size());
57 for (
auto state : initialStates) {
58 if (constraintStates.
get(state)) {
59 stack.push_back(state);
64 std::vector<uint_fast64_t> stepStack;
65 std::vector<uint_fast64_t> remainingSteps;
67 stepStack.reserve(numberOfStates);
68 stepStack.insert(stepStack.begin(), stack.size(), maximalSteps);
69 remainingSteps.resize(numberOfStates);
70 for (
auto state : stack) {
71 remainingSteps[state] = maximalSteps;
76 uint_fast64_t currentState = 0, currentStepBound = 0;
77 while (!stack.empty()) {
78 currentState = stack.back();
82 currentStepBound = stepStack.back();
85 if (currentStepBound == 0) {
92 row = choiceFilter->getNextSetIndex(row);
95 while (row < rowGroupEnd) {
96 for (
auto const& successor : transitionMatrix.
getRow(row)) {
100 (!reachableStates.
get(successor.getColumn()) || (useStepBound && remainingSteps[successor.getColumn()] < currentStepBound - 1))) {
103 if (targetStates.
get(successor.getColumn())) {
104 reachableStates.
set(successor.getColumn());
105 }
else if (constraintStates.
get(successor.getColumn())) {
109 remainingSteps[successor.getColumn()] = currentStepBound - 1;
110 stepStack.push_back(currentStepBound - 1);
112 reachableStates.
set(successor.getColumn());
113 stack.push_back(successor.getColumn());
119 row = choiceFilter->getNextSetIndex(row);
124 return reachableStates;
134 for (
auto const& scc : decomposition) {
135 result.
set(*scc.begin());
146 unexploredStates = subsystem.
get();
147 acyclicStates = ~subsystem.
get();
152 std::vector<uint64_t> dfsStack;
154 dfsStack.push_back(start);
155 while (!dfsStack.empty()) {
156 uint64_t state = dfsStack.back();
157 if (unexploredStates.
get(state)) {
158 unexploredStates.
set(state,
false);
159 for (
auto const& entry : transitionMatrix.
getRowGroup(state)) {
161 if (unexploredStates.
get(entry.getColumn())) {
162 dfsStack.push_back(entry.getColumn());
164 if (!acyclicStates.
get(entry.getColumn())) {
172 acyclicStates.
set(state,
true);
191 uint_fast64_t state = 0;
192 for (
auto choice : choices) {
199 if (subsystem.
get(state)) {
200 bool choiceStaysInSubsys =
true;
201 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
202 if (!subsystem.
get(entry.getColumn())) {
203 choiceStaysInSubsys =
false;
207 if (choiceStaysInSubsys) {
208 statesWithChoice.
set(state,
true);
224 statesWithChoice &= candidateStates;
226 for (
auto state : statesWithChoice) {
229 bool choiceStaysInCandidateSet =
true;
230 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
231 if (!candidateStates.
get(entry.getColumn())) {
232 choiceStaysInCandidateSet =
false;
236 if (choiceStaysInCandidateSet) {
237 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
238 choiceTargets.
set(entry.getColumn(),
true);
248 while (!candidateStates.
empty()) {
250 statesWithChoice &= candidateStates;
251 for (
auto state : statesWithChoice) {
252 bool stateHasChoice =
false;
255 bool choiceStaysInCandidateSet =
true;
256 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
257 if (!candidateStates.
get(entry.getColumn())) {
258 choiceStaysInCandidateSet =
false;
262 if (choiceStaysInCandidateSet) {
263 stateHasChoice =
true;
267 if (!stateHasChoice) {
268 statesWithChoice.
set(state,
false);
274 backwardTransitions, candidateStates, statesWithChoice);
277 if (newCandidates == candidateStates) {
278 assert(!candidateStates.
empty());
281 candidateStates = std::move(newCandidates);
288 boost::optional<storm::storage::BitVector>
const& subsystem) {
291 std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> stateQueue;
296 for (
auto initialState : initialStates) {
297 stateQueue.emplace_back(initialState, 0);
298 statesInQueue.
set(initialState);
302 while (currentPosition < stateQueue.size()) {
303 std::pair<storm::storage::sparse::state_type, std::size_t>
const& stateDistancePair = stateQueue[currentPosition];
304 distances[stateDistancePair.first] = stateDistancePair.second;
306 for (
auto const& successorEntry : transitionMatrix.
getRowGroup(stateDistancePair.first)) {
307 if (!statesInQueue.
get(successorEntry.getColumn())) {
308 if (!subsystem || subsystem.get()[successorEntry.getColumn()]) {
309 stateQueue.emplace_back(successorEntry.getColumn(), stateDistancePair.second + 1);
310 statesInQueue.
set(successorEntry.getColumn());
324 uint_fast64_t numberOfStates = phiStates.
size();
328 statesWithProbabilityGreater0 |= psiStates;
331 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
334 std::vector<uint_fast64_t> stepStack;
335 std::vector<uint_fast64_t> remainingSteps;
337 stepStack.reserve(numberOfStates);
339 remainingSteps.resize(numberOfStates);
340 for (
auto state : psiStates) {
341 remainingSteps[state] = maximalSteps;
346 uint_fast64_t currentState, currentStepBound;
347 while (!stack.empty()) {
348 currentState = stack.back();
352 currentStepBound = stepStack.back();
353 stepStack.pop_back();
354 if (currentStepBound == 0) {
360 entryIte = backwardTransitions.
end(currentState);
361 entryIt != entryIte; ++entryIt) {
362 if (phiStates[entryIt->getColumn()] &&
363 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
364 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
369 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
370 stepStack.push_back(currentStepBound - 1);
372 stack.push_back(entryIt->getColumn());
378 return statesWithProbabilityGreater0;
386 return statesWithProbability1;
395 return statesWithProbability1;
402 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
405 result.second =
performProb1(backwardTransitions, phiStates, psiStates, result.first);
406 result.first.complement();
414 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
416 result.second =
performProb1(backwardTransitions, phiStates, psiStates, result.first);
417 result.first.complement();
421template<storm::dd::DdType Type,
typename ValueType>
424 boost::optional<uint_fast64_t>
const& stepBound) {
430 uint_fast64_t iterations = 0;
431 while (lastIterationStates != statesWithProbabilityGreater0) {
432 if (stepBound && iterations >= stepBound.get()) {
436 lastIterationStates = statesWithProbabilityGreater0;
437 statesWithProbabilityGreater0 =
439 statesWithProbabilityGreater0 &= phiStates;
440 statesWithProbabilityGreater0 |= lastIterationStates;
444 return statesWithProbabilityGreater0;
447template<storm::dd::DdType Type,
typename ValueType>
454 return statesWithProbability1;
457template<storm::dd::DdType Type,
typename ValueType>
461 return performProb1(model, transitionMatrix, phiStates, psiStates, statesWithProbabilityGreater0);
464template<storm::dd::DdType Type,
typename ValueType>
476template<storm::dd::DdType Type,
typename ValueType>
488template<
typename T,
typename SchedulerValueType>
491 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
493 for (
auto state : states) {
494 [[maybe_unused]]
bool setValue{
false};
496 if (rowFilter && !rowFilter->get(choice)) {
499 auto const row = transitionMatrix.
getRow(choice);
500 bool const allSuccessorsInStates = std::all_of(row.begin(), row.end(), [&states](
auto const& entry) { return states.get(entry.getColumn()); });
501 if (allSuccessorsInStates) {
503 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
509 STORM_LOG_ASSERT(setValue,
"Expected that at least one action for state " << state <<
" stays within the selected state");
513template<
typename T,
typename SchedulerValueType>
516 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
518 for (
auto state : states) {
519 [[maybe_unused]]
bool setValue =
false;
520 for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) {
521 bool oneSuccessorInStates =
false;
522 for (
auto const& element : transitionMatrix.
getRow(choice)) {
523 if (states.
get(element.getColumn())) {
524 oneSuccessorInStates =
true;
528 if (oneSuccessorInStates) {
530 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
536 STORM_LOG_ASSERT(setValue,
"Expected that at least one action for state " << state <<
" leads with positive probability to the selected state");
540template<
typename T,
typename SchedulerValueType>
546 std::vector<uint_fast64_t> stack;
548 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
549 uint_fast64_t currentState = 0;
551 while (!stack.empty()) {
552 currentState = stack.back();
556 predecessorEntryIte = backwardTransitions.
end(currentState);
557 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
558 uint_fast64_t
const& predecessor = predecessorEntryIt->getColumn();
559 if (phiStates.
get(predecessor) && !currentStates.
get(predecessor)) {
562 bool foundValidChoice =
false;
565 if (rowFilter && !rowFilter->get(row)) {
569 successorEntryIte = transitionMatrix.
end(row);
570 successorEntryIt != successorEntryIte; ++successorEntryIt) {
571 if (currentStates.
get(successorEntryIt->getColumn())) {
572 foundValidChoice =
true;
576 if (foundValidChoice) {
580 currentStates.
set(predecessor,
true);
581 stack.push_back(predecessor);
585 STORM_LOG_INFO_COND(foundValidChoice,
"Could not find a valid choice for ProbGreater0E state " << predecessor <<
".");
591template<
typename T,
typename SchedulerValueType>
597template<
typename T,
typename SchedulerValueType>
607 auto remainingStates = rewInfStates & ~trapStates;
608 if (!remainingStates.empty()) {
613template<
typename T,
typename SchedulerValueType>
617 boost::optional<storm::storage::BitVector>
const& rowFilter) {
619 for (
auto psiState : psiStates) {
621 if (!scheduler.
getChoice(psiState, memState).isDefined()) {
622 scheduler.
setChoice(0, psiState, memState);
628 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
629 std::vector<uint_fast64_t> stack;
631 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
632 uint_fast64_t currentState = 0;
634 while (!stack.empty()) {
635 currentState = stack.back();
639 predecessorEntryIte = backwardTransitions.
end(currentState);
640 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
641 if (phiStates.
get(predecessorEntryIt->getColumn()) && !currentStates.
get(predecessorEntryIt->getColumn())) {
644 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
645 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
646 if (!rowFilter || rowFilter.get().get(row)) {
647 bool allSuccessorsInProb1EStates =
true;
648 bool hasSuccessorInCurrentStates =
false;
650 successorEntryIte = transitionMatrix.
end(row);
651 successorEntryIt != successorEntryIte; ++successorEntryIt) {
652 if (!prob1EStates.
get(successorEntryIt->getColumn())) {
653 allSuccessorsInProb1EStates =
false;
655 }
else if (currentStates.
get(successorEntryIt->getColumn())) {
656 hasSuccessorInCurrentStates =
true;
662 if (allSuccessorsInProb1EStates && hasSuccessorInCurrentStates) {
664 scheduler.
setChoice(row - nondeterministicChoiceIndices[predecessorEntryIt->getColumn()], predecessorEntryIt->getColumn(),
667 currentStates.
set(predecessorEntryIt->getColumn(),
true);
668 stack.push_back(predecessorEntryIt->getColumn());
681 size_t numberOfStates = phiStates.
size();
687 statesWithProbabilityGreater0 |= psiStates;
690 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
693 std::vector<uint_fast64_t> stepStack;
694 std::vector<uint_fast64_t> remainingSteps;
696 stepStack.reserve(numberOfStates);
698 remainingSteps.resize(numberOfStates);
699 for (
auto state : psiStates) {
700 remainingSteps[state] = maximalSteps;
705 uint_fast64_t currentState, currentStepBound;
706 while (!stack.empty()) {
707 currentState = stack.back();
711 currentStepBound = stepStack.back();
712 stepStack.pop_back();
713 if (currentStepBound == 0) {
719 entryIte = backwardTransitions.
end(currentState);
720 entryIt != entryIte; ++entryIt) {
721 if (phiStates.
get(entryIt->getColumn()) &&
722 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
726 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
727 stepStack.push_back(currentStepBound - 1);
729 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
730 stack.push_back(entryIt->getColumn());
735 return statesWithProbabilityGreater0;
743 return statesWithProbability0;
748 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
751 size_t numberOfStates = phiStates.
size();
755 std::vector<uint_fast64_t> stack;
756 stack.reserve(numberOfStates);
760 uint_fast64_t currentState;
764 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
766 while (!stack.empty()) {
767 currentState = stack.back();
771 predecessorEntryIte = backwardTransitions.
end(currentState);
772 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
773 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
776 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
777 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
778 if (!choiceConstraint || choiceConstraint.get().get(row)) {
779 bool allSuccessorsInCurrentStates =
true;
780 bool hasNextStateSuccessor =
false;
782 successorEntryIte = transitionMatrix.
end(row);
783 successorEntryIt != successorEntryIte; ++successorEntryIt) {
784 if (!currentStates.
get(successorEntryIt->getColumn())) {
785 allSuccessorsInCurrentStates =
false;
787 }
else if (nextStates.
get(successorEntryIt->getColumn())) {
788 hasNextStateSuccessor =
true;
795 if (allSuccessorsInCurrentStates && hasNextStateSuccessor) {
796 nextStates.
set(predecessorEntryIt->getColumn(),
true);
797 stack.push_back(predecessorEntryIt->getColumn());
807 if (currentStates == nextStates) {
810 currentStates = std::move(nextStates);
814 return currentStates;
817template<
typename T,
typename RM>
826 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
830 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
832 result.first =
performProb0A(backwardTransitions, phiStates, psiStates);
834 result.second =
performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
838template<
typename T,
typename RM>
848 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
851 boost::optional<storm::storage::BitVector>
const& choiceConstraint) {
852 size_t numberOfStates = phiStates.
size();
858 statesWithProbabilityGreater0 |= psiStates;
861 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
864 std::vector<uint_fast64_t> stepStack;
865 std::vector<uint_fast64_t> remainingSteps;
867 stepStack.reserve(numberOfStates);
869 remainingSteps.resize(numberOfStates);
870 for (
auto state : psiStates) {
871 remainingSteps[state] = maximalSteps;
876 uint_fast64_t currentState, currentStepBound;
877 while (!stack.empty()) {
878 currentState = stack.back();
882 currentStepBound = stepStack.back();
883 stepStack.pop_back();
884 if (currentStepBound == 0) {
890 predecessorEntryIte = backwardTransitions.
end(currentState);
891 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
892 if (phiStates.
get(predecessorEntryIt->getColumn())) {
893 if (!statesWithProbabilityGreater0.
get(predecessorEntryIt->getColumn())) {
899 uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
900 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
901 if (!choiceConstraint || choiceConstraint->getNextSetIndex(row) < endOfGroup) {
902 bool addToStatesWithProbabilityGreater0 =
true;
903 for (; row < endOfGroup; ++row) {
904 if (!choiceConstraint || choiceConstraint->get(row)) {
905 bool hasAtLeastOneSuccessorWithProbabilityGreater0 =
false;
907 successorEntryIte = transitionMatrix.
end(row);
908 successorEntryIt != successorEntryIte; ++successorEntryIt) {
909 if (statesWithProbabilityGreater0.
get(successorEntryIt->getColumn())) {
910 hasAtLeastOneSuccessorWithProbabilityGreater0 =
true;
915 if (!hasAtLeastOneSuccessorWithProbabilityGreater0) {
916 addToStatesWithProbabilityGreater0 =
false;
923 if (addToStatesWithProbabilityGreater0) {
927 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
928 stepStack.push_back(currentStepBound - 1);
930 statesWithProbabilityGreater0.
set(predecessorEntryIt->getColumn(),
true);
931 stack.push_back(predecessorEntryIt->getColumn());
935 }
else if (useStepBound && remainingSteps[predecessorEntryIt->getColumn()] < currentStepBound - 1) {
938 bool predecessorIsValid =
true;
939 if (choiceConstraint) {
940 predecessorIsValid =
false;
941 uint_fast64_t row = choiceConstraint->getNextSetIndex(nondeterministicChoiceIndices[predecessorEntryIt->getColumn()]);
942 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
943 for (; row < endOfGroup && !predecessorIsValid; row = choiceConstraint->getNextSetIndex(row + 1)) {
944 for (
auto const& entry : transitionMatrix.
getRow(row)) {
945 if (entry.getColumn() == currentState) {
946 predecessorIsValid =
true;
952 if (predecessorIsValid) {
953 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
954 stepStack.push_back(currentStepBound - 1);
955 stack.push_back(predecessorEntryIt->getColumn());
962 return statesWithProbabilityGreater0;
965template<
typename T,
typename RM>
972 return statesWithProbability0;
977 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
981 performProbGreater0A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
983 return statesWithProbability0;
986template<
typename T,
typename RM>
995 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
998 size_t numberOfStates = phiStates.
size();
1002 std::vector<uint_fast64_t> stack;
1003 stack.reserve(numberOfStates);
1007 uint_fast64_t currentState;
1011 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1013 while (!stack.empty()) {
1014 currentState = stack.back();
1018 predecessorEntryIte = backwardTransitions.
end(currentState);
1019 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
1020 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
1024 bool addToStatesWithProbability1 =
true;
1025 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
1026 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
1027 bool hasAtLeastOneSuccessorWithProbability1 =
false;
1029 successorEntryIte = transitionMatrix.
end(row);
1030 successorEntryIt != successorEntryIte; ++successorEntryIt) {
1031 if (!currentStates.
get(successorEntryIt->getColumn())) {
1032 addToStatesWithProbability1 =
false;
1033 goto afterCheckLoop;
1035 if (nextStates.
get(successorEntryIt->getColumn())) {
1036 hasAtLeastOneSuccessorWithProbability1 =
true;
1040 if (!hasAtLeastOneSuccessorWithProbability1) {
1041 addToStatesWithProbability1 =
false;
1050 if (addToStatesWithProbability1) {
1051 nextStates.
set(predecessorEntryIt->getColumn(),
true);
1052 stack.push_back(predecessorEntryIt->getColumn());
1059 if (currentStates == nextStates) {
1062 currentStates = std::move(nextStates);
1065 return currentStates;
1070 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1074 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
1075 result.first =
performProb0E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
1079 result.second =
performProb0A(backwardTransitions, ~psiStates, result.first);
1083template<
typename T,
typename RM>
1091template<storm::dd::DdType Type,
typename ValueType>
1101 while (!frontier.
isZero()) {
1105 scheduler = scheduler || (frontier && statesAndChoicesWithProbabilityGreater0E).existsAbstractRepresentative(model.
getNondeterminismVariables());
1106 statesWithProbabilityGreater0E |= frontier;
1112template<storm::dd::DdType Type,
typename ValueType>
1122 while (lastIterationStates != statesWithProbabilityGreater0E) {
1123 lastIterationStates = statesWithProbabilityGreater0E;
1124 statesWithProbabilityGreater0E =
1126 statesWithProbabilityGreater0E &= phiStates;
1127 statesWithProbabilityGreater0E |= lastIterationStates;
1130 return statesWithProbabilityGreater0E;
1133template<storm::dd::DdType Type,
typename ValueType>
1139template<storm::dd::DdType Type,
typename ValueType>
1148 while (lastIterationStates != statesWithProbabilityGreater0A) {
1149 lastIterationStates = statesWithProbabilityGreater0A;
1150 statesWithProbabilityGreater0A =
1154 statesWithProbabilityGreater0A &= phiStates;
1155 statesWithProbabilityGreater0A |= psiStates;
1158 return statesWithProbabilityGreater0A;
1161template<storm::dd::DdType Type,
typename ValueType>
1167template<storm::dd::DdType Type,
typename ValueType>
1175 while (lastIterationStates != statesWithProbability1A) {
1176 lastIterationStates = statesWithProbability1A;
1178 statesWithProbability1A = transitionMatrix.
implies(statesWithProbability1A).universalAbstract(model.
getColumnVariables());
1181 statesWithProbability1A &= statesWithProbabilityGreater0A;
1182 statesWithProbability1A |= psiStates;
1185 return statesWithProbability1A;
1188template<storm::dd::DdType Type,
typename ValueType>
1196 bool outerLoopDone =
false;
1197 while (!outerLoopDone) {
1200 bool innerLoopDone =
false;
1201 while (!innerLoopDone) {
1209 temporary &= phiStates;
1210 temporary |= psiStates;
1212 if (innerStates == temporary) {
1213 innerLoopDone =
true;
1215 innerStates = temporary;
1219 if (statesWithProbability1E == innerStates) {
1220 outerLoopDone =
true;
1222 statesWithProbability1E = innerStates;
1226 return statesWithProbability1E;
1229template<storm::dd::DdType Type,
typename ValueType>
1239 bool innerLoopDone =
false;
1240 while (!innerLoopDone) {
1246 temporary &= temporary2;
1247 temporary &= phiStates;
1253 temporary |= psiStates;
1255 if (innerStates == temporary) {
1256 innerLoopDone =
true;
1258 innerStates = temporary;
1265template<storm::dd::DdType Type,
typename ValueType>
1271template<storm::dd::DdType Type,
typename ValueType>
1276 result.first =
performProb0A(model, transitionMatrix, phiStates, psiStates);
1281template<storm::dd::DdType Type,
typename ValueType>
1287template<storm::dd::DdType Type,
typename ValueType>
1292 result.first =
performProb0E(model, transitionMatrix, phiStates, psiStates);
1297template<
typename ValueType>
1306 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
1309 uint_fast64_t currentState;
1310 while (!stack.empty()) {
1311 currentState = stack.back();
1315 for (
auto const& player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1316 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1318 bool addPlayer2State =
false;
1319 if (player2Direction == OptimizationDirection::Minimize) {
1320 bool allChoicesHavePlayer1State =
true;
1323 bool choiceHasPlayer1State =
false;
1324 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1326 choiceHasPlayer1State =
true;
1330 if (!choiceHasPlayer1State) {
1331 allChoicesHavePlayer1State =
false;
1334 if (allChoicesHavePlayer1State) {
1335 addPlayer2State =
true;
1338 addPlayer2State =
true;
1341 if (addPlayer2State) {
1346 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1349 bool addPlayer1State =
false;
1350 if (player1Direction == OptimizationDirection::Minimize) {
1351 bool allPlayer2Successors =
true;
1352 for (uint64_t player2State = player1Groups[player1Predecessor]; player2State < player1Groups[player1Predecessor + 1];
1355 allPlayer2Successors =
false;
1359 if (allPlayer2Successors) {
1360 addPlayer1State =
true;
1363 addPlayer1State =
true;
1366 if (addPlayer1State) {
1368 stack.emplace_back(player1Predecessor);
1383 if (player1Direction == storm::OptimizationDirection::Minimize) {
1385 [[maybe_unused]]
bool foundProb0Successor =
false;
1386 uint64_t player2State;
1387 for (player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1389 foundProb0Successor =
true;
1393 STORM_LOG_ASSERT(foundProb0Successor,
"Expected at least one state 2 successor with probability 0.");
1405 if (player2Direction == storm::OptimizationDirection::Minimize) {
1407 [[maybe_unused]]
bool foundProb0SuccessorDistribution =
false;
1411 bool distributionHasOnlyProb0Successors =
true;
1412 for (
auto const& player1SuccessorEntry : transitionMatrix.
getRow(row)) {
1414 distributionHasOnlyProb0Successors =
false;
1418 if (distributionHasOnlyProb0Successors) {
1419 foundProb0SuccessorDistribution =
true;
1424 STORM_LOG_ASSERT(foundProb0SuccessorDistribution,
"Expected at least one distribution with only successors with probability 0.");
1436template<storm::dd::DdType Type,
typename ValueType>
1450 if (player2Strategy == OptimizationDirection::Minimize) {
1455 player2States |= tmp;
1457 if (player1Strategy == OptimizationDirection::Minimize) {
1464 tmp |= player1States;
1466 if (tmp == player1States) {
1470 player1States = tmp;
1476 std::set<storm::expressions::Variable> variablesToAbstract(model.
getColumnVariables());
1478 player2States = !player2States && transitionMatrix.
existsAbstract(variablesToAbstract);
1487 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1488 if (producePlayer2Strategy) {
1493 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1494 if (producePlayer1Strategy) {
1496 onlyProb0Successors = (player1States && onlyProb0Successors).existsAbstract(model.
getPlayer2Variables());
1499 player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.
getPlayer1Variables());
1505template<
typename ValueType>
1511 boost::optional<storm::storage::BitVector>
const& player1Candidates) {
1514 if (player1Candidates) {
1521 bool produceStrategiesInIteration =
false;
1524 std::vector<uint_fast64_t> stack;
1525 bool maybeStatesDone =
false;
1526 while (!maybeStatesDone || produceStrategiesInIteration) {
1531 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1534 uint_fast64_t currentState;
1535 while (!stack.empty()) {
1536 currentState = stack.back();
1539 for (
auto player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1540 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1541 if (!player2Solution.
get(player2PredecessorEntry.getColumn())) {
1542 bool addPlayer2State = player2Direction == storm::OptimizationDirection::Minimize ? true :
false;
1545 for (uint64_t row = validChoice; row < transitionMatrix.
getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1546 bool choiceHasSolutionSuccessor =
false;
1547 bool choiceStaysInMaybeStates =
true;
1548 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1549 if (player1Solution.
get(entry.getColumn())) {
1550 choiceHasSolutionSuccessor =
true;
1553 choiceStaysInMaybeStates =
false;
1558 if (choiceHasSolutionSuccessor && choiceStaysInMaybeStates) {
1559 if (player2Direction == storm::OptimizationDirection::Maximize) {
1561 addPlayer2State =
true;
1564 }
else if (player2Direction == storm::OptimizationDirection::Minimize) {
1565 addPlayer2State =
false;
1570 if (addPlayer2State) {
1571 player2Solution.
set(player2Predecessor);
1572 if (produceStrategiesInIteration) {
1578 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1580 if (!player1Solution.
get(player1Predecessor)) {
1581 bool addPlayer1State = player1Direction == storm::OptimizationDirection::Minimize ? true :
false;
1583 validChoice = player1Groups[player1Predecessor];
1584 for (uint64_t player2Successor = validChoice; player2Successor < player1Groups[player1Predecessor + 1]; ++player2Successor) {
1585 if (player2Solution.
get(player2Successor)) {
1586 if (player1Direction == storm::OptimizationDirection::Maximize) {
1587 validChoice = player2Successor;
1588 addPlayer1State =
true;
1591 }
else if (player1Direction == storm::OptimizationDirection::Minimize) {
1592 addPlayer1State =
false;
1597 if (addPlayer1State) {
1598 player1Solution.
set(player1Predecessor);
1600 if (produceStrategiesInIteration) {
1604 stack.emplace_back(player1Predecessor);
1613 maybeStatesDone =
true;
1618 produceStrategiesInIteration = !produceStrategiesInIteration && strategyPair;
1628template<storm::dd::DdType Type,
typename ValueType>
1636 if (player1Candidates) {
1637 maybePlayer1States &= player1Candidates.get();
1644 bool produceStrategiesInIteration =
false;
1645 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1646 boost::optional<storm::dd::Bdd<Type>> consideredPlayer1States;
1647 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1648 boost::optional<storm::dd::Bdd<Type>> consideredPlayer2States;
1650 bool maybeStatesDone =
false;
1651 while (!maybeStatesDone || produceStrategiesInIteration) {
1652 bool solutionStatesDone =
false;
1655 if (produceStrategiesInIteration) {
1656 if (player1Strategy == storm::OptimizationDirection::Maximize) {
1657 player1StrategyBdd = model.
getManager().getBddZero();
1658 consideredPlayer1States = model.
getManager().getBddZero();
1660 if (player2Strategy == storm::OptimizationDirection::Maximize) {
1661 player2StrategyBdd = model.
getManager().getBddZero();
1662 consideredPlayer2States = model.
getManager().getBddZero();
1668 while (!solutionStatesDone) {
1681 storm::dd::Bdd<Type> valid = phiStates && distributionsStayingInMaybe && distributionsWithProb1Successor;
1685 if (player2Strategy == OptimizationDirection::Minimize) {
1688 if (produceStrategiesInIteration) {
1695 if (produceStrategiesInIteration) {
1696 consideredPlayer2States.get() |= valid;
1700 player2Solution |= valid;
1703 if (player1Strategy == OptimizationDirection::Minimize) {
1706 if (produceStrategiesInIteration) {
1713 if (produceStrategiesInIteration) {
1714 consideredPlayer1States.get() |= valid;
1724 if (valid == player1Solution) {
1725 solutionStatesDone =
true;
1727 player1Solution = valid;
1733 if (player1Solution == maybePlayer1States) {
1734 maybePlayer2States = player2Solution;
1735 maybeStatesDone =
true;
1739 produceStrategiesInIteration = !produceStrategiesInIteration && ((producePlayer1Strategy && player1Strategy == OptimizationDirection::Maximize) ||
1740 (producePlayer2Strategy && player2Strategy == OptimizationDirection::Maximize));
1744 maybePlayer1States = player1Solution;
1752 bool strategiesToCompute = (producePlayer1Strategy && !player1StrategyBdd) || (producePlayer2Strategy && !player2StrategyBdd);
1753 if (strategiesToCompute) {
1755 if (producePlayer2Strategy && !player2StrategyBdd) {
1758 if (producePlayer1Strategy && !player1StrategyBdd) {
1759 relevantStates = (maybePlayer1States && relevantStates).existsAbstract(model.
getPlayer2Variables());
1769 std::vector<uint_fast64_t>& recursionStack,
1772 if (!visitedStates.
get(state)) {
1773 recursionStack.push_back(state);
1774 iteratorRecursionStack.push_back(matrix.
begin(state));
1776 recursionStepForward:
1777 while (!recursionStack.empty()) {
1778 uint_fast64_t currentState = recursionStack.back();
1781 visitedStates.
set(currentState,
true);
1783 recursionStepBackward:
1784 for (; successorIterator != matrix.
end(currentState); ++successorIterator) {
1785 if (!visitedStates.
get(successorIterator->getColumn())) {
1787 recursionStack.push_back(successorIterator->getColumn());
1790 iteratorRecursionStack.push_back(matrix.
begin(successorIterator->getColumn()));
1792 goto recursionStepForward;
1796 topologicalSort.push_back(currentState);
1800 recursionStack.pop_back();
1801 iteratorRecursionStack.pop_back();
1806 if (recursionStack.size() > 0) {
1807 currentState = recursionStack.back();
1808 successorIterator = iteratorRecursionStack.back();
1810 goto recursionStepBackward;
1820 std::vector<uint_fast64_t> stateQueue;
1822 std::vector<uint_fast64_t> result;
1827 for (
auto const& state : firstStates) {
1828 stateQueue.push_back(state);
1829 result[count] = state;
1834 while (!stateQueue.empty()) {
1835 auto state = stateQueue.back();
1836 stateQueue.pop_back();
1837 seenStates.
set(state);
1838 for (
auto const& successorEntry : matrix.
getRowGroup(state)) {
1839 auto succ = successorEntry.geColumn();
1840 if (!seenStates[succ]) {
1841 result[count] = succ;
1843 stateQueue.insert(stateQueue.begin(), succ);
1854 throw storm::exceptions::InvalidArgumentException() <<
"Provided matrix is required to be square.";
1857 uint_fast64_t numberOfStates = matrix.
getRowCount();
1860 std::vector<uint_fast64_t> topologicalSort;
1861 topologicalSort.reserve(numberOfStates);
1864 std::vector<uint_fast64_t> recursionStack;
1866 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator> iteratorRecursionStack;
1867 iteratorRecursionStack.reserve(numberOfStates);
1871 for (
auto const state : firstStates) {
1872 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1874 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
1875 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1878 return topologicalSort;
1884 boost::optional<storm::storage::BitVector>
const& choiceFilter);
1895 boost::optional<storm::storage::BitVector>
const& subsystem);
1899 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1918 boost::optional<storm::storage::BitVector>
const& rowFilter);
1929 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
1933 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1939 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1942 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1949 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1959 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1962 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
1963 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1968#ifdef STORM_HAVE_CARL
1974 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1981#ifdef STORM_HAVE_CARL
1987 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1992 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2000#ifdef STORM_HAVE_CARL
2001template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2017 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2022#ifdef STORM_HAVE_CARL
2026 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2031 boost::optional<storm::storage::BitVector>
const& subsystem);
2042 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2051template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2055template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2063 boost::optional<storm::storage::BitVector>
const& rowFilter);
2075 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2079 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2085 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2088 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2094template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2099template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2104 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2107 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2108 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2115 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2120 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2124template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2129template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2134 std::vector<uint64_t>
const& player1RowGrouping,
2141 std::vector<uint64_t>
const& player1RowGrouping,
2146 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2149 std::vector<uint64_t>
const& firstStates);
2159 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2174 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2205 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2209 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2215 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2218 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2224template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2229template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2234 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2237 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2238 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2245 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2250 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2254template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2259template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2264 std::vector<uint64_t>
const& player1RowGrouping,
2271 std::vector<uint64_t>
const& player1RowGrouping,
2276 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2284 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2289 boost::optional<storm::storage::BitVector>
const& subsystem);
2300 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2309template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2313template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2322 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2326 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2332 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2335 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2341template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2346template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2351 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2354 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2355 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2361 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2369 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2373template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2378template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2383 std::vector<uint64_t>
const& firstStates);
2392 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2491 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2575 bool producePlayer2Strategy);