31 for (uint64_t currentState : initialStates) {
32 for (
auto const& successor : transitionMatrix.
getRowGroup(currentState)) {
34 result.set(successor.getColumn());
43 bool useStepBound, uint_fast64_t maximalSteps, boost::optional<storm::storage::BitVector>
const& choiceFilter) {
49 std::vector<uint_fast64_t> stack;
50 stack.reserve(initialStates.
size());
51 for (
auto state : initialStates) {
52 if (constraintStates.
get(state)) {
53 stack.push_back(state);
58 std::vector<uint_fast64_t> stepStack;
59 std::vector<uint_fast64_t> remainingSteps;
61 stepStack.reserve(numberOfStates);
62 stepStack.insert(stepStack.begin(), stack.size(), maximalSteps);
63 remainingSteps.resize(numberOfStates);
64 for (
auto state : stack) {
65 remainingSteps[state] = maximalSteps;
70 uint_fast64_t currentState = 0, currentStepBound = 0;
71 while (!stack.empty()) {
72 currentState = stack.back();
76 currentStepBound = stepStack.back();
79 if (currentStepBound == 0) {
86 row = choiceFilter->getNextSetIndex(row);
89 while (row < rowGroupEnd) {
90 for (
auto const& successor : transitionMatrix.
getRow(row)) {
94 (!reachableStates.
get(successor.getColumn()) || (useStepBound && remainingSteps[successor.getColumn()] < currentStepBound - 1))) {
97 if (targetStates.
get(successor.getColumn())) {
98 reachableStates.
set(successor.getColumn());
99 }
else if (constraintStates.
get(successor.getColumn())) {
103 remainingSteps[successor.getColumn()] = currentStepBound - 1;
104 stepStack.push_back(currentStepBound - 1);
106 reachableStates.
set(successor.getColumn());
107 stack.push_back(successor.getColumn());
113 row = choiceFilter->getNextSetIndex(row);
118 return reachableStates;
128 for (
auto const& scc : decomposition) {
129 result.
set(*scc.begin());
140 unexploredStates = subsystem.
get();
141 acyclicStates = ~subsystem.
get();
146 std::vector<uint64_t> dfsStack;
148 dfsStack.push_back(start);
149 while (!dfsStack.empty()) {
150 uint64_t state = dfsStack.back();
151 if (unexploredStates.
get(state)) {
152 unexploredStates.
set(state,
false);
153 for (
auto const& entry : transitionMatrix.
getRowGroup(state)) {
155 if (unexploredStates.
get(entry.getColumn())) {
156 dfsStack.push_back(entry.getColumn());
158 if (!acyclicStates.
get(entry.getColumn())) {
166 acyclicStates.
set(state,
true);
185 uint_fast64_t state = 0;
186 for (
auto choice : choices) {
193 if (subsystem.
get(state)) {
194 bool choiceStaysInSubsys =
true;
195 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
196 if (!subsystem.
get(entry.getColumn())) {
197 choiceStaysInSubsys =
false;
201 if (choiceStaysInSubsys) {
202 statesWithChoice.
set(state,
true);
218 statesWithChoice &= candidateStates;
220 for (
auto state : statesWithChoice) {
223 bool choiceStaysInCandidateSet =
true;
224 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
225 if (!candidateStates.
get(entry.getColumn())) {
226 choiceStaysInCandidateSet =
false;
230 if (choiceStaysInCandidateSet) {
231 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
232 choiceTargets.
set(entry.getColumn(),
true);
242 while (!candidateStates.
empty()) {
244 statesWithChoice &= candidateStates;
245 for (
auto state : statesWithChoice) {
246 bool stateHasChoice =
false;
249 bool choiceStaysInCandidateSet =
true;
250 for (
auto const& entry : transitionMatrix.
getRow(choice)) {
251 if (!candidateStates.
get(entry.getColumn())) {
252 choiceStaysInCandidateSet =
false;
256 if (choiceStaysInCandidateSet) {
257 stateHasChoice =
true;
261 if (!stateHasChoice) {
262 statesWithChoice.
set(state,
false);
268 backwardTransitions, candidateStates, statesWithChoice);
271 if (newCandidates == candidateStates) {
272 assert(!candidateStates.
empty());
275 candidateStates = std::move(newCandidates);
282 boost::optional<storm::storage::BitVector>
const& subsystem) {
285 std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> stateQueue;
290 for (
auto initialState : initialStates) {
291 stateQueue.emplace_back(initialState, 0);
292 statesInQueue.
set(initialState);
296 while (currentPosition < stateQueue.size()) {
297 std::pair<storm::storage::sparse::state_type, std::size_t>
const& stateDistancePair = stateQueue[currentPosition];
298 distances[stateDistancePair.first] = stateDistancePair.second;
300 for (
auto const& successorEntry : transitionMatrix.
getRowGroup(stateDistancePair.first)) {
301 if (!statesInQueue.
get(successorEntry.getColumn())) {
302 if (!subsystem || subsystem.get()[successorEntry.getColumn()]) {
303 stateQueue.emplace_back(successorEntry.getColumn(), stateDistancePair.second + 1);
304 statesInQueue.
set(successorEntry.getColumn());
318 uint_fast64_t numberOfStates = phiStates.
size();
322 statesWithProbabilityGreater0 |= psiStates;
325 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
328 std::vector<uint_fast64_t> stepStack;
329 std::vector<uint_fast64_t> remainingSteps;
331 stepStack.reserve(numberOfStates);
333 remainingSteps.resize(numberOfStates);
334 for (
auto state : psiStates) {
335 remainingSteps[state] = maximalSteps;
340 uint_fast64_t currentState, currentStepBound;
341 while (!stack.empty()) {
342 currentState = stack.back();
346 currentStepBound = stepStack.back();
347 stepStack.pop_back();
348 if (currentStepBound == 0) {
354 entryIte = backwardTransitions.
end(currentState);
355 entryIt != entryIte; ++entryIt) {
356 if (phiStates[entryIt->getColumn()] &&
357 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
358 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
363 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
364 stepStack.push_back(currentStepBound - 1);
366 stack.push_back(entryIt->getColumn());
372 return statesWithProbabilityGreater0;
380 return statesWithProbability1;
389 return statesWithProbability1;
396 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
399 result.second =
performProb1(backwardTransitions, phiStates, psiStates, result.first);
400 result.first.complement();
408 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
410 result.second =
performProb1(backwardTransitions, phiStates, psiStates, result.first);
411 result.first.complement();
415template<storm::dd::DdType Type,
typename ValueType>
418 boost::optional<uint_fast64_t>
const& stepBound) {
424 uint_fast64_t iterations = 0;
425 while (lastIterationStates != statesWithProbabilityGreater0) {
426 if (stepBound && iterations >= stepBound.get()) {
430 lastIterationStates = statesWithProbabilityGreater0;
431 statesWithProbabilityGreater0 =
433 statesWithProbabilityGreater0 &= phiStates;
434 statesWithProbabilityGreater0 |= lastIterationStates;
438 return statesWithProbabilityGreater0;
441template<storm::dd::DdType Type,
typename ValueType>
448 return statesWithProbability1;
451template<storm::dd::DdType Type,
typename ValueType>
455 return performProb1(model, transitionMatrix, phiStates, psiStates, statesWithProbabilityGreater0);
458template<storm::dd::DdType Type,
typename ValueType>
470template<storm::dd::DdType Type,
typename ValueType>
482template<
typename T,
typename SchedulerValueType>
485 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
487 for (
auto state : states) {
488 [[maybe_unused]]
bool setValue{
false};
490 if (rowFilter && !rowFilter->get(choice)) {
493 auto const row = transitionMatrix.
getRow(choice);
494 bool const allSuccessorsInStates = std::all_of(row.begin(), row.end(), [&states](
auto const& entry) { return states.get(entry.getColumn()); });
495 if (allSuccessorsInStates) {
497 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
503 STORM_LOG_ASSERT(setValue,
"Expected that at least one action for state " << state <<
" stays within the selected state");
507template<
typename T,
typename SchedulerValueType>
510 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
512 for (
auto state : states) {
513 [[maybe_unused]]
bool setValue =
false;
514 for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) {
515 bool oneSuccessorInStates =
false;
516 for (
auto const& element : transitionMatrix.
getRow(choice)) {
517 if (states.
get(element.getColumn())) {
518 oneSuccessorInStates =
true;
522 if (oneSuccessorInStates) {
524 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
530 STORM_LOG_ASSERT(setValue,
"Expected that at least one action for state " << state <<
" leads with positive probability to the selected state");
534template<
typename T,
typename SchedulerValueType>
540 std::vector<uint_fast64_t> stack;
542 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
543 uint_fast64_t currentState = 0;
545 while (!stack.empty()) {
546 currentState = stack.back();
550 predecessorEntryIte = backwardTransitions.
end(currentState);
551 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
552 uint_fast64_t
const& predecessor = predecessorEntryIt->getColumn();
553 if (phiStates.
get(predecessor) && !currentStates.
get(predecessor)) {
556 bool foundValidChoice =
false;
559 if (rowFilter && !rowFilter->get(row)) {
563 successorEntryIte = transitionMatrix.
end(row);
564 successorEntryIt != successorEntryIte; ++successorEntryIt) {
565 if (currentStates.
get(successorEntryIt->getColumn())) {
566 foundValidChoice =
true;
570 if (foundValidChoice) {
574 currentStates.
set(predecessor,
true);
575 stack.push_back(predecessor);
579 STORM_LOG_INFO_COND(foundValidChoice,
"Could not find a valid choice for ProbGreater0E state " << predecessor <<
".");
585template<
typename T,
typename SchedulerValueType>
591template<
typename T,
typename SchedulerValueType>
601 auto remainingStates = rewInfStates & ~trapStates;
602 if (!remainingStates.empty()) {
607template<
typename T,
typename SchedulerValueType>
611 boost::optional<storm::storage::BitVector>
const& rowFilter) {
613 for (
auto psiState : psiStates) {
615 if (!scheduler.
getChoice(psiState, memState).isDefined()) {
616 scheduler.
setChoice(0, psiState, memState);
622 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
623 std::vector<uint_fast64_t> stack;
625 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
626 uint_fast64_t currentState = 0;
628 while (!stack.empty()) {
629 currentState = stack.back();
633 predecessorEntryIte = backwardTransitions.
end(currentState);
634 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
635 if (phiStates.
get(predecessorEntryIt->getColumn()) && !currentStates.
get(predecessorEntryIt->getColumn())) {
638 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
639 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
640 if (!rowFilter || rowFilter.get().get(row)) {
641 bool allSuccessorsInProb1EStates =
true;
642 bool hasSuccessorInCurrentStates =
false;
644 successorEntryIte = transitionMatrix.
end(row);
645 successorEntryIt != successorEntryIte; ++successorEntryIt) {
646 if (!prob1EStates.
get(successorEntryIt->getColumn())) {
647 allSuccessorsInProb1EStates =
false;
649 }
else if (currentStates.
get(successorEntryIt->getColumn())) {
650 hasSuccessorInCurrentStates =
true;
656 if (allSuccessorsInProb1EStates && hasSuccessorInCurrentStates) {
658 scheduler.
setChoice(row - nondeterministicChoiceIndices[predecessorEntryIt->getColumn()], predecessorEntryIt->getColumn(),
661 currentStates.
set(predecessorEntryIt->getColumn(),
true);
662 stack.push_back(predecessorEntryIt->getColumn());
675 size_t numberOfStates = phiStates.
size();
681 statesWithProbabilityGreater0 |= psiStates;
684 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
687 std::vector<uint_fast64_t> stepStack;
688 std::vector<uint_fast64_t> remainingSteps;
690 stepStack.reserve(numberOfStates);
692 remainingSteps.resize(numberOfStates);
693 for (
auto state : psiStates) {
694 remainingSteps[state] = maximalSteps;
699 uint_fast64_t currentState, currentStepBound;
700 while (!stack.empty()) {
701 currentState = stack.back();
705 currentStepBound = stepStack.back();
706 stepStack.pop_back();
707 if (currentStepBound == 0) {
713 entryIte = backwardTransitions.
end(currentState);
714 entryIt != entryIte; ++entryIt) {
715 if (phiStates.
get(entryIt->getColumn()) &&
716 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
720 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
721 stepStack.push_back(currentStepBound - 1);
723 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
724 stack.push_back(entryIt->getColumn());
729 return statesWithProbabilityGreater0;
737 return statesWithProbability0;
742 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
745 size_t numberOfStates = phiStates.
size();
749 std::vector<uint_fast64_t> stack;
750 stack.reserve(numberOfStates);
754 uint_fast64_t currentState;
758 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
760 while (!stack.empty()) {
761 currentState = stack.back();
765 predecessorEntryIte = backwardTransitions.
end(currentState);
766 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
767 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
770 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
771 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
772 if (!choiceConstraint || choiceConstraint.get().get(row)) {
773 bool allSuccessorsInCurrentStates =
true;
774 bool hasNextStateSuccessor =
false;
776 successorEntryIte = transitionMatrix.
end(row);
777 successorEntryIt != successorEntryIte; ++successorEntryIt) {
778 if (!currentStates.
get(successorEntryIt->getColumn())) {
779 allSuccessorsInCurrentStates =
false;
781 }
else if (nextStates.
get(successorEntryIt->getColumn())) {
782 hasNextStateSuccessor =
true;
789 if (allSuccessorsInCurrentStates && hasNextStateSuccessor) {
790 nextStates.
set(predecessorEntryIt->getColumn(),
true);
791 stack.push_back(predecessorEntryIt->getColumn());
801 if (currentStates == nextStates) {
804 currentStates = std::move(nextStates);
808 return currentStates;
811template<
typename T,
typename RM>
820 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
824 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
826 result.first =
performProb0A(backwardTransitions, phiStates, psiStates);
828 result.second =
performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
832template<
typename T,
typename RM>
842 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
845 boost::optional<storm::storage::BitVector>
const& choiceConstraint) {
846 size_t numberOfStates = phiStates.
size();
852 statesWithProbabilityGreater0 |= psiStates;
855 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
858 std::vector<uint_fast64_t> stepStack;
859 std::vector<uint_fast64_t> remainingSteps;
861 stepStack.reserve(numberOfStates);
863 remainingSteps.resize(numberOfStates);
864 for (
auto state : psiStates) {
865 remainingSteps[state] = maximalSteps;
870 uint_fast64_t currentState, currentStepBound;
871 while (!stack.empty()) {
872 currentState = stack.back();
876 currentStepBound = stepStack.back();
877 stepStack.pop_back();
878 if (currentStepBound == 0) {
884 predecessorEntryIte = backwardTransitions.
end(currentState);
885 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
886 if (phiStates.
get(predecessorEntryIt->getColumn())) {
887 if (!statesWithProbabilityGreater0.
get(predecessorEntryIt->getColumn())) {
893 uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
894 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
895 if (!choiceConstraint || choiceConstraint->getNextSetIndex(row) < endOfGroup) {
896 bool addToStatesWithProbabilityGreater0 =
true;
897 for (; row < endOfGroup; ++row) {
898 if (!choiceConstraint || choiceConstraint->get(row)) {
899 bool hasAtLeastOneSuccessorWithProbabilityGreater0 =
false;
901 successorEntryIte = transitionMatrix.
end(row);
902 successorEntryIt != successorEntryIte; ++successorEntryIt) {
903 if (statesWithProbabilityGreater0.
get(successorEntryIt->getColumn())) {
904 hasAtLeastOneSuccessorWithProbabilityGreater0 =
true;
909 if (!hasAtLeastOneSuccessorWithProbabilityGreater0) {
910 addToStatesWithProbabilityGreater0 =
false;
917 if (addToStatesWithProbabilityGreater0) {
921 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
922 stepStack.push_back(currentStepBound - 1);
924 statesWithProbabilityGreater0.
set(predecessorEntryIt->getColumn(),
true);
925 stack.push_back(predecessorEntryIt->getColumn());
929 }
else if (useStepBound && remainingSteps[predecessorEntryIt->getColumn()] < currentStepBound - 1) {
932 bool predecessorIsValid =
true;
933 if (choiceConstraint) {
934 predecessorIsValid =
false;
935 uint_fast64_t row = choiceConstraint->getNextSetIndex(nondeterministicChoiceIndices[predecessorEntryIt->getColumn()]);
936 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
937 for (; row < endOfGroup && !predecessorIsValid; row = choiceConstraint->getNextSetIndex(row + 1)) {
938 for (
auto const& entry : transitionMatrix.
getRow(row)) {
939 if (entry.getColumn() == currentState) {
940 predecessorIsValid =
true;
946 if (predecessorIsValid) {
947 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
948 stepStack.push_back(currentStepBound - 1);
949 stack.push_back(predecessorEntryIt->getColumn());
956 return statesWithProbabilityGreater0;
959template<
typename T,
typename RM>
966 return statesWithProbability0;
971 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
975 performProbGreater0A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
977 return statesWithProbability0;
980template<
typename T,
typename RM>
989 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
992 size_t numberOfStates = phiStates.
size();
996 std::vector<uint_fast64_t> stack;
997 stack.reserve(numberOfStates);
1001 uint_fast64_t currentState;
1005 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1007 while (!stack.empty()) {
1008 currentState = stack.back();
1012 predecessorEntryIte = backwardTransitions.
end(currentState);
1013 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
1014 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
1018 bool addToStatesWithProbability1 =
true;
1019 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
1020 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
1021 bool hasAtLeastOneSuccessorWithProbability1 =
false;
1023 successorEntryIte = transitionMatrix.
end(row);
1024 successorEntryIt != successorEntryIte; ++successorEntryIt) {
1025 if (!currentStates.
get(successorEntryIt->getColumn())) {
1026 addToStatesWithProbability1 =
false;
1027 goto afterCheckLoop;
1029 if (nextStates.
get(successorEntryIt->getColumn())) {
1030 hasAtLeastOneSuccessorWithProbability1 =
true;
1034 if (!hasAtLeastOneSuccessorWithProbability1) {
1035 addToStatesWithProbability1 =
false;
1044 if (addToStatesWithProbability1) {
1045 nextStates.
set(predecessorEntryIt->getColumn(),
true);
1046 stack.push_back(predecessorEntryIt->getColumn());
1053 if (currentStates == nextStates) {
1056 currentStates = std::move(nextStates);
1059 return currentStates;
1064 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1068 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
1069 result.first =
performProb0E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
1073 result.second =
performProb0A(backwardTransitions, ~psiStates, result.first);
1077template<
typename T,
typename RM>
1085template<storm::dd::DdType Type,
typename ValueType>
1095 while (!frontier.
isZero()) {
1099 scheduler = scheduler || (frontier && statesAndChoicesWithProbabilityGreater0E).existsAbstractRepresentative(model.
getNondeterminismVariables());
1100 statesWithProbabilityGreater0E |= frontier;
1106template<storm::dd::DdType Type,
typename ValueType>
1116 while (lastIterationStates != statesWithProbabilityGreater0E) {
1117 lastIterationStates = statesWithProbabilityGreater0E;
1118 statesWithProbabilityGreater0E =
1120 statesWithProbabilityGreater0E &= phiStates;
1121 statesWithProbabilityGreater0E |= lastIterationStates;
1124 return statesWithProbabilityGreater0E;
1127template<storm::dd::DdType Type,
typename ValueType>
1133template<storm::dd::DdType Type,
typename ValueType>
1142 while (lastIterationStates != statesWithProbabilityGreater0A) {
1143 lastIterationStates = statesWithProbabilityGreater0A;
1144 statesWithProbabilityGreater0A =
1148 statesWithProbabilityGreater0A &= phiStates;
1149 statesWithProbabilityGreater0A |= psiStates;
1152 return statesWithProbabilityGreater0A;
1155template<storm::dd::DdType Type,
typename ValueType>
1161template<storm::dd::DdType Type,
typename ValueType>
1169 while (lastIterationStates != statesWithProbability1A) {
1170 lastIterationStates = statesWithProbability1A;
1172 statesWithProbability1A = transitionMatrix.
implies(statesWithProbability1A).universalAbstract(model.
getColumnVariables());
1175 statesWithProbability1A &= statesWithProbabilityGreater0A;
1176 statesWithProbability1A |= psiStates;
1179 return statesWithProbability1A;
1182template<storm::dd::DdType Type,
typename ValueType>
1190 bool outerLoopDone =
false;
1191 while (!outerLoopDone) {
1194 bool innerLoopDone =
false;
1195 while (!innerLoopDone) {
1203 temporary &= phiStates;
1204 temporary |= psiStates;
1206 if (innerStates == temporary) {
1207 innerLoopDone =
true;
1209 innerStates = temporary;
1213 if (statesWithProbability1E == innerStates) {
1214 outerLoopDone =
true;
1216 statesWithProbability1E = innerStates;
1220 return statesWithProbability1E;
1223template<storm::dd::DdType Type,
typename ValueType>
1233 bool innerLoopDone =
false;
1234 while (!innerLoopDone) {
1240 temporary &= temporary2;
1241 temporary &= phiStates;
1247 temporary |= psiStates;
1249 if (innerStates == temporary) {
1250 innerLoopDone =
true;
1252 innerStates = temporary;
1259template<storm::dd::DdType Type,
typename ValueType>
1265template<storm::dd::DdType Type,
typename ValueType>
1270 result.first =
performProb0A(model, transitionMatrix, phiStates, psiStates);
1275template<storm::dd::DdType Type,
typename ValueType>
1281template<storm::dd::DdType Type,
typename ValueType>
1286 result.first =
performProb0E(model, transitionMatrix, phiStates, psiStates);
1291template<
typename ValueType>
1300 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
1303 uint_fast64_t currentState;
1304 while (!stack.empty()) {
1305 currentState = stack.back();
1309 for (
auto const& player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1310 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1312 bool addPlayer2State =
false;
1313 if (player2Direction == OptimizationDirection::Minimize) {
1314 bool allChoicesHavePlayer1State =
true;
1317 bool choiceHasPlayer1State =
false;
1318 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1320 choiceHasPlayer1State =
true;
1324 if (!choiceHasPlayer1State) {
1325 allChoicesHavePlayer1State =
false;
1328 if (allChoicesHavePlayer1State) {
1329 addPlayer2State =
true;
1332 addPlayer2State =
true;
1335 if (addPlayer2State) {
1340 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1343 bool addPlayer1State =
false;
1344 if (player1Direction == OptimizationDirection::Minimize) {
1345 bool allPlayer2Successors =
true;
1346 for (uint64_t player2State = player1Groups[player1Predecessor]; player2State < player1Groups[player1Predecessor + 1];
1349 allPlayer2Successors =
false;
1353 if (allPlayer2Successors) {
1354 addPlayer1State =
true;
1357 addPlayer1State =
true;
1360 if (addPlayer1State) {
1362 stack.emplace_back(player1Predecessor);
1377 if (player1Direction == storm::OptimizationDirection::Minimize) {
1379 [[maybe_unused]]
bool foundProb0Successor =
false;
1380 uint64_t player2State;
1381 for (player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1383 foundProb0Successor =
true;
1387 STORM_LOG_ASSERT(foundProb0Successor,
"Expected at least one state 2 successor with probability 0.");
1399 if (player2Direction == storm::OptimizationDirection::Minimize) {
1401 [[maybe_unused]]
bool foundProb0SuccessorDistribution =
false;
1405 bool distributionHasOnlyProb0Successors =
true;
1406 for (
auto const& player1SuccessorEntry : transitionMatrix.
getRow(row)) {
1408 distributionHasOnlyProb0Successors =
false;
1412 if (distributionHasOnlyProb0Successors) {
1413 foundProb0SuccessorDistribution =
true;
1418 STORM_LOG_ASSERT(foundProb0SuccessorDistribution,
"Expected at least one distribution with only successors with probability 0.");
1430template<storm::dd::DdType Type,
typename ValueType>
1444 if (player2Strategy == OptimizationDirection::Minimize) {
1449 player2States |= tmp;
1451 if (player1Strategy == OptimizationDirection::Minimize) {
1458 tmp |= player1States;
1460 if (tmp == player1States) {
1464 player1States = tmp;
1470 std::set<storm::expressions::Variable> variablesToAbstract(model.
getColumnVariables());
1472 player2States = !player2States && transitionMatrix.
existsAbstract(variablesToAbstract);
1481 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1482 if (producePlayer2Strategy) {
1487 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1488 if (producePlayer1Strategy) {
1490 onlyProb0Successors = (player1States && onlyProb0Successors).existsAbstract(model.
getPlayer2Variables());
1493 player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.
getPlayer1Variables());
1499template<
typename ValueType>
1505 boost::optional<storm::storage::BitVector>
const& player1Candidates) {
1508 if (player1Candidates) {
1515 bool produceStrategiesInIteration =
false;
1518 std::vector<uint_fast64_t> stack;
1519 bool maybeStatesDone =
false;
1520 while (!maybeStatesDone || produceStrategiesInIteration) {
1525 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1528 uint_fast64_t currentState;
1529 while (!stack.empty()) {
1530 currentState = stack.back();
1533 for (
auto player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1534 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1535 if (!player2Solution.
get(player2PredecessorEntry.getColumn())) {
1536 bool addPlayer2State = player2Direction == storm::OptimizationDirection::Minimize ? true :
false;
1539 for (uint64_t row = validChoice; row < transitionMatrix.
getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1540 bool choiceHasSolutionSuccessor =
false;
1541 bool choiceStaysInMaybeStates =
true;
1542 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1543 if (player1Solution.
get(entry.getColumn())) {
1544 choiceHasSolutionSuccessor =
true;
1547 choiceStaysInMaybeStates =
false;
1552 if (choiceHasSolutionSuccessor && choiceStaysInMaybeStates) {
1553 if (player2Direction == storm::OptimizationDirection::Maximize) {
1555 addPlayer2State =
true;
1558 }
else if (player2Direction == storm::OptimizationDirection::Minimize) {
1559 addPlayer2State =
false;
1564 if (addPlayer2State) {
1565 player2Solution.
set(player2Predecessor);
1566 if (produceStrategiesInIteration) {
1572 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1574 if (!player1Solution.
get(player1Predecessor)) {
1575 bool addPlayer1State = player1Direction == storm::OptimizationDirection::Minimize ? true :
false;
1577 validChoice = player1Groups[player1Predecessor];
1578 for (uint64_t player2Successor = validChoice; player2Successor < player1Groups[player1Predecessor + 1]; ++player2Successor) {
1579 if (player2Solution.
get(player2Successor)) {
1580 if (player1Direction == storm::OptimizationDirection::Maximize) {
1581 validChoice = player2Successor;
1582 addPlayer1State =
true;
1585 }
else if (player1Direction == storm::OptimizationDirection::Minimize) {
1586 addPlayer1State =
false;
1591 if (addPlayer1State) {
1592 player1Solution.
set(player1Predecessor);
1594 if (produceStrategiesInIteration) {
1598 stack.emplace_back(player1Predecessor);
1607 maybeStatesDone =
true;
1612 produceStrategiesInIteration = !produceStrategiesInIteration && strategyPair;
1622template<storm::dd::DdType Type,
typename ValueType>
1630 if (player1Candidates) {
1631 maybePlayer1States &= player1Candidates.get();
1638 bool produceStrategiesInIteration =
false;
1639 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1640 boost::optional<storm::dd::Bdd<Type>> consideredPlayer1States;
1641 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1642 boost::optional<storm::dd::Bdd<Type>> consideredPlayer2States;
1644 bool maybeStatesDone =
false;
1645 while (!maybeStatesDone || produceStrategiesInIteration) {
1646 bool solutionStatesDone =
false;
1649 if (produceStrategiesInIteration) {
1650 if (player1Strategy == storm::OptimizationDirection::Maximize) {
1651 player1StrategyBdd = model.
getManager().getBddZero();
1652 consideredPlayer1States = model.
getManager().getBddZero();
1654 if (player2Strategy == storm::OptimizationDirection::Maximize) {
1655 player2StrategyBdd = model.
getManager().getBddZero();
1656 consideredPlayer2States = model.
getManager().getBddZero();
1662 while (!solutionStatesDone) {
1675 storm::dd::Bdd<Type> valid = phiStates && distributionsStayingInMaybe && distributionsWithProb1Successor;
1679 if (player2Strategy == OptimizationDirection::Minimize) {
1682 if (produceStrategiesInIteration) {
1689 if (produceStrategiesInIteration) {
1690 consideredPlayer2States.get() |= valid;
1694 player2Solution |= valid;
1697 if (player1Strategy == OptimizationDirection::Minimize) {
1700 if (produceStrategiesInIteration) {
1707 if (produceStrategiesInIteration) {
1708 consideredPlayer1States.get() |= valid;
1718 if (valid == player1Solution) {
1719 solutionStatesDone =
true;
1721 player1Solution = valid;
1727 if (player1Solution == maybePlayer1States) {
1728 maybePlayer2States = player2Solution;
1729 maybeStatesDone =
true;
1733 produceStrategiesInIteration = !produceStrategiesInIteration && ((producePlayer1Strategy && player1Strategy == OptimizationDirection::Maximize) ||
1734 (producePlayer2Strategy && player2Strategy == OptimizationDirection::Maximize));
1738 maybePlayer1States = player1Solution;
1746 bool strategiesToCompute = (producePlayer1Strategy && !player1StrategyBdd) || (producePlayer2Strategy && !player2StrategyBdd);
1747 if (strategiesToCompute) {
1749 if (producePlayer2Strategy && !player2StrategyBdd) {
1752 if (producePlayer1Strategy && !player1StrategyBdd) {
1753 relevantStates = (maybePlayer1States && relevantStates).existsAbstract(model.
getPlayer2Variables());
1763 std::vector<uint_fast64_t>& recursionStack,
1766 if (!visitedStates.
get(state)) {
1767 recursionStack.push_back(state);
1768 iteratorRecursionStack.push_back(matrix.
begin(state));
1770 recursionStepForward:
1771 while (!recursionStack.empty()) {
1772 uint_fast64_t currentState = recursionStack.back();
1775 visitedStates.
set(currentState,
true);
1777 recursionStepBackward:
1778 for (; successorIterator != matrix.
end(currentState); ++successorIterator) {
1779 if (!visitedStates.
get(successorIterator->getColumn())) {
1781 recursionStack.push_back(successorIterator->getColumn());
1784 iteratorRecursionStack.push_back(matrix.
begin(successorIterator->getColumn()));
1786 goto recursionStepForward;
1790 topologicalSort.push_back(currentState);
1794 recursionStack.pop_back();
1795 iteratorRecursionStack.pop_back();
1800 if (recursionStack.size() > 0) {
1801 currentState = recursionStack.back();
1802 successorIterator = iteratorRecursionStack.back();
1804 goto recursionStepBackward;
1814 std::vector<uint_fast64_t> stateQueue;
1816 std::vector<uint_fast64_t> result;
1821 for (
auto const& state : firstStates) {
1822 stateQueue.push_back(state);
1823 result[count] = state;
1828 while (!stateQueue.empty()) {
1829 auto state = stateQueue.back();
1830 stateQueue.pop_back();
1831 seenStates.
set(state);
1832 for (
auto const& successorEntry : matrix.
getRowGroup(state)) {
1833 auto succ = successorEntry.geColumn();
1834 if (!seenStates[succ]) {
1835 result[count] = succ;
1837 stateQueue.insert(stateQueue.begin(), succ);
1848 throw storm::exceptions::InvalidArgumentException() <<
"Provided matrix is required to be square.";
1851 uint_fast64_t numberOfStates = matrix.
getRowCount();
1854 std::vector<uint_fast64_t> topologicalSort;
1855 topologicalSort.reserve(numberOfStates);
1858 std::vector<uint_fast64_t> recursionStack;
1860 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator> iteratorRecursionStack;
1861 iteratorRecursionStack.reserve(numberOfStates);
1865 for (
auto const state : firstStates) {
1866 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1868 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
1869 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1872 return topologicalSort;
1878 boost::optional<storm::storage::BitVector>
const& choiceFilter);
1889 boost::optional<storm::storage::BitVector>
const& subsystem);
1893 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1912 boost::optional<storm::storage::BitVector>
const& rowFilter);
1923 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
1927 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1933 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1936 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1943 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1953 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1956 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
1957 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1966 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1977 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1982 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2005 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2013 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2018 boost::optional<storm::storage::BitVector>
const& subsystem);
2029 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2038template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2042template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2050 boost::optional<storm::storage::BitVector>
const& rowFilter);
2062 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2066 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2072 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2075 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2091 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2094 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2095 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2102 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2107 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2121 std::vector<uint64_t>
const& player1RowGrouping,
2128 std::vector<uint64_t>
const& player1RowGrouping,
2133 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2136 std::vector<uint64_t>
const& firstStates);
2146 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2161 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2192 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2196 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2202 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2205 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2221 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2224 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2225 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2232 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2237 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2251 std::vector<uint64_t>
const& player1RowGrouping,
2258 std::vector<uint64_t>
const& player1RowGrouping,
2263 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2271 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2276 boost::optional<storm::storage::BitVector>
const& subsystem);
2287 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2296template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2300template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2309 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2313 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2319 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2322 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2338 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2341 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2342 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2348 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2356 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2370 std::vector<uint64_t>
const& firstStates);
2378 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2477 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2561 bool producePlayer2Strategy);