Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
RobustMaximalEndComponentDecomposition.cpp
Go to the documentation of this file.
2
3#include <numeric>
4
10#include "storm/utility/graph.h"
11
12namespace storm {
13namespace storage {
14
15template<typename ValueType>
19
20template<typename ValueType>
21template<typename RewardModelType>
26
27template<typename ValueType>
29 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
30 std::vector<ValueType> const& vector) {
31 performRobustMaximalEndComponentDecomposition(transitionMatrix, backwardTransitions, vector);
32}
33
34template<typename ValueType>
36 storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
37 std::vector<ValueType> const& vector,
38 storm::storage::BitVector const& states) {
39 performRobustMaximalEndComponentDecomposition(transitionMatrix, backwardTransitions, vector, states);
40}
41
42template<typename ValueType>
47
48template<typename ValueType>
54
55template<typename ValueType>
60
61template<typename ValueType>
67
68template<typename ValueType>
70 storm::storage::SparseMatrix<ValueType> const& transitionMatrix, storm::storage::SparseMatrix<ValueType> const& backwardTransitions,
71 storm::OptionalRef<std::vector<ValueType> const> vector, storm::OptionalRef<storm::storage::BitVector const> states) {
72 // Adapted from Haddad-Monmege Algorithm 3
73 storm::storage::BitVector remainingEcCandidates;
74 SccDecompositionResult sccDecRes;
77 storm::storage::SparseMatrix<ValueType> updatingMatrix(transitionMatrix);
78 sccDecOptions.dropNaiveSccs();
79 if (states) {
80 sccDecOptions.subsystem(*states);
81 }
82
83 while (true) {
84 performSccDecomposition(updatingMatrix, sccDecOptions, sccDecRes, sccDecCache);
85
86 remainingEcCandidates = sccDecRes.nonTrivialStates;
87 storm::storage::BitVector ecSccIndices(sccDecRes.sccCount, true);
88 storm::storage::BitVector nonTrivSccIndices(sccDecRes.sccCount, false);
89
90 // find the choices that do not stay in their SCC
91 for (auto state : remainingEcCandidates) {
92 auto const sccIndex = sccDecRes.stateToSccMapping[state];
93 nonTrivSccIndices.set(sccIndex, true);
94
95 // If this probability is >= 1, we are able to stay in the SCC
96 // Otherwise not
97 double probabilityToStayInScc = 0;
98 // If the lower of the vector is > 0, the probability to stay in the SCC stays zero
99 if (vector && vector->at(state).lower() == 0) {
100 // Check if we can stay in the SCC
101 for (auto const& entry : transitionMatrix.getRow(state)) {
102 const bool targetInSCC = sccIndex == sccDecRes.stateToSccMapping[entry.getColumn()];
103 auto const& interval = entry.getValue();
104 if (!utility::isZero(interval.lower()) && !targetInSCC) {
105 // You have to leave the SCC here
106 probabilityToStayInScc = 0;
107 break;
108 } else if (targetInSCC) {
109 probabilityToStayInScc += interval.upper();
110 }
111 }
112 }
113
114 // if (probabilityToStayInScc < 1 && !utility::isAlmostOne(probabilityToStayInScc)) {
115 if (probabilityToStayInScc < 1) {
116 // This state is not in an EC
117 remainingEcCandidates.set(state, false);
118 // This SCC is not an EC
119 ecSccIndices.set(sccIndex, false);
120 }
121 }
122
123 // process the MECs that we've found, i.e. SCCs where every state can stay inside the SCC
124 ecSccIndices &= nonTrivSccIndices;
125
126 for (auto sccIndex : ecSccIndices) {
127 StronglyConnectedComponent newMec;
128 for (auto state : remainingEcCandidates) {
129 // skip states from different SCCs
130 if (sccDecRes.stateToSccMapping[state] != sccIndex) {
131 continue;
132 }
133 // This is no longer a candidate
134 remainingEcCandidates.set(state, false);
135 // but a state in the EC
136 newMec.insert(state);
137 }
138 this->blocks.emplace_back(std::move(newMec));
139 }
140
141 // Populate the transitions that stay inside the EC (sort of Haddad-Monmege line 10-11)
142 for (auto sccIndex : nonTrivSccIndices) {
143 for (uint64_t state = 0; state < transitionMatrix.getRowCount(); state++) {
144 // Populate new edges for search that only consider intervals within the EC
145 // Tally up lower probability to stay inside of the EC. Once this is >= 1, our EC is done.
146 double stayInsideECProb = 0;
147 for (auto& entry : updatingMatrix.getRow(state)) {
148 const bool targetInEC = sccIndex == sccDecRes.stateToSccMapping[entry.getColumn()];
149 if (!targetInEC) {
150 entry.setValue(0);
151 continue;
152 }
153 auto const& interval = entry.getValue();
154
155 // Haddad-Monmege line 11
156 if (interval.upper() > 0 && stayInsideECProb < 1) {
157 stayInsideECProb += interval.upper();
158 } else {
159 entry.setValue(0);
160 }
161 }
162 }
163 }
164
165 if (nonTrivSccIndices == ecSccIndices) {
166 // All non trivial SCCs are MECs, nothing left to do!
167 break;
168 }
169
170 sccDecOptions.subsystem(remainingEcCandidates);
171 }
172
173 STORM_LOG_DEBUG("MEC decomposition found " << this->size() << " MEC(s).");
174}
175
176template<typename ValueType>
177std::vector<uint64_t> RobustMaximalEndComponentDecomposition<ValueType>::computeStateToSccIndexMap(uint64_t numberOfStates) const {
178 std::vector<uint64_t> result(numberOfStates, std::numeric_limits<uint64_t>::max());
179 uint64_t sccIndex = 0;
180 for (auto const& scc : *this) {
181 for (auto const& state : scc) {
182 result[state] = sccIndex;
183 }
184 ++sccIndex;
185 }
186 return result;
187}
188
189// Explicitly instantiate the MEC decomposition.
193
194} // namespace storage
195} // 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:199
storm::storage::SparseMatrix< ValueType > getBackwardTransitions() const
Retrieves the backward transition relation of the model, i.e.
Definition Model.cpp:159
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:39
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.