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>
605 for (
auto state : rewInfStates) {
606 STORM_LOG_ASSERT(nondeterministicChoiceIndices[state + 1] - nondeterministicChoiceIndices[state] > 0,
607 "Expected at least one action enabled in state " << state);
608 for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) {
609 auto const& row = transitionMatrix.
getRow(choice);
610 if (std::all_of(row.begin(), row.end(), [&rewInfStates](
auto const& entry) { return rewInfStates.get(entry.getColumn()); })) {
611 trapStates.
set(state,
true);
613 scheduler.
setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
623template<
typename T,
typename SchedulerValueType>
627 boost::optional<storm::storage::BitVector>
const& rowFilter) {
629 for (
auto psiState : psiStates) {
631 if (!scheduler.
getChoice(psiState, memState).isDefined()) {
632 scheduler.
setChoice(0, psiState, memState);
638 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices = transitionMatrix.
getRowGroupIndices();
639 std::vector<uint_fast64_t> stack;
641 stack.insert(stack.end(), currentStates.
begin(), currentStates.
end());
642 uint_fast64_t currentState = 0;
644 while (!stack.empty()) {
645 currentState = stack.back();
649 predecessorEntryIte = backwardTransitions.
end(currentState);
650 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
651 if (phiStates.
get(predecessorEntryIt->getColumn()) && !currentStates.
get(predecessorEntryIt->getColumn())) {
654 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
655 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
656 if (!rowFilter || rowFilter.get().get(row)) {
657 bool allSuccessorsInProb1EStates =
true;
658 bool hasSuccessorInCurrentStates =
false;
660 successorEntryIte = transitionMatrix.
end(row);
661 successorEntryIt != successorEntryIte; ++successorEntryIt) {
662 if (!prob1EStates.
get(successorEntryIt->getColumn())) {
663 allSuccessorsInProb1EStates =
false;
665 }
else if (currentStates.
get(successorEntryIt->getColumn())) {
666 hasSuccessorInCurrentStates =
true;
672 if (allSuccessorsInProb1EStates && hasSuccessorInCurrentStates) {
674 scheduler.
setChoice(row - nondeterministicChoiceIndices[predecessorEntryIt->getColumn()], predecessorEntryIt->getColumn(),
677 currentStates.
set(predecessorEntryIt->getColumn(),
true);
678 stack.push_back(predecessorEntryIt->getColumn());
691 size_t numberOfStates = phiStates.
size();
697 statesWithProbabilityGreater0 |= psiStates;
700 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
703 std::vector<uint_fast64_t> stepStack;
704 std::vector<uint_fast64_t> remainingSteps;
706 stepStack.reserve(numberOfStates);
708 remainingSteps.resize(numberOfStates);
709 for (
auto state : psiStates) {
710 remainingSteps[state] = maximalSteps;
715 uint_fast64_t currentState, currentStepBound;
716 while (!stack.empty()) {
717 currentState = stack.back();
721 currentStepBound = stepStack.back();
722 stepStack.pop_back();
723 if (currentStepBound == 0) {
729 entryIte = backwardTransitions.
end(currentState);
730 entryIt != entryIte; ++entryIt) {
731 if (phiStates.
get(entryIt->getColumn()) &&
732 (!statesWithProbabilityGreater0.
get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
736 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
737 stepStack.push_back(currentStepBound - 1);
739 statesWithProbabilityGreater0.
set(entryIt->getColumn(),
true);
740 stack.push_back(entryIt->getColumn());
745 return statesWithProbabilityGreater0;
753 return statesWithProbability0;
758 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
761 size_t numberOfStates = phiStates.
size();
765 std::vector<uint_fast64_t> stack;
766 stack.reserve(numberOfStates);
770 uint_fast64_t currentState;
774 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
776 while (!stack.empty()) {
777 currentState = stack.back();
781 predecessorEntryIte = backwardTransitions.
end(currentState);
782 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
783 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
786 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
787 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
788 if (!choiceConstraint || choiceConstraint.get().get(row)) {
789 bool allSuccessorsInCurrentStates =
true;
790 bool hasNextStateSuccessor =
false;
792 successorEntryIte = transitionMatrix.
end(row);
793 successorEntryIt != successorEntryIte; ++successorEntryIt) {
794 if (!currentStates.
get(successorEntryIt->getColumn())) {
795 allSuccessorsInCurrentStates =
false;
797 }
else if (nextStates.
get(successorEntryIt->getColumn())) {
798 hasNextStateSuccessor =
true;
805 if (allSuccessorsInCurrentStates && hasNextStateSuccessor) {
806 nextStates.
set(predecessorEntryIt->getColumn(),
true);
807 stack.push_back(predecessorEntryIt->getColumn());
817 if (currentStates == nextStates) {
820 currentStates = std::move(nextStates);
824 return currentStates;
827template<
typename T,
typename RM>
836 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
840 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
842 result.first =
performProb0A(backwardTransitions, phiStates, psiStates);
844 result.second =
performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
848template<
typename T,
typename RM>
858 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
861 boost::optional<storm::storage::BitVector>
const& choiceConstraint) {
862 size_t numberOfStates = phiStates.
size();
868 statesWithProbabilityGreater0 |= psiStates;
871 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
874 std::vector<uint_fast64_t> stepStack;
875 std::vector<uint_fast64_t> remainingSteps;
877 stepStack.reserve(numberOfStates);
879 remainingSteps.resize(numberOfStates);
880 for (
auto state : psiStates) {
881 remainingSteps[state] = maximalSteps;
886 uint_fast64_t currentState, currentStepBound;
887 while (!stack.empty()) {
888 currentState = stack.back();
892 currentStepBound = stepStack.back();
893 stepStack.pop_back();
894 if (currentStepBound == 0) {
900 predecessorEntryIte = backwardTransitions.
end(currentState);
901 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
902 if (phiStates.
get(predecessorEntryIt->getColumn())) {
903 if (!statesWithProbabilityGreater0.
get(predecessorEntryIt->getColumn())) {
909 uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
910 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
911 if (!choiceConstraint || choiceConstraint->getNextSetIndex(row) < endOfGroup) {
912 bool addToStatesWithProbabilityGreater0 =
true;
913 for (; row < endOfGroup; ++row) {
914 if (!choiceConstraint || choiceConstraint->get(row)) {
915 bool hasAtLeastOneSuccessorWithProbabilityGreater0 =
false;
917 successorEntryIte = transitionMatrix.
end(row);
918 successorEntryIt != successorEntryIte; ++successorEntryIt) {
919 if (statesWithProbabilityGreater0.
get(successorEntryIt->getColumn())) {
920 hasAtLeastOneSuccessorWithProbabilityGreater0 =
true;
925 if (!hasAtLeastOneSuccessorWithProbabilityGreater0) {
926 addToStatesWithProbabilityGreater0 =
false;
933 if (addToStatesWithProbabilityGreater0) {
937 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
938 stepStack.push_back(currentStepBound - 1);
940 statesWithProbabilityGreater0.
set(predecessorEntryIt->getColumn(),
true);
941 stack.push_back(predecessorEntryIt->getColumn());
945 }
else if (useStepBound && remainingSteps[predecessorEntryIt->getColumn()] < currentStepBound - 1) {
948 bool predecessorIsValid =
true;
949 if (choiceConstraint) {
950 predecessorIsValid =
false;
951 uint_fast64_t row = choiceConstraint->getNextSetIndex(nondeterministicChoiceIndices[predecessorEntryIt->getColumn()]);
952 uint_fast64_t
const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
953 for (; row < endOfGroup && !predecessorIsValid; row = choiceConstraint->getNextSetIndex(row + 1)) {
954 for (
auto const& entry : transitionMatrix.
getRow(row)) {
955 if (entry.getColumn() == currentState) {
956 predecessorIsValid =
true;
962 if (predecessorIsValid) {
963 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
964 stepStack.push_back(currentStepBound - 1);
965 stack.push_back(predecessorEntryIt->getColumn());
972 return statesWithProbabilityGreater0;
975template<
typename T,
typename RM>
982 return statesWithProbability0;
987 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
991 performProbGreater0A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
993 return statesWithProbability0;
996template<
typename T,
typename RM>
1005 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1008 size_t numberOfStates = phiStates.
size();
1012 std::vector<uint_fast64_t> stack;
1013 stack.reserve(numberOfStates);
1017 uint_fast64_t currentState;
1021 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1023 while (!stack.empty()) {
1024 currentState = stack.back();
1028 predecessorEntryIte = backwardTransitions.
end(currentState);
1029 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
1030 if (phiStates.
get(predecessorEntryIt->getColumn()) && !nextStates.
get(predecessorEntryIt->getColumn())) {
1034 bool addToStatesWithProbability1 =
true;
1035 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
1036 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
1037 bool hasAtLeastOneSuccessorWithProbability1 =
false;
1039 successorEntryIte = transitionMatrix.
end(row);
1040 successorEntryIt != successorEntryIte; ++successorEntryIt) {
1041 if (!currentStates.
get(successorEntryIt->getColumn())) {
1042 addToStatesWithProbability1 =
false;
1043 goto afterCheckLoop;
1045 if (nextStates.
get(successorEntryIt->getColumn())) {
1046 hasAtLeastOneSuccessorWithProbability1 =
true;
1050 if (!hasAtLeastOneSuccessorWithProbability1) {
1051 addToStatesWithProbability1 =
false;
1060 if (addToStatesWithProbability1) {
1061 nextStates.
set(predecessorEntryIt->getColumn(),
true);
1062 stack.push_back(predecessorEntryIt->getColumn());
1069 if (currentStates == nextStates) {
1072 currentStates = std::move(nextStates);
1075 return currentStates;
1080 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1084 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
1085 result.first =
performProb0E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
1089 result.second =
performProb0A(backwardTransitions, ~psiStates, result.first);
1093template<
typename T,
typename RM>
1101template<storm::dd::DdType Type,
typename ValueType>
1111 while (!frontier.
isZero()) {
1115 scheduler = scheduler || (frontier && statesAndChoicesWithProbabilityGreater0E).existsAbstractRepresentative(model.
getNondeterminismVariables());
1116 statesWithProbabilityGreater0E |= frontier;
1122template<storm::dd::DdType Type,
typename ValueType>
1132 while (lastIterationStates != statesWithProbabilityGreater0E) {
1133 lastIterationStates = statesWithProbabilityGreater0E;
1134 statesWithProbabilityGreater0E =
1136 statesWithProbabilityGreater0E &= phiStates;
1137 statesWithProbabilityGreater0E |= lastIterationStates;
1140 return statesWithProbabilityGreater0E;
1143template<storm::dd::DdType Type,
typename ValueType>
1149template<storm::dd::DdType Type,
typename ValueType>
1158 while (lastIterationStates != statesWithProbabilityGreater0A) {
1159 lastIterationStates = statesWithProbabilityGreater0A;
1160 statesWithProbabilityGreater0A =
1164 statesWithProbabilityGreater0A &= phiStates;
1165 statesWithProbabilityGreater0A |= psiStates;
1168 return statesWithProbabilityGreater0A;
1171template<storm::dd::DdType Type,
typename ValueType>
1177template<storm::dd::DdType Type,
typename ValueType>
1185 while (lastIterationStates != statesWithProbability1A) {
1186 lastIterationStates = statesWithProbability1A;
1188 statesWithProbability1A = transitionMatrix.
implies(statesWithProbability1A).universalAbstract(model.
getColumnVariables());
1191 statesWithProbability1A &= statesWithProbabilityGreater0A;
1192 statesWithProbability1A |= psiStates;
1195 return statesWithProbability1A;
1198template<storm::dd::DdType Type,
typename ValueType>
1206 bool outerLoopDone =
false;
1207 while (!outerLoopDone) {
1210 bool innerLoopDone =
false;
1211 while (!innerLoopDone) {
1219 temporary &= phiStates;
1220 temporary |= psiStates;
1222 if (innerStates == temporary) {
1223 innerLoopDone =
true;
1225 innerStates = temporary;
1229 if (statesWithProbability1E == innerStates) {
1230 outerLoopDone =
true;
1232 statesWithProbability1E = innerStates;
1236 return statesWithProbability1E;
1239template<storm::dd::DdType Type,
typename ValueType>
1249 bool innerLoopDone =
false;
1250 while (!innerLoopDone) {
1256 temporary &= temporary2;
1257 temporary &= phiStates;
1263 temporary |= psiStates;
1265 if (innerStates == temporary) {
1266 innerLoopDone =
true;
1268 innerStates = temporary;
1275template<storm::dd::DdType Type,
typename ValueType>
1281template<storm::dd::DdType Type,
typename ValueType>
1286 result.first =
performProb0A(model, transitionMatrix, phiStates, psiStates);
1291template<storm::dd::DdType Type,
typename ValueType>
1297template<storm::dd::DdType Type,
typename ValueType>
1302 result.first =
performProb0E(model, transitionMatrix, phiStates, psiStates);
1307template<
typename ValueType>
1316 std::vector<uint_fast64_t> stack(psiStates.
begin(), psiStates.
end());
1319 uint_fast64_t currentState;
1320 while (!stack.empty()) {
1321 currentState = stack.back();
1325 for (
auto const& player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1326 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1328 bool addPlayer2State =
false;
1329 if (player2Direction == OptimizationDirection::Minimize) {
1330 bool allChoicesHavePlayer1State =
true;
1333 bool choiceHasPlayer1State =
false;
1334 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1336 choiceHasPlayer1State =
true;
1340 if (!choiceHasPlayer1State) {
1341 allChoicesHavePlayer1State =
false;
1344 if (allChoicesHavePlayer1State) {
1345 addPlayer2State =
true;
1348 addPlayer2State =
true;
1351 if (addPlayer2State) {
1356 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1359 bool addPlayer1State =
false;
1360 if (player1Direction == OptimizationDirection::Minimize) {
1361 bool allPlayer2Successors =
true;
1362 for (uint64_t player2State = player1Groups[player1Predecessor]; player2State < player1Groups[player1Predecessor + 1];
1365 allPlayer2Successors =
false;
1369 if (allPlayer2Successors) {
1370 addPlayer1State =
true;
1373 addPlayer1State =
true;
1376 if (addPlayer1State) {
1378 stack.emplace_back(player1Predecessor);
1393 if (player1Direction == storm::OptimizationDirection::Minimize) {
1395 [[maybe_unused]]
bool foundProb0Successor =
false;
1396 uint64_t player2State;
1397 for (player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1399 foundProb0Successor =
true;
1403 STORM_LOG_ASSERT(foundProb0Successor,
"Expected at least one state 2 successor with probability 0.");
1415 if (player2Direction == storm::OptimizationDirection::Minimize) {
1417 [[maybe_unused]]
bool foundProb0SuccessorDistribution =
false;
1421 bool distributionHasOnlyProb0Successors =
true;
1422 for (
auto const& player1SuccessorEntry : transitionMatrix.
getRow(row)) {
1424 distributionHasOnlyProb0Successors =
false;
1428 if (distributionHasOnlyProb0Successors) {
1429 foundProb0SuccessorDistribution =
true;
1434 STORM_LOG_ASSERT(foundProb0SuccessorDistribution,
"Expected at least one distribution with only successors with probability 0.");
1446template<storm::dd::DdType Type,
typename ValueType>
1460 if (player2Strategy == OptimizationDirection::Minimize) {
1465 player2States |= tmp;
1467 if (player1Strategy == OptimizationDirection::Minimize) {
1474 tmp |= player1States;
1476 if (tmp == player1States) {
1480 player1States = tmp;
1486 std::set<storm::expressions::Variable> variablesToAbstract(model.
getColumnVariables());
1488 player2States = !player2States && transitionMatrix.
existsAbstract(variablesToAbstract);
1497 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1498 if (producePlayer2Strategy) {
1503 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1504 if (producePlayer1Strategy) {
1506 onlyProb0Successors = (player1States && onlyProb0Successors).existsAbstract(model.
getPlayer2Variables());
1509 player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.
getPlayer1Variables());
1515template<
typename ValueType>
1521 boost::optional<storm::storage::BitVector>
const& player1Candidates) {
1524 if (player1Candidates) {
1531 bool produceStrategiesInIteration =
false;
1534 std::vector<uint_fast64_t> stack;
1535 bool maybeStatesDone =
false;
1536 while (!maybeStatesDone || produceStrategiesInIteration) {
1541 stack.insert(stack.end(), psiStates.
begin(), psiStates.
end());
1544 uint_fast64_t currentState;
1545 while (!stack.empty()) {
1546 currentState = stack.back();
1549 for (
auto player2PredecessorEntry : player1BackwardTransitions.
getRow(currentState)) {
1550 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1551 if (!player2Solution.
get(player2PredecessorEntry.getColumn())) {
1552 bool addPlayer2State = player2Direction == storm::OptimizationDirection::Minimize ? true :
false;
1555 for (uint64_t row = validChoice; row < transitionMatrix.
getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1556 bool choiceHasSolutionSuccessor =
false;
1557 bool choiceStaysInMaybeStates =
true;
1558 for (
auto const& entry : transitionMatrix.
getRow(row)) {
1559 if (player1Solution.
get(entry.getColumn())) {
1560 choiceHasSolutionSuccessor =
true;
1563 choiceStaysInMaybeStates =
false;
1568 if (choiceHasSolutionSuccessor && choiceStaysInMaybeStates) {
1569 if (player2Direction == storm::OptimizationDirection::Maximize) {
1571 addPlayer2State =
true;
1574 }
else if (player2Direction == storm::OptimizationDirection::Minimize) {
1575 addPlayer2State =
false;
1580 if (addPlayer2State) {
1581 player2Solution.
set(player2Predecessor);
1582 if (produceStrategiesInIteration) {
1588 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1590 if (!player1Solution.
get(player1Predecessor)) {
1591 bool addPlayer1State = player1Direction == storm::OptimizationDirection::Minimize ? true :
false;
1593 validChoice = player1Groups[player1Predecessor];
1594 for (uint64_t player2Successor = validChoice; player2Successor < player1Groups[player1Predecessor + 1]; ++player2Successor) {
1595 if (player2Solution.
get(player2Successor)) {
1596 if (player1Direction == storm::OptimizationDirection::Maximize) {
1597 validChoice = player2Successor;
1598 addPlayer1State =
true;
1601 }
else if (player1Direction == storm::OptimizationDirection::Minimize) {
1602 addPlayer1State =
false;
1607 if (addPlayer1State) {
1608 player1Solution.
set(player1Predecessor);
1610 if (produceStrategiesInIteration) {
1614 stack.emplace_back(player1Predecessor);
1623 maybeStatesDone =
true;
1628 produceStrategiesInIteration = !produceStrategiesInIteration && strategyPair;
1638template<storm::dd::DdType Type,
typename ValueType>
1646 if (player1Candidates) {
1647 maybePlayer1States &= player1Candidates.get();
1654 bool produceStrategiesInIteration =
false;
1655 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1656 boost::optional<storm::dd::Bdd<Type>> consideredPlayer1States;
1657 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1658 boost::optional<storm::dd::Bdd<Type>> consideredPlayer2States;
1660 bool maybeStatesDone =
false;
1661 while (!maybeStatesDone || produceStrategiesInIteration) {
1662 bool solutionStatesDone =
false;
1665 if (produceStrategiesInIteration) {
1666 if (player1Strategy == storm::OptimizationDirection::Maximize) {
1667 player1StrategyBdd = model.
getManager().getBddZero();
1668 consideredPlayer1States = model.
getManager().getBddZero();
1670 if (player2Strategy == storm::OptimizationDirection::Maximize) {
1671 player2StrategyBdd = model.
getManager().getBddZero();
1672 consideredPlayer2States = model.
getManager().getBddZero();
1678 while (!solutionStatesDone) {
1691 storm::dd::Bdd<Type> valid = phiStates && distributionsStayingInMaybe && distributionsWithProb1Successor;
1695 if (player2Strategy == OptimizationDirection::Minimize) {
1698 if (produceStrategiesInIteration) {
1705 if (produceStrategiesInIteration) {
1706 consideredPlayer2States.get() |= valid;
1710 player2Solution |= valid;
1713 if (player1Strategy == OptimizationDirection::Minimize) {
1716 if (produceStrategiesInIteration) {
1723 if (produceStrategiesInIteration) {
1724 consideredPlayer1States.get() |= valid;
1734 if (valid == player1Solution) {
1735 solutionStatesDone =
true;
1737 player1Solution = valid;
1743 if (player1Solution == maybePlayer1States) {
1744 maybePlayer2States = player2Solution;
1745 maybeStatesDone =
true;
1749 produceStrategiesInIteration = !produceStrategiesInIteration && ((producePlayer1Strategy && player1Strategy == OptimizationDirection::Maximize) ||
1750 (producePlayer2Strategy && player2Strategy == OptimizationDirection::Maximize));
1754 maybePlayer1States = player1Solution;
1762 bool strategiesToCompute = (producePlayer1Strategy && !player1StrategyBdd) || (producePlayer2Strategy && !player2StrategyBdd);
1763 if (strategiesToCompute) {
1765 if (producePlayer2Strategy && !player2StrategyBdd) {
1768 if (producePlayer1Strategy && !player1StrategyBdd) {
1769 relevantStates = (maybePlayer1States && relevantStates).existsAbstract(model.
getPlayer2Variables());
1779 std::vector<uint_fast64_t>& recursionStack,
1782 if (!visitedStates.
get(state)) {
1783 recursionStack.push_back(state);
1784 iteratorRecursionStack.push_back(matrix.
begin(state));
1786 recursionStepForward:
1787 while (!recursionStack.empty()) {
1788 uint_fast64_t currentState = recursionStack.back();
1791 visitedStates.
set(currentState,
true);
1793 recursionStepBackward:
1794 for (; successorIterator != matrix.
end(currentState); ++successorIterator) {
1795 if (!visitedStates.
get(successorIterator->getColumn())) {
1797 recursionStack.push_back(successorIterator->getColumn());
1800 iteratorRecursionStack.push_back(matrix.
begin(successorIterator->getColumn()));
1802 goto recursionStepForward;
1806 topologicalSort.push_back(currentState);
1810 recursionStack.pop_back();
1811 iteratorRecursionStack.pop_back();
1816 if (recursionStack.size() > 0) {
1817 currentState = recursionStack.back();
1818 successorIterator = iteratorRecursionStack.back();
1820 goto recursionStepBackward;
1830 std::vector<uint_fast64_t> stateQueue;
1832 std::vector<uint_fast64_t> result;
1837 for (
auto const& state : firstStates) {
1838 stateQueue.push_back(state);
1839 result[count] = state;
1844 while (!stateQueue.empty()) {
1845 auto state = stateQueue.back();
1846 stateQueue.pop_back();
1847 seenStates.
set(state);
1848 for (
auto const& successorEntry : matrix.
getRowGroup(state)) {
1849 auto succ = successorEntry.geColumn();
1850 if (!seenStates[succ]) {
1851 result[count] = succ;
1853 stateQueue.insert(stateQueue.begin(), succ);
1864 throw storm::exceptions::InvalidArgumentException() <<
"Provided matrix is required to be square.";
1867 uint_fast64_t numberOfStates = matrix.
getRowCount();
1870 std::vector<uint_fast64_t> topologicalSort;
1871 topologicalSort.reserve(numberOfStates);
1874 std::vector<uint_fast64_t> recursionStack;
1876 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator> iteratorRecursionStack;
1877 iteratorRecursionStack.reserve(numberOfStates);
1881 for (
auto const state : firstStates) {
1882 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1884 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
1885 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1888 return topologicalSort;
1894 boost::optional<storm::storage::BitVector>
const& choiceFilter);
1905 boost::optional<storm::storage::BitVector>
const& subsystem);
1909 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1928 boost::optional<storm::storage::BitVector>
const& rowFilter);
1939 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
1943 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
1949 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1952 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1959 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1969 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1972 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
1973 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
1978#ifdef STORM_HAVE_CARL
1984 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
1991#ifdef STORM_HAVE_CARL
1997 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2002 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2010#ifdef STORM_HAVE_CARL
2011template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2027 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2032#ifdef STORM_HAVE_CARL
2036 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2041 boost::optional<storm::storage::BitVector>
const& subsystem);
2052 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2061template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2065template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2073 boost::optional<storm::storage::BitVector>
const& rowFilter);
2085 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2089 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2095 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2098 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2104template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2109template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2114 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2117 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2118 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2125 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2130 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2134template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2139template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2144 std::vector<uint64_t>
const& player1RowGrouping,
2151 std::vector<uint64_t>
const& player1RowGrouping,
2156 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2159 std::vector<uint64_t>
const& firstStates);
2169 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2184 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2215 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2219 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2225 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2228 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2234template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2239template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2244 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2247 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2248 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2255 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2260 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2264template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2269template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2274 std::vector<uint64_t>
const& player1RowGrouping,
2281 std::vector<uint64_t>
const& player1RowGrouping,
2286 boost::optional<storm::storage::BitVector>
const& player1Candidates);
2294 boost::optional<storm::storage::BitVector>
const& choiceFilter);
2299 boost::optional<storm::storage::BitVector>
const& subsystem);
2310 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2319template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2323template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01(
2332 boost::optional<storm::storage::BitVector>
const& rowFilter = boost::none);
2336 bool useStepBound =
false, uint_fast64_t maximalSteps = 0);
2342 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2345 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2351template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2356template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Max(
2361 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2364 bool useStepBound =
false, uint_fast64_t maximalSteps = 0,
2365 boost::optional<storm::storage::BitVector>
const& choiceConstraint = boost::none);
2371 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2379 std::vector<uint_fast64_t>
const& nondeterministicChoiceIndices,
2383template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2388template std::pair<storm::storage::BitVector, storm::storage::BitVector>
performProb01Min(
2393 std::vector<uint64_t>
const& firstStates);
2402 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2501 boost::optional<uint_fast64_t>
const& stepBound = boost::optional<uint_fast64_t>());
2585 bool producePlayer2Strategy);