44 preorderNumbers.assign(numStates, std::numeric_limits<uint64_t>::max());
51 return preorderNumbers[stateIndex] != std::numeric_limits<uint64_t>::max();
59 if (computeSccDepths) {
74template<
typename ValueType>
79template<
typename ValueType>
85template<
typename ValueType>
91template<
typename ValueType>
94 this->blocks = other.
blocks;
98template<
typename ValueType>
104template<
typename ValueType>
107 this->blocks = std::move(other.blocks);
134template<
typename ValueType>
147 assert(!subsystem || subsystem->get(currentState));
153 cache.
s.push_back(currentState);
154 cache.
p.push_back(currentState);
157 row != rowEnd; ++row) {
158 if (choices && !choices->get(row)) {
162 for (
auto const& successor : transitionMatrix.
getRow(row)) {
163 if ((!subsystem || subsystem->get(successor.getColumn())) && successor.getValue() != storm::utility::zero<ValueType>()) {
164 if (currentState == successor.getColumn()) {
185 if (currentState == cache.
p.back()) {
188 uint64_t sccDepth = 0;
190 auto stateIt = cache.
s.end();
194 row != rowEnd; ++row) {
195 if (choices && !choices->get(row)) {
198 for (
auto const& successor : transitionMatrix.
getRow(row)) {
199 if ((!subsystem || subsystem->get(successor.getColumn())) && successor.getValue() != storm::utility::zero<ValueType>() &&
205 }
while (*stateIt != currentState);
208 bool nonSingletonScc = cache.
s.back() != currentState;
209 uint64_t poppedState = 0;
211 poppedState = cache.
s.back();
214 if (nonSingletonScc) {
217 }
while (poppedState != currentState);
226template<
typename ValueType>
228 StronglyConnectedComponentDecompositionOptions
const& options) {
229 SccDecompositionResult result;
232 STORM_LOG_ASSERT(!options.areOnlyBottomSccsConsidered || result.sccDepths.has_value(),
"Scc depths not computed but needed.");
233 if (result.sccDepths) {
234 this->sccDepths = std::move(*result.sccDepths);
238 this->blocks.resize(result.sccCount);
239 for (uint64_t state = 0; state < transitionMatrix.
getRowGroupCount(); ++state) {
241 if ((!options.optSubsystem || options.optSubsystem->get(state))) {
242 if (!options.areNaiveSccsDropped || result.nonTrivialStates.get(state)) {
243 uint64_t sccIndex = result.stateToSccMapping[state];
244 if (!options.areOnlyBottomSccsConsidered || sccDepths.value()[sccIndex] == 0) {
245 this->blocks[sccIndex].insert(state);
246 if (!result.nonTrivialStates.get(state)) {
247 this->blocks[sccIndex].setIsTrivial(
true);
248 STORM_LOG_ASSERT(this->blocks[sccIndex].size() == 1,
"Unexpected number of states in a trivial SCC.");
256 if (options.areOnlyBottomSccsConsidered || options.areNaiveSccsDropped) {
258 for (uint64_t sccIndex = 0; sccIndex < result.sccCount; ++sccIndex) {
259 if (this->blocks[sccIndex].empty()) {
260 blocksToDrop.set(sccIndex,
true);
265 if (this->sccDepths) {
271template<
typename ValueType>
278template<
typename ValueType>
288 uint64_t currentIndex = 0;
289 auto performSccDecompFromState = [&](uint64_t startState) {
298 performSccDecompFromState(state);
301 for (uint64_t state = 0; state < numberOfStates; ++state) {
302 performSccDecompFromState(state);
307template<
typename ValueType>
309 return sccDepths.has_value();
312template<
typename ValueType>
314 STORM_LOG_THROW(sccDepths.has_value(), storm::exceptions::InvalidOperationException,
315 "Tried to get the SCC depth but SCC depths were not computed upon construction.");
316 STORM_LOG_ASSERT(sccIndex < sccDepths->size(),
"SCC index " << sccIndex <<
" is out of range (" << sccDepths->size() <<
")");
317 return sccDepths.value()[sccIndex];
320template<
typename ValueType>
322 STORM_LOG_THROW(sccDepths.has_value(), storm::exceptions::InvalidOperationException,
323 "Tried to get the maximum SCC depth but SCC depths were not computed upon construction.");
324 STORM_LOG_THROW(!sccDepths->empty(), storm::exceptions::InvalidOperationException,
325 "Tried to get the maximum SCC depth but this SCC decomposition seems to be empty.");
326 return *std::max_element(sccDepths->begin(), sccDepths->end());
329template<
typename ValueType>
331 std::vector<uint64_t> result(numberOfStates, std::numeric_limits<uint64_t>::max());
332 uint64_t sccIndex = 0;
333 for (
auto const& scc : *
this) {
334 for (
auto const& state : scc) {
335 result[state] = sccIndex;
Helper class that optionally holds a reference to an object of type T.
A bit vector that is internally represented as a vector of 64-bit values.
void clear()
Removes all set bits from the bit vector.
void resize(uint_fast64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
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.
std::vector< block_type > blocks
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
This class represents the decomposition of a graph-like structure into its strongly connected compone...
StronglyConnectedComponentDecomposition & operator=(StronglyConnectedComponentDecomposition const &other)
Assigns the contents of the given SCC decomposition to the current one by copying its contents.
uint_fast64_t getSccDepth(uint_fast64_t const &sccIndex) const
Gets the depth of the SCC with the given index.
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.
bool hasSccDepth() const
Retrieves whether SCCDepths have been computed during construction of this.
uint_fast64_t getMaxSccDepth() const
Gets the maximum depth of an SCC.
StronglyConnectedComponentDecomposition()
Creates an empty SCC decomposition.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
void performSccDecompositionGCM(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::OptionalRef< storm::storage::BitVector const > subsystem, storm::OptionalRef< storm::storage::BitVector const > choices, bool, uint64_t startState, uint64_t ¤tIndex, SccDecompositionResult &result, SccDecompositionMemoryCache &cache)
Uses the algorithm by Gabow/Cheriyan/Mehlhorn ("Path-based strongly connected component algorithm") t...
void performSccDecomposition(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, StronglyConnectedComponentDecompositionOptions const &options, SccDecompositionResult &result)
Computes an SCC decomposition for the given matrix and options.
void filterVectorInPlace(std::vector< Type > &v, storm::storage::BitVector const &filter)
Holds temporary computation data used during the SCC decomposition algorithm.
bool hasPreorderNumber(uint64_t stateIndex) const
std::vector< uint64_t > recursionStateStack
std::vector< uint64_t > preorderNumbers
void initialize(uint64_t numStates)
std::vector< uint64_t > p
std::vector< uint64_t > s
Holds the result data of the implemented SCC decomposition algorithm.
std::vector< uint64_t > stateToSccMapping
Number of found SCCs.
void initialize(uint64_t numStates, bool computeSccDepths)
storm::storage::BitVector nonTrivialStates
Mapping from states to the SCC it belongs to.
bool stateHasScc(uint64_t stateIndex) const
uint64_t sccCount
True if an SCC is associated to the given state.
std::optional< std::vector< uint64_t > > sccDepths
Keep track of trivial states (singleton SCCs without selfloop).
StronglyConnectedComponentDecompositionOptions & computeSccDepths(bool value=true)
Sets if scc depths can be retrieved.
storm::OptionalRef< storm::storage::BitVector const > optChoices
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...
bool isTopologicalSortForced
StronglyConnectedComponentDecompositionOptions & forceTopologicalSort(bool value=true)
Enforces that the returned SCCs are sorted in a topological order.
StronglyConnectedComponentDecompositionOptions & subsystem(storm::storage::BitVector const &subsystem)
Sets a bit vector indicating which subsystem to consider for the decomposition into SCCs.
StronglyConnectedComponentDecompositionOptions & choices(storm::storage::BitVector const &choices)
Sets a bit vector indicating which choices of the states are contained in the subsystem.
bool isComputeSccDepthsSet
bool areOnlyBottomSccsConsidered
StronglyConnectedComponentDecompositionOptions & onlyBottomSccs(bool value=true)
Sets if only bottom SCCs, i.e. SCCs in which all states have no way of leaving the SCC),...
storm::OptionalRef< storm::storage::BitVector const > optSubsystem