Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
GmmxxLinearEquationSolver.cpp
Go to the documentation of this file.
2
3#include <cmath>
4#include <utility>
5
13
14namespace storm {
15namespace solver {
16
17template<typename ValueType>
21
22template<typename ValueType>
26
27template<typename ValueType>
31
32template<typename ValueType>
37
38template<typename ValueType>
43
44template<typename ValueType>
45GmmxxLinearEquationSolverMethod GmmxxLinearEquationSolver<ValueType>::getMethod(Environment const& env) const {
46 STORM_LOG_ERROR_COND(!env.solver().isForceSoundness(), "This linear equation solver does not support sound computations. Using unsound methods now...");
47 STORM_LOG_ERROR_COND(!env.solver().isForceExact(), "This linear equation solver does not support exact computations. Using unsound methods now...");
48 return env.solver().gmmxx().getMethod();
49}
50
51template<typename ValueType>
52bool GmmxxLinearEquationSolver<ValueType>::internalSolveEquations(Environment const& env, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
53 auto method = getMethod(env);
54 auto preconditioner = env.solver().gmmxx().getPreconditioner();
55
56 STORM_LOG_INFO("Solving linear equation system (" << x.size() << " rows) with Gmmxx linear equation solver with method '" << toString(method)
57 << "' and preconditioner '" << toString(preconditioner) << "'.");
58
59 if (method == GmmxxLinearEquationSolverMethod::Bicgstab || method == GmmxxLinearEquationSolverMethod::Qmr ||
60 method == GmmxxLinearEquationSolverMethod::Gmres) {
61 // Make sure that the requested preconditioner is available
62 if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Ilu && !iluPreconditioner) {
63 iluPreconditioner = std::make_unique<gmm::ilu_precond<gmm::csr_matrix<ValueType>>>(*gmmxxA);
64 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Diagonal) {
65 diagonalPreconditioner = std::make_unique<gmm::diagonal_precond<gmm::csr_matrix<ValueType>>>(*gmmxxA);
66 }
67
68 // Prepare an iteration object that determines the accuracy and the maximum number of iterations.
69 gmm::size_type maxIter = std::numeric_limits<gmm::size_type>::max();
70 if (env.solver().gmmxx().getMaximalNumberOfIterations() < static_cast<uint64_t>(maxIter)) {
71 maxIter = env.solver().gmmxx().getMaximalNumberOfIterations();
72 }
73 gmm::iteration iter(storm::utility::convertNumber<ValueType>(env.solver().gmmxx().getPrecision()), 0, maxIter);
74 iter.set_callback([](const gmm::iteration& iteration) -> void {
75 STORM_LOG_THROW(!storm::utility::resources::isTerminate(), storm::exceptions::AbortException,
76 "Gmm++ (externally) aborted after " << iteration.get_iteration() << " iterations.");
77 });
78
79 // We use throwing an exception to abort within Gmm++
80 try {
81 // Invoke gmm with the corresponding settings
82 if (method == GmmxxLinearEquationSolverMethod::Bicgstab) {
83 if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Ilu) {
84 gmm::bicgstab(*gmmxxA, x, b, *iluPreconditioner, iter);
85 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Diagonal) {
86 gmm::bicgstab(*gmmxxA, x, b, *diagonalPreconditioner, iter);
87 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::None) {
88 gmm::bicgstab(*gmmxxA, x, b, gmm::identity_matrix(), iter);
89 }
90 } else if (method == GmmxxLinearEquationSolverMethod::Qmr) {
91 if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Ilu) {
92 gmm::qmr(*gmmxxA, x, b, *iluPreconditioner, iter);
93 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Diagonal) {
94 gmm::qmr(*gmmxxA, x, b, *diagonalPreconditioner, iter);
95 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::None) {
96 gmm::qmr(*gmmxxA, x, b, gmm::identity_matrix(), iter);
97 }
98 } else if (method == GmmxxLinearEquationSolverMethod::Gmres) {
99 if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Ilu) {
100 gmm::gmres(*gmmxxA, x, b, *iluPreconditioner, env.solver().gmmxx().getRestartThreshold(), iter);
101 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::Diagonal) {
102 gmm::gmres(*gmmxxA, x, b, *diagonalPreconditioner, env.solver().gmmxx().getRestartThreshold(), iter);
103 } else if (preconditioner == GmmxxLinearEquationSolverPreconditioner::None) {
104 gmm::gmres(*gmmxxA, x, b, gmm::identity_matrix(), env.solver().gmmxx().getRestartThreshold(), iter);
105 }
106 }
107 } catch (storm::exceptions::AbortException const& e) {
108 // Do nothing
109 }
110
111 if (!this->isCachingEnabled()) {
112 clearCache();
113 }
114
115 // Make sure that all results conform to the bounds.
116 storm::utility::vector::clip(x, this->lowerBound, this->upperBound);
117
118 // Check if the solver converged and issue a warning otherwise.
119 if (iter.converged()) {
120 STORM_LOG_INFO("Iterative solver converged after " << iter.get_iteration() << " iteration(s).");
121 return true;
122 } else {
123 STORM_LOG_WARN("Iterative solver did not converge within " << iter.get_iteration() << " iteration(s).");
124 return false;
125 }
126 }
127
128 STORM_LOG_ERROR("Selected method is not available");
129 return false;
130}
131
132template<typename ValueType>
136
137template<typename ValueType>
139 iluPreconditioner.reset();
140 diagonalPreconditioner.reset();
142}
143
144template<typename ValueType>
146 return gmmxxA->nr;
147}
148
149template<typename ValueType>
150uint64_t GmmxxLinearEquationSolver<ValueType>::getMatrixColumnCount() const {
151 return gmmxxA->nc;
152}
153
154template<typename ValueType>
155std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> GmmxxLinearEquationSolverFactory<ValueType>::create(Environment const& env) const {
156 return std::make_unique<storm::solver::GmmxxLinearEquationSolver<ValueType>>();
157}
158
159template<typename ValueType>
160std::unique_ptr<LinearEquationSolverFactory<ValueType>> GmmxxLinearEquationSolverFactory<ValueType>::clone() const {
161 return std::make_unique<GmmxxLinearEquationSolverFactory<ValueType>>(*this);
162}
163
164// Explicitly instantiate the solver.
167
168} // namespace solver
169} // namespace storm
SolverEnvironment & solver()
storm::RationalNumber const & getPrecision() const
uint64_t const & getMaximalNumberOfIterations() const
storm::solver::GmmxxLinearEquationSolverMethod const & getMethod() const
uint64_t const & getRestartThreshold() const
storm::solver::GmmxxLinearEquationSolverPreconditioner const & getPreconditioner() const
GmmxxSolverEnvironment & gmmxx()
static std::unique_ptr< gmm::csr_matrix< T > > toGmmxxSparseMatrix(storm::storage::SparseMatrix< T > const &matrix)
Converts a sparse matrix into a sparse matrix in the gmm++ format.
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.
A class that uses the gmm++ library to implement the LinearEquationSolver interface.
virtual bool internalSolveEquations(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 LinearEquationSolverProblemFormat getEquationProblemFormat(Environment const &env) const override
Retrieves the format in which this solver expects to solve equations.
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_INFO(message)
Definition logging.h:29
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_ERROR(message)
Definition logging.h:31
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:52
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
std::string toString(GurobiSolverMethod const &method)
Yields a string representation of the GurobiSolverMethod.
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
void clip(std::vector< ValueType > &x, boost::optional< ValueType > const &lowerBound, boost::optional< ValueType > const &upperBound)
Takes the input vector and ensures that all entries conform to the bounds.
Definition vector.h:1041
LabParser.cpp.
Definition cli.cpp:18