From e4c270288904fdb531969501823b1a177bedb5b8 Mon Sep 17 00:00:00 2001 From: Mavo <matthias.volk@rwth-aachen.de> Date: Tue, 1 Mar 2016 12:18:01 +0100 Subject: [PATCH] Fixed problem in MaximalEndComponents Former-commit-id: 950b9cfdfa677f47567e2c90fdadd3a65867dac4 --- .../helper/SparseMarkovAutomatonCslHelper.cpp | 46 +++++++------ src/storage/Decomposition.cpp | 5 ++ src/storage/Decomposition.h | 7 ++ .../MaximalEndComponentDecomposition.cpp | 68 ++++++++++--------- 4 files changed, 72 insertions(+), 54 deletions(-) diff --git a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp index d926917a5..95007a9e6 100644 --- a/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp +++ b/src/modelchecker/csl/helper/SparseMarkovAutomatonCslHelper.cpp @@ -407,33 +407,35 @@ namespace storm { infinityStates = storm::storage::BitVector(numberOfStates); } } - // Now we identify the states for which values need to be computed. storm::storage::BitVector maybeStates = ~(goalStates | infinityStates); - - // Then, we can eliminate the rows and columns for all states whose values are already known to be 0. - std::vector<ValueType> x(maybeStates.getNumberOfSetBits()); - storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates); - - // Now prepare the expected reward values for all states so they can be used as the right-hand side of the equation system. - std::vector<ValueType> rewardValues(stateRewards); - for (auto state : markovianStates) { - rewardValues[state] = rewardValues[state] / exitRateVector[state]; - } - - // Finally, prepare the actual right-hand side. - std::vector<ValueType> b(submatrix.getRowCount()); - storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, transitionMatrix.getRowGroupIndices(), rewardValues); - - // Solve the corresponding system of equations. - std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = minMaxLinearEquationSolverFactory.create(submatrix); - solver->solveEquationSystem(dir, x, b); - + // Create resulting vector. std::vector<ValueType> result(numberOfStates); - // Set values of resulting vector according to previous result and return the result. - storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, x); + if (!maybeStates.empty()) { + // Then, we can eliminate the rows and columns for all states whose values are already known. + std::vector<ValueType> x(maybeStates.getNumberOfSetBits()); + storm::storage::SparseMatrix<ValueType> submatrix = transitionMatrix.getSubmatrix(true, maybeStates, maybeStates); + + // Now prepare the expected reward values for all states so they can be used as the right-hand side of the equation system. + std::vector<ValueType> rewardValues(stateRewards); + for (auto state : markovianStates) { + rewardValues[state] = rewardValues[state] / exitRateVector[state]; + } + + // Finally, prepare the actual right-hand side. + std::vector<ValueType> b(submatrix.getRowCount()); + storm::utility::vector::selectVectorValuesRepeatedly(b, maybeStates, transitionMatrix.getRowGroupIndices(), rewardValues); + + // Solve the corresponding system of equations. + std::unique_ptr<storm::solver::MinMaxLinearEquationSolver<ValueType>> solver = minMaxLinearEquationSolverFactory.create(submatrix); + solver->solveEquationSystem(dir, x, b); + + // Set values of resulting vector according to previous result and return the result. + storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, x); + } + storm::utility::vector::setVectorValues(result, goalStates, storm::utility::zero<ValueType>()); storm::utility::vector::setVectorValues(result, infinityStates, storm::utility::infinity<ValueType>()); diff --git a/src/storage/Decomposition.cpp b/src/storage/Decomposition.cpp index 4e2ebcb02..54d7ef12e 100644 --- a/src/storage/Decomposition.cpp +++ b/src/storage/Decomposition.cpp @@ -41,6 +41,11 @@ namespace storm { return blocks.size(); } + template <typename BlockType> + bool Decomposition<BlockType>::empty() const { + return blocks.empty(); + } + template <typename BlockType> typename Decomposition<BlockType>::iterator Decomposition<BlockType>::begin() { return blocks.begin(); diff --git a/src/storage/Decomposition.h b/src/storage/Decomposition.h index ce522c171..76f8a28a8 100644 --- a/src/storage/Decomposition.h +++ b/src/storage/Decomposition.h @@ -63,6 +63,13 @@ namespace storm { */ std::size_t size() const; + /*! + * Checks if the decomposition is empty. + * + * @return True, if the decomposition is empty. + */ + bool empty() const; + /*! * Retrieves an iterator that points to the first block of this decomposition. * diff --git a/src/storage/MaximalEndComponentDecomposition.cpp b/src/storage/MaximalEndComponentDecomposition.cpp index 31c421224..a944ecd23 100644 --- a/src/storage/MaximalEndComponentDecomposition.cpp +++ b/src/storage/MaximalEndComponentDecomposition.cpp @@ -86,48 +86,52 @@ namespace storm { mecChanged |= sccs.size() > 1 || (sccs.size() > 0 && sccs[0].size() < mec.size()); // Check for each of the SCCs whether there is at least one action for each state that does not leave the SCC. - for (auto& scc : sccs) { - statesToCheck.set(scc.begin(), scc.end()); - - while (!statesToCheck.empty()) { - storm::storage::BitVector statesToRemove(numberOfStates); + if (sccs.empty()) { + mecChanged = true; + } else { + for (auto& scc : sccs) { + statesToCheck.set(scc.begin(), scc.end()); - for (auto state : statesToCheck) { - bool keepStateInMEC = false; + while (!statesToCheck.empty()) { + storm::storage::BitVector statesToRemove(numberOfStates); - for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { - bool choiceContainedInMEC = true; - for (auto const& entry : transitionMatrix.getRow(choice)) { - if (!scc.containsState(entry.getColumn())) { - choiceContainedInMEC = false; + for (auto state : statesToCheck) { + bool keepStateInMEC = false; + + for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { + bool choiceContainedInMEC = true; + for (auto const& entry : transitionMatrix.getRow(choice)) { + if (!scc.containsState(entry.getColumn())) { + choiceContainedInMEC = false; + break; + } + } + + // If there is at least one choice whose successor states are fully contained in the MEC, we can leave the state in the MEC. + if (choiceContainedInMEC) { + keepStateInMEC = true; break; } } - // If there is at least one choice whose successor states are fully contained in the MEC, we can leave the state in the MEC. - if (choiceContainedInMEC) { - keepStateInMEC = true; - break; + if (!keepStateInMEC) { + statesToRemove.set(state, true); } } - if (!keepStateInMEC) { - statesToRemove.set(state, true); + // Now erase the states that have no option to stay inside the MEC with all successors. + mecChanged |= !statesToRemove.empty(); + for (uint_fast64_t state : statesToRemove) { + scc.erase(state); } - } - - // Now erase the states that have no option to stay inside the MEC with all successors. - mecChanged |= !statesToRemove.empty(); - for (uint_fast64_t state : statesToRemove) { - scc.erase(state); - } - - // Now check which states should be reconsidered, because successors of them were removed. - statesToCheck.clear(); - for (auto state : statesToRemove) { - for (auto const& entry : backwardTransitions.getRow(state)) { - if (scc.containsState(entry.getColumn())) { - statesToCheck.set(entry.getColumn()); + + // Now check which states should be reconsidered, because successors of them were removed. + statesToCheck.clear(); + for (auto state : statesToRemove) { + for (auto const& entry : backwardTransitions.getRow(state)) { + if (scc.containsState(entry.getColumn())) { + statesToCheck.set(entry.getColumn()); + } } } }