14template<
typename ValueType>
19template<
typename ValueType>
24template<
typename ValueType>
29template<
typename ValueType>
36template<
typename ValueType>
38 localA = std::make_unique<storm::storage::SparseMatrix<ValueType>>(std::move(A));
39 this->A = localA.get();
43template<
typename ValueType>
49 STORM_LOG_ASSERT(this->longestSccChainSize,
"Did not compute the longest SCC chain size although it is needed.");
50 auto subEnvPrec = subEnv.solver().getPrecisionOfLinearEquationSolver(subEnv.solver().getLinearEquationSolverType());
51 subEnv.solver().setLinearEquationSolverPrecision(
57template<
typename ValueType>
59 std::vector<ValueType>
const& b)
const {
61 bool needAdaptPrecision =
65 if (!this->sortedSccDecomposition || (needAdaptPrecision && !this->longestSccChainSize)) {
68 createSortedSccDecomposition(needAdaptPrecision);
71 << sccSw <<
". Found " << this->sortedSccDecomposition->size() <<
" SCC(s) containing a total of " << x.size()
72 <<
" states. Average SCC size is "
73 <<
static_cast<double>(this->getMatrixRowCount()) /
static_cast<double>(this->sortedSccDecomposition->size()) <<
".");
77 needAdaptPrecision = needAdaptPrecision && (this->sortedSccDecomposition->size() != this->getMatrixRowCount());
79 storm::Environment sccSolverEnvironment = getEnvironmentForUnderlyingSolver(env, needAdaptPrecision);
81 if (this->longestSccChainSize) {
82 STORM_LOG_INFO(
"Longest SCC chain size is " << this->longestSccChainSize.get() <<
".");
86 bool returnValue =
true;
87 if (this->sortedSccDecomposition->size() == 1) {
88 if (
auto const& scc = *this->sortedSccDecomposition->begin(); scc.size() == 1) {
90 returnValue = solveTrivialScc(*scc.begin(), x, b);
92 returnValue = solveFullyConnectedEquationSystem(sccSolverEnvironment, x, b);
96 std::optional<storm::storage::BitVector> newRelevantValues;
98 this->sortedSccDecomposition->size() < this->A->getRowGroupCount()) {
101 std::vector<uint64_t> rowGroupToScc = this->sortedSccDecomposition->computeStateToSccIndexMap(this->A->getRowGroupCount());
102 for (uint64_t rowGroup = 0; rowGroup < this->A->getRowGroupCount(); ++rowGroup) {
103 auto currScc = rowGroupToScc[rowGroup];
104 for (
auto const& successor : this->A->getRowGroup(rowGroup)) {
105 if (rowGroupToScc[successor.getColumn()] != currScc) {
106 newRelevantValues->set(successor.getColumn(),
true);
112 uint64_t sccIndex = 0;
116 for (
auto const& scc : *this->sortedSccDecomposition) {
117 if (scc.size() == 1) {
118 returnValue = solveTrivialScc(*scc.begin(), x, b) && returnValue;
120 sccAsBitVector.
clear();
121 for (
auto const& state : scc) {
122 sccAsBitVector.
set(state,
true);
124 returnValue = solveScc(sccSolverEnvironment, sccAsBitVector, x, b, newRelevantValues) && returnValue;
129 STORM_LOG_WARN(
"Topological solver aborted after analyzing " << sccIndex <<
"/" << this->sortedSccDecomposition->size() <<
" SCCs.");
142template<
typename ValueType>
143void TopologicalLinearEquationSolver<ValueType>::createSortedSccDecomposition(
bool needLongestChainSize)
const {
145 this->sortedSccDecomposition = std::make_unique<storm::storage::StronglyConnectedComponentDecomposition<ValueType>>(
147 if (needLongestChainSize) {
148 this->longestSccChainSize = this->sortedSccDecomposition->getMaxSccDepth() + 1;
152template<
typename ValueType>
153bool TopologicalLinearEquationSolver<ValueType>::solveTrivialScc(uint64_t
const& sccState, std::vector<ValueType>& globalX,
154 std::vector<ValueType>
const& globalB)
const {
155 ValueType& xi = globalX[sccState];
156 xi = globalB[sccState];
157 bool hasDiagonalEntry =
false;
158 ValueType denominator;
159 for (
auto const& entry : this->A->getRow(sccState)) {
160 if (entry.getColumn() == sccState) {
162 hasDiagonalEntry =
true;
165 xi += entry.getValue() * globalX[entry.getColumn()];
169 if (hasDiagonalEntry) {
172 "State " << sccState <<
" has a selfloop with probability '1-(" << denominator <<
")'. This could be an indication for numerical issues.");
182template<
typename ValueType>
183bool TopologicalLinearEquationSolver<ValueType>::solveFullyConnectedEquationSystem(storm::Environment
const& sccSolverEnvironment, std::vector<ValueType>& x,
184 std::vector<ValueType>
const& b)
const {
185 if (!this->sccSolver) {
187 this->sccSolver->setCachingEnabled(
true);
189 if (this->hasRelevantValues()) {
190 this->sccSolver->setRelevantValues(this->getRelevantValues());
192 this->sccSolver->setBoundsFromOtherSolver(*
this);
195 storm::storage::SparseMatrix<ValueType> eqSysA(*this->A,
true);
196 eqSysA.convertToEquationSystem();
197 this->sccSolver->setMatrix(std::move(eqSysA));
199 this->sccSolver->setMatrix(*this->A);
202 return this->sccSolver->solveEquations(sccSolverEnvironment, x, b);
205template<
typename ValueType>
206bool TopologicalLinearEquationSolver<ValueType>::solveScc(storm::Environment
const& sccSolverEnvironment, storm::storage::BitVector
const& scc,
207 std::vector<ValueType>& globalX, std::vector<ValueType>
const& globalB,
208 std::optional<storm::storage::BitVector>
const& globalRelevantValues)
const {
210 if (!this->sccSolver) {
212 this->sccSolver->setCachingEnabled(
true);
214 if (globalRelevantValues) {
215 this->sccSolver->setRelevantValues((*globalRelevantValues) % scc);
220 storm::storage::SparseMatrix<ValueType> sccA = this->A->getSubmatrix(
true, scc, scc, asEquationSystem);
221 if (asEquationSystem) {
224 this->sccSolver->setMatrix(std::move(sccA));
230 std::vector<ValueType> sccB;
232 for (
auto row : scc) {
234 for (
auto const& entry : this->A->getRow(row)) {
235 if (!scc.get(entry.getColumn())) {
236 bi += entry.getValue() * globalX[entry.getColumn()];
239 sccB.push_back(std::move(bi));
244 this->sccSolver->setLowerBound(this->getLowerBound());
249 this->sccSolver->setUpperBound(this->getUpperBound());
257 bool returnvalue = this->sccSolver->solveEquations(sccSolverEnvironment, sccX, sccB);
262template<
typename ValueType>
267template<
typename ValueType>
273template<
typename ValueType>
275 sortedSccDecomposition.reset();
276 longestSccChainSize = boost::none;
281template<
typename ValueType>
282uint64_t TopologicalLinearEquationSolver<ValueType>::getMatrixRowCount()
const {
283 return this->A->getRowCount();
286template<
typename ValueType>
287uint64_t TopologicalLinearEquationSolver<ValueType>::getMatrixColumnCount()
const {
288 return this->A->getColumnCount();
291template<
typename ValueType>
293 return std::make_unique<storm::solver::TopologicalLinearEquationSolver<ValueType>>();
296template<
typename ValueType>
298 return std::make_unique<TopologicalLinearEquationSolverFactory<ValueType>>(*this);
SolverEnvironment & solver()
TopologicalSolverEnvironment & topological()
bool isForceSoundness() const
std::pair< boost::optional< storm::RationalNumber >, boost::optional< bool > > getPrecisionOfLinearEquationSolver(storm::solver::EquationSolverType const &solverType) const
storm::solver::EquationSolverType const & getUnderlyingEquationSolverType() const
bool isExtendRelevantValues() const
bool const & isUnderlyingEquationSolverTypeSetFromDefault() const
storm::storage::BitVector const & getRelevantValues() const
Retrieves the relevant values (if there are any).
virtual std::unique_ptr< LinearEquationSolver< ValueType > > create(Environment const &env) const override
Creates an equation solver with the current settings, but without a matrix.
LinearEquationSolverRequirements getRequirements(Environment const &env) const
Retrieves the requirements of the solver if it was created with the current settings.
virtual void clearCache() const
bool isCachingEnabled() const
Retrieves whether some of the generated data during solver calls should be cached.
virtual std::unique_ptr< LinearEquationSolverFactory< ValueType > > clone() const override
Creates a copy of this factory.
virtual std::unique_ptr< storm::solver::LinearEquationSolver< ValueType > > create(Environment const &env) const override
Creates an equation solver with the current settings, but without a matrix.
virtual LinearEquationSolverProblemFormat getEquationProblemFormat(storm::Environment const &env) const override
Retrieves the format in which this solver expects to solve equations.
virtual bool internalSolveEquations(storm::Environment const &env, std::vector< ValueType > &x, std::vector< ValueType > const &b) const override
virtual void setMatrix(storm::storage::SparseMatrix< ValueType > const &A) override
virtual LinearEquationSolverRequirements getRequirements(Environment const &env) const override
Retrieves the requirements of the solver under the current settings.
TopologicalLinearEquationSolver()
virtual void clearCache() const override
A bit vector that is internally represented as a vector of 64-bit values.
void clear()
Removes all set bits from the bit vector.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
A class that holds a possibly non-square matrix in the compressed row storage format.
void convertToEquationSystem()
Transforms the matrix into an equation system.
A class that provides convenience operations to display run times.
bool updateProgress(uint64_t count)
Updates the progress to the current count and prints it if the delay passed.
void setMaxCount(uint64_t maxCount)
Sets the maximal possible count.
void startNewMeasurement(uint64_t startCount)
Starts a new measurement, dropping all progress information collected so far.
A class that provides convenience operations to display run times.
void stop()
Stop stopwatch and add measured time to total time.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
#define STORM_LOG_WARN_COND_DEBUG(cond, message)
SFTBDDChecker::ValueType ValueType
LinearEquationSolverProblemFormat
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
void setVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Sets the provided values at the provided positions in the given vector.
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
bool isOne(ValueType const &a)
NumberTraits< RationalType >::IntegerType denominator(RationalType const &number)
bool isAlmostZero(ValueType const &a)
bool isZero(ValueType const &a)
TargetType convertNumber(SourceType const &number)
static const bool IsExact
StronglyConnectedComponentDecompositionOptions & computeSccDepths(bool value=true)
Sets if scc depths can be retrieved.
StronglyConnectedComponentDecompositionOptions & forceTopologicalSort(bool value=true)
Enforces that the returned SCCs are sorted in a topological order.