Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
AcyclicMinMaxLinearEquationSolver.cpp
Go to the documentation of this file.
2
4
6
7namespace storm {
8namespace solver {
9
10template<typename ValueType>
14
15template<typename ValueType>
20
21template<typename ValueType>
26
27template<typename ValueType>
29 std::vector<ValueType> const& b) const {
30 STORM_LOG_ASSERT(x.size() == this->A->getRowGroupCount(), "Provided x-vector has invalid size.");
31 STORM_LOG_ASSERT(b.size() == this->A->getRowCount(), "Provided b-vector has invalid size.");
32
33 if (!multiplier) {
34 // We have not allocated cache memory, yet
35 rowGroupOrdering = helper::computeTopologicalGroupOrdering(*this->A);
36 if (!rowGroupOrdering) {
37 // It is not required to reorder the elements.
38 this->multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, *this->A);
39 } else {
40 bFactors.clear();
41 orderedMatrix = helper::createReorderedMatrix(*this->A, *rowGroupOrdering, bFactors);
42 this->multiplier = storm::solver::MultiplierFactory<ValueType>().create(env, *orderedMatrix);
43 }
44 auxiliaryRowVector = std::vector<ValueType>(this->A->getRowCount());
45 auxiliaryRowGroupVector = std::vector<ValueType>(this->A->getRowGroupCount());
46 }
47
48 std::vector<ValueType>* xPtr = &x;
49 std::vector<ValueType> const* bPtr = &b;
50 if (rowGroupOrdering) {
51 STORM_LOG_ASSERT(rowGroupOrdering->size() == x.size(), "X-vector has unexpected size.");
52 STORM_LOG_ASSERT(auxiliaryRowGroupVector->size() == x.size(), "X-vector has unexpected size.");
53 STORM_LOG_ASSERT(auxiliaryRowVector->size() == b.size(), "B-vector has unexpected size.");
54 for (uint64_t newGroupIndex = 0; newGroupIndex < x.size(); ++newGroupIndex) {
55 uint64_t newRow = orderedMatrix->getRowGroupIndices()[newGroupIndex];
56 uint64_t newRowGroupEnd = orderedMatrix->getRowGroupIndices()[newGroupIndex + 1];
57 uint64_t oldRow = this->A->getRowGroupIndices()[(*rowGroupOrdering)[newGroupIndex]];
58 for (; newRow < newRowGroupEnd; ++newRow, ++oldRow) {
59 (*auxiliaryRowVector)[newRow] = b[oldRow];
60 }
61 }
62 for (auto const& bFactor : bFactors) {
63 if (bFactor.second) {
64 (*auxiliaryRowVector)[bFactor.first] *= *bFactor.second;
65 } else {
66 // A selfloop of probability one: the equation for this row can only be satisfied if it contributes nothing.
67 STORM_LOG_ASSERT(storm::utility::isZero((*auxiliaryRowVector)[bFactor.first]),
68 "Expected a zero b vector entry for a row with a selfloop of probability one.");
69 }
70 }
71 xPtr = &auxiliaryRowGroupVector.get();
72 bPtr = &auxiliaryRowVector.get();
73 }
74
75 // Allocate memory for the scheduler (if required)
76 std::vector<uint64_t>* choicesPtr = nullptr;
77 if (this->isTrackSchedulerSet()) {
78 if (this->schedulerChoices) {
79 this->schedulerChoices->resize(this->A->getRowGroupCount());
80 } else {
81 this->schedulerChoices = std::vector<uint64_t>(this->A->getRowGroupCount());
82 }
83 if (rowGroupOrdering) {
84 if (auxiliaryRowGroupIndexVector) {
85 auxiliaryRowGroupIndexVector->resize(this->A->getRowGroupCount());
86 } else {
87 auxiliaryRowGroupIndexVector = std::vector<uint64_t>(this->A->getRowGroupCount());
88 }
89 choicesPtr = &(auxiliaryRowGroupIndexVector.get());
90 } else {
91 choicesPtr = &(this->schedulerChoices.get());
92 }
93 }
94
95 // Since a topological ordering is guaranteed, we can solve the equations with a single matrix-vector Multiplication step.
96 this->multiplier->multiplyAndReduceGaussSeidel(env, dir, *xPtr, bPtr, choicesPtr, true);
97
98 if (rowGroupOrdering) {
99 // Restore the correct input-order for the output vector
100 for (uint64_t newGroupIndex = 0; newGroupIndex < x.size(); ++newGroupIndex) {
101 x[(*rowGroupOrdering)[newGroupIndex]] = (*xPtr)[newGroupIndex];
102 }
103 if (this->isTrackSchedulerSet()) {
104 // Do the same for the scheduler choices
105 for (uint64_t newGroupIndex = 0; newGroupIndex < x.size(); ++newGroupIndex) {
106 this->schedulerChoices.get()[(*rowGroupOrdering)[newGroupIndex]] = (*choicesPtr)[newGroupIndex];
107 }
108 }
109 }
110
111 if (!this->isCachingEnabled()) {
112 this->clearCache();
113 }
114 return true;
115}
116
117template<typename ValueType>
119 Environment const&, boost::optional<storm::solver::OptimizationDirection> const& direction, bool const& hasInitialScheduler) const {
120 // Return the requirements of the underlying solver
122 requirements.requireAcyclic();
123 return requirements;
124}
125
126template<typename ValueType>
128 multiplier.reset();
129 orderedMatrix = boost::none;
130 rowGroupOrdering = boost::none;
131 auxiliaryRowVector = boost::none;
132 auxiliaryRowGroupVector = boost::none;
133 auxiliaryRowGroupIndexVector = boost::none;
134 bFactors.clear();
135}
136
137// Explicitly instantiate the min max linear equation solver.
140} // namespace solver
141} // namespace storm
This solver can be used on equation systems that are known to be acyclic.
virtual bool internalSolveEquations(storm::Environment const &env, OptimizationDirection d, std::vector< ValueType > &x, std::vector< ValueType > const &b) const override
virtual MinMaxLinearEquationSolverRequirements getRequirements(Environment const &env, boost::optional< storm::solver::OptimizationDirection > const &direction=boost::none, bool const &hasInitialScheduler=false) const override
Retrieves the requirements of this solver for solving equations with the current settings.
virtual void clearCache() const override
Clears the currently cached data that has been stored during previous calls of the solver.
MinMaxLinearEquationSolverRequirements & requireAcyclic(bool critical=true)
std::unique_ptr< Multiplier< ValueType, SolutionType > > create(Environment const &env, storm::storage::SparseMatrix< ValueType > const &matrix)
storm::storage::SparseMatrix< ValueType > const * A
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
boost::optional< std::vector< uint64_t > > computeTopologicalGroupOrdering(storm::storage::SparseMatrix< ValueType > const &matrix)
Returns a reordering of the matrix row(groups) and columns such that we can solve the (minmax or line...
storm::storage::SparseMatrix< ValueType > createReorderedMatrix(storm::storage::SparseMatrix< ValueType > const &matrix, std::vector< uint64_t > const &newToOrigIndexMap, std::vector< std::pair< uint64_t, std::optional< ValueType > > > &bFactors)
reorders the row group such that the i'th row of the new matrix corresponds to the order[i]'th row of...
bool isZero(ValueType const &a)
Definition constants.cpp:42