Storm 1.10.0.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 uint64_t step = 0;
89 while (true) {
90 performSccDecomposition(updatingMatrix, sccDecOptions, sccDecRes, sccDecCache);
91
92 remainingEcCandidates = sccDecRes.nonTrivialStates;
93 storm::storage::BitVector ecSccIndices(sccDecRes.sccCount, true);
94 storm::storage::BitVector nonTrivSccIndices(sccDecRes.sccCount, false);
95
96 // find the choices that do not stay in their SCC
97 for (auto state : remainingEcCandidates) {
98 auto const sccIndex = sccDecRes.stateToSccMapping[state];
99 nonTrivSccIndices.set(sccIndex, true);
100
101 // If this probability is >= 1, we are able to stay in the SCC
102 // Otherwise not
103 double probabilityToStayInScc = 0;
104 // If the lower of the vector is > 0, the probability to stay in the SCC stays zero
105 if (vector && vector->at(state).lower() == 0) {
106 // Check if we can stay in the SCC
107 for (auto const& entry : transitionMatrix.getRow(state)) {
108 auto const& target = entry.getColumn();
109 const bool targetInSCC = sccIndex == sccDecRes.stateToSccMapping[entry.getColumn()];
110 auto const& interval = entry.getValue();
111 if (!utility::isZero(interval.lower()) && !targetInSCC) {
112 // You have to leave the SCC here
113 probabilityToStayInScc = 0;
114 break;
115 } else if (targetInSCC) {
116 probabilityToStayInScc += interval.upper();
117 }
118 }
119 }
120
121 // if (probabilityToStayInScc < 1 && !utility::isAlmostOne(probabilityToStayInScc)) {
122 if (probabilityToStayInScc < 1) {
123 // This state is not in an EC
124 remainingEcCandidates.set(state, false);
125 // This SCC is not an EC
126 ecSccIndices.set(sccIndex, false);
127 }
128 }
129
130 // process the MECs that we've found, i.e. SCCs where every state can stay inside the SCC
131 ecSccIndices &= nonTrivSccIndices;
132
133 for (auto sccIndex : ecSccIndices) {
134 StronglyConnectedComponent newMec;
135 for (auto state : remainingEcCandidates) {
136 // skip states from different SCCs
137 if (sccDecRes.stateToSccMapping[state] != sccIndex) {
138 continue;
139 }
140 // This is no longer a candidate
141 remainingEcCandidates.set(state, false);
142 // but a state in the EC
143 newMec.insert(state);
144 }
145 this->blocks.emplace_back(std::move(newMec));
146 }
147
148 // Populate the transitions that stay inside the EC (sort of Haddad-Monmege line 10-11)
149 for (auto sccIndex : nonTrivSccIndices) {
150 for (uint64_t state = 0; state < transitionMatrix.getRowCount(); state++) {
151 // Populate new edges for search that only consider intervals within the EC
152 // Tally up lower probability to stay inside of the EC. Once this is >= 1, our EC is done.
153 double stayInsideECProb = 0;
154 for (auto& entry : updatingMatrix.getRow(state)) {
155 auto const& target = entry.getColumn();
156 const bool targetInEC = sccIndex == sccDecRes.stateToSccMapping[entry.getColumn()];
157 if (!targetInEC) {
158 entry.setValue(0);
159 continue;
160 }
161 auto const& interval = entry.getValue();
162
163 // Haddad-Monmege line 11
164 if (interval.upper() > 0 && stayInsideECProb < 1) {
165 stayInsideECProb += interval.upper();
166 } else {
167 entry.setValue(0);
168 }
169 }
170 }
171 }
172
173 if (nonTrivSccIndices == ecSccIndices) {
174 // All non trivial SCCs are MECs, nothing left to do!
175 break;
176 }
177
178 sccDecOptions.subsystem(remainingEcCandidates);
179 }
180
181 STORM_LOG_DEBUG("MEC decomposition found " << this->size() << " MEC(s).");
182}
183
184template<typename ValueType>
185std::vector<uint64_t> RobustMaximalEndComponentDecomposition<ValueType>::computeStateToSccIndexMap(uint64_t numberOfStates) const {
186 std::vector<uint64_t> result(numberOfStates, std::numeric_limits<uint64_t>::max());
187 uint64_t sccIndex = 0;
188 for (auto const& scc : *this) {
189 for (auto const& state : scc) {
190 result[state] = sccIndex;
191 }
192 ++sccIndex;
193 }
194 return result;
195}
196
197// Explicitly instantiate the MEC decomposition.
201
202} // namespace storage
203} // 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:18
void set(uint_fast64_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:23
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:41
LabParser.cpp.
Definition cli.cpp:18
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.