Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
RobustMaximalEndComponentDecomposition.cpp
Go to the documentation of this file.
1#include <list>
2#include <numeric>
3#include <queue>
4
10
15#include "storm/utility/graph.h"
16
17namespace storm {
18namespace storage {
19
20template<typename ValueType>
24
25template<typename ValueType>
26template<typename RewardModelType>
31
32template<typename ValueType>
34 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
35 std::vector<ValueType> const& vector) {
36 performRobustMaximalEndComponentDecomposition(transitionMatrix, backwardTransitions, vector);
37}
38
39template<typename ValueType>
41 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
42 std::vector<ValueType> const& vector,
43 storm::storage::BitVector const& states) {
44 performRobustMaximalEndComponentDecomposition(transitionMatrix, backwardTransitions, vector, states);
45}
46
47template<typename ValueType>
52
53template<typename ValueType>
59
60template<typename ValueType>
65
66template<typename ValueType>
72
73template<typename ValueType>
75 storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
76 storm::OptionalRef<std::vector<ValueType> const> vector, storm::OptionalRef<storm::storage::BitVector const> states) {
77 // Adapted from Haddad-Monmege Algorithm 3
78 storm::storage::BitVector remainingEcCandidates;
79 SccDecompositionResult sccDecRes;
82 storm::storage::SparseMatrix<ValueType> updatingMatrix(transitionMatrix);
83 sccDecOptions.dropNaiveSccs();
84 if (states) {
85 sccDecOptions.subsystem(*states);
86 }
87
88 while (true) {
89 performSccDecomposition(updatingMatrix, sccDecOptions, sccDecRes, sccDecCache);
90
91 remainingEcCandidates = sccDecRes.nonTrivialStates;
92 storm::storage::BitVector ecSccIndices(sccDecRes.sccCount, true);
93 storm::storage::BitVector nonTrivSccIndices(sccDecRes.sccCount, false);
94
95 // find the choices that do not stay in their SCC
96 for (auto state : remainingEcCandidates) {
97 auto const sccIndex = sccDecRes.stateToSccMapping[state];
98 nonTrivSccIndices.set(sccIndex, true);
99
100 // If this probability is >= 1, we are able to stay in the SCC
101 // Otherwise not
102 double probabilityToStayInScc = 0;
103 // If the lower of the vector is > 0, the probability to stay in the SCC stays zero
104 if (vector && vector->at(state).lower() == 0) {
105 // Check if we can stay in the SCC
106 for (auto const& entry : transitionMatrix.getRow(state)) {
107 const bool targetInSCC = sccIndex == sccDecRes.stateToSccMapping[entry.getColumn()];
108 auto const& interval = entry.getValue();
109 if (!utility::isZero(interval.lower()) && !targetInSCC) {
110 // You have to leave the SCC here
111 probabilityToStayInScc = 0;
112 break;
113 } else if (targetInSCC) {
114 probabilityToStayInScc += interval.upper();
115 }
116 }
117 }
118
119 // if (probabilityToStayInScc < 1 && !utility::isAlmostOne(probabilityToStayInScc)) {
120 if (probabilityToStayInScc < 1) {
121 // This state is not in an EC
122 remainingEcCandidates.set(state, false);
123 // This SCC is not an EC
124 ecSccIndices.set(sccIndex, false);
125 }
126 }
127
128 // process the MECs that we've found, i.e. SCCs where every state can stay inside the SCC
129 ecSccIndices &= nonTrivSccIndices;
130
131 for (auto sccIndex : ecSccIndices) {
132 StronglyConnectedComponent newMec;
133 for (auto state : remainingEcCandidates) {
134 // skip states from different SCCs
135 if (sccDecRes.stateToSccMapping[state] != sccIndex) {
136 continue;
137 }
138 // This is no longer a candidate
139 remainingEcCandidates.set(state, false);
140 // but a state in the EC
141 newMec.insert(state);
142 }
143 this->blocks.emplace_back(std::move(newMec));
144 }
145
146 // Populate the transitions that stay inside the EC (sort of Haddad-Monmege line 10-11)
147 for (auto sccIndex : nonTrivSccIndices) {
148 for (uint64_t state = 0; state < transitionMatrix.getRowCount(); state++) {
149 // Populate new edges for search that only consider intervals within the EC
150 // Tally up lower probability to stay inside of the EC. Once this is >= 1, our EC is done.
151 double stayInsideECProb = 0;
152 for (auto& entry : updatingMatrix.getRow(state)) {
153 const bool targetInEC = sccIndex == sccDecRes.stateToSccMapping[entry.getColumn()];
154 if (!targetInEC) {
155 entry.setValue(0);
156 continue;
157 }
158 auto const& interval = entry.getValue();
159
160 // Haddad-Monmege line 11
161 if (interval.upper() > 0 && stayInsideECProb < 1) {
162 stayInsideECProb += interval.upper();
163 } else {
164 entry.setValue(0);
165 }
166 }
167 }
168 }
169
170 if (nonTrivSccIndices == ecSccIndices) {
171 // All non trivial SCCs are MECs, nothing left to do!
172 break;
173 }
174
175 sccDecOptions.subsystem(remainingEcCandidates);
176 }
177
178 STORM_LOG_DEBUG("MEC decomposition found " << this->size() << " MEC(s).");
179}
180
181template<typename ValueType>
182std::vector<uint64_t> RobustMaximalEndComponentDecomposition<ValueType>::computeStateToSccIndexMap(uint64_t numberOfStates) const {
183 std::vector<uint64_t> result(numberOfStates, std::numeric_limits<uint64_t>::max());
184 uint64_t sccIndex = 0;
185 for (auto const& scc : *this) {
186 for (auto const& state : scc) {
187 result[state] = sccIndex;
188 }
189 ++sccIndex;
190 }
191 return result;
192}
193
194// Explicitly instantiate the MEC decomposition.
198
199} // namespace storage
200} // namespace storm
Helper class that optionally holds a reference to an object of type T.
Definition OptionalRef.h:48
The base class of all sparse deterministic models.
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:197
storm::storage::SparseMatrix< ValueType > getBackwardTransitions() const
Retrieves the backward transition relation of the model, i.e.
Definition Model.cpp:152
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
This class represents the decomposition of a model into blocks which are of the template type.
Decomposition & operator=(Decomposition const &other)
Assigns the contents of the given decomposition to the current one by copying the contents.
This class represents the decomposition of a nondeterministic model into its maximal end components.
RobustMaximalEndComponentDecomposition & operator=(RobustMaximalEndComponentDecomposition const &other)
Assigns the contents of the given MEC decomposition to the current one by copying its contents.
std::vector< uint64_t > computeStateToSccIndexMap(uint64_t numberOfStates) const
Computes a vector that for each state has the index of the scc of that state in it.
A class that holds a possibly non-square matrix in the compressed row storage format.
index_type getRowCount() const
Returns the number of rows of the matrix.
#define STORM_LOG_DEBUG(message)
Definition logging.h:18
void performSccDecomposition(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, StronglyConnectedComponentDecompositionOptions const &options, SccDecompositionResult &result)
Computes an SCC decomposition for the given matrix and options.
bool isZero(ValueType const &a)
Definition constants.cpp:42
LabParser.cpp.
Holds temporary computation data used during the SCC decomposition algorithm.
Holds the result data of the implemented SCC decomposition algorithm.
std::vector< uint64_t > stateToSccMapping
Number of found SCCs.
storm::storage::BitVector nonTrivialStates
Mapping from states to the SCC it belongs to.
uint64_t sccCount
True if an SCC is associated to the given state.
StronglyConnectedComponentDecompositionOptions & dropNaiveSccs(bool value=true)
Sets if trivial SCCs (i.e. SCCs consisting of just one state without a self-loop) are to be kept in t...
StronglyConnectedComponentDecompositionOptions & subsystem(storm::storage::BitVector const &subsystem)
Sets a bit vector indicating which subsystem to consider for the decomposition into SCCs.