35template<
typename ValueType>
36std::optional<typename storm::transformer::EndComponentEliminator<ValueType>::EndComponentEliminatorReturnType>
eliminateEndComponents(
37 storm::storage::BitVector const& possibleEcStates,
bool addRowAtRepresentativeState, std::optional<uint64_t>
const representativeRowEntry,
47 matrix, ecs, allRowGroups, addRowAtRepresentativeState ? allRowGroups : ~allRowGroups, representativeRowEntry.has_value());
50 matrix = std::move(ecElimResult.matrix);
51 if (addRowAtRepresentativeState && representativeRowEntry) {
52 auto const columnIndex = ecElimResult.oldToNewStateMapping[*representativeRowEntry];
53 for (
auto representativeRowIndex : ecElimResult.sinkRows) {
54 auto row = matrix.
getRow(representativeRowIndex);
55 STORM_LOG_ASSERT(row.getNumberOfEntries() == 1,
"unexpected number of entries in representative row.");
56 auto& entry = *row.begin();
57 entry.setColumn(columnIndex);
62 auto updateRowValue = [&ecElimResult](std::vector<ValueType>& rowValues) {
63 std::vector<ValueType> newRowValues;
64 newRowValues.reserve(ecElimResult.newToOldRowMapping.size());
65 for (
auto oldRowIndex : ecElimResult.newToOldRowMapping) {
66 newRowValues.push_back(rowValues[oldRowIndex]);
68 rowValues = std::move(newRowValues);
70 std::all_of(ecElimResult.sinkRows.begin(), ecElimResult.sinkRows.end(), [&rowValues](
auto i) { return storm::utility::isZero(rowValues[i]); }),
71 "Sink rows are expected to have zero value");
73 updateRowValue(rowValues1);
75 updateRowValue(*rowValues2);
79 storm::storage::BitVector newRowsWithSum1(ecElimResult.newToOldRowMapping.size(),
true);
80 uint64_t newRowIndex = 0;
81 for (
auto oldRowIndex : ecElimResult.newToOldRowMapping) {
82 if ((addRowAtRepresentativeState && !representativeRowEntry.has_value() && ecElimResult.sinkRows.get(newRowIndex)) || !rowsWithSum1.
get(oldRowIndex)) {
83 newRowsWithSum1.set(newRowIndex,
false);
87 rowsWithSum1 = std::move(newRowsWithSum1);
92template<
typename ValueType,
typename SolutionType = ValueType>
96 std::optional<std::vector<uint64_t>>& schedulerOutput) {
103 relevantValues.
set(initialState,
true);
108 return {goal.
direction(), relevantValues};
115 solver->setRequirementsChecked();
116 solver->setHasUniqueSolution(
true);
117 solver->setHasNoEndComponents(
true);
120 solver->setTrackScheduler(schedulerOutput.has_value());
123 solver->solveEquations(env, x, rowValues);
125 if (schedulerOutput) {
126 *schedulerOutput = std::move(
solver->getSchedulerChoices());
129 return x[initialState];
136template<
typename ValueType>
141 std::unique_ptr<storm::storage::Scheduler<ValueType>> scheduler;
142 if (computeScheduler) {
143 scheduler = std::make_unique<storm::storage::Scheduler<ValueType>>(transitionMatrix.
getRowGroupCount());
146 auto reachabilityEnv = env;
150 if (initialStates.
empty()) {
154 auto const subTargets = targetStates % reachableStates;
156 if (subTargets.empty()) {
159 auto const subInits = initialStates % reachableStates;
160 auto const submatrix = transitionMatrix.
getSubmatrix(
true, reachableStates, reachableStates);
165 auto origInitIt = initialStates.
begin();
166 for (
auto subInit : subInits) {
167 auto const& val = subResult.values[subInit];
169 nonZeroResults.emplace(*origInitIt, val);
174 if (computeScheduler) {
175 auto submatrixIdx = 0;
176 for (
auto state : reachableStates) {
177 scheduler->setChoice(subResult.scheduler->getChoice(submatrixIdx), state);
185template<
typename ValueType>
204 std::unique_ptr<storm::storage::Scheduler<ValueType>>
206 std::unique_ptr<storm::storage::Scheduler<ValueType>>
223template<
typename ValueType>
229 auto extendedConditionStates =
232 std::map<uint64_t, ValueType> nonZeroTargetStateValues;
233 auto const extendedTargetStates =
235 auto const targetAndNotCondFailStates = extendedTargetStates & ~(extendedConditionStates | universalObservationFailureStates);
239 env, nonZeroTargetStateValues, dir, transitionMatrix, extendedConditionStates, allStates, extendedTargetStates, computeScheduler);
241 env, nonZeroTargetStateValues, dir, transitionMatrix, targetAndNotCondFailStates, allStates, extendedConditionStates, computeScheduler);
244 auto terminalStatesThatReachCondition = extendedConditionStates;
245 for (
auto state : targetAndNotCondFailStates) {
246 if (nonZeroTargetStateValues.contains(state)) {
247 terminalStatesThatReachCondition.set(state,
true);
252 auto terminalStates = extendedConditionStates | extendedTargetStates | universalObservationFailureStates;
261 auto nonTerminalStates = ~terminalStates;
264 backwardTransitions, nonTerminalStates, terminalStatesThatReachCondition);
270 .terminalStates = std::move(terminalStates),
271 .conditionStates = std::move(extendedConditionStates),
272 .targetStates = std::move(extendedTargetStates),
273 .universalObservationFailureStates = std::move(universalObservationFailureStates),
274 .existentialObservationFailureStates = std::move(existentialObservationFailureStates),
275 .nonZeroTargetStateValues = std::move(nonZeroTargetStateValues),
276 .schedulerChoicesForReachingTargetStates = std::move(schedulerChoicesForReachingTargetStates),
277 .schedulerChoicesForReachingConditionStates = std::move(schedulerChoicesForReachingConditionStates)};
281template<
typename ValueType,
typename SolutionType = ValueType>
285 std::vector<uint64_t>
const& stateToFinalEc,
NormalFormData<ValueType> const& normalForm, uint64_t initialComponentIndex,
287 uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit) {
293 for (
auto state : maybeStates) {
294 auto ecIndex = stateToFinalEc[state];
295 if (ecIndex == initialComponentIndex) {
296 initialComponentStates.
set(state,
true);
298 }
else if (ecIndex == std::numeric_limits<uint64_t>::max()) {
302 bool isEcStayChoice =
true;
303 for (
auto const& entry : transitionMatrix.
getRow(choiceIndex)) {
304 auto targetState = entry.getColumn();
305 if (stateToFinalEc[targetState] != ecIndex) {
306 isEcStayChoice =
false;
310 if (isEcStayChoice) {
311 ecStayChoices.
set(choiceIndex,
true);
317 auto const maybeNonICStatesWithoutChoice = maybeStatesWithoutChoice & ~initialComponentStates;
319 scheduler, ecStayChoices);
326 for (uint64_t state = 0; state < rowGroupCount; ++state) {
328 auto choiceIndex = scheduler.
getChoice(state).getDeterministicChoice();
329 allowedChoices.
set(rowGroups[state] + choiceIndex,
true);
330 }
else if (initialComponentStates.
get(state) || condOrTargetStates.get(state)) {
332 allowedChoices.
set(choiceIndex,
true);
339 std::stack<uint64_t> toProcess;
340 for (
auto state : condOrTargetStates) {
341 toProcess.push(state);
343 auto visitedStates = condOrTargetStates;
344 while (!toProcess.empty()) {
345 auto currentState = toProcess.top();
347 for (
auto const& entry : backwardTransitions.
getRow(currentState)) {
348 uint64_t
const predecessorState = entry.getColumn();
349 for (uint64_t
const predecessorChoice : transitionMatrix.
getRowGroupIndices(predecessorState)) {
350 if (!allowedChoices.
get(predecessorChoice) || choicesThatCanVisitCondOrTargetStates.
get(predecessorChoice)) {
353 if (
auto const r = transitionMatrix.
getRow(predecessorChoice);
354 std::none_of(r.begin(), r.end(), [¤tState](
auto const& e) { return e.getColumn() == currentState; })) {
357 choicesThatCanVisitCondOrTargetStates.
set(predecessorChoice,
true);
358 if (!visitedStates.get(predecessorState)) {
359 visitedStates.set(predecessorState,
true);
360 toProcess.push(predecessorState);
367 storm::storage::BitVector disallowedInitialComponentExits = initialComponentExitRows & choicesThatCanVisitCondOrTargetStates;
368 disallowedInitialComponentExits.
set(chosenInitialComponentExit,
false);
372 bool progress =
false;
373 for (
auto state : initialComponentExitStates) {
376 bool const allChoicesAreDisallowed = disallowedInitialComponentExits.
getNextUnsetIndex(groupStart) >= groupEnd;
377 if (allChoicesAreDisallowed) {
378 goodInitialComponentStates.
set(state,
false);
384 for (
auto state : goodInitialComponentStates) {
385 bool allChoicesAreDisallowed =
true;
387 auto row = transitionMatrix.
getRow(choiceIndex);
388 bool const hasBadSuccessor = std::any_of(
389 row.begin(), row.end(), [&goodInitialComponentStates](
auto const& entry) { return !goodInitialComponentStates.get(entry.getColumn()); });
390 if (hasBadSuccessor) {
391 choicesAllowedForInitialComponent.
set(choiceIndex,
false);
393 allChoicesAreDisallowed =
false;
396 if (allChoicesAreDisallowed) {
397 goodInitialComponentStates.set(state,
false);
404 exitStateBitvector.
set(chosenInitialComponentExitState,
true);
407 choicesAllowedForInitialComponent);
411 for (
auto state : initialComponentStates) {
414 if (choicesAllowedForInitialComponent.
get(choiceIndex)) {
415 scheduler.
setChoice(choiceIndex - rowGroups[state], state);
423template<
typename ValueType,
typename SolutionType = ValueType>
435 std::unique_ptr<storm::storage::Scheduler<SolutionType>>
scheduler;
442template<
typename ValueType,
typename SolutionType = ValueType>
450 auto const numMaybeStates = maybeStates.getNumberOfSetBits();
455 std::vector<ValueType> rowValues;
457 rowValues.reserve(numMaybeChoices);
458 uint64_t currentRow = 0;
459 for (
auto state : maybeStates) {
467 bool rowSumIsLess1 =
false;
468 for (
auto const& entry : transitionMatrix.
getRow(origRowIndex)) {
470 ValueType
const targetValue = normalForm.
getTargetValue(entry.getColumn());
471 targetProbability += targetValue * entry.getValue();
473 rowSumIsLess1 =
true;
476 rowSumIsLess1 =
true;
478 restartProbability += entry.getValue() * normalForm.
failProbability(entry.getColumn());
483 rowsWithSum1.
set(currentRow,
false);
485 rowValues.push_back(targetProbability);
487 for (
auto const& entry : transitionMatrix.
getRow(origRowIndex)) {
490 if (addRestartTransition && entry.getColumn() > initialState) {
491 matrixBuilder.
addNextValue(currentRow, originalToReducedStateIndexMap[initialState], restartProbability);
492 addRestartTransition =
false;
494 if (maybeStates.get(entry.getColumn())) {
495 matrixBuilder.
addNextValue(currentRow, originalToReducedStateIndexMap[entry.getColumn()], entry.getValue());
499 if (addRestartTransition) {
500 matrixBuilder.
addNextValue(currentRow, originalToReducedStateIndexMap[initialState], restartProbability);
505 STORM_LOG_ASSERT(currentRow == numMaybeChoices,
"Unexpected number of constructed rows.");
507 auto matrix = matrixBuilder.
build();
508 auto initStateInReduced = originalToReducedStateIndexMap[initialState];
514 selectedStatesInReduced.
set(initStateInReduced,
false);
515 auto ecElimResult1 =
eliminateEndComponents(selectedStatesInReduced,
true, initStateInReduced, matrix, rowsWithSum1, rowValues);
516 selectedStatesInReduced.
set(initStateInReduced,
true);
519 initStateInReduced = ecElimResult1->oldToNewStateMapping[initStateInReduced];
523 auto ecElimResult2 =
eliminateEndComponents(selectedStatesInReduced,
false, std::nullopt, matrix, rowsWithSum1, rowValues);
525 initStateInReduced = ecElimResult2->oldToNewStateMapping[initStateInReduced];
532 std::optional<std::vector<uint64_t>> reducedSchedulerChoices;
533 if (computeScheduler) {
534 reducedSchedulerChoices.emplace();
536 auto resultValue =
solveMinMaxEquationSystem(env, matrix, rowValues, rowsWithSum1, goal, initStateInReduced, reducedSchedulerChoices);
541 if (!computeScheduler) {
546 "Requested scheduler, but it was not computed or has invalid size.");
548 std::vector<uint64_t> originalRowToStateIndexMap;
550 originalRowToStateIndexMap.reserve(transitionMatrix.
getRowCount());
551 for (uint64_t originalStateIndex = 0; originalStateIndex < transitionMatrix.
getRowGroupCount(); ++originalStateIndex) {
552 originalRowToStateIndexMap.insert(originalRowToStateIndexMap.end(), transitionMatrix.
getRowGroupSize(originalStateIndex), originalStateIndex);
554 std::vector<uint64_t> reducedToOriginalRowIndexMap;
555 reducedToOriginalRowIndexMap.reserve(numMaybeChoices);
556 for (uint64_t
const originalMaybeState : maybeStates) {
557 for (
auto const originalRowIndex : transitionMatrix.
getRowGroupIndices(originalMaybeState)) {
558 reducedToOriginalRowIndexMap.push_back(originalRowIndex);
561 if (ecElimResult1.has_value() || ecElimResult2.has_value()) {
563 std::vector<uint64_t> tmpReducedToOriginalRowIndexMap;
564 tmpReducedToOriginalRowIndexMap.reserve(matrix.
getRowCount());
565 for (uint64_t reducedRow = 0; reducedRow < matrix.
getRowCount(); ++reducedRow) {
566 uint64_t intermediateRow = reducedRow;
567 if (ecElimResult2.has_value()) {
568 intermediateRow = ecElimResult2->newToOldRowMapping.at(intermediateRow);
570 if (ecElimResult1.has_value()) {
571 intermediateRow = ecElimResult1->newToOldRowMapping.at(intermediateRow);
573 tmpReducedToOriginalRowIndexMap.push_back(reducedToOriginalRowIndexMap[intermediateRow]);
575 reducedToOriginalRowIndexMap = std::move(tmpReducedToOriginalRowIndexMap);
577 for (uint64_t originalStateIndex = 0; originalStateIndex < transitionMatrix.
getRowGroupCount(); ++originalStateIndex) {
578 auto& reducedIndex = originalToReducedStateIndexMap[originalStateIndex];
579 if (maybeStates.get(originalStateIndex)) {
580 if (ecElimResult1.has_value()) {
581 reducedIndex = ecElimResult1->oldToNewStateMapping.at(reducedIndex);
583 if (ecElimResult2.has_value()) {
584 reducedIndex = ecElimResult2->oldToNewStateMapping.at(reducedIndex);
587 reducedIndex = std::numeric_limits<uint64_t>::max();
595 uint64_t
const originalRowIndex = reducedToOriginalRowIndexMap[reducedRowIndex];
596 uint64_t
const originalState = originalRowToStateIndexMap[originalRowIndex];
598 initialComponentExitRows.
set(originalRowIndex,
true);
599 initialComponentExitStates.
set(originalState,
true);
604 uint64_t chosenInitialComponentExitState = std::numeric_limits<uint64_t>::max();
605 uint64_t chosenInitialComponentExit = std::numeric_limits<uint64_t>::max();
606 auto scheduler = std::make_unique<storm::storage::Scheduler<SolutionType>>(transitionMatrix.
getRowGroupCount());
608 uint64_t reducedState = 0;
609 for (
auto const& choice : reducedSchedulerChoices.value()) {
611 uint64_t
const originalRowIndex = reducedToOriginalRowIndexMap[reducedRowIndex];
612 uint64_t
const originalState = originalRowToStateIndexMap[originalRowIndex];
613 uint64_t
const originalChoice = originalRowIndex - transitionMatrix.
getRowGroupIndices()[originalState];
614 scheduler->setChoice(originalChoice, originalState);
615 maybeStatesWithChoice.
set(originalState,
true);
616 if (reducedState == initStateInReduced) {
617 chosenInitialComponentExitState = originalState;
618 chosenInitialComponentExit = originalRowIndex;
623 auto const maybeStatesWithoutChoice = maybeStates & ~maybeStatesWithChoice;
625 originalToReducedStateIndexMap, normalForm, initStateInReduced, initialComponentExitStates, initialComponentExitRows,
626 chosenInitialComponentExitState, chosenInitialComponentExit);
628 finalResult.scheduler = std::move(scheduler);
638template<
typename ValueType,
typename SolutionType = ValueType>
655 subMatrixRowGroups.set(initialState,
false);
656 std::vector<uint64_t> dfsStack = {initialState};
657 while (!dfsStack.empty()) {
658 auto const state = dfsStack.back();
661 auto const row = transitionMatrix.
getRow(rowIndex);
662 if (std::all_of(row.begin(), row.end(),
663 [&normalForm](
auto const& entry) { return normalForm.existentialObservationFailureStates.get(entry.getColumn()); })) {
664 for (
auto const& entry : row) {
665 auto const& successor = entry.getColumn();
666 if (subMatrixRowGroups.get(successor)) {
667 subMatrixRowGroups.set(successor,
false);
668 dfsStack.push_back(successor);
672 initialComponentExitRows.set(rowIndex,
true);
673 initialComponentExitStates.set(state,
true);
677 auto const numSubmatrixRows = transitionMatrix.
getNumRowsInRowGroups(subMatrixRowGroups) + initialComponentExitRows.getNumberOfSetBits();
678 subMatrixRowGroups.set(initialState,
true);
679 auto const numSubmatrixRowGroups = subMatrixRowGroups.getNumberOfSetBits();
681 if (computeScheduler) {
682 reducedToOriginalRowIndexMap.reserve(numSubmatrixRows);
686 originalToReducedStateIndexMap = subMatrixRowGroups.getNumberOfSetBitsBeforeIndices();
687 initialStateInSubmatrix = originalToReducedStateIndexMap[initialState];
688 auto const eliminatedInitialComponentStates = normalForm.
maybeStates & ~subMatrixRowGroups;
691 for (
auto state : eliminatedInitialComponentStates) {
692 originalToReducedStateIndexMap[state] = initialStateInSubmatrix;
698 targetRowValues.reserve(numSubmatrixRows);
699 conditionRowValues.reserve(numSubmatrixRows);
700 uint64_t currentRow = 0;
701 for (
auto state : subMatrixRowGroups) {
705 auto processRow = [&](uint64_t origRowIndex) {
709 bool rowSumIsLess1 =
false;
710 for (
auto const& entry : transitionMatrix.
getRow(origRowIndex)) {
713 rowSumIsLess1 =
true;
714 ValueType
const scaledTargetValue = normalForm.
getTargetValue(entry.getColumn()) * entry.getValue();
715 targetProbability += scaledTargetValue;
717 conditionProbability += entry.getValue();
719 conditionProbability += scaledTargetValue;
721 }
else if (eliminatedInitialComponentStates.get(entry.getColumn())) {
722 rowSumIsLess1 =
true;
724 auto const columnIndex = originalToReducedStateIndexMap[entry.getColumn()];
725 matrixBuilder.
addNextValue(currentRow, columnIndex, entry.getValue());
729 rowsWithSum1.set(currentRow,
false);
731 targetRowValues.push_back(targetProbability);
732 conditionRowValues.push_back(conditionProbability);
736 if (state == initialState) {
737 for (
auto origRowIndex : initialComponentExitRows) {
738 processRow(origRowIndex);
739 reducedToOriginalRowIndexMap.push_back(origRowIndex);
743 processRow(origRowIndex);
744 reducedToOriginalRowIndexMap.push_back(origRowIndex);
748 submatrix = matrixBuilder.
build();
753 allExceptInit.
set(initialStateInSubmatrix,
false);
756 initialStateInSubmatrix = ecResult->oldToNewStateMapping[initialStateInSubmatrix];
759 STORM_LOG_INFO(
"Processed model has " << submatrix.getRowGroupCount() <<
" states and " << submatrix.getRowGroupCount() <<
" choices and "
760 << submatrix.getEntryCount() <<
" transitions. Matrix is " << (isAcyclic ?
"acyclic." :
"cyclic."));
762 if (computeScheduler) {
764 STORM_LOG_ASSERT(reducedToOriginalRowIndexMap.size() == numSubmatrixRows,
"Unexpected size of reducedToOriginalRowIndexMap.");
765 if (ecResult.has_value()) {
767 std::vector<uint64_t> tmpReducedToOriginalRowIndexMap;
768 tmpReducedToOriginalRowIndexMap.reserve(submatrix.getRowCount());
769 for (uint64_t reducedRow = 0; reducedRow < submatrix.getRowCount(); ++reducedRow) {
770 uint64_t intermediateRow = ecResult->newToOldRowMapping.at(reducedRow);
771 tmpReducedToOriginalRowIndexMap.push_back(reducedToOriginalRowIndexMap[intermediateRow]);
773 reducedToOriginalRowIndexMap = std::move(tmpReducedToOriginalRowIndexMap);
775 for (uint64_t originalStateIndex = 0; originalStateIndex < transitionMatrix.
getRowGroupCount(); ++originalStateIndex) {
776 auto& reducedIndex = originalToReducedStateIndexMap[originalStateIndex];
777 if (subMatrixRowGroups.get(originalStateIndex)) {
778 reducedIndex = ecResult->oldToNewStateMapping.at(reducedIndex);
780 reducedIndex = std::numeric_limits<uint64_t>::max();
786 originalToReducedStateIndexMap.clear();
787 reducedToOriginalRowIndexMap.clear();
789 initialComponentExitRows.clear();
790 initialComponentExitStates.clear();
795 ValueType
const& conditionWeight,
storm::OptionalRef<std::vector<uint64_t>> schedulerOutput = {}) {
798 auto solverEnv = env;
800 STORM_LOG_INFO(
"Using acyclic min-max solver for weighted reachability computation.");
801 solverEnv.solver().minMax().setMethod(storm::solver::MinMaxMethod::Acyclic);
804 cachedSolver->setCachingEnabled(
true);
805 cachedSolver->setRequirementsChecked();
806 cachedSolver->setHasUniqueSolution(
true);
807 cachedSolver->setHasNoEndComponents(
true);
811 cachedSolver->setTrackScheduler(schedulerOutput.has_value());
812 cachedSolver->setOptimizationDirection(dir);
815 createScaledVector(cachedB, targetWeight, targetRowValues, conditionWeight, conditionRowValues);
820 cachedSolver->solveEquations(env, cachedX, cachedB);
821 if (schedulerOutput) {
822 *schedulerOutput = cachedSolver->getSchedulerChoices();
824 return cachedX[initialStateInSubmatrix];
828 return initialStateInSubmatrix;
832 std::vector<SolutionType>& conditionResults) {
833 if (scheduler.empty()) {
834 scheduler.resize(submatrix.getRowGroupCount(), 0);
836 if (targetResults.empty()) {
839 if (conditionResults.empty()) {
842 auto solver = getScheduledSolver(env, scheduler);
844 cachedB.resize(submatrix.getRowGroupCount());
846 solver->solveEquations(env, targetResults, cachedB);
849 solver->solveEquations(env, conditionResults, cachedB);
853 STORM_LOG_ASSERT(scheduler.size() == submatrix.getRowGroupCount(),
"Scheduler size does not match number of row groups");
854 auto solver = getScheduledSolver(env, scheduler);
855 cachedB.resize(submatrix.getRowGroupCount());
856 cachedX.resize(submatrix.getRowGroupCount());
859 solver->solveEquations(env, cachedX, cachedB);
860 SolutionType targetValue = cachedX[initialStateInSubmatrix];
863 solver->solveEquations(env, cachedX, cachedB);
864 SolutionType conditionValue = cachedX[initialStateInSubmatrix];
866 return targetValue / conditionValue;
869 template<OptimizationDirection Dir>
870 bool improveScheduler(std::vector<uint64_t>& scheduler, ValueType
const& lambda, std::vector<SolutionType>
const& targetResults,
871 std::vector<SolutionType>
const& conditionResults) {
872 bool improved =
false;
873 for (uint64_t rowGroupIndex = 0; rowGroupIndex < scheduler.size(); ++rowGroupIndex) {
875 uint64_t optimalRowIndex{0};
876 ValueType scheduledValue;
877 for (
auto rowIndex : submatrix.getRowGroupIndices(rowGroupIndex)) {
878 ValueType rowValue = targetRowValues[rowIndex] - lambda * conditionRowValues[rowIndex];
879 for (
auto const& entry : submatrix.getRow(rowIndex)) {
880 rowValue += entry.getValue() * (targetResults[entry.getColumn()] - lambda * conditionResults[entry.getColumn()]);
882 if (rowIndex == scheduler[rowGroupIndex] + submatrix.getRowGroupIndices()[rowGroupIndex]) {
883 scheduledValue = rowValue;
885 if (groupValue &= rowValue) {
886 optimalRowIndex = rowIndex;
889 if (scheduledValue != *groupValue) {
890 scheduler[rowGroupIndex] = optimalRowIndex - submatrix.getRowGroupIndices()[rowGroupIndex];
900 std::vector<uint64_t> originalRowToStateIndexMap;
902 originalRowToStateIndexMap.reserve(originalTransitionMatrix.
getRowCount());
903 for (uint64_t originalStateIndex = 0; originalStateIndex < originalTransitionMatrix.
getRowGroupCount(); ++originalStateIndex) {
904 originalRowToStateIndexMap.insert(originalRowToStateIndexMap.end(), originalTransitionMatrix.
getRowGroupSize(originalStateIndex),
909 uint64_t chosenInitialComponentExitState = std::numeric_limits<uint64_t>::max();
910 uint64_t chosenInitialComponentExit = std::numeric_limits<uint64_t>::max();
911 auto scheduler = std::make_unique<storm::storage::Scheduler<SolutionType>>(originalTransitionMatrix.
getRowGroupCount());
913 uint64_t reducedState = 0;
914 for (
auto const& choice : schedulerForReducedModel) {
915 uint64_t
const reducedRowIndex = submatrix.getRowGroupIndices()[reducedState] + choice;
916 uint64_t
const originalRowIndex = reducedToOriginalRowIndexMap[reducedRowIndex];
917 uint64_t
const originalState = originalRowToStateIndexMap[originalRowIndex];
918 uint64_t
const originalChoice = originalRowIndex - originalTransitionMatrix.
getRowGroupIndices()[originalState];
919 scheduler->setChoice(originalChoice, originalState);
920 maybeStatesWithChoice.
set(originalState,
true);
921 if (reducedState == initialStateInSubmatrix) {
922 chosenInitialComponentExitState = originalState;
923 chosenInitialComponentExit = originalRowIndex;
928 auto const maybeStatesWithoutChoice = normalForm.
maybeStates & ~maybeStatesWithChoice;
930 maybeStatesWithChoice, originalToReducedStateIndexMap, normalForm, initialStateInSubmatrix, initialComponentExitStates,
931 initialComponentExitRows, chosenInitialComponentExitState, chosenInitialComponentExit);
936 void createScaledVector(std::vector<ValueType>& out, ValueType
const& w1, std::vector<ValueType>
const& v1, ValueType
const& w2,
937 std::vector<ValueType>
const& v2)
const {
939 out.resize(v1.size());
943 auto getScheduledSolver(
storm::Environment const& env, std::vector<uint64_t>
const& scheduler)
const {
947 auto scheduledMatrix = submatrix.selectRowsFromRowGroups(scheduler, convertToEquationSystem);
948 if (convertToEquationSystem) {
949 scheduledMatrix.convertToEquationSystem();
951 auto solver = factory.
create(env, std::move(scheduledMatrix));
953 solver->setCachingEnabled(
true);
957 storm::storage::SparseMatrix<ValueType> submatrix;
958 storm::storage::BitVector rowsWithSum1;
959 std::vector<ValueType> targetRowValues;
960 std::vector<ValueType> conditionRowValues;
961 uint64_t initialStateInSubmatrix;
963 std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType, SolutionType>> cachedSolver;
964 std::vector<ValueType> cachedX;
965 std::vector<ValueType> cachedB;
968 std::vector<uint64_t> originalToReducedStateIndexMap;
969 std::vector<uint64_t> reducedToOriginalRowIndexMap;
970 std::optional<typename storm::transformer::EndComponentEliminator<ValueType>::EndComponentEliminatorReturnType> ecResult;
971 storm::storage::BitVector initialComponentExitRows;
972 storm::storage::BitVector initialComponentExitStates;
975template<
typename ValueType,
typename SolutionType = ValueType>
983 "Bisection method does not adequately handle propagation of errors. Result is not necessarily sound.");
992 if (useAdvancedBounds) {
1001 std::optional<std::vector<uint64_t>> lowerScheduler, upperScheduler, middleScheduler;
1003 if (usePolicyTracking) {
1004 lowerScheduler.emplace();
1005 upperScheduler.emplace();
1006 middleScheduler.emplace();
1007 middleSchedulerRef.
reset(*middleScheduler);
1011 [[maybe_unused]] SolutionType rationalCandiate = middle;
1012 [[maybe_unused]] uint64_t rationalCandidateCount = 0;
1013 std::set<SolutionType> checkedMiddleValues;
1014 bool terminatedThroughPolicyTracking =
false;
1015 for (uint64_t iterationCount = 1;
true; ++iterationCount) {
1018 checkedMiddleValues.insert(middle);
1020 if (!useAdvancedBounds) {
1022 if (lowerBound &= middle) {
1023 lowerScheduler.swap(middleScheduler);
1027 if (upperBound &= middle) {
1028 upperScheduler.swap(middleScheduler);
1031 middle = (*lowerBound + *upperBound) / 2;
1034 if (lowerBound &= middle + (middleValue / pMax)) {
1035 lowerScheduler.swap(middleScheduler);
1037 upperBound &= middle + (middleValue / pMin);
1040 lowerBound &= middle + (middleValue / pMin);
1041 if (upperBound &= middle + (middleValue / pMax)) {
1042 upperScheduler.swap(middleScheduler);
1052 if (*lowerBound > *upperBound) {
1053 std::swap(*lowerBound, *upperBound);
1056 STORM_LOG_ASSERT(middle >= *lowerBound && middle <= *upperBound,
"Bisection method bounds are inconsistent.");
1060 SolutionType
const boundDiff = *upperBound - *lowerBound;
1061 STORM_LOG_TRACE(
"Iteration #" << iterationCount <<
":\n\t Lower bound: " << *lowerBound <<
",\n\t Upper bound: " << *upperBound
1062 <<
",\n\t Difference: " << boundDiff <<
",\n\t Middle val: " << middleValue
1063 <<
",\n\t Difference bound: " << (relative ? (precision * *lowerBound) : precision) <<
".");
1069 if (boundDiff <= (relative ? (precision * *lowerBound) : precision)) {
1070 STORM_LOG_INFO(
"Bisection method converged after " << iterationCount <<
" iterations. Difference is "
1071 << std::setprecision(std::numeric_limits<double>::digits10)
1074 }
else if (usePolicyTracking && lowerScheduler && upperScheduler && (*lowerScheduler == *upperScheduler)) {
1075 STORM_LOG_INFO(
"Bisection method converged after " << iterationCount <<
" iterations due to identical schedulers for lower and upper bound.");
1077 lowerBound &= result;
1078 upperBound &= result;
1079 terminatedThroughPolicyTracking =
true;
1084 STORM_LOG_INFO(
"Bisection method determined result after " << iterationCount <<
" iterations. Found bounds are ["
1091 STORM_LOG_WARN(
"Precision of non-exact type exceeded: Bisection method has not terminated, but the difference between upper and lower bound is "
1092 << boundDiff <<
".");
1096 STORM_LOG_WARN(
"Bisection solver aborted after " << iterationCount <<
"iterations. Bound difference is "
1108 if (rationalCandidateCount >= 4 && rationalCandiate >= *lowerBound && rationalCandiate <= *upperBound &&
1109 !checkedMiddleValues.contains(rationalCandiate)) {
1110 middle = rationalCandiate;
1111 rationalCandidateCount = 0;
1114 bool const includeLower = !checkedMiddleValues.contains(*lowerBound);
1115 bool const includeUpper = !checkedMiddleValues.contains(*upperBound);
1117 if (rationalCandiate == newRationalCandiate) {
1118 ++rationalCandidateCount;
1120 rationalCandiate = newRationalCandiate;
1121 rationalCandidateCount = 0;
1124 SolutionType delta =
1130 if (iterationCount == 8) {
1142 if (!computeScheduler) {
1146 std::vector<uint64_t> reducedSchedulerChoices;
1147 if (terminatedThroughPolicyTracking) {
1149 reducedSchedulerChoices = std::move(*lowerScheduler);
1158template<
typename ValueType,
typename SolutionType = ValueType>
1166 "Unhandled Bisection algorithm " << alg <<
".");
1169 return computeViaBisection(env, useAdvancedBounds, usePolicyTracking, initialState, goal, computeScheduler, transitionMatrix, backwardTransitions,
1173template<
typename ValueType,
typename SolutionType = ValueType>
1183 std::optional<std::vector<uint64_t>> scheduler;
1185 if (computeScheduler) {
1186 scheduler.emplace();
1187 schedulerRef.
reset(*scheduler);
1191 SolutionType outputProbability;
1200 outputProbability = threshold;
1204 if (computeScheduler) {
1211template<
typename ValueType,
typename SolutionType = ValueType>
1218 std::vector<uint64_t> scheduler;
1219 std::vector<SolutionType> targetResults, conditionResults;
1220 for (uint64_t iterationCount = 1;
true; ++iterationCount) {
1224 "Potential numerical issues: the probability to reach the target is greater than the probability to reach the condition. Difference is "
1231 bool schedulerChanged{
false};
1233 schedulerChanged = wrh.template improveScheduler<storm::OptimizationDirection::Minimize>(scheduler, lambda, targetResults, conditionResults);
1235 schedulerChanged = wrh.template improveScheduler<storm::OptimizationDirection::Maximize>(scheduler, lambda, targetResults, conditionResults);
1237 if (!schedulerChanged) {
1238 STORM_LOG_INFO(
"Policy iteration for conditional probabilities converged after " << iterationCount <<
" iterations.");
1242 STORM_LOG_WARN(
"Policy iteration for conditional probabilities converged aborted after " << iterationCount <<
"iterations.");
1248template<
typename ValueType,
typename SolutionType = ValueType>
1256 "Trying to compute undefined conditional probability: the condition has probability 0 under all policies.");
1267 return std::nullopt;
1272template<
typename ValueType,
typename SolutionType>
1279 STORM_LOG_INFO(
"Setting the conditional precision to 0 since the value type is exact and the precision was not explicitly set by the user.");
1284 auto normalFormConstructionEnv = env;
1285 auto analysisEnv = env;
1290 normalFormConstructionEnv.modelchecker().conditional().setPrecision(precision * normalFormPrecisionFactor,
false);
1293 normalFormConstructionEnv.modelchecker().conditional().setPrecision(precision,
false);
1294 analysisEnv.modelchecker().conditional().setPrecision(precision,
false);
1299 STORM_LOG_THROW(goal.hasRelevantValues(), storm::exceptions::NotSupportedException,
1300 "No initial state given. Conditional probabilities can only be computed for models with a single initial state.");
1301 STORM_LOG_THROW(goal.relevantValues().hasUniqueSetBit(), storm::exceptions::NotSupportedException,
1302 "Only one initial state is supported for conditional probabilities");
1305 auto normalFormData =
internal::obtainNormalForm(normalFormConstructionEnv, goal.direction(), produceSchedulers, transitionMatrix, backwardTransitions,
1306 goal.relevantValues(), targetStates, conditionStates);
1308 auto const initialState = *goal.relevantValues().begin();
1310 std::unique_ptr<storm::storage::Scheduler<SolutionType>> scheduler =
nullptr;
1312 initialStateValue = *trivialValue;
1316 initialStateBitVector.set(initialState,
true);
1323 for (uint64_t state = 0; state < transitionMatrix.
getRowGroupCount(); ++state) {
1324 scheduler->setChoice(conditionReachResult.scheduler->getChoice(stateId), state);
1331 STORM_LOG_DEBUG(
"Initial state has trivial value " << initialStateValue);
1333 STORM_LOG_ASSERT(normalFormData.maybeStates.get(initialState),
"Initial state must be a maybe state if it is not a terminal state");
1334 auto alg = analysisEnv.modelchecker().conditional().getAlgorithm();
1339 STORM_LOG_INFO(
"Analyzing normal form with " << normalFormData.maybeStates.getNumberOfSetBits() <<
" maybe states using algorithm '" << alg <<
".");
1343 auto restartEnv = analysisEnv;
1344 restartEnv.solver().minMax().setPrecision(analysisEnv.modelchecker().conditional().getPrecision());
1345 restartEnv.solver().minMax().setRelativeTerminationCriterion(analysisEnv.modelchecker().conditional().isRelativePrecision());
1355 if (goal.isBounded()) {
1356 result =
internal::decideThreshold(analysisEnv, initialState, goal.direction(), goal.thresholdValue(), produceSchedulers, transitionMatrix,
1357 backwardTransitions, normalFormData);
1369 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"Unknown conditional probability algorithm: " << alg);
1373 scheduler = std::move(result.
scheduler);
1378 if (produceSchedulers && scheduler) {
1380 targetStates, *scheduler);
1382 conditionStates, *scheduler);
1385 for (uint64_t state = 0; state < transitionMatrix.
getRowGroupCount(); ++state) {
1386 if (!scheduler->isChoiceSelected(state)) {
1388 scheduler->setChoice(0, state);
1395 memoryStateLabeling.
addLabel(
"init_memory");
1396 memoryStateLabeling.
addLabel(
"condition_reached");
1397 memoryStateLabeling.
addLabel(
"target_reached");
1406 for (
auto state : conditionStates) {
1408 for (
auto entryIt = transitionMatrix.
getRow(choice).
begin(); entryIt < transitionMatrix.
getRow(choice).
end(); ++entryIt) {
1409 conditionExitTransitions.
set(entryIt - transitionMatrix.
begin(),
true);
1413 for (
auto state : targetStates) {
1415 for (
auto entryIt = transitionMatrix.
getRow(choice).
begin(); entryIt < transitionMatrix.
getRow(choice).
end(); ++entryIt) {
1416 targetExitTransitions.
set(entryIt - transitionMatrix.
begin(),
true);
1421 memoryTransitions[0][0] =
1422 allTransitions & ~conditionExitTransitions & ~targetExitTransitions;
1423 memoryTransitions[0][1] = conditionExitTransitions;
1424 memoryTransitions[0][2] = targetExitTransitions & ~conditionExitTransitions;
1425 memoryTransitions[1][1] = allTransitions;
1426 memoryTransitions[2][2] = allTransitions;
1431 auto finalScheduler = std::unique_ptr<storm::storage::Scheduler<SolutionType>>(
1434 for (uint64_t state = 0; state < transitionMatrix.
getRowGroupCount(); ++state) {
1436 if (conditionStates.get(state)) {
1437 if (normalFormData.schedulerChoicesForReachingTargetStates->isChoiceSelected(state)) {
1438 finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates->getChoice(state), state, 0);
1440 finalScheduler->setChoice(0, state, 0);
1442 }
else if (targetStates.get(state)) {
1443 if (normalFormData.schedulerChoicesForReachingConditionStates->isChoiceSelected(state)) {
1444 finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates->getChoice(state), state, 0);
1446 finalScheduler->setChoice(0, state, 0);
1449 finalScheduler->setChoice(scheduler->getChoice(state), state, 0);
1453 if (normalFormData.schedulerChoicesForReachingTargetStates->isChoiceSelected(state)) {
1454 finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingTargetStates->getChoice(state), state, 1);
1456 finalScheduler->setChoice(0, state, 1);
1459 if (normalFormData.schedulerChoicesForReachingConditionStates->isChoiceSelected(state)) {
1460 finalScheduler->setChoice(normalFormData.schedulerChoicesForReachingConditionStates->getChoice(state), state, 2);
1462 finalScheduler->setChoice(0, state, 2);
1466 result->asExplicitQuantitativeCheckResult<SolutionType>().setScheduler(std::move(finalScheduler));
1478 bool produceSchedulers,
bool isPrecisionSetFromDefault() const
bool isRelativePrecision() const
storm::RationalNumber getPrecision() const
SolverEnvironment & solver()
ModelCheckerEnvironment & modelchecker()
void setPrecision(storm::RationalNumber value)
ConditionalModelCheckerEnvironment & conditional()
Helper class that optionally holds a reference to an object of type T.
void reset()
Unsets the reference.
MinMaxSolverEnvironment & minMax()
bool isForceSoundness() const
static MDPSparseModelCheckingHelperReturnType< SolutionType > computeUntilProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool qualitative, bool produceScheduler, ModelCheckerHint const &hint=ModelCheckerHint())
A helper class that computes (weighted) reachability probabilities for a given MDP in normal form.
bool improveScheduler(std::vector< uint64_t > &scheduler, ValueType const &lambda, std::vector< SolutionType > const &targetResults, std::vector< SolutionType > const &conditionResults)
void evaluateScheduler(storm::Environment const &env, std::vector< uint64_t > &scheduler, std::vector< SolutionType > &targetResults, std::vector< SolutionType > &conditionResults)
SolutionType evaluateScheduler(storm::Environment const &env, std::vector< uint64_t > const &scheduler)
SolutionType computeWeightedDiff(storm::Environment const &env, storm::OptimizationDirection const dir, ValueType const &targetWeight, ValueType const &conditionWeight, storm::OptionalRef< std::vector< uint64_t > > schedulerOutput={})
WeightedReachabilityHelper(uint64_t const initialState, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, NormalFormData< ValueType > const &normalForm, bool computeScheduler)
std::unique_ptr< storm::storage::Scheduler< ValueType > > constructSchedulerForInputModel(std::vector< uint64_t > const &schedulerForReducedModel, storm::storage::SparseMatrix< ValueType > const &originalTransitionMatrix, storm::storage::SparseMatrix< ValueType > const &originalBackwardTransitions, NormalFormData< ValueType > const &normalForm) const
auto getInternalInitialState() const
void addLabel(std::string const &label)
Adds a new label to the labelings.
This class manages the labeling of the state space with a number of (atomic) labels.
void addLabelToState(std::string const &label, storm::storage::sparse::state_type state)
Adds a label to a given state.
virtual std::unique_ptr< LinearEquationSolver< ValueType > > create(Environment const &env) const override
Creates an equation solver with the current settings, but without a matrix.
virtual std::unique_ptr< MinMaxLinearEquationSolver< ValueType, SolutionType > > create(Environment const &env) const override
virtual LinearEquationSolverProblemFormat getEquationProblemFormat(Environment const &env) const
Retrieves the problem format that the solver expects if it was created with the current settings.
bool boundIsStrict() const
bool boundIsALowerBound() const
SolutionType const & thresholdValue() const
OptimizationDirection direction() const
storm::logic::ComparisonType boundComparisonType() const
A bit vector that is internally represented as a vector of 64-bit values.
std::vector< uint64_t > getNumberOfSetBitsBeforeIndices() const
Retrieves a vector that holds at position i the number of bits set before index i.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint64_t getNextUnsetIndex(uint64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to false in the bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
size_t size() const
Retrieves the number of bits this bit vector can store.
void resize(uint64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
bool get(uint64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
This class represents the decomposition of a nondeterministic model into its maximal end components.
This class represents a (deterministic) memory structure that can be used to encode certain events (s...
std::vector< std::vector< boost::optional< storm::storage::BitVector > > > TransitionMatrix
This class defines which action is chosen in a particular state of a non-deterministic model.
SchedulerChoice< ValueType > const & getChoice(uint_fast64_t modelState, uint_fast64_t memoryState=0) const
Gets the choice defined by the scheduler for the given model and memory state.
void setChoice(SchedulerChoice< ValueType > const &choice, uint_fast64_t modelState, uint_fast64_t memoryState=0)
Sets the choice defined by the scheduler for the given state.
bool isChoiceSelected(BitVector const &selectedStates, uint64_t memoryState=0) const
Is the scheduler defined on the states indicated by the selected-states bitvector?
const_iterator end() const
Retrieves an iterator that points past the last entry of the rows.
const_iterator begin() const
Retrieves an iterator that points to the beginning of the rows.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
index_type getEntryCount() const
Returns the number of entries in the matrix.
index_type getNumRowsInRowGroups(storm::storage::BitVector const &groupConstraint) const
Returns the total number of rows that are in one of the specified row groups.
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
const_iterator begin(index_type row) const
Retrieves an iterator that points to the beginning of the given row.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
index_type getRowGroupSize(index_type group) const
Returns the size of the given row group.
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
Stores and manages an extremal (maximal or minimal) value.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
std::unique_ptr< storm::storage::Scheduler< ValueType > > computeReachabilityProbabilities(Environment const &env, std::map< uint64_t, ValueType > &nonZeroResults, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &allowedStates, storm::storage::BitVector const &targetStates, bool computeScheduler=true)
Computes the reachability probabilities for the given target states and inserts all non-zero values i...
NormalFormData< ValueType > obtainNormalForm(Environment const &env, storm::solver::OptimizationDirection const dir, bool computeScheduler, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &relevantStates, storm::storage::BitVector const &targetStates, storm::storage::BitVector const &conditionStates)
std::optional< typename storm::transformer::EndComponentEliminator< ValueType >::EndComponentEliminatorReturnType > eliminateEndComponents(storm::storage::BitVector const &possibleEcStates, bool addRowAtRepresentativeState, std::optional< uint64_t > const representativeRowEntry, storm::storage::SparseMatrix< ValueType > &matrix, storm::storage::BitVector &rowsWithSum1, std::vector< ValueType > &rowValues1, storm::OptionalRef< std::vector< ValueType > > rowValues2={})
internal::ResultReturnType< ValueType > computeViaRestartMethod(Environment const &env, uint64_t const initialState, storm::solver::SolveGoal< ValueType, SolutionType > const &goal, bool computeScheduler, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, NormalFormData< ValueType > const &normalForm)
Uses the restart method by Baier et al.
internal::ResultReturnType< SolutionType > computeViaPolicyIteration(Environment const &env, uint64_t const initialState, storm::solver::OptimizationDirection const dir, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, NormalFormData< ValueType > const &normalForm)
SolutionType solveMinMaxEquationSystem(storm::Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix, std::vector< ValueType > const &rowValues, storm::storage::BitVector const &rowsWithSum1, storm::solver::SolveGoal< ValueType, SolutionType > const &goal, uint64_t const initialState, std::optional< std::vector< uint64_t > > &schedulerOutput)
internal::ResultReturnType< ValueType > computeViaBisection(Environment const &env, bool const useAdvancedBounds, bool const usePolicyTracking, uint64_t const initialState, storm::solver::SolveGoal< ValueType, SolutionType > const &goal, bool computeScheduler, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, NormalFormData< ValueType > const &normalForm)
std::optional< SolutionType > handleTrivialCases(uint64_t const initialState, NormalFormData< ValueType > const &normalForm)
internal::ResultReturnType< ValueType > decideThreshold(Environment const &env, uint64_t const initialState, storm::OptimizationDirection const &direction, SolutionType const &threshold, bool computeScheduler, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, NormalFormData< ValueType > const &normalForm)
void finalizeSchedulerForMaybeStates(storm::storage::Scheduler< SolutionType > &scheduler, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &maybeStates, storm::storage::BitVector const &maybeStatesWithoutChoice, storm::storage::BitVector const &maybeStatesWithChoice, std::vector< uint64_t > const &stateToFinalEc, NormalFormData< ValueType > const &normalForm, uint64_t initialComponentIndex, storm::storage::BitVector const &initialComponentExitStates, storm::storage::BitVector const &initialComponentExitRows, uint64_t chosenInitialComponentExitState, uint64_t chosenInitialComponentExit)
std::unique_ptr< CheckResult > computeConditionalProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, bool produceSchedulers, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &targetStates, storm::storage::BitVector const &conditionStates)
std::unique_ptr< storm::solver::MinMaxLinearEquationSolver< ValueType, SolutionType > > configureMinMaxLinearEquationSolver(Environment const &env, SolveGoal< ValueType, SolutionType > &&goal, storm::solver::MinMaxLinearEquationSolverFactory< ValueType, SolutionType > const &factory, MatrixType &&matrix, OptimizationDirectionSetting optimizationDirectionSetting=OptimizationDirectionSetting::Unset)
bool constexpr minimize(OptimizationDirection d)
void computeSchedulerProbGreater0E(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the ProbGreater0E-States such that in the induced system the given psiStates...
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
void computeSchedulerProb1E(storm::storage::BitVector const &prob1EStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the given prob1EStates such that in the induced system the given psiStates a...
bool hasCycle(storm::storage::SparseMatrix< T > const &transitionMatrix, boost::optional< storm::storage::BitVector > const &subsystem)
Returns true if the graph represented by the given matrix has a cycle.
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
storm::storage::BitVector performProb0A(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 of satisfying phi until psi under at least one po...
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
void selectVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Selects the elements from a vector at the specified positions and writes them consecutively into anot...
void applyPointwise(std::vector< InValueType1 > const &firstOperand, std::vector< InValueType2 > const &secondOperand, std::vector< OutValueType > &target, Operation f=Operation())
Applies the given operation pointwise on the two given vectors and writes the result to the third vec...
bool isOne(ValueType const &a)
Extremum< storm::OptimizationDirection::Maximize, ValueType > Maximum
Extremum< storm::OptimizationDirection::Minimize, ValueType > Minimum
bool isAlmostZero(ValueType const &a)
bool isZero(ValueType const &a)
storm::RationalNumber findRational(storm::RationalNumber const &lowerBound, bool lowerInclusive, storm::RationalNumber const &upperBound, bool upperInclusive)
Finds the "simplest" rational number in the given interval, where "simplest" means having the smalles...
TargetType convertNumber(SourceType const &number)
solver::OptimizationDirection OptimizationDirection
ConditionalAlgorithmSetting
@ BisectionPolicyTracking
@ BisectionAdvancedPolicyTracking
static const bool IsExact
ResultReturnType(ValueType initialStateValue, std::unique_ptr< storm::storage::Scheduler< ValueType > > &&scheduler=nullptr)
bool hasScheduler() const
std::unique_ptr< storm::storage::Scheduler< SolutionType > > scheduler
ValueType initialStateValue