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 this->setSolutionBoundsExact(x);
112
113 if (!this->isCachingEnabled()) {
114 this->clearCache();
115 }
116 return true;
117}
118
119template<typename ValueType>
121 Environment const&, boost::optional<storm::solver::OptimizationDirection> const& direction, bool const& hasInitialScheduler) const {
122 // Return the requirements of the underlying solver
124 requirements.requireAcyclic();
125 return requirements;
126}
127
128template<typename ValueType>
130 multiplier.reset();
131 orderedMatrix = boost::none;
132 rowGroupOrdering = boost::none;
133 auxiliaryRowVector = boost::none;
134 auxiliaryRowGroupVector = boost::none;
135 auxiliaryRowGroupIndexVector = boost::none;
136 bFactors.clear();
137}
138
139// Explicitly instantiate the min max linear equation solver.
142} // namespace solver
143} // namespace storm
void setSolutionBoundsExact(std::vector< ValueType > const &x) const
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:44