diff --git a/src/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp b/src/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp index 1561464fc..2f4d9389d 100644 --- a/src/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp +++ b/src/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp @@ -499,14 +499,34 @@ namespace storm { template std::unique_ptr SparseMdpPrctlHelper::computeConditionalProbabilities(OptimizationDirection dir, storm::storage::sparse::state_type initialState, storm::storage::SparseMatrix const& transitionMatrix, storm::storage::SparseMatrix const& backwardTransitions, storm::storage::BitVector const& targetStates, storm::storage::BitVector const& conditionStates, bool qualitative, storm::utility::solver::MinMaxLinearEquationSolverFactory const& minMaxLinearEquationSolverFactory) { + // For the max-case, we can simply take the given target states. For the min-case, however, we need to + // find the MECs of non-target states and make them the new target states. + storm::storage::BitVector fixedTargetStates; + if (dir == OptimizationDirection::Maximize) { + fixedTargetStates = targetStates; + } else { + fixedTargetStates = storm::storage::BitVector(targetStates.size()); + storm::storage::MaximalEndComponentDecomposition mecDecomposition(transitionMatrix, backwardTransitions, ~targetStates); + for (auto const& mec : mecDecomposition) { + for (auto const& stateActionsPair : mec) { + fixedTargetStates.set(stateActionsPair.first); + } + } + } + // We solve the max-case and later adjust the result if the optimization direction was to minimize. - // FIXME: actually do this. storm::storage::BitVector initialStatesBitVector(transitionMatrix.getRowGroupCount()); initialStatesBitVector.set(initialState); storm::storage::BitVector allStates(initialStatesBitVector.size(), true); std::vector conditionProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, conditionStates, false, false, minMaxLinearEquationSolverFactory).result); - std::vector targetProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, targetStates, false, false, minMaxLinearEquationSolverFactory).result); + + // If the conditional probability is undefined for the initial state, we return directly. + if (storm::utility::isZero(conditionProbabilities[initialState])) { + return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, storm::utility::infinity())); + } + + std::vector targetProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, transitionMatrix, backwardTransitions, allStates, fixedTargetStates, false, false, minMaxLinearEquationSolverFactory).result); storm::storage::BitVector statesWithProbabilityGreater0E(transitionMatrix.getRowGroupCount(), true); storm::storage::sparse::state_type state = 0; @@ -517,16 +537,11 @@ namespace storm { ++state; } - // If the conditional probability is undefined for the initial state, we return directly. - if (!statesWithProbabilityGreater0E.get(initialState)) { - return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, storm::utility::infinity())); - } - // Determine those states that need to be equipped with a restart mechanism. - storm::storage::BitVector problematicStates = storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates | targetStates); + storm::storage::BitVector problematicStates = storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, allStates, conditionStates | fixedTargetStates); // Otherwise, we build the transformed MDP. - storm::storage::BitVector relevantStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStatesBitVector, allStates, conditionStates | targetStates); + storm::storage::BitVector relevantStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStatesBitVector, allStates, conditionStates | fixedTargetStates); std::vector numberOfStatesBeforeRelevantStates = relevantStates.getNumberOfSetBitsBeforeIndices(); storm::storage::sparse::state_type newGoalState = relevantStates.getNumberOfSetBits(); storm::storage::sparse::state_type newStopState = newGoalState + 1; @@ -537,7 +552,7 @@ namespace storm { uint_fast64_t currentRow = 0; for (auto state : relevantStates) { builder.newRowGroup(currentRow); - if (targetStates.get(state)) { + if (fixedTargetStates.get(state)) { builder.addNextValue(currentRow, newGoalState, conditionProbabilities[state]); if (!storm::utility::isZero(conditionProbabilities[state])) { builder.addNextValue(currentRow, newFailState, 1 - conditionProbabilities[state]); @@ -581,7 +596,7 @@ namespace storm { storm::storage::SparseMatrix newBackwardTransitions = newTransitionMatrix.transpose(true); std::vector goalProbabilities = std::move(computeUntilProbabilities(OptimizationDirection::Maximize, newTransitionMatrix, newBackwardTransitions, storm::storage::BitVector(newFailState + 1, true), newGoalStates, false, false, minMaxLinearEquationSolverFactory).result); - return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]])); + return std::unique_ptr(new ExplicitQuantitativeCheckResult(initialState, dir == OptimizationDirection::Maximize ? goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]] : storm::utility::one() - goalProbabilities[numberOfStatesBeforeRelevantStates[initialState]])); } template class SparseMdpPrctlHelper;