8 template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }
12 template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
19 extern double dnrm2_(int *, double *, int *);
20 extern double ddot_(int *, double *, int *, double *, int *);
21 extern int daxpy_(int *, double *, double *, int *, double *, int *);
22 extern int dscal_(int *, double *, double *, int *);
28 static void default_print(const char *buf)
34 // On entry *f must be the function value of w
35 // On exit w is updated and *f is the new function value
36 double function::linesearch_and_update(double *w, double *s, double *f, double *g, double alpha)
40 int n = get_nr_variable();
41 int max_num_linesearch = 20;
42 double *w_new = new double[n];
48 int num_linesearch = 0;
49 for(num_linesearch=0; num_linesearch < max_num_linesearch; num_linesearch++)
52 w_new[i] = w[i] + alpha*s[i];
54 if (*f - fold <= eta * alpha * gTs)
60 if (num_linesearch >= max_num_linesearch)
66 memcpy(w, w_new, sizeof(double)*n);
72 void NEWTON::info(const char *fmt,...)
79 (*newton_print_string)(buf);
82 NEWTON::NEWTON(const function *fun_obj, double eps, double eps_cg, int max_iter)
84 this->fun_obj=const_cast<function *>(fun_obj);
87 this->max_iter=max_iter;
88 newton_print_string = default_print;
95 void NEWTON::newton(double *w)
97 int n = fun_obj->get_nr_variable();
100 double f, fold, actred;
101 double init_step_size = 1;
102 int search = 1, iter = 1, inc = 1;
103 double *s = new double[n];
104 double *r = new double[n];
105 double *g = new double[n];
107 const double alpha_pcg = 0.01;
108 double *M = new double[n];
110 // calculate gradient norm at w=0 for stopping condition.
111 double *w0 = new double[n];
115 fun_obj->grad(w0, g);
116 double gnorm0 = dnrm2_(&n, g, &inc);
121 double gnorm = dnrm2_(&n, g, &inc);
122 info("init f %5.3e |g| %5.3e\n", f, gnorm);
124 if (gnorm <= eps*gnorm0)
127 while (iter <= max_iter && search)
129 fun_obj->get_diag_preconditioner(M);
131 M[i] = (1-alpha_pcg) + alpha_pcg*M[i];
132 cg_iter = pcg(g, M, s, r);
135 step_size = fun_obj->linesearch_and_update(w, s, &f, g, init_step_size);
139 info("WARNING: line search fails\n");
144 gnorm = dnrm2_(&n, g, &inc);
146 info("iter %2d f %5.3e |g| %5.3e CG %3d step_size %4.2e \n", iter, f, gnorm, cg_iter, step_size);
148 if (gnorm <= eps*gnorm0)
152 info("WARNING: f < -1.0e+32\n");
156 if (fabs(actred) <= 1.0e-12*fabs(f))
158 info("WARNING: actred too small\n");
166 info("\nWARNING: reaching max number of Newton iterations\n");
174 int NEWTON::pcg(double *g, double *M, double *s, double *r)
177 int n = fun_obj->get_nr_variable();
179 double *d = new double[n];
180 double *Hd = new double[n];
181 double zTr, znewTrnew, alpha, beta, cgtol, dHd;
182 double *z = new double[n];
183 double Q = 0, newQ, Qdiff;
193 zTr = ddot_(&n, z, &inc, r, &inc);
194 double gMinv_norm = sqrt(zTr);
195 cgtol = min(eps_cg, sqrt(gMinv_norm));
197 int max_cg_iter = max(n, 5);
199 while (cg_iter < max_cg_iter)
204 dHd = ddot_(&n, d, &inc, Hd, &inc);
205 // avoid 0/0 in getting alpha
210 daxpy_(&n, &alpha, d, &inc, s, &inc);
212 daxpy_(&n, &alpha, Hd, &inc, r, &inc);
214 // Using quadratic approximation as CG stopping criterion
215 newQ = -0.5*(ddot_(&n, s, &inc, r, &inc) - ddot_(&n, s, &inc, g, &inc));
217 if (newQ <= 0 && Qdiff <= 0)
219 if (cg_iter * Qdiff >= cgtol * newQ)
224 info("WARNING: quadratic approximation > 0 or increasing in CG\n");
231 znewTrnew = ddot_(&n, z, &inc, r, &inc);
232 beta = znewTrnew/zTr;
233 dscal_(&n, &beta, d, &inc);
234 daxpy_(&n, &one, z, &inc, d, &inc);
238 if (cg_iter == max_cg_iter)
239 info("WARNING: reaching maximal number of CG steps\n");
248 void NEWTON::set_print_string(void (*print_string) (const char *buf))
250 newton_print_string = print_string;