[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/ |