| 
									
										
										
										
											2019-01-23 11:28:59 +11:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  |  * modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  |  * as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  |  * of the License, or (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  |  * along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) Blender Foundation | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-18 20:10:18 +11:00
										 |  |  | #ifndef __CONSTRAINEDCONJUGATEGRADIENT_H__
 | 
					
						
							|  |  |  | #define __CONSTRAINEDCONJUGATEGRADIENT_H__
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <Eigen/Core>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | namespace Eigen { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace internal { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \internal Low-level conjugate gradient algorithm
 | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |  * \param mat: The matrix A | 
					
						
							|  |  |  |  * \param rhs: The right hand side vector b | 
					
						
							|  |  |  |  * \param x: On input and initial solution, on output the computed solution. | 
					
						
							|  |  |  |  * \param precond: A preconditioner being able to efficiently solve for an | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |  * approximation of Ax=b (regardless of b) | 
					
						
							|  |  |  |  * \param iters: On input the max number of iteration, | 
					
						
							|  |  |  |  * on output the number of performed iterations. | 
					
						
							|  |  |  |  * \param tol_error: On input the tolerance error, | 
					
						
							|  |  |  |  * on output an estimation of the relative error. | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | template<typename MatrixType, | 
					
						
							|  |  |  |          typename Rhs, | 
					
						
							|  |  |  |          typename Dest, | 
					
						
							|  |  |  |          typename FilterMatrixType, | 
					
						
							|  |  |  |          typename Preconditioner> | 
					
						
							|  |  |  | EIGEN_DONT_INLINE void constrained_conjugate_gradient(const MatrixType &mat, | 
					
						
							|  |  |  |                                                       const Rhs &rhs, | 
					
						
							|  |  |  |                                                       Dest &x, | 
					
						
							|  |  |  |                                                       const FilterMatrixType &filter, | 
					
						
							|  |  |  |                                                       const Preconditioner &precond, | 
					
						
							|  |  |  |                                                       int &iters, | 
					
						
							|  |  |  |                                                       typename Dest::RealScalar &tol_error) | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  |   using std::abs; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   using std::sqrt; | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   typedef typename Dest::RealScalar RealScalar; | 
					
						
							|  |  |  |   typedef typename Dest::Scalar Scalar; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   typedef Matrix<Scalar, Dynamic, 1> VectorType; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   RealScalar tol = tol_error; | 
					
						
							|  |  |  |   int maxIters = iters; | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   int n = mat.cols(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |   VectorType residual = filter * (rhs - mat * x);  // initial residual
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   RealScalar rhsNorm2 = (filter * rhs).squaredNorm(); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (rhsNorm2 == 0) { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |     /* XXX TODO set constrained result here */ | 
					
						
							|  |  |  |     x.setZero(); | 
					
						
							|  |  |  |     iters = 0; | 
					
						
							|  |  |  |     tol_error = 0; | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   RealScalar threshold = tol * tol * rhsNorm2; | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   RealScalar residualNorm2 = residual.squaredNorm(); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (residualNorm2 < threshold) { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |     iters = 0; | 
					
						
							|  |  |  |     tol_error = sqrt(residualNorm2 / rhsNorm2); | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   VectorType p(n); | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |   p = filter * precond.solve(residual);  // initial search direction
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   VectorType z(n), tmp(n); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   RealScalar absNew = numext::real( | 
					
						
							|  |  |  |       residual.dot(p));  // the square of the absolute value of r scaled by invM
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   int i = 0; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   while (i < maxIters) { | 
					
						
							|  |  |  |     tmp.noalias() = filter * (mat * p);  // the bottleneck of the algorithm
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     Scalar alpha = absNew / p.dot(tmp);  // the amount we travel on dir
 | 
					
						
							|  |  |  |     x += alpha * p;                      // update solution
 | 
					
						
							|  |  |  |     residual -= alpha * tmp;             // update residue
 | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |     residualNorm2 = residual.squaredNorm(); | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |     if (residualNorm2 < threshold) { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |       break; | 
					
						
							| 
									
										
										
										
											2019-05-31 23:21:16 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     z = precond.solve(residual);  // approximately solve for "A z = residual"
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     RealScalar absOld = absNew; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     absNew = numext::real(residual.dot(z));  // update the absolute value of r
 | 
					
						
							|  |  |  |     RealScalar beta = | 
					
						
							|  |  |  |         absNew / | 
					
						
							|  |  |  |         absOld;  // calculate the Gram-Schmidt value used to create the new search direction
 | 
					
						
							|  |  |  |     p = filter * (z + beta * p);  // update search direction
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |     i++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   tol_error = sqrt(residualNorm2 / rhsNorm2); | 
					
						
							|  |  |  |   iters = i; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | }  // namespace internal
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if 0 /* unused */
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  | template<typename MatrixType> struct MatrixFilter { | 
					
						
							|  |  |  |   MatrixFilter() : m_cmat(NULL) | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   MatrixFilter(const MatrixType &cmat) : m_cmat(&cmat) | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   void setMatrix(const MatrixType &cmat) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     m_cmat = &cmat; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |   template<typename VectorType> void apply(VectorType v) const | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     v = (*m_cmat) * v; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 08:24:14 +02:00
										 |  |  |  protected: | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const MatrixType *m_cmat; | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | template<typename _MatrixType, | 
					
						
							|  |  |  |          int _UpLo = Lower, | 
					
						
							|  |  |  |          typename _FilterMatrixType = _MatrixType, | 
					
						
							|  |  |  |          typename _Preconditioner = DiagonalPreconditioner<typename _MatrixType::Scalar>> | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | class ConstrainedConjugateGradient; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace internal { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | template<typename _MatrixType, int _UpLo, typename _FilterMatrixType, typename _Preconditioner> | 
					
						
							|  |  |  | struct traits< | 
					
						
							|  |  |  |     ConstrainedConjugateGradient<_MatrixType, _UpLo, _FilterMatrixType, _Preconditioner>> { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   typedef _MatrixType MatrixType; | 
					
						
							|  |  |  |   typedef _FilterMatrixType FilterMatrixType; | 
					
						
							|  |  |  |   typedef _Preconditioner Preconditioner; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | }  // namespace internal
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** \ingroup IterativeLinearSolvers_Module
 | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |  * \brief A conjugate gradient solver for sparse self-adjoint problems with additional constraints | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |  * This class allows to solve for A.x = b sparse linear problems using a conjugate gradient | 
					
						
							|  |  |  |  * algorithm. The sparse matrix A must be selfadjoint. The vectors x and b can be either dense or | 
					
						
							|  |  |  |  * sparse. | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * \tparam _MatrixType the type of the sparse matrix A, can be a dense or a sparse matrix. | 
					
						
							|  |  |  |  * \tparam _UpLo the triangular part that will be used for the computations. It can be Lower | 
					
						
							|  |  |  |  *               or Upper. Default is Lower. | 
					
						
							|  |  |  |  * \tparam _Preconditioner the type of the preconditioner. Default is DiagonalPreconditioner | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-04-30 14:41:33 +10:00
										 |  |  |  * The maximal number of iterations and tolerance value can be controlled via the | 
					
						
							|  |  |  |  * setMaxIterations() and setTolerance() methods. The defaults are the size of the problem for the | 
					
						
							|  |  |  |  * maximal number of iterations and NumTraits<Scalar>::epsilon() for the tolerance. | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This class can be used as the direct solver classes. Here is a typical usage example: | 
					
						
							|  |  |  |  * \code | 
					
						
							|  |  |  |  * int n = 10000; | 
					
						
							|  |  |  |  * VectorXd x(n), b(n); | 
					
						
							|  |  |  |  * SparseMatrix<double> A(n,n); | 
					
						
							|  |  |  |  * // fill A and b
 | 
					
						
							|  |  |  |  * ConjugateGradient<SparseMatrix<double> > cg; | 
					
						
							|  |  |  |  * cg.compute(A); | 
					
						
							|  |  |  |  * x = cg.solve(b); | 
					
						
							|  |  |  |  * std::cout << "#iterations:     " << cg.iterations() << std::endl; | 
					
						
							|  |  |  |  * std::cout << "estimated error: " << cg.error()      << std::endl; | 
					
						
							|  |  |  |  * // update b, and solve again
 | 
					
						
							|  |  |  |  * x = cg.solve(b); | 
					
						
							|  |  |  |  * \endcode | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * By default the iterations start with x=0 as an initial guess of the solution. | 
					
						
							|  |  |  |  * One can control the start using the solveWithGuess() method. Here is a step by | 
					
						
							|  |  |  |  * step execution example starting with a random guess and printing the evolution | 
					
						
							|  |  |  |  * of the estimated error: | 
					
						
							|  |  |  |  * * \code | 
					
						
							|  |  |  |  * x = VectorXd::Random(n); | 
					
						
							|  |  |  |  * cg.setMaxIterations(1); | 
					
						
							|  |  |  |  * int i = 0; | 
					
						
							|  |  |  |  * do { | 
					
						
							|  |  |  |  *   x = cg.solveWithGuess(b,x); | 
					
						
							|  |  |  |  *   std::cout << i << " : " << cg.error() << std::endl; | 
					
						
							|  |  |  |  *   ++i; | 
					
						
							|  |  |  |  * } while (cg.info()!=Success && i<100); | 
					
						
							|  |  |  |  * \endcode | 
					
						
							|  |  |  |  * Note that such a step by step execution is slightly slower. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * \sa class SimplicialCholesky, DiagonalPreconditioner, IdentityPreconditioner | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | template<typename _MatrixType, int _UpLo, typename _FilterMatrixType, typename _Preconditioner> | 
					
						
							|  |  |  | class ConstrainedConjugateGradient | 
					
						
							|  |  |  |     : public IterativeSolverBase< | 
					
						
							|  |  |  |           ConstrainedConjugateGradient<_MatrixType, _UpLo, _FilterMatrixType, _Preconditioner>> { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   typedef IterativeSolverBase<ConstrainedConjugateGradient> Base; | 
					
						
							|  |  |  |   using Base::m_error; | 
					
						
							|  |  |  |   using Base::m_info; | 
					
						
							|  |  |  |   using Base::m_isInitialized; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   using Base::m_iterations; | 
					
						
							|  |  |  |   using Base::mp_matrix; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |  public: | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   typedef _MatrixType MatrixType; | 
					
						
							|  |  |  |   typedef typename MatrixType::Scalar Scalar; | 
					
						
							|  |  |  |   typedef typename MatrixType::Index Index; | 
					
						
							|  |  |  |   typedef typename MatrixType::RealScalar RealScalar; | 
					
						
							|  |  |  |   typedef _FilterMatrixType FilterMatrixType; | 
					
						
							|  |  |  |   typedef _Preconditioner Preconditioner; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   enum { UpLo = _UpLo }; | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |  public: | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   /** Default constructor. */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ConstrainedConjugateGradient() : Base() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** Initialize the solver with matrix \a A for further \c Ax=b solving.
 | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |    * | 
					
						
							|  |  |  |    * This constructor is a shortcut for the default constructor followed | 
					
						
							|  |  |  |    * by a call to compute(). | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * \warning this class stores a reference to the matrix A as well as some | 
					
						
							|  |  |  |    * precomputed values that depend on it. Therefore, if \a A is changed | 
					
						
							|  |  |  |    * this class becomes invalid. Call compute() to update it with the new | 
					
						
							|  |  |  |    * matrix A, or modify a copy of A. | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ConstrainedConjugateGradient(const MatrixType &A) : Base(A) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   ~ConstrainedConjugateGradient() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   FilterMatrixType &filter() | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return m_filter; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const FilterMatrixType &filter() const | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     return m_filter; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /** \returns the solution x of \f$ A x = b \f$ using the current decomposition of A
 | 
					
						
							| 
									
										
										
										
											2019-04-18 07:21:26 +02:00
										 |  |  |    * \a x0 as an initial solution. | 
					
						
							|  |  |  |    * | 
					
						
							|  |  |  |    * \sa compute() | 
					
						
							|  |  |  |    */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   template<typename Rhs, typename Guess> | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   inline const internal::solve_retval_with_guess<ConstrainedConjugateGradient, Rhs, Guess> | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   solveWithGuess(const MatrixBase<Rhs> &b, const Guess &x0) const | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     eigen_assert(m_isInitialized && "ConjugateGradient is not initialized."); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     eigen_assert( | 
					
						
							|  |  |  |         Base::rows() == b.rows() && | 
					
						
							|  |  |  |         "ConjugateGradient::solve(): invalid number of rows of the right hand side matrix b"); | 
					
						
							|  |  |  |     return internal::solve_retval_with_guess<ConstrainedConjugateGradient, Rhs, Guess>( | 
					
						
							|  |  |  |         *this, b.derived(), x0); | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /** \internal */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   template<typename Rhs, typename Dest> void _solveWithGuess(const Rhs &b, Dest &x) const | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     m_iterations = Base::maxIterations(); | 
					
						
							|  |  |  |     m_error = Base::m_tolerance; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 00:12:26 +10:00
										 |  |  |     for (int j = 0; j < b.cols(); j++) { | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |       m_iterations = Base::maxIterations(); | 
					
						
							|  |  |  |       m_error = Base::m_tolerance; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       typename Dest::ColXpr xj(x, j); | 
					
						
							|  |  |  |       internal::constrained_conjugate_gradient(mp_matrix->template selfadjointView<UpLo>(), | 
					
						
							|  |  |  |                                                b.col(j), | 
					
						
							|  |  |  |                                                xj, | 
					
						
							|  |  |  |                                                m_filter, | 
					
						
							|  |  |  |                                                Base::m_preconditioner, | 
					
						
							|  |  |  |                                                m_iterations, | 
					
						
							|  |  |  |                                                m_error); | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_isInitialized = true; | 
					
						
							|  |  |  |     m_info = m_error <= Base::m_tolerance ? Success : NoConvergence; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-08 08:07:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   /** \internal */ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   template<typename Rhs, typename Dest> void _solve(const Rhs &b, Dest &x) const | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     x.setOnes(); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     _solveWithGuess(b, x); | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |  protected: | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   FilterMatrixType m_filter; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace internal { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | template<typename _MatrixType, int _UpLo, typename _Filter, typename _Preconditioner, typename Rhs> | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | struct solve_retval<ConstrainedConjugateGradient<_MatrixType, _UpLo, _Filter, _Preconditioner>, | 
					
						
							|  |  |  |                     Rhs> | 
					
						
							|  |  |  |     : solve_retval_base<ConstrainedConjugateGradient<_MatrixType, _UpLo, _Filter, _Preconditioner>, | 
					
						
							|  |  |  |                         Rhs> { | 
					
						
							|  |  |  |   typedef ConstrainedConjugateGradient<_MatrixType, _UpLo, _Filter, _Preconditioner> Dec; | 
					
						
							|  |  |  |   EIGEN_MAKE_SOLVE_HELPERS(Dec, Rhs) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   template<typename Dest> void evalTo(Dest &dst) const | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     dec()._solve(rhs(), dst); | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | }  // end namespace internal
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | }  // end namespace Eigen
 | 
					
						
							| 
									
										
										
										
											2014-09-08 12:31:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | #endif  // __CONSTRAINEDCONJUGATEGRADIENT_H__
 |