| [eigen] Iterative solver module |
[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]
I needed an iterative solver for my project, so I implemented Jacobi,
Gauss-Seidel, and Southwell iterative solvers. They work well, but
they probably can be made much faster. Consider only the API.
Mentioned in http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2010/06/msg00269.html
My notes:
- I tried to follow the Eigen model of providing meaningful names,
and separate concrete types for the different solver objects.
- I think passing matrix A as a pointer breaks some of the Eigen3
conventions, but is necessary to avoid copying large matrices (unless
we accept const Eigen::MatrixXd & A, and retain a pointer to it that
way).
- I think the use of inheritance is good for forcing consistency
between the solver classes but potentially bad for efficiency
Comments?
#ifndef ITERATIVE_SOLVER_H
#define ITERATIVE_SOLVER_H
#include <Eigen/Eigen>
#define real double
class IterativeSolver
{
public:
enum SolutionState
{
/// Solver hasn't even
/// started yet
Indeterminate,
/// The solution is in progress
/// and has neither converged nor
/// diverged yet, but it looks
/// like it is converging as the
/// error is decreasing
IsConverging,
/// The solution has completed
/// and we have a good "x" solution
Converged,
/// The solution is going backwards
/// and error is increasing with each
/// iteration
IsDiverging,
/// Diverged. Got an infinity somewhere.
/// The iterative solver
/// selected cannot actually solve
/// the system specified
Diverged
} ;
protected:
SolutionState solutionState ;
/// The main system to solve.
/// A copy of the system A is
/// NOT made, because that's a
/// huge waste of memory.
/// The IterativeSolver
/// series of classes will never
/// modify the system A
const Eigen::MatrixXd * A ;
/// The solution vector that we
/// want A*x = b.
const Eigen::VectorXd * b ;
/// A has N rows, the solution vector
/// has N columns.
int N ;
/// 'curRow' is an important state variable
/// its the row we are currently relaxing
long long curRow ;
/// 'iteration' is different from I.
/// It is the MAJOR outer loop iteration.
/// For Gauss-Seidel and Jacobi, one iteration
/// constitutes a FULL PASS through the
/// all the rows of the A matrix,
/// but for the Southwell algorithm, its
/// relaxation of a single row of the A
/// matrix. At each "iteration", the
/// Southwell needs to find the maximal error
/// row, so, its concept of an "iteration" is
/// different.
long long iteration ; // long long.. support a huge number of iterations!
/// how far each element may be from 0.0
/// in order for xGuess to be close enough
/// to the true value of "x" for us to call
/// it quits on the iterative process
/// Solving to an iterative solver
/// necessarily is accompanied by
/// "to what precision"?
real tolerance ;
/// Every iterative technique has
/// a residual that needs to be
/// updated after each _major_ iteration
Eigen::VectorXd residual ;
/// xGuess -- our progressively
/// (iteratively) refined estimate
/// of what "x" should be
Eigen::VectorXd xGuess ;
/// Maintain copies of the length
/// squared of the xGuess vector
/// for this iteration AND the
/// previous iteration. Difference
/// between them can be used to
/// identify whether solution is
/// in fact converging or possibly diverging
real norm2, lastNorm2 ;
public:
IterativeSolver( const Eigen::MatrixXd * A_System,
const Eigen::VectorXd * b_solution,
real iTolerance ) ;
/// returns the
real getLastNorm() ;
/// Gives you the estimated
/// solution vector x as computed
/// by the iterative solver
Eigen::VectorXd& getSolutionX() ;
/// The "residual" is a vector that
/// measures "how far off" our xG
/// currently is from the true solution
/// that should produce A*xG - b = 0
void updateResidual() ;
/// Updates the solutionState member
/// and returns to you the current
/// SolutionState
SolutionState checkConvergence() ;
/// Returns true if a Eigen::MatrixXd is
/// diagonally dominant. DD is
/// a sufficient condition for
/// convergence with the Gauss-Seidel method.
bool isDiagonallyDominant( const Eigen::MatrixXd * mat ) ;
/// Tells you if the matrix is DD,
/// and returns the first row that
/// was not DD
bool isDiagonallyDominant( const Eigen::MatrixXd * mat, int *rowNotDD ) ;
/// Completely solves the system to
/// the tolerance precision you have
/// specified in the ctor call
virtual void solve() = 0 ;
/// Things to be done prior to an
/// iterate() call
virtual void preIterate() = 0 ;
/// Performs an actual iteration
virtual void iterate() = 0 ;
/// Things to be done following an
/// iterate call()
virtual void postIterate() = 0 ;
} ;
#endif
Attachment:
IterativeSolver_interface_draft_1.h
Description: Binary data
| Mail converted by MHonArc 2.6.19+ | http://listengine.tuxfamily.org/ |