KrisLibrary  1.0.0
conjgrad.h
Go to the documentation of this file.
1 #ifndef MATH_CONJUGATE_GRADIENT_H
2 #define MATH_CONJUGATE_GRADIENT_H
3 
11 #include <KrisLibrary/Logger.h>
12 #include "vector.h"
13 
14 namespace Math {
15 
19 template < class Matrix >
21 {
22  void set(const Matrix& m) {}
23 
24  void solve(const Vector& r, Vector& x) const {
25  x = r;
26  }
27 };
28 
32 template < class Matrix >
34 {
35  JacobiPreconditioner() : isSet(false) {}
36  JacobiPreconditioner(const Matrix& m) { set(m); }
37 
38  void set(const Matrix& m)
39  {
40  assert(m.m == m.n);
41  diagInv.resize(m.m);
42  isSet = true;
43  for(int i=0; i<m.m; i++) {
44  if(m(i,i) == Zero) {
45  LOG4CXX_INFO(KrisLibrary::logger(),"Preconditioning won't work, there's a zero entry on diagonal!\n");
46  abort();
47  isSet = false;
48  }
49  diagInv(i) = Inv(m(i,i));
50  }
51  }
52 
53  void solve(const Vector& r, Vector& x) const {
54  if(!isSet) {
55  x = r;
56  return;
57  }
58  x.resize(r.n);
59  for(int i=0; i<r.n; i++)
60  x(i) = r(i)*diagInv(i);
61  }
62 
63  bool isSet;
64  Vector diagInv;
65 };
66 
67 
88 template < class Matrix, class Preconditioner >
89 int
90 CG(const Matrix &A, Vector &x, const Vector &b,
91  const Preconditioner &M, int &max_iter, Real &tol)
92 {
93  Real resid;
94  static Vector p, z, q;
95  Real alpha, beta, rho, rho_1;
96 
97  p.resize(x.n);
98  z.resize(x.n);
99  q.resize(x.n);
100 
101  Real normb = norm(b);
102  static Vector r;
103  //r = b - A*x;
104  r.resize(x.n);
105  A.mul(x,p);
106  r.sub(b,p);
107 
108  if (normb == 0.0)
109  normb = 1;
110 
111  if ((resid = norm(r) / normb) <= tol) {
112  tol = resid;
113  max_iter = 0;
114  return 0;
115  }
116 
117  for (int i = 1; i <= max_iter; i++) {
118  //z = M.solve(r);
119  M.solve(r,z);
120  rho = dot(r, z);
121 
122  if (i == 1)
123  p = z;
124  else {
125  beta = rho / rho_1;
126  //p = z + beta * p;
127  p.mul(p,beta);
128  p.add(p,z);
129  }
130 
131  //q = A*p;
132  A.mul(p,q);
133 
134 
135  Real d = dot(p, q);
136  if(d == Zero) {
137  LOG4CXX_INFO(KrisLibrary::logger(),"matrix is not SPD\n");
138  max_iter = 0;
139  return 0;
140  }
141 
142  alpha = rho / d;
143 
144  //x += alpha * p;
145  //r -= alpha * q;
146  x.madd(p,alpha);
147  r.madd(q,-alpha);
148 
149  if ((resid = norm(r) / normb) <= tol) {
150  tol = resid;
151  max_iter = i;
152  return 0;
153  }
154 
155  rho_1 = rho;
156  }
157 
158  tol = resid;
159  return 1;
160 }
161 
162 
163 /*
164 template < class Matrix, class Vector, class Preconditioner, class Real >
165 int
166 CG(const Matrix &A, Vector &x, const Vector &b,
167  const Preconditioner &M, int &max_iter, Real &tol)
168 {
169  Real resid;
170  Vector p, z, q;
171  Vector alpha(1), beta(1), rho(1), rho_1(1);
172 
173  Real normb = norm(b);
174  Vector r = b - A*x;
175 
176  if (normb == 0.0)
177  normb = 1;
178 
179  if ((resid = norm(r) / normb) <= tol) {
180  tol = resid;
181  max_iter = 0;
182  return 0;
183  }
184 
185  for (int i = 1; i <= max_iter; i++) {
186  z = M.solve(r);
187  rho(0) = dot(r, z);
188 
189  if (i == 1)
190  p = z;
191  else {
192  beta(0) = rho(0) / rho_1(0);
193  p = z + beta(0) * p;
194  }
195 
196  q = A*p;
197  alpha(0) = rho(0) / dot(p, q);
198 
199  x += alpha(0) * p;
200  r -= alpha(0) * q;
201 
202  if ((resid = norm(r) / normb) <= tol) {
203  tol = resid;
204  max_iter = i;
205  return 0;
206  }
207 
208  rho_1(0) = rho(0);
209  }
210 
211  tol = resid;
212  return 1;
213 }
214 */
215 
216 } //namespace Math
217 
218 
219 #endif
int CG(const Matrix &A, Vector &x, const Vector &b, const Preconditioner &M, int &max_iter, Real &tol)
Definition: conjgrad.h:90
The logging system used in KrisLibrary.
Identity precondtioner.
Definition: conjgrad.h:20
Jacobi preconditioning (inverse of diagonal)
Definition: conjgrad.h:33
Contains all definitions in the Math package.
Definition: WorkspaceBound.h:12