Browse Source

refactored auxData in linear equation solvers

Former-commit-id: 9e0deb255c
tempestpy_adaptions
TimQu 8 years ago
parent
commit
48b82e7b14
  1. 1
      src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp
  2. 1
      src/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp
  3. 141
      src/solver/GmmxxLinearEquationSolver.cpp
  4. 24
      src/solver/GmmxxLinearEquationSolver.h
  5. 58
      src/solver/LinearEquationSolver.cpp
  6. 41
      src/solver/LinearEquationSolver.h
  7. 2
      src/solver/MinMaxLinearEquationSolver.h
  8. 106
      src/solver/NativeLinearEquationSolver.cpp
  9. 14
      src/solver/NativeLinearEquationSolver.h
  10. 50
      src/solver/StandardMinMaxLinearEquationSolver.cpp
  11. 10
      src/solver/StandardMinMaxLinearEquationSolver.h
  12. 4
      src/utility/policyguessing.cpp
  13. 78
      test/functional/solver/GmmxxLinearEquationSolverTest.cpp

1
src/modelchecker/csl/helper/SparseCtmcCslHelper.cpp

@ -629,7 +629,6 @@ namespace storm {
}
std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(std::move(uniformizedMatrix));
solver->allocateAuxMemory(storm::solver::LinearEquationSolverOperation::MultiplyRepeatedly);
if (!useMixedPoissonProbabilities && std::get<0>(foxGlynnResult) > 1) {
// Perform the matrix-vector multiplications (without adding).

1
src/modelchecker/multiobjective/pcaa/SparseMaPcaaWeightVectorChecker.cpp

@ -365,7 +365,6 @@ namespace storm {
storm::storage::SparseMatrix<ValueType> linEqMatrix = PS.toPS.selectRowsFromRowGroups(optimalChoicesAtCurrentEpoch, true);
linEqMatrix.convertToEquationSystem();
linEq.solver = linEq.factory.create(std::move(linEqMatrix));
linEq.solver->allocateAuxMemory(storm::solver::LinearEquationSolverOperation::SolveEquations);
}
// Get the results for the individual objectives.

141
src/solver/GmmxxLinearEquationSolver.cpp

@ -111,12 +111,12 @@ namespace storm {
}
template<typename ValueType>
GmmxxLinearEquationSolver<ValueType>::GmmxxLinearEquationSolver(storm::storage::SparseMatrix<ValueType> const& A, GmmxxLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), gmmxxMatrix(nullptr), settings(settings), auxiliaryJacobiMemory(nullptr) {
GmmxxLinearEquationSolver<ValueType>::GmmxxLinearEquationSolver(storm::storage::SparseMatrix<ValueType> const& A, GmmxxLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings) {
this->setMatrix(A);
}
template<typename ValueType>
GmmxxLinearEquationSolver<ValueType>::GmmxxLinearEquationSolver(storm::storage::SparseMatrix<ValueType>&& A, GmmxxLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), gmmxxMatrix(nullptr), settings(settings), auxiliaryJacobiMemory(nullptr) {
GmmxxLinearEquationSolver<ValueType>::GmmxxLinearEquationSolver(storm::storage::SparseMatrix<ValueType>&& A, GmmxxLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings) {
this->setMatrix(std::move(A));
}
@ -124,66 +124,79 @@ namespace storm {
void GmmxxLinearEquationSolver<ValueType>::setMatrix(storm::storage::SparseMatrix<ValueType> const& A) {
localA.reset();
this->A = &A;
gmmxxMatrix = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(A);
jacobiDecomposition.reset();
resetAuxiliaryData();
}
template<typename ValueType>
void GmmxxLinearEquationSolver<ValueType>::setMatrix(storm::storage::SparseMatrix<ValueType>&& A) {
localA = std::make_unique<storm::storage::SparseMatrix<ValueType>>(std::move(A));
this->A = localA.get();
gmmxxMatrix = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(*localA);
resetAuxiliaryData();
}
template<typename ValueType>
bool GmmxxLinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
auto method = this->getSettings().getSolutionMethod();
auto preconditioner = this->getSettings().getPreconditioner();
STORM_LOG_INFO("Using method '" << method << "' with preconditioner '" << preconditioner << "' (max. " << this->getSettings().getMaximalNumberOfIterations() << " iterations).");
STORM_LOG_DEBUG("Using method '" << method << "' with preconditioner '" << preconditioner << "' (max. " << this->getSettings().getMaximalNumberOfIterations() << " iterations).");
if (method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Jacobi && preconditioner != GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::None) {
STORM_LOG_WARN("Jacobi method currently does not support preconditioners. The requested preconditioner will be ignored.");
}
if (method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Bicgstab || method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Qmr || method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Gmres) {
// Translate the matrix into gmm++ format (if not already done)
if(!gmmxxA) {
gmmxxA = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(*A);
}
// Make sure that the requested preconditioner is available
if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Ilu && !iluPreconditioner) {
iluPreconditioner = std::make_unique<gmm::ilu_precond<gmm::csr_matrix<ValueType>>>(*gmmxxA);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Diagonal) {
diagonalPreconditioner = std::make_unique<gmm::diagonal_precond<gmm::csr_matrix<ValueType>>>(*gmmxxA);
}
// Prepare an iteration object that determines the accuracy and the maximum number of iterations.
gmm::iteration iter(this->getSettings().getPrecision(), 0, this->getSettings().getMaximalNumberOfIterations());
// Invoke gmm with the corresponding settings
if (method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Bicgstab) {
if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Ilu) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::ilu_precond<gmm::csr_matrix<ValueType>>(*gmmxxMatrix), iter);
gmm::bicgstab(*gmmxxA, x, b, *iluPreconditioner, iter);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Diagonal) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::diagonal_precond<gmm::csr_matrix<ValueType>>(*gmmxxMatrix), iter);
gmm::bicgstab(*gmmxxA, x, b, *diagonalPreconditioner, iter);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::None) {
gmm::bicgstab(*gmmxxMatrix, x, b, gmm::identity_matrix(), iter);
gmm::bicgstab(*gmmxxA, x, b, gmm::identity_matrix(), iter);
}
} else if (method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Qmr) {
if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Ilu) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::ilu_precond<gmm::csr_matrix<ValueType>>(*gmmxxMatrix), iter);
gmm::qmr(*gmmxxA, x, b, *iluPreconditioner, iter);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Diagonal) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::diagonal_precond<gmm::csr_matrix<ValueType>>(*gmmxxMatrix), iter);
gmm::qmr(*gmmxxA, x, b, *diagonalPreconditioner, iter);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::None) {
gmm::qmr(*gmmxxMatrix, x, b, gmm::identity_matrix(), iter);
gmm::qmr(*gmmxxA, x, b, gmm::identity_matrix(), iter);
}
} else if (method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Gmres) {
if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Ilu) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::ilu_precond<gmm::csr_matrix<ValueType>>(*gmmxxMatrix), this->getSettings().getNumberOfIterationsUntilRestart(), iter);
gmm::gmres(*gmmxxA, x, b, *iluPreconditioner, this->getSettings().getNumberOfIterationsUntilRestart(), iter);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::Diagonal) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::diagonal_precond<gmm::csr_matrix<ValueType>>(*gmmxxMatrix), this->getSettings().getNumberOfIterationsUntilRestart(), iter);
gmm::gmres(*gmmxxA, x, b, *diagonalPreconditioner, this->getSettings().getNumberOfIterationsUntilRestart(), iter);
} else if (preconditioner == GmmxxLinearEquationSolverSettings<ValueType>::Preconditioner::None) {
gmm::gmres(*gmmxxMatrix, x, b, gmm::identity_matrix(), this->getSettings().getNumberOfIterationsUntilRestart(), iter);
gmm::gmres(*gmmxxA, x, b, gmm::identity_matrix(), this->getSettings().getNumberOfIterationsUntilRestart(), iter);
}
}
// Check if the solver converged and issue a warning otherwise.
if (iter.converged()) {
STORM_LOG_INFO("Iterative solver converged after " << iter.get_iteration() << " iterations.");
STORM_LOG_DEBUG("Iterative solver converged after " << iter.get_iteration() << " iterations.");
return true;
} else {
STORM_LOG_WARN("Iterative solver did not converge.");
return false;
}
} else if (method == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Jacobi) {
uint_fast64_t iterations = solveLinearEquationSystemWithJacobi(*A, x, b);
uint_fast64_t iterations = solveLinearEquationSystemWithJacobi(x, b);
// Check if the solver converged and issue a warning otherwise.
if (iterations < this->getSettings().getMaximalNumberOfIterations()) {
@ -200,39 +213,44 @@ namespace storm {
template<typename ValueType>
void GmmxxLinearEquationSolver<ValueType>::multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const {
if(!gmmxxA) {
gmmxxA = storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(*A);
}
if (b) {
gmm::mult_add(*gmmxxMatrix, x, *b, result);
gmm::mult_add(*gmmxxA, x, *b, result);
} else {
gmm::mult(*gmmxxMatrix, x, result);
gmm::mult(*gmmxxA, x, result);
}
}
template<typename ValueType>
uint_fast64_t GmmxxLinearEquationSolver<ValueType>::solveLinearEquationSystemWithJacobi(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
bool allocatedAuxMemory = !this->hasAuxMemory(LinearEquationSolverOperation::SolveEquations);
if (allocatedAuxMemory) {
this->allocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
}
uint_fast64_t GmmxxLinearEquationSolver<ValueType>::solveLinearEquationSystemWithJacobi(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
// Get a Jacobi decomposition of the matrix A (if not already available).
if(jacobiDecomposition == nullptr) {
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> nativeJacobiDecomposition = A.getJacobiDecomposition();
if(!jacobiDecomposition) {
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> nativeJacobiDecomposition = A->getJacobiDecomposition();
// Convert the LU matrix to gmm++'s format.
jacobiDecomposition = std::make_unique<std::pair<gmm::csr_matrix<ValueType>, std::vector<ValueType>>>(*storm::adapters::GmmxxAdapter::toGmmxxSparseMatrix<ValueType>(std::move(nativeJacobiDecomposition.first)),
std::move(nativeJacobiDecomposition.second));
}
gmm::csr_matrix<ValueType> const& jacobiLU = jacobiDecomposition->first;
std::vector<ValueType> const& jacobiD = jacobiDecomposition->second;
std::vector<ValueType>* currentX = &x;
std::vector<ValueType>* nextX = auxiliaryJacobiMemory.get();
if(!this->auxiliaryRowVector) {
this->auxiliaryRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount());
}
std::vector<ValueType>* nextX = this->auxiliaryRowVector.get();
// Set up additional environment variables.
uint_fast64_t iterationCount = 0;
bool converged = false;
while (!converged && iterationCount < this->getSettings().getMaximalNumberOfIterations() && !(this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(*currentX))) {
// Compute D^-1 * (b - LU * x) and store result in nextX.
gmm::mult_add(jacobiDecomposition->first, gmm::scaled(*currentX, -storm::utility::one<ValueType>()), b, *nextX);
storm::utility::vector::multiplyVectorsPointwise(jacobiDecomposition->second, *nextX, *nextX);
gmm::mult_add(jacobiLU, gmm::scaled(*currentX, -storm::utility::one<ValueType>()), b, *nextX);
storm::utility::vector::multiplyVectorsPointwise(jacobiD, *nextX, *nextX);
// Now check if the process already converged within our precision.
converged = storm::utility::vector::equalModuloPrecision(*currentX, *nextX, this->getSettings().getPrecision(), this->getSettings().getRelativeTerminationCriterion());
@ -246,21 +264,16 @@ namespace storm {
// If the last iteration did not write to the original x we have to swap the contents, because the
// output has to be written to the input parameter x.
if (currentX == auxiliaryJacobiMemory.get()) {
if (currentX == this->auxiliaryRowVector.get()) {
std::swap(x, *currentX);
}
// If we allocated auxiliary memory, we need to dispose of it now.
if (allocatedAuxMemory) {
this->deallocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
}
return iterationCount;
}
template<typename ValueType>
GmmxxLinearEquationSolverSettings<ValueType>& GmmxxLinearEquationSolver<ValueType>::getSettings() {
return settings;
void GmmxxLinearEquationSolver<ValueType>::setSettings(GmmxxLinearEquationSolverSettings<ValueType> const& newSettings) {
settings = newSettings;
}
template<typename ValueType>
@ -269,54 +282,12 @@ namespace storm {
}
template<typename ValueType>
bool GmmxxLinearEquationSolver<ValueType>::allocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
if (this->getSettings().getSolutionMethod() == GmmxxLinearEquationSolverSettings<ValueType>::SolutionMethod::Jacobi) {
if (!auxiliaryJacobiMemory) {
auxiliaryJacobiMemory = std::make_unique<std::vector<ValueType>>(this->getMatrixRowCount());
result = true;
}
}
}
result |= LinearEquationSolver<ValueType>::allocateAuxMemory(operation);
return result;
}
template<typename ValueType>
bool GmmxxLinearEquationSolver<ValueType>::deallocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
if (auxiliaryJacobiMemory) {
result = true;
auxiliaryJacobiMemory.reset();
}
}
result |= LinearEquationSolver<ValueType>::deallocateAuxMemory(operation);
return result;
}
template<typename ValueType>
bool GmmxxLinearEquationSolver<ValueType>::reallocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
if (auxiliaryJacobiMemory) {
result = auxiliaryJacobiMemory->size() != this->getMatrixColumnCount();
auxiliaryJacobiMemory->resize(this->getMatrixRowCount());
}
}
result |= LinearEquationSolver<ValueType>::reallocateAuxMemory(operation);
return result;
}
template<typename ValueType>
bool GmmxxLinearEquationSolver<ValueType>::hasAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
result |= static_cast<bool>(auxiliaryJacobiMemory);
}
result |= LinearEquationSolver<ValueType>::hasAuxMemory(operation);
return result;
void GmmxxLinearEquationSolver<ValueType>::resetAuxiliaryData() const {
gmmxxA.reset();
iluPreconditioner.reset();
diagonalPreconditioner.reset();
jacobiDecomposition.reset();
LinearEquationSolver<ValueType>::resetAuxiliaryData();
}
template<typename ValueType>

24
src/solver/GmmxxLinearEquationSolver.h

@ -95,29 +95,26 @@ namespace storm {
virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
virtual void multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const override;
GmmxxLinearEquationSolverSettings<ValueType>& getSettings();
void setSettings(GmmxxLinearEquationSolverSettings<ValueType> const& newSettings);
GmmxxLinearEquationSolverSettings<ValueType> const& getSettings() const;
virtual bool allocateAuxMemory(LinearEquationSolverOperation operation) const override;
virtual bool deallocateAuxMemory(LinearEquationSolverOperation operation) const override;
virtual bool reallocateAuxMemory(LinearEquationSolverOperation operation) const override;
virtual bool hasAuxMemory(LinearEquationSolverOperation operation) const override;
/*
* Clears auxiliary data that has possibly been stored during previous calls of the solver.
*/
virtual void resetAuxiliaryData() const override;
private:
/*!
* Solves the linear equation system A*x = b given by the parameters using the Jacobi method.
*
* @param A The matrix specifying the coefficients of the linear equations.
* @param x The solution vector x. The initial values of x represent a guess of the real values to the
* solver, but may be set to zero.
* @param b The right-hand side of the equation system.
* @return The number of iterations needed until convergence if the solver converged and
* maximalNumberOfIteration otherwise.
* @param multiplyResult If non-null, this memory is used as a scratch memory. If given, the length of this
* vector must be equal to the number of rows of A.
*/
uint_fast64_t solveLinearEquationSystemWithJacobi(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
uint_fast64_t solveLinearEquationSystemWithJacobi(std::vector<ValueType>& x, std::vector<ValueType> const& b) const;
virtual uint64_t getMatrixRowCount() const override;
virtual uint64_t getMatrixColumnCount() const override;
@ -130,14 +127,13 @@ namespace storm {
// the pointer refers to localA.
storm::storage::SparseMatrix<ValueType> const* A;
// The (gmm++) matrix associated with this equation solver.
std::unique_ptr<gmm::csr_matrix<ValueType>> gmmxxMatrix;
// The settings used by the solver.
GmmxxLinearEquationSolverSettings<ValueType> settings;
// Auxiliary storage for the Jacobi method.
mutable std::unique_ptr<std::vector<ValueType>> auxiliaryJacobiMemory;
// Auxiliary data obtained during solving
mutable std::unique_ptr<gmm::csr_matrix<ValueType>> gmmxxA;
mutable std::unique_ptr<gmm::ilu_precond<gmm::csr_matrix<ValueType>>> iluPreconditioner;
mutable std::unique_ptr<gmm::diagonal_precond<gmm::csr_matrix<ValueType>>> diagonalPreconditioner;
mutable std::unique_ptr<std::pair<gmm::csr_matrix<ValueType>, std::vector<ValueType>>> jacobiDecomposition;
};

58
src/solver/LinearEquationSolver.cpp

@ -14,21 +14,21 @@ namespace storm {
namespace solver {
template<typename ValueType>
LinearEquationSolver<ValueType>::LinearEquationSolver() : auxiliaryRepeatedMultiplyMemory(nullptr) {
LinearEquationSolver<ValueType>::LinearEquationSolver() {
// Intentionally left empty.
}
template<typename ValueType>
void LinearEquationSolver<ValueType>::repeatedMultiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, uint_fast64_t n) const {
bool allocatedAuxMemory = !this->hasAuxMemory(LinearEquationSolverOperation::MultiplyRepeatedly);
if (allocatedAuxMemory) {
this->allocateAuxMemory(LinearEquationSolverOperation::MultiplyRepeatedly);
if(!auxiliaryRowVector) {
auxiliaryRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount());
}
// Set up some temporary variables so that we can just swap pointers instead of copying the result after
// each iteration.
std::vector<ValueType>* currentX = &x;
std::vector<ValueType>* nextX = auxiliaryRepeatedMultiplyMemory.get();
std::vector<ValueType>* nextX = auxiliaryRowVector.get();
// Now perform matrix-vector multiplication as long as we meet the bound.
for (uint_fast64_t i = 0; i < n; ++i) {
@ -38,56 +38,16 @@ namespace storm {
// If we performed an odd number of repetitions, we need to swap the contents of currentVector and x,
// because the output is supposed to be stored in the input vector x.
if (currentX == auxiliaryRepeatedMultiplyMemory.get()) {
if (currentX == auxiliaryRowVector.get()) {
std::swap(x, *currentX);
}
// If we allocated auxiliary memory, we need to dispose of it now.
if (allocatedAuxMemory) {
this->deallocateAuxMemory(LinearEquationSolverOperation::MultiplyRepeatedly);
}
}
template<typename ValueType>
bool LinearEquationSolver<ValueType>::allocateAuxMemory(LinearEquationSolverOperation operation) const {
if (!auxiliaryRepeatedMultiplyMemory) {
auxiliaryRepeatedMultiplyMemory = std::make_unique<std::vector<ValueType>>(this->getMatrixColumnCount());
return true;
}
return false;
void LinearEquationSolver<ValueType>::resetAuxiliaryData() const {
auxiliaryRowVector.reset();
}
template<typename ValueType>
bool LinearEquationSolver<ValueType>::deallocateAuxMemory(LinearEquationSolverOperation operation) const {
if (operation == LinearEquationSolverOperation::MultiplyRepeatedly) {
if (auxiliaryRepeatedMultiplyMemory) {
auxiliaryRepeatedMultiplyMemory.reset();
return true;
}
}
return false;
}
template<typename ValueType>
bool LinearEquationSolver<ValueType>::reallocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::MultiplyRepeatedly) {
if (auxiliaryRepeatedMultiplyMemory) {
result = auxiliaryRepeatedMultiplyMemory->size() != this->getMatrixColumnCount();
auxiliaryRepeatedMultiplyMemory->resize(this->getMatrixColumnCount());
}
}
return result;
}
template<typename ValueType>
bool LinearEquationSolver<ValueType>::hasAuxMemory(LinearEquationSolverOperation operation) const {
if (operation == LinearEquationSolverOperation::MultiplyRepeatedly) {
return static_cast<bool>(auxiliaryRepeatedMultiplyMemory);
}
return false;
}
template<typename ValueType>
std::unique_ptr<LinearEquationSolver<ValueType>> LinearEquationSolverFactory<ValueType>::create(storm::storage::SparseMatrix<ValueType>&& matrix) const {
return create(matrix);

41
src/solver/LinearEquationSolver.h

@ -68,40 +68,15 @@ namespace storm {
*/
void repeatedMultiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, uint_fast64_t n) const;
// Methods related to allocating/freeing auxiliary storage.
/*!
* Allocates auxiliary memory that can be used to perform the provided operation. Repeated calls to the
* corresponding function can then be run without allocating/deallocating this memory repeatedly.
* Note: Since the allocated memory is fit to the currently selected options of the solver, they must not
* be changed any more after allocating the auxiliary memory until it is deallocated again.
*
* @return True iff auxiliary memory was allocated.
*/
virtual bool allocateAuxMemory(LinearEquationSolverOperation operation) const;
/*!
* Destroys previously allocated auxiliary memory for the provided operation.
*
* @return True iff auxiliary memory was deallocated.
*/
virtual bool deallocateAuxMemory(LinearEquationSolverOperation operation) const;
/*!
* If the matrix dimensions changed and auxiliary memory was allocated, this function needs to be called to
* update the auxiliary memory.
*
* @return True iff the auxiliary memory was reallocated.
*/
virtual bool reallocateAuxMemory(LinearEquationSolverOperation operation) const;
/*!
* Checks whether the solver has allocated auxiliary memory for the provided operation.
*
* @return True iff auxiliary memory was previously allocated (and not yet deallocated).
/*
* Clears auxiliary data that has possibly been stored during previous calls of the solver.
*/
virtual bool hasAuxMemory(LinearEquationSolverOperation operation) const;
virtual void resetAuxiliaryData() const;
protected:
// auxiliary storage. If set, this vector has getMatrixRowCount() entries.
mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRowVector;
private:
/*!
* Retrieves the row count of the matrix associated with this solver.
@ -113,8 +88,6 @@ namespace storm {
*/
virtual uint64_t getMatrixColumnCount() const = 0;
// Auxiliary memory for repeated matrix-vector multiplication.
mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRepeatedMultiplyMemory;
};
template<typename ValueType>

2
src/solver/MinMaxLinearEquationSolver.h

@ -129,7 +129,7 @@ namespace storm {
virtual bool getRelative() const = 0;
/*
* Resets the auxiliary data that has been stored during previous calls of this solver
* Clears auxiliary data that has possibly been stored during previous calls of the solver.
*/
virtual void resetAuxiliaryData() const;

106
src/solver/NativeLinearEquationSolver.cpp

@ -84,12 +84,12 @@ namespace storm {
}
template<typename ValueType>
NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver(storm::storage::SparseMatrix<ValueType> const& A, NativeLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings), auxiliarySolvingMemory(nullptr) {
NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver(storm::storage::SparseMatrix<ValueType> const& A, NativeLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings) {
this->setMatrix(A);
}
template<typename ValueType>
NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver(storm::storage::SparseMatrix<ValueType>&& A, NativeLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings), auxiliarySolvingMemory(nullptr) {
NativeLinearEquationSolver<ValueType>::NativeLinearEquationSolver(storm::storage::SparseMatrix<ValueType>&& A, NativeLinearEquationSolverSettings<ValueType> const& settings) : localA(nullptr), A(nullptr), settings(settings) {
this->setMatrix(std::move(A));
}
@ -97,20 +97,21 @@ namespace storm {
void NativeLinearEquationSolver<ValueType>::setMatrix(storm::storage::SparseMatrix<ValueType> const& A) {
localA.reset();
this->A = &A;
resetAuxiliaryData();
}
template<typename ValueType>
void NativeLinearEquationSolver<ValueType>::setMatrix(storm::storage::SparseMatrix<ValueType>&& A) {
localA = std::make_unique<storm::storage::SparseMatrix<ValueType>>(std::move(A));
this->A = localA.get();
resetAuxiliaryData();
}
template<typename ValueType>
bool NativeLinearEquationSolver<ValueType>::solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
bool allocatedAuxStorage = !this->hasAuxMemory(LinearEquationSolverOperation::SolveEquations);
if (allocatedAuxStorage) {
this->allocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
if(!this->auxiliaryRowVector) {
this->auxiliaryRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount());
}
if (this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::SOR || this->getSettings().getSolutionMethod() == NativeLinearEquationSolverSettings<ValueType>::SolutionMethod::GaussSeidel) {
@ -125,29 +126,29 @@ namespace storm {
A->performSuccessiveOverRelaxationStep(omega, x, b);
// Now check if the process already converged within our precision.
converged = storm::utility::vector::equalModuloPrecision<ValueType>(*auxiliarySolvingMemory, x, static_cast<ValueType>(this->getSettings().getPrecision()), this->getSettings().getRelativeTerminationCriterion()) || (this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(x));
converged = storm::utility::vector::equalModuloPrecision<ValueType>(*this->auxiliaryRowVector, x, static_cast<ValueType>(this->getSettings().getPrecision()), this->getSettings().getRelativeTerminationCriterion()) || (this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(x));
// If we did not yet converge, we need to backup the contents of x.
if (!converged) {
*auxiliarySolvingMemory = x;
*this->auxiliaryRowVector = x;
}
// Increase iteration count so we can abort if convergence is too slow.
++iterationCount;
}
// If we allocated auxiliary memory, we need to dispose of it now.
if (allocatedAuxStorage) {
this->deallocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
}
return converged;
} else {
// Get a Jacobi decomposition of the matrix A.
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> jacobiDecomposition = A->getJacobiDecomposition();
if(!jacobiDecomposition) {
jacobiDecomposition = std::make_unique<std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>>>(A->getJacobiDecomposition());
}
storm::storage::SparseMatrix<ValueType> const& jacobiLU = jacobiDecomposition->first;
std::vector<ValueType> const& jacobiD = jacobiDecomposition->second;
std::vector<ValueType>* currentX = &x;
std::vector<ValueType>* nextX = auxiliarySolvingMemory.get();
std::vector<ValueType>* nextX = this->auxiliaryRowVector.get();
// Set up additional environment variables.
uint_fast64_t iterationCount = 0;
@ -155,9 +156,9 @@ namespace storm {
while (!converged && iterationCount < this->getSettings().getMaximalNumberOfIterations() && !(this->hasCustomTerminationCondition() && this->getTerminationCondition().terminateNow(*currentX))) {
// Compute D^-1 * (b - LU * x) and store result in nextX.
jacobiDecomposition.first.multiplyWithVector(*currentX, *nextX);
jacobiLU.multiplyWithVector(*currentX, *nextX);
storm::utility::vector::subtractVectors(b, *nextX, *nextX);
storm::utility::vector::multiplyVectorsPointwise(jacobiDecomposition.second, *nextX, *nextX);
storm::utility::vector::multiplyVectorsPointwise(jacobiD, *nextX, *nextX);
// Now check if the process already converged within our precision.
converged = storm::utility::vector::equalModuloPrecision<ValueType>(*currentX, *nextX, static_cast<ValueType>(this->getSettings().getPrecision()), this->getSettings().getRelativeTerminationCriterion());
@ -171,18 +172,12 @@ namespace storm {
// If the last iteration did not write to the original x we have to swap the contents, because the
// output has to be written to the input parameter x.
if (currentX == auxiliarySolvingMemory.get()) {
if (currentX == this->auxiliaryRowVector.get()) {
std::swap(x, *currentX);
}
// If we allocated auxiliary memory, we need to dispose of it now.
if (allocatedAuxStorage) {
this->deallocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
}
return iterationCount < this->getSettings().getMaximalNumberOfIterations();
}
}
template<typename ValueType>
@ -194,17 +189,21 @@ namespace storm {
}
} else {
// If the two vectors are aliases, we need to create a temporary.
std::vector<ValueType> tmp(result.size());
A->multiplyWithVector(x, tmp);
if(!this->auxiliaryRowVector) {
this->auxiliaryRowVector = std::make_unique<std::vector<ValueType>>(getMatrixRowCount());
}
A->multiplyWithVector(x, *this->auxiliaryRowVector);
if (b != nullptr) {
storm::utility::vector::addVectors(tmp, *b, result);
storm::utility::vector::addVectors(*this->auxiliaryRowVector, *b, result);
} else {
result.swap(*this->auxiliaryRowVector);
}
}
}
template<typename ValueType>
NativeLinearEquationSolverSettings<ValueType>& NativeLinearEquationSolver<ValueType>::getSettings() {
return settings;
void NativeLinearEquationSolver<ValueType>::setSettings(NativeLinearEquationSolverSettings<ValueType> const& newSettings) {
settings = newSettings;
}
template<typename ValueType>
@ -213,52 +212,9 @@ namespace storm {
}
template<typename ValueType>
bool NativeLinearEquationSolver<ValueType>::allocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
if (!auxiliarySolvingMemory) {
auxiliarySolvingMemory = std::make_unique<std::vector<ValueType>>(this->getMatrixRowCount());
result = true;
}
}
result |= LinearEquationSolver<ValueType>::allocateAuxMemory(operation);
return result;
}
template<typename ValueType>
bool NativeLinearEquationSolver<ValueType>::deallocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
if (auxiliarySolvingMemory) {
result = true;
auxiliarySolvingMemory.reset();
}
}
result |= LinearEquationSolver<ValueType>::deallocateAuxMemory(operation);
return result;
}
template<typename ValueType>
bool NativeLinearEquationSolver<ValueType>::reallocateAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
if (auxiliarySolvingMemory) {
result = auxiliarySolvingMemory->size() != this->getMatrixColumnCount();
auxiliarySolvingMemory->resize(this->getMatrixRowCount());
}
}
result |= LinearEquationSolver<ValueType>::reallocateAuxMemory(operation);
return result;
}
template<typename ValueType>
bool NativeLinearEquationSolver<ValueType>::hasAuxMemory(LinearEquationSolverOperation operation) const {
bool result = false;
if (operation == LinearEquationSolverOperation::SolveEquations) {
result |= static_cast<bool>(auxiliarySolvingMemory);
}
result |= LinearEquationSolver<ValueType>::hasAuxMemory(operation);
return result;
void NativeLinearEquationSolver<ValueType>::resetAuxiliaryData() const {
jacobiDecomposition.reset();
LinearEquationSolver<ValueType>::resetAuxiliaryData();
}
template<typename ValueType>
@ -301,4 +257,4 @@ namespace storm {
template class NativeLinearEquationSolver<double>;
template class NativeLinearEquationSolverFactory<double>;
}
}
}

14
src/solver/NativeLinearEquationSolver.h

@ -52,15 +52,14 @@ namespace storm {
virtual bool solveEquations(std::vector<ValueType>& x, std::vector<ValueType> const& b) const override;
virtual void multiply(std::vector<ValueType>& x, std::vector<ValueType> const* b, std::vector<ValueType>& result) const override;
NativeLinearEquationSolverSettings<ValueType>& getSettings();
void setSettings(NativeLinearEquationSolverSettings<ValueType> const& newSettings);
NativeLinearEquationSolverSettings<ValueType> const& getSettings() const;
virtual bool allocateAuxMemory(LinearEquationSolverOperation operation) const override;
virtual bool deallocateAuxMemory(LinearEquationSolverOperation operation) const override;
virtual bool reallocateAuxMemory(LinearEquationSolverOperation operation) const override;
virtual bool hasAuxMemory(LinearEquationSolverOperation operation) const override;
/*
* Clears auxiliary data that has possibly been stored during previous calls of the solver.
*/
virtual void resetAuxiliaryData() const override;
storm::storage::SparseMatrix<ValueType> const& getMatrix() const { return *A; }
private:
virtual uint64_t getMatrixRowCount() const override;
virtual uint64_t getMatrixColumnCount() const override;
@ -76,8 +75,7 @@ namespace storm {
// The settings used by the solver.
NativeLinearEquationSolverSettings<ValueType> settings;
// Auxiliary memory for the equation solving methods.
mutable std::unique_ptr<std::vector<ValueType>> auxiliarySolvingMemory;
mutable std::unique_ptr<std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>>> jacobiDecomposition;
};
template<typename ValueType>

50
src/solver/StandardMinMaxLinearEquationSolver.cpp

@ -99,10 +99,10 @@ namespace storm {
std::vector<storm::storage::sparse::state_type> scheduler(this->A.getRowGroupCount());
// Get a vector for storing the right-hand side of the inner equation system.
if(!auxiliaryData.rowGroupVector) {
auxiliaryData.rowGroupVector = std::make_unique<std::vector<ValueType>>(this->A.getRowGroupCount());
if(!auxiliaryRowGroupVector) {
auxiliaryRowGroupVector = std::make_unique<std::vector<ValueType>>(this->A.getRowGroupCount());
}
std::vector<ValueType>& subB = *auxiliaryData.rowGroupVector;
std::vector<ValueType>& subB = *auxiliaryRowGroupVector;
// Resolve the nondeterminism according to the current scheduler.
storm::storage::SparseMatrix<ValueType> submatrix = this->A.selectRowsFromRowGroups(scheduler, true);
@ -111,7 +111,6 @@ namespace storm {
// Create a solver that we will use throughout the procedure. We will modify the matrix in each iteration.
auto solver = linearEquationSolverFactory->create(std::move(submatrix));
solver->allocateAuxMemory(LinearEquationSolverOperation::SolveEquations);
Status status = Status::InProgress;
uint64_t iterations = 0;
@ -139,6 +138,8 @@ namespace storm {
choiceValue += b[choice];
// If the value is strictly better than the solution of the inner system, we need to improve the scheduler.
// TODO: If the underlying solver is not precise, this might run forever (i.e. when a state has two choices where the (exact) values are equal).
// only changing the scheduler if the values are not equal (modulo precision) would make this unsound.
if (valueImproved(dir, x[group], choiceValue)) {
schedulerImproved = true;
scheduler[group] = choice - this->A.getRowGroupIndices()[group];
@ -205,19 +206,19 @@ namespace storm {
template<typename ValueType>
bool StandardMinMaxLinearEquationSolver<ValueType>::solveEquationsValueIteration(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const {
if(!auxiliaryData.linEqSolver) {
auxiliaryData.linEqSolver = linearEquationSolverFactory->create(A);
if(!linEqSolverA) {
linEqSolverA = linearEquationSolverFactory->create(A);
}
if (!auxiliaryData.rowVector.get()) {
auxiliaryData.rowVector = std::make_unique<std::vector<ValueType>>(A.getRowCount());
if (!auxiliaryRowVector.get()) {
auxiliaryRowVector = std::make_unique<std::vector<ValueType>>(A.getRowCount());
}
std::vector<ValueType>& multiplyResult = *auxiliaryData.rowVector;
std::vector<ValueType>& multiplyResult = *auxiliaryRowVector;
if (!auxiliaryData.rowGroupVector.get()) {
auxiliaryData.rowGroupVector = std::make_unique<std::vector<ValueType>>(A.getRowGroupCount());
if (!auxiliaryRowGroupVector.get()) {
auxiliaryRowGroupVector = std::make_unique<std::vector<ValueType>>(A.getRowGroupCount());
}
std::vector<ValueType>* newX = auxiliaryData.rowGroupVector.get();
std::vector<ValueType>* newX = auxiliaryRowGroupVector.get();
std::vector<ValueType>* currentX = &x;
@ -227,7 +228,7 @@ namespace storm {
Status status = Status::InProgress;
while (status == Status::InProgress) {
// Compute x' = A*x + b.
auxiliaryData.linEqSolver->multiply(*currentX, &b, multiplyResult);
linEqSolverA->multiply(*currentX, &b, multiplyResult);
// Reduce the vector x' by applying min/max for all non-deterministic choices.
storm::utility::vector::reduceVectorMinOrMax(dir, multiplyResult, *newX, this->A.getRowGroupIndices());
@ -248,14 +249,14 @@ namespace storm {
// If we performed an odd number of iterations, we need to swap the x and currentX, because the newest result
// is currently stored in currentX, but x is the output vector.
if (currentX == auxiliaryData.rowGroupVector.get()) {
if (currentX == auxiliaryRowGroupVector.get()) {
std::swap(x, *currentX);
}
// If requested, we store the scheduler for retrieval.
if (this->isTrackSchedulerSet()) {
if(iterations==0){ //may happen due to custom termination condition. Then we need to compute x'= A*x+b
auxiliaryData.linEqSolver->multiply(x, &b, multiplyResult);
linEqSolverA->multiply(x, &b, multiplyResult);
}
std::vector<storm::storage::sparse::state_type> choices(this->A.getRowGroupCount());
// Reduce the multiplyResult and keep track of the choices made
@ -272,17 +273,17 @@ namespace storm {
template<typename ValueType>
void StandardMinMaxLinearEquationSolver<ValueType>::repeatedMultiply(OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType>* b, uint_fast64_t n) const {
if(!auxiliaryData.linEqSolver) {
auxiliaryData.linEqSolver = linearEquationSolverFactory->create(A);
if(!linEqSolverA) {
linEqSolverA = linearEquationSolverFactory->create(A);
}
if (!auxiliaryData.rowVector.get()) {
auxiliaryData.rowVector = std::make_unique<std::vector<ValueType>>(A.getRowCount());
if (!auxiliaryRowVector.get()) {
auxiliaryRowVector = std::make_unique<std::vector<ValueType>>(A.getRowCount());
}
std::vector<ValueType>& multiplyResult = *auxiliaryData.rowVector;
std::vector<ValueType>& multiplyResult = *auxiliaryRowVector;
for (uint64_t i = 0; i < n; ++i) {
auxiliaryData.linEqSolver->multiply(x, b, multiplyResult);
linEqSolverA->multiply(x, b, multiplyResult);
// Reduce the vector x' by applying min/max for all non-deterministic choices as given by the topmost
// element of the min/max operator stack.
@ -325,9 +326,10 @@ namespace storm {
template<typename ValueType>
void StandardMinMaxLinearEquationSolver<ValueType>::resetAuxiliaryData() const {
auxiliaryData.linEqSolver.reset();
auxiliaryData.rowVector.reset();
auxiliaryData.rowGroupVector.reset();
linEqSolverA.reset();
auxiliaryRowVector.reset();
auxiliaryRowGroupVector.reset();
MinMaxLinearEquationSolver<ValueType>::resetAuxiliaryData();
}
template<typename ValueType>

10
src/solver/StandardMinMaxLinearEquationSolver.h

@ -60,13 +60,9 @@ namespace storm {
Converged, TerminatedEarly, MaximalIterationsExceeded, InProgress
};
struct AuxiliaryData {
std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> linEqSolver;
std::unique_ptr<std::vector<ValueType>> rowVector; // A.rowCount() entries
std::unique_ptr<std::vector<ValueType>> rowGroupVector; // A.rowGroupCount() entries
};
mutable AuxiliaryData auxiliaryData;
mutable std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> linEqSolverA;
mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRowVector; // A.rowCount() entries
mutable std::unique_ptr<std::vector<ValueType>> auxiliaryRowGroupVector; // A.rowGroupCount() entries
Status updateStatusIfNotConverged(Status status, std::vector<ValueType> const& x, uint64_t iterations) const;
void reportStatus(Status status, uint64_t iterations) const;

4
src/utility/policyguessing.cpp

@ -171,14 +171,16 @@ namespace storm {
storm::utility::vector::selectVectorValues(subB, probGreater0States, b);
std::unique_ptr<storm::solver::GmmxxLinearEquationSolver<ValueType>> linEqSysSolver(static_cast<storm::solver::GmmxxLinearEquationSolver<ValueType>*>(storm::solver::GmmxxLinearEquationSolverFactory<ValueType>().create(eqSysA).release()));
auto& eqSettings = linEqSysSolver->getSettings();
auto eqSettings = linEqSysSolver->getSettings();
eqSettings.setRelativeTerminationCriterion(relative);
eqSettings.setMaximalNumberOfIterations(500);
linEqSysSolver->setSettings(eqSettings);
std::size_t iterations = 0;
std::vector<ValueType> copyX(subX.size());
ValueType precisionChangeFactor = storm::utility::one<ValueType>();
do {
eqSettings.setPrecision(eqSettings.getPrecision() * precisionChangeFactor);
linEqSysSolver->setSettings(eqSettings);
if(!linEqSysSolver->solveEquations(subX, subB)){
// break; //Solver did not converge.. so we have to go on with the current solution.
}

78
test/functional/solver/GmmxxLinearEquationSolverTest.cpp

@ -54,11 +54,13 @@ TEST(GmmxxLinearEquationSolver, gmres) {
std::vector<double> b = {16, -4, -7};
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
solver.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Gmres);
solver.getSettings().setPrecision(1e-6);
solver.getSettings().setMaximalNumberOfIterations(10000);
solver.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
solver.getSettings().setNumberOfIterationsUntilRestart(50);
auto settings = solver.getSettings();
settings.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Gmres);
settings.setPrecision(1e-6);
settings.setMaximalNumberOfIterations(10000);
settings.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
settings.setNumberOfIterationsUntilRestart(50);
solver.setSettings(settings);
ASSERT_NO_THROW(solver.solveEquations(x, b));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
@ -86,16 +88,20 @@ TEST(GmmxxLinearEquationSolver, qmr) {
std::vector<double> b = {16, -4, -7};
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
solver.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Qmr);
solver.getSettings().setPrecision(1e-6);
solver.getSettings().setMaximalNumberOfIterations(10000);
solver.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
auto settings = solver.getSettings();
settings.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Qmr);
settings.setPrecision(1e-6);
settings.setMaximalNumberOfIterations(10000);
settings.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
solver.setSettings(settings);
storm::solver::GmmxxLinearEquationSolver<double> solver2(A);
solver2.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Qmr);
solver2.getSettings().setPrecision(1e-6);
solver2.getSettings().setMaximalNumberOfIterations(10000);
solver2.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
auto settings2 = solver2.getSettings();
settings2.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Qmr);
settings2.setPrecision(1e-6);
settings2.setMaximalNumberOfIterations(10000);
settings2.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
solver2.setSettings(settings2);
ASSERT_NO_THROW(solver2.solveEquations(x, b));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
@ -123,10 +129,12 @@ TEST(GmmxxLinearEquationSolver, bicgstab) {
std::vector<double> b = {16, -4, -7};
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
solver.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Bicgstab);
solver.getSettings().setPrecision(1e-6);
solver.getSettings().setMaximalNumberOfIterations(10000);
solver.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
auto settings = solver.getSettings();
settings.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Bicgstab);
settings.setPrecision(1e-6);
settings.setMaximalNumberOfIterations(10000);
settings.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
solver.setSettings(settings);
ASSERT_NO_THROW(solver.solveEquations(x, b));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
@ -154,10 +162,12 @@ TEST(GmmxxLinearEquationSolver, jacobi) {
std::vector<double> b = {11, -16, 1};
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
solver.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Jacobi);
solver.getSettings().setPrecision(1e-6);
solver.getSettings().setMaximalNumberOfIterations(10000);
solver.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
auto settings = solver.getSettings();
settings.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Jacobi);
settings.setPrecision(1e-6);
settings.setMaximalNumberOfIterations(10000);
settings.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::None);
solver.setSettings(settings);
ASSERT_NO_THROW(solver.solveEquations(x, b));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
ASSERT_LT(std::abs(x[1] - 3), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
@ -184,11 +194,13 @@ TEST(GmmxxLinearEquationSolver, gmresilu) {
std::vector<double> b = {16, -4, -7};
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
solver.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Gmres);
solver.getSettings().setPrecision(1e-6);
solver.getSettings().setMaximalNumberOfIterations(10000);
solver.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::Ilu);
solver.getSettings().setNumberOfIterationsUntilRestart(50);
auto settings = solver.getSettings();
settings.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Gmres);
settings.setPrecision(1e-6);
settings.setMaximalNumberOfIterations(10000);
settings.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::Ilu);
settings.setNumberOfIterationsUntilRestart(50);
solver.setSettings(settings);
ASSERT_NO_THROW(solver.solveEquations(x, b));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
ASSERT_LT(std::abs(x[1] - 3), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
@ -215,11 +227,13 @@ TEST(GmmxxLinearEquationSolver, gmresdiag) {
std::vector<double> b = {16, -4, -7};
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
solver.getSettings().setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Gmres);
solver.getSettings().setPrecision(1e-6);
solver.getSettings().setMaximalNumberOfIterations(10000);
solver.getSettings().setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::Diagonal);
solver.getSettings().setNumberOfIterationsUntilRestart(50);
auto settings = solver.getSettings();
settings.setSolutionMethod(storm::solver::GmmxxLinearEquationSolverSettings<double>::SolutionMethod::Gmres);
settings.setPrecision(1e-6);
settings.setMaximalNumberOfIterations(10000);
settings.setPreconditioner(storm::solver::GmmxxLinearEquationSolverSettings<double>::Preconditioner::Diagonal);
settings.setNumberOfIterationsUntilRestart(50);
solver.setSettings(settings);
ASSERT_NO_THROW(solver.solveEquations(x, b));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
@ -248,4 +262,4 @@ TEST(GmmxxLinearEquationSolver, MatrixVectorMultiplication) {
storm::solver::GmmxxLinearEquationSolver<double> solver(A);
ASSERT_NO_THROW(solver.repeatedMultiply(x, nullptr, 4));
ASSERT_LT(std::abs(x[0] - 1), storm::settings::getModule<storm::settings::modules::GmmxxEquationSolverSettings>().getPrecision());
}
}
Loading…
Cancel
Save