1 /*
2 * gretl -- Gnu Regression, Econometrics and Time-series Library
3 * Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 /* The BFGS and Newton optimizers plus the fdjac Jacobian function */
21
22 #include "libgretl.h"
23 #include "gretl_bfgs.h"
24 #include "libset.h"
25 #include "matrix_extra.h"
26 #include "usermat.h"
27 #include "uservar.h"
28 #include "gretl_func.h"
29
30 #include "../../minpack/minpack.h"
31 #include <float.h>
32 #include <errno.h>
33
34 #define BFGS_DEBUG 0
35
36 #define BFGS_MAXITER_DEFAULT 600
37
BFGS_defaults(int * maxit,double * tol,int ci)38 void BFGS_defaults (int *maxit, double *tol, int ci)
39 {
40 *maxit = libset_get_int(BFGS_MAXITER);
41 *tol = libset_get_user_tolerance(BFGS_TOLER);
42
43 if (ci != MLE && ci != GMM && *maxit <= 0) {
44 *maxit = 1000;
45 }
46
47 if (ci == PROBIT || ci == INTREG || ci == ARMA ||
48 ci == NEGBIN || ci == DURATION) {
49 if (na(*tol)) {
50 *tol = 1.0e-12;
51 }
52 } else if (ci == TOBIT) {
53 if (na(*tol)) {
54 *tol = 1.0e-10; /* calibrated against Wm Greene */
55 }
56 } else if (ci == HECKIT) {
57 if (na(*tol)) {
58 *tol = 1.0e-09;
59 }
60 } else if (ci == GARCH) {
61 if (na(*tol)) {
62 *tol = 1.0e-13;
63 }
64 } else if (ci == MLE || ci == GMM) {
65 if (*maxit <= 0) {
66 *maxit = BFGS_MAXITER_DEFAULT;
67 }
68 if (na(*tol)) {
69 *tol = libset_get_double(BFGS_TOLER);
70 }
71 }
72 }
73
free_triangular_array(double ** m,int n)74 static void free_triangular_array (double **m, int n)
75 {
76 if (m != NULL) {
77 int i;
78
79 for (i=0; i<n; i++) {
80 free(m[i]);
81 }
82 free(m);
83 }
84 }
85
triangular_array_new(int n)86 static double **triangular_array_new (int n)
87 {
88 double **m = malloc(n * sizeof *m);
89 int i;
90
91 if (m != NULL) {
92 for (i=0; i<n; i++) {
93 m[i] = NULL;
94 }
95 for (i=0; i<n; i++) {
96 m[i] = malloc((i + 1) * sizeof **m);
97 if (m[i] == NULL) {
98 free_triangular_array(m, n);
99 return NULL;
100 }
101 }
102 }
103
104 return m;
105 }
106
107 /* State variable set when doing hessian_from_score(), to alert
108 the gradient function to the fact that the parameters will
109 be changing and in general NOT the same as in the last call
110 to the loglikelihood function.
111 */
112 static int doing_hess_score;
113
114 /* accessor for the above */
hess_score_on(void)115 int hess_score_on (void)
116 {
117 return doing_hess_score;
118 }
119
120 /**
121 * hessian_from_score:
122 * @b: array of k parameter estimates.
123 * @H: k x k matrix to receive the (negative) Hessian.
124 * @gradfunc: function to compute gradient.
125 * @cfunc: function to compute criterion (or NULL, see below).
126 * @data: data to be passed to the @gradfunc callback.
127 *
128 * Uses the score function (@gradfunc) is to construct a
129 * numerical approximation to the Hessian. This is primarily
130 * intended for building a covariance matrix at convergence;
131 * note that it may not work well at an arbitrary point in
132 * the parameter space.
133 *
134 * Note that the only use of @cfunc within this function is
135 * as an argument to be passed to @gradfunc. It is therefore
136 * OK to pass NULL for @cfunc provided that @gradfunc does not
137 * use its 4th argument, which corresponds to the BFGS_CRIT_FUNC
138 * parameter.
139 *
140 * Returns: 0 on successful completion, non-zero error code
141 * on error.
142 */
143
hessian_from_score(double * b,gretl_matrix * H,BFGS_GRAD_FUNC gradfunc,BFGS_CRIT_FUNC cfunc,void * data)144 int hessian_from_score (double *b, gretl_matrix *H,
145 BFGS_GRAD_FUNC gradfunc,
146 BFGS_CRIT_FUNC cfunc,
147 void *data)
148 {
149 double *g, *splus, *sminus, *splus2, *sminus2;
150 double x, den, b0, eps = 1.0e-05;
151 int n = gretl_matrix_rows(H);
152 int extra_precision = 0;
153 int i, j, err = 0;
154
155 char *s = getenv("H_EXTRA");
156
157 if (s != NULL && *s != '\0') {
158 extra_precision = 1;
159 fprintf(stderr, "hessian_from_score: using extra precision\n");
160 }
161
162 if (extra_precision) {
163 splus = malloc(5 * n * sizeof *splus);
164 splus2 = splus + n;
165 sminus = splus2 + n;
166 sminus2 = sminus + n;
167 g = sminus2 + n;
168 den = 12*eps;
169 } else {
170 splus = malloc(3 * n * sizeof *splus);
171 sminus = splus + n;
172 g = sminus + n;
173 splus2 = sminus2 = NULL;
174 den = 2*eps;
175 }
176
177 if (splus == NULL) {
178 return E_ALLOC;
179 }
180
181 doing_hess_score = 1;
182
183 for (i=0; i<n; i++) {
184 b0 = b[i];
185 b[i] = b0 + eps;
186 err = gradfunc(b, g, n, cfunc, data);
187 if (err) goto restore;
188 for (j=0; j<n; j++) {
189 splus[j] = g[j];
190 }
191 b[i] = b0 - eps;
192 err = gradfunc(b, g, n, cfunc, data);
193 if (err) goto restore;
194 for (j=0; j<n; j++) {
195 sminus[j] = g[j];
196 }
197 if (extra_precision) {
198 b[i] = b0 - 2*eps;
199 err = gradfunc(b, g, n, cfunc, data);
200 if (err) goto restore;
201 for (j=0; j<n; j++) {
202 sminus2[j] = g[j];
203 }
204 b[i] = b0 + 2*eps;
205 err = gradfunc(b, g, n, cfunc, data);
206 if (err) goto restore;
207 for (j=0; j<n; j++) {
208 splus2[j] = g[j];
209 }
210 }
211 restore:
212 b[i] = b0;
213 if (err) {
214 break;
215 }
216 for (j=0; j<n; j++) {
217 if (extra_precision) {
218 x = -(splus2[j] - sminus2[j]) + 8*(splus[j] - sminus[j]);
219 } else {
220 x = splus[j] - sminus[j];
221 }
222 gretl_matrix_set(H, i, j, -x / den);
223 }
224 }
225
226 doing_hess_score = 0;
227
228 if (!err) {
229 gretl_matrix_xtr_symmetric(H);
230 }
231
232 free(splus);
233
234 return err;
235 }
236
237 /**
238 * hessian_inverse_from_score:
239 * @b: array of parameter estimates.
240 * @n: the number of elements in @b.
241 * @gradfunc: function to compute gradient.
242 * @cfunc: function to compute criterion.
243 * @data: data to be passed to the @gradfunc callback.
244 * @err: location to receive error code.
245 *
246 * A wrapper for hessian_from_score() which takes care of
247 * (a) allocation of the Hessian and (b) inversion.
248 *
249 * Returns: the inverse of the (negative) Hessian on successful
250 * completion, NULL on error.
251 */
252
hessian_inverse_from_score(double * b,int n,BFGS_GRAD_FUNC gradfunc,BFGS_CRIT_FUNC cfunc,void * data,int * err)253 gretl_matrix *hessian_inverse_from_score (double *b, int n,
254 BFGS_GRAD_FUNC gradfunc,
255 BFGS_CRIT_FUNC cfunc,
256 void *data, int *err)
257 {
258 gretl_matrix *H = gretl_zero_matrix_new(n, n);
259
260 if (H == NULL) {
261 *err = E_ALLOC;
262 } else {
263 *err = hessian_from_score(b, H, gradfunc, cfunc, data);
264 }
265
266 if (!*err) {
267 *err = gretl_invert_symmetric_matrix(H);
268 if (*err) {
269 fprintf(stderr, "hessian_inverse_from_score: failed\n");
270 gretl_matrix_free(H);
271 H = NULL;
272 }
273 }
274
275 return H;
276 }
277
278 struct uhess_data {
279 GENERATOR *genr;
280 DATASET *dset;
281 };
282
283 /* Callback from numerical_hessian() for use in user_hess().
284 The first argument is redundant here, since the user
285 matrix referenced in the function-call in @genr will
286 already contain the values in @b. But we need to
287 respect the typedef for BFGS_CRIT_FUNC.
288 */
289
uhess_callback(const double * b,void * data)290 static double uhess_callback (const double *b, void *data)
291 {
292 struct uhess_data *uh = data;
293 double ret = NADBL;
294 int err;
295
296 err = execute_genr(uh->genr, uh->dset, NULL);
297 if (!err) {
298 ret = get_scalar_value_by_name("$umax", &err);
299 }
300
301 return ret;
302 }
303
304 /* apparatus for constructing numerical approximation to
305 the Hessian */
306
hess_h_init(double * h,double * h0,int n)307 static void hess_h_init (double *h, double *h0, int n)
308 {
309 memcpy(h, h0, n * sizeof *h);
310 }
311
hess_h_reduce(double * h,double v,int n)312 static void hess_h_reduce (double *h, double v, int n)
313 {
314 int i;
315
316 for (i=0; i<n; i++) {
317 h[i] /= v;
318 }
319 }
320
321 /* number of Richardson steps */
322 #define RSTEPS 4
323
324 /* Default @d for numerical_hessian (2017-10-03: was 0.0001).
325 Note 2018-10-05: this "new" value seems to be much too big
326 in some cases.
327 */
328 #define numhess_d 0.01
329
330 /* The algorithm below implements the method of Richardson
331 Extrapolation. It is derived from code in the gnu R package
332 "numDeriv" by Paul Gilbert, which was in turn derived from code
333 by Xinqiao Liu. Turned into C and modified for gretl by
334 Allin Cottrell, June 2006. On successful completion, writes
335 the Hessian (or the negative Hessian, if @neg is non-zero)
336 into @H, which must be correctly sized to receive the result.
337 */
338
numerical_hessian(double * b,gretl_matrix * H,BFGS_CRIT_FUNC func,void * data,int neg,double d)339 int numerical_hessian (double *b, gretl_matrix *H,
340 BFGS_CRIT_FUNC func, void *data,
341 int neg, double d)
342 {
343 double Dx[RSTEPS];
344 double Hx[RSTEPS];
345 double *wspace;
346 double *h0, *h, *Hd, *D;
347 int r = RSTEPS;
348 double dsmall = 0.0001;
349 double ztol, eps = 1e-4;
350 double v = 2.0; /* reduction factor for h */
351 double f0, f1, f2;
352 double p4m, hij;
353 double bi0, bj0;
354 int n = gretl_matrix_rows(H);
355 int vn = (n * (n + 1)) / 2;
356 int dn = vn + n;
357 int i, j, k, m, u;
358 int err = 0;
359
360 if (d == 0.0) {
361 d = numhess_d;
362 }
363
364 wspace = malloc((3 * n + dn) * sizeof *wspace);
365 if (wspace == NULL) {
366 return E_ALLOC;
367 }
368
369 h0 = wspace;
370 h = h0 + n;
371 Hd = h + n;
372 D = Hd + n; /* D is of length dn */
373
374 #if 0
375 ztol = sqrt(DBL_EPSILON / 7e-7); /* as per R */
376 #else
377 ztol = 0.01;
378 #endif
379
380 try_again:
381
382 /* note: numDeriv has
383
384 h0 <- abs(d*x) + eps * (abs(x) < zero.tol)
385
386 where the defaults are eps = 1e-4, d = 0.1,
387 and zero.tol = sqrt(double.eps/7e-7)
388
389 C translation:
390 double ztol = sqrt(DBL_EPSILON / 7e-7);
391 h0[i] = fabs(d*b[i]) + eps * (fabs(b[i]) < ztol);
392
393 The above @ztol is about 1.78e-05. Below, we are
394 currently using a bigger value, 0.01.
395 */
396 for (i=0; i<n; i++) {
397 h0[i] = fabs(d*b[i]) + eps * (fabs(b[i]) < ztol);
398 }
399
400 f0 = func(b, data);
401
402 /* first derivatives and Hessian diagonal */
403
404 for (i=0; i<n; i++) {
405 bi0 = b[i];
406 hess_h_init(h, h0, n);
407 for (k=0; k<r; k++) {
408 b[i] = bi0 + h[i];
409 f1 = func(b, data);
410 if (na(f1)) {
411 if (d <= dsmall) {
412 fprintf(stderr, "numerical_hessian: 1st derivative: "
413 "criterion=NA for theta[%d] = %g (d=%g)\n", i, b[i], d);
414 }
415 b[i] = bi0;
416 err = E_NAN;
417 goto end_first_try;
418 }
419 b[i] = bi0 - h[i];
420 f2 = func(b, data);
421 if (na(f2)) {
422 if (d <= dsmall) {
423 fprintf(stderr, "numerical_hessian: 1st derivative: "
424 "criterion=NA for theta[%d] = %g (d=%g)\n", i, b[i], d);
425 }
426 b[i] = bi0;
427 err = E_NAN;
428 goto end_first_try;
429 }
430 /* F'(i) */
431 Dx[k] = (f1 - f2) / (2 * h[i]);
432 /* F''(i) */
433 Hx[k] = (f1 - 2*f0 + f2) / (h[i] * h[i]);
434 hess_h_reduce(h, v, n);
435 }
436 b[i] = bi0;
437 p4m = 4.0;
438 for (m=0; m<r-1; m++) {
439 for (k=0; k<r-m-1; k++) {
440 Dx[k] = (Dx[k+1] * p4m - Dx[k]) / (p4m - 1);
441 Hx[k] = (Hx[k+1] * p4m - Hx[k]) / (p4m - 1);
442 }
443 p4m *= 4.0;
444 }
445 D[i] = Dx[0];
446 Hd[i] = Hx[0];
447 }
448
449 /* second derivatives: lower half of Hessian only */
450
451 u = n;
452 for (i=0; i<n; i++) {
453 bi0 = b[i];
454 for (j=0; j<=i; j++) {
455 if (i == j) {
456 D[u] = Hd[i];
457 } else {
458 hess_h_init(h, h0, n);
459 bj0 = b[j];
460 for (k=0; k<r; k++) {
461 b[i] = bi0 + h[i];
462 b[j] = bj0 + h[j];
463 f1 = func(b, data);
464 if (na(f1)) {
465 if (d <= dsmall) {
466 fprintf(stderr, "numerical_hessian: 2nd derivatives (%d,%d): "
467 "objective function gave NA\n", i, j);
468 }
469 b[i] = bi0;
470 b[j] = bj0;
471 err = E_NAN;
472 goto end_first_try;
473 }
474 b[i] = bi0 - h[i];
475 b[j] = bj0 - h[j];
476 f2 = func(b, data);
477 if (na(f2)) {
478 if (d <= dsmall) {
479 fprintf(stderr, "numerical_hessian: 2nd derivatives (%d,%d): "
480 "objective function gave NA\n", i, j);
481 }
482 b[i] = bi0;
483 b[j] = bj0;
484 err = E_NAN;
485 goto end_first_try;
486 }
487 /* cross-partial */
488 Dx[k] = (f1 - 2*f0 + f2 - Hd[i]*h[i]*h[i]
489 - Hd[j]*h[j]*h[j]) / (2*h[i]*h[j]);
490 hess_h_reduce(h, v, n);
491 }
492 p4m = 4.0;
493 for (m=0; m<r-1; m++) {
494 for (k=0; k<r-m-1; k++) {
495 Dx[k] = (Dx[k+1] * p4m - Dx[k]) / (p4m - 1);
496 }
497 p4m *= 4.0;
498 }
499 D[u] = Dx[0];
500 b[j] = bj0;
501 }
502 u++;
503 }
504 b[i] = bi0;
505 }
506
507 end_first_try:
508 if (err == E_NAN && d > dsmall) {
509 err = 0;
510 gretl_error_clear();
511 d /= 10;
512 goto try_again;
513 }
514
515 if (!err) {
516 /* transcribe the (negative of?) the Hessian */
517 u = n;
518 for (i=0; i<n; i++) {
519 for (j=0; j<=i; j++) {
520 hij = neg ? -D[u] : D[u];
521 gretl_matrix_set(H, i, j, hij);
522 gretl_matrix_set(H, j, i, hij);
523 u++;
524 }
525 }
526 }
527
528 if (neg) {
529 /* internal use, not user_numhess(): we should ensure
530 that the original criterion value is restored after
531 calculating with a perturbed version of @b
532 */
533 func(b, data);
534 }
535
536 if (err && err != E_ALLOC) {
537 gretl_errmsg_set(_("Failed to compute numerical Hessian"));
538 }
539
540 free(wspace);
541
542 return err;
543 }
544
545 /**
546 * numerical_hessian_inverse:
547 * @b: array of parameter estimates.
548 * @n: the number of elements in @b.
549 * @func: function to compute criterion.
550 * @data: data to be passed to the @gradfunc callback.
551 * @d: step size (give 0.0 for automatic).
552 * @err: location to receive error code.
553 *
554 * A wrapper for numerical_hessian() which takes care of
555 * (a) allocation of the Hessian and (b) inversion.
556 *
557 * Returns: the inverse of the (negative) Hessian on successful
558 * completion, NULL on error.
559 */
560
numerical_hessian_inverse(const double * b,int n,BFGS_CRIT_FUNC func,void * data,double d,int * err)561 gretl_matrix *numerical_hessian_inverse (const double *b, int n,
562 BFGS_CRIT_FUNC func,
563 void *data, double d,
564 int *err)
565 {
566 gretl_matrix *H = gretl_zero_matrix_new(n, n);
567
568 if (H == NULL) {
569 *err = E_ALLOC;
570 } else {
571 *err = numerical_hessian((double *) b, H, func, data, 1, d);
572 }
573
574 if (!*err) {
575 *err = gretl_invert_symmetric_matrix(H);
576 if (*err) {
577 fprintf(stderr, "numerical_hessian_inverse: failed\n");
578 gretl_errmsg_set(_("Failed to compute numerical Hessian"));
579 gretl_matrix_free(H);
580 H = NULL;
581 }
582 }
583
584 return H;
585 }
586
NR_fallback_hessian(double * b,gretl_matrix * H,BFGS_GRAD_FUNC gradfunc,BFGS_CRIT_FUNC cfunc,void * data)587 static int NR_fallback_hessian (double *b, gretl_matrix *H,
588 BFGS_GRAD_FUNC gradfunc,
589 BFGS_CRIT_FUNC cfunc,
590 void *data)
591 {
592 if (gradfunc != NULL) {
593 return hessian_from_score(b, H, gradfunc, cfunc, data);
594 } else {
595 return numerical_hessian(b, H, cfunc, data, 1, 0.0);
596 }
597 }
598
599 #define ALT_OPG 0
600
601 /* build the T x k matrix G, given a set of coefficient estimates,
602 @b, and a function for calculating the per-observation contributions
603 to the loglikelihood, @lltfun
604 */
605
numerical_score_matrix(double * b,int T,int k,BFGS_LLT_FUNC lltfun,void * data,int * err)606 gretl_matrix *numerical_score_matrix (double *b, int T, int k,
607 BFGS_LLT_FUNC lltfun,
608 void *data, int *err)
609 {
610 double h = 1e-8;
611 #if ALT_OPG
612 double d = 1.0e-4;
613 #endif
614 gretl_matrix *G;
615 const double *x;
616 double bi0, x0;
617 int i, t;
618
619 G = gretl_zero_matrix_new(T, k);
620 if (G == NULL) {
621 *err = E_ALLOC;
622 return NULL;
623 }
624
625 for (i=0; i<k; i++) {
626 bi0 = b[i];
627 #if ALT_OPG
628 h = d * bi0 + d * (floateq(b[i], 0.0));
629 #endif
630 b[i] = bi0 - h;
631 x = lltfun(b, i, data);
632 if (x == NULL) {
633 *err = E_NAN;
634 goto bailout;
635 }
636 for (t=0; t<T; t++) {
637 gretl_matrix_set(G, t, i, x[t]);
638 }
639 b[i] = bi0 + h;
640 x = lltfun(b, i, data);
641 if (x == NULL) {
642 *err = E_NAN;
643 goto bailout;
644 }
645 for (t=0; t<T; t++) {
646 x0 = gretl_matrix_get(G, t, i);
647 gretl_matrix_set(G, t, i, (x[t] - x0) / (2.0 * h));
648 }
649 b[i] = bi0;
650 #if NLS_DEBUG
651 fprintf(stderr, "b[%d]: using %#.12g and %#.12g\n", i, bi0 - h, bi0 + h);
652 #endif
653 }
654
655 #if NLS_DEBUG
656 gretl_matrix_print(G, "Numerically estimated score");
657 #endif
658
659 bailout:
660
661 if (*err) {
662 gretl_matrix_free(G);
663 G = NULL;
664 }
665
666 return G;
667 }
668
richardson_gradient(double * b,double * g,int n,BFGS_CRIT_FUNC func,void * data)669 static int richardson_gradient (double *b, double *g, int n,
670 BFGS_CRIT_FUNC func, void *data)
671 {
672 double df[RSTEPS];
673 double eps = 1.0e-4;
674 double d = 0.0001;
675 double h, p4m;
676 double bi0, f1, f2;
677 int r = RSTEPS;
678 int i, k, m;
679
680 for (i=0; i<n; i++) {
681 bi0 = b[i];
682 h = fabs(d * b[i]) + eps * (floateq(b[i], 0.0));
683 for (k=0; k<r; k++) {
684 b[i] = bi0 - h;
685 f1 = func(b, data);
686 b[i] = bi0 + h;
687 f2 = func(b, data);
688 if (na(f1) || na(f2)) {
689 b[i] = bi0;
690 return 1;
691 }
692 df[k] = (f2 - f1) / (2 * h);
693 h /= 2.0;
694 }
695 b[i] = bi0;
696 p4m = 4.0;
697 for (m=0; m<r-1; m++) {
698 for (k=0; k<r-m-1; k++) {
699 df[k] = (df[k+1] * p4m - df[k]) / (p4m - 1.0);
700 }
701 p4m *= 4.0;
702 }
703 g[i] = df[0];
704 }
705
706 return 0;
707 }
708
709 /* trigger for switch to Richardson gradient */
710 #define B_RELMIN 1.0e-14
711
simple_gradient(double * b,double * g,int n,BFGS_CRIT_FUNC func,void * data,int * redo)712 static int simple_gradient (double *b, double *g, int n,
713 BFGS_CRIT_FUNC func, void *data,
714 int *redo)
715 {
716 const double h = 1.0e-8;
717 double bi0, f1, f2;
718 int i;
719
720 for (i=0; i<n; i++) {
721 bi0 = b[i];
722 b[i] = bi0 - h;
723 if (bi0 != 0.0 && fabs((bi0 - b[i]) / bi0) < B_RELMIN) {
724 fprintf(stderr, "numerical gradient: switching to Richardson\n");
725 *redo = 1;
726 return 0;
727 }
728 f1 = func(b, data);
729 b[i] = bi0 + h;
730 f2 = func(b, data);
731 b[i] = bi0;
732 if (na(f1) || na(f2)) {
733 return 1;
734 }
735 g[i] = (f2 - f1) / (2.0 * h);
736 #if BFGS_DEBUG > 1
737 fprintf(stderr, "g[%d] = (%.16g - %.16g) / (2.0 * %g) = %g\n",
738 i, f2, f1, h, g[i]);
739 #endif
740 }
741
742 return 0;
743 }
744
745 /* default numerical calculation of gradient in context of BFGS */
746
numeric_gradient(double * b,double * g,int n,BFGS_CRIT_FUNC func,void * data)747 int numeric_gradient (double *b, double *g, int n,
748 BFGS_CRIT_FUNC func, void *data)
749 {
750 int err = 0;
751
752 if (libset_get_bool(BFGS_RSTEP)) {
753 err = richardson_gradient(b, g, n, func, data);
754 } else {
755 int redo = 0;
756
757 err = simple_gradient(b, g, n, func, data, &redo);
758 if (redo) {
759 err = richardson_gradient(b, g, n, func, data);
760 }
761 }
762
763 #if BFGS_DEBUG
764 fprintf(stderr, "numeric_gradient returning, err = %d\n", err);
765 #endif
766
767 return err;
768 }
769
770 #define STEPFRAC 0.2
771 #define acctol 1.0e-7 /* alt: 0.0001 or 1.0e-7 (?) */
772 #define reltest 10.0
773
774 #define coeff_unchanged(a,b) (reltest + a == reltest + b)
775
broken_gradient(double * g,int n)776 static int broken_gradient (double *g, int n)
777 {
778 int i;
779
780 for (i=0; i<n; i++) {
781 if (isnan(g[i])) {
782 return 1;
783 }
784 }
785
786 return 0;
787 }
788
789 /*
790 If "set initvals" has been used, replace whatever initial values
791 might have been in place with those given by the user (the customer
792 is always right). In addition, respect user settings for the
793 maximum number of iterations, the convergence tolerance and
794 so on.
795 */
796
optim_get_user_values(double * b,int n,int * maxit,double * reltol,double * gradmax,gretlopt opt,PRN * prn)797 static void optim_get_user_values (double *b, int n, int *maxit,
798 double *reltol, double *gradmax,
799 gretlopt opt, PRN *prn)
800 {
801 int umaxit;
802 double utol;
803
804 if (opt & OPT_U) {
805 /* we first check to see if we've been a usable initialization
806 for the parameter estimates */
807 gretl_matrix *uinit;
808 int i, uilen;
809
810 uinit = get_initvals();
811 uilen = gretl_vector_get_length(uinit);
812
813 if (uilen > 0) {
814 /* the user has given something */
815 if (uilen < n) {
816 fprintf(stderr, "Only %d initial values given, but %d "
817 "are necessary\n", uilen, n);
818 } else {
819 for (i=0; i<n; i++) {
820 b[i] = uinit->val[i];
821 }
822 if ((opt & OPT_V) && !(opt & OPT_A)) {
823 /* OPT_A: arma: this is handled elsewhere */
824 pputs(prn, _("\n\n*** User-specified starting values:\n"));
825 for (i=0; i<n; i++) {
826 pprintf(prn, " %12.6f", b[i]);
827 if (i % 6 == 5) {
828 pputc(prn, '\n');
829 }
830 }
831 pputs(prn, "\n\n");
832 }
833 }
834 }
835 gretl_matrix_free(uinit);
836 }
837
838 if (reltol == NULL || gradmax == NULL) {
839 /* Newton */
840 return;
841 }
842
843 /* check for a setting of the maximum number of iterations */
844 umaxit = libset_get_int(BFGS_MAXITER);
845 if (umaxit >= 0) {
846 *maxit = umaxit;
847 } else if (*maxit < 0) {
848 *maxit = BFGS_MAXITER_DEFAULT;
849 }
850
851 /* convergence tolerance */
852 utol = libset_get_user_tolerance(BFGS_TOLER);
853 if (!na(utol)) {
854 /* the user has actually set a value */
855 *reltol = utol;
856 if (!(opt & OPT_Q)) {
857 fprintf(stderr, "user-specified BFGS tolerance = %g\n", utol);
858 }
859 } else if (*reltol == 0) {
860 /* use the generic BFGS default */
861 *reltol = libset_get_double(BFGS_TOLER);
862 }
863
864 /* maximum acceptable gradient norm */
865 *gradmax = libset_get_double(BFGS_MAXGRAD);
866 }
867
868 #define bfgs_print_iter(v,s,i) (v && (s == 1 || i % s == 0))
869
870 #define GRAD_TOLER 1.0
871
copy_initial_hessian(double ** H,const gretl_matrix * A,int n)872 static int copy_initial_hessian (double **H,
873 const gretl_matrix *A,
874 int n)
875 {
876 int i, j, vlen = gretl_vector_get_length(A);
877 int err = 0;
878
879 #if BFGS_DEBUG > 1
880 gretl_matrix_print(A, "BFGS: initial Hessian inverse");
881 #endif
882
883 if (gretl_is_null_matrix(A)) {
884 /* set identity matrix */
885 for (i=0; i<n; i++) {
886 for (j=0; j<i; j++) {
887 H[i][j] = 0.0;
888 }
889 H[i][i] = 1.0;
890 }
891 } else if (vlen == n) {
892 /* set the diagonal */
893 for (i=0; i<n; i++) {
894 for (j=0; j<i; j++) {
895 H[i][j] = 0.0;
896 }
897 H[i][i] = A->val[i];
898 }
899 } else if (A->rows == n && A->cols == n) {
900 /* set the whole matrix */
901 for (i=0; i<n; i++) {
902 for (j=0; j<=i; j++) {
903 H[i][j] = gretl_matrix_get(A, i, j);
904 }
905 }
906 } else {
907 err = E_NONCONF;
908 }
909
910 return err;
911 }
912
optim_fncall(BFGS_CRIT_FUNC cfunc,double * b,void * data,int minimize)913 static double optim_fncall (BFGS_CRIT_FUNC cfunc,
914 double *b, void *data,
915 int minimize)
916 {
917 double ret = cfunc(b, data);
918
919 return na(ret) ? ret : minimize ? -ret : ret;
920 }
921
optim_gradcall(BFGS_GRAD_FUNC gradfunc,double * b,double * g,int n,BFGS_CRIT_FUNC cfunc,void * data,int minimize)922 static int optim_gradcall (BFGS_GRAD_FUNC gradfunc,
923 double *b, double *g, int n,
924 BFGS_CRIT_FUNC cfunc,
925 void *data,
926 int minimize)
927 {
928 int ret = gradfunc(b, g, n, cfunc, data);
929
930 if (minimize) {
931 int i;
932
933 for (i=0; i<n; i++) {
934 if (!na(g[i])) {
935 g[i] = -g[i];
936 }
937 }
938 }
939
940 return ret;
941 }
942
simple_slen(int n,int * pndelta,double * b,double * X,double * t,double * pf,BFGS_CRIT_FUNC cfunc,void * data,double g0,double f0,int * pfcount,int minimize)943 static double simple_slen (int n, int *pndelta, double *b, double *X, double *t,
944 double *pf, BFGS_CRIT_FUNC cfunc, void *data,
945 double g0, double f0, int *pfcount, int minimize)
946 {
947 double d, steplen = 1.0;
948 double f1 = *pf;
949 int i, crit_ok = 0, fcount = 0;
950 int ndelta = *pndelta;
951
952 /* Below: iterate so long as (a) we haven't achieved an acceptable
953 value of the criterion and (b) there is still some prospect
954 of doing so.
955 */
956
957 do {
958 ndelta = n;
959 crit_ok = 0;
960 for (i=0; i<n; i++) {
961 b[i] = X[i] + steplen * t[i];
962 if (coeff_unchanged(b[i], X[i])) {
963 ndelta--;
964 }
965 }
966 if (ndelta > 0) {
967 f1 = optim_fncall(cfunc, b, data, minimize);
968 fcount++;
969 d = g0 * steplen * acctol;
970 crit_ok = !na(f1) && (f1 >= f0 + d);
971 if (!crit_ok) {
972 /* calculated criterion no good: try smaller step */
973 steplen *= STEPFRAC;
974 }
975 }
976 } while (ndelta != 0 && !crit_ok);
977
978 *pndelta = ndelta;
979 *pfcount += fcount;
980 *pf = f1;
981
982 return steplen;
983 }
984
BFGS_orig(double * b,int n,int maxit,double reltol,int * fncount,int * grcount,BFGS_CRIT_FUNC cfunc,int crittype,BFGS_GRAD_FUNC gradfunc,void * data,const gretl_matrix * A0,gretlopt opt,PRN * prn)985 static int BFGS_orig (double *b, int n, int maxit, double reltol,
986 int *fncount, int *grcount, BFGS_CRIT_FUNC cfunc,
987 int crittype, BFGS_GRAD_FUNC gradfunc, void *data,
988 const gretl_matrix *A0, gretlopt opt, PRN *prn)
989 {
990 int verbskip, verbose = (opt & OPT_V);
991 int minimize = (opt & OPT_I);
992 double *wspace = NULL;
993 double **H = NULL;
994 double *g, *t, *X, *c;
995 int fcount, gcount, ndelta = 0;
996 int show_activity = 0;
997 double sumgrad, gradmax, gradnorm = 0.0;
998 double fmax, f, f0, s, steplen = 0.0;
999 double fdiff, D1, D2;
1000 int i, j, ilast, iter, done = 0;
1001 int err = 0;
1002
1003 optim_get_user_values(b, n, &maxit, &reltol, &gradmax, opt, prn);
1004
1005 wspace = malloc(4 * n * sizeof *wspace);
1006 H = triangular_array_new(n);
1007 if (wspace == NULL || H == NULL) {
1008 err = E_ALLOC;
1009 goto bailout;
1010 }
1011
1012 if (gradfunc == NULL) {
1013 gradfunc = numeric_gradient;
1014 }
1015
1016 /* initialize curvature matrix */
1017 if (A0 != NULL) {
1018 err = copy_initial_hessian(H, A0, n);
1019 } else {
1020 gretl_matrix *A1 = get_initcurv();
1021
1022 err = copy_initial_hessian(H, A1, n);
1023 gretl_matrix_free(A1);
1024 }
1025 if (err) {
1026 goto bailout;
1027 }
1028
1029 g = wspace;
1030 t = g + n;
1031 X = t + n;
1032 c = X + n;
1033
1034 f = optim_fncall(cfunc, b, data, minimize);
1035
1036 if (na(f)) {
1037 gretl_errmsg_set(_("BFGS: initial value of objective function is not finite"));
1038 err = E_NAN;
1039 goto bailout;
1040 }
1041
1042 #if BFGS_DEBUG
1043 fprintf(stderr, "*** BFGS: first evaluation of f = %g\n", f);
1044 #endif
1045
1046 f0 = fmax = f;
1047 iter = ilast = fcount = gcount = 1;
1048 optim_gradcall(gradfunc, b, g, n, cfunc, data, minimize);
1049
1050 #if BFGS_DEBUG > 1
1051 fprintf(stderr, "initial gradient:\n");
1052 for (i=0; i<n; i++) {
1053 fprintf(stderr, " g[%d] = %g\n", i, g[i]);
1054 }
1055 #endif
1056
1057 if (maxit == 0) {
1058 goto skipcalc;
1059 }
1060
1061 verbskip = libset_get_int(BFGS_VERBSKIP);
1062 show_activity = show_activity_func_installed();
1063
1064 do {
1065 if (bfgs_print_iter(verbose, verbskip, iter)) {
1066 print_iter_info(iter, f, crittype, n, b, g, steplen, prn);
1067 }
1068
1069 if (show_activity && (iter % 10 == 0)) {
1070 show_activity_callback();
1071 }
1072
1073 if (iter > 1 && ilast == gcount) {
1074 /* restart: set curvature matrix to I */
1075 for (i=0; i<n; i++) {
1076 for (j=0; j<i; j++) {
1077 H[i][j] = 0.0;
1078 }
1079 H[i][i] = 1.0;
1080 }
1081 }
1082
1083 for (i=0; i<n; i++) {
1084 /* copy coefficients to X, gradient to c */
1085 X[i] = b[i];
1086 c[i] = g[i];
1087 }
1088
1089 gradnorm = sumgrad = 0.0;
1090
1091 for (i=0; i<n; i++) {
1092 s = 0.0;
1093 for (j=0; j<=i; j++) {
1094 s += H[i][j] * g[j];
1095 }
1096 for (j=i+1; j<n; j++) {
1097 s += H[j][i] * g[j];
1098 }
1099 t[i] = s;
1100 sumgrad += s * g[i];
1101 gradnorm += fabs(b[i] * g[i]);
1102 }
1103
1104 gradnorm = sqrt(gradnorm / n);
1105
1106 #if BFGS_DEBUG
1107 fprintf(stderr, "\niter %d: sumgrad=%g, gradnorm=%g\n",
1108 iter, sumgrad, gradnorm);
1109 #endif
1110
1111 #if BFGS_DEBUG > 1
1112 fprintf(stderr, "H = \n");
1113 for (i=0; i<n; i++) {
1114 for (j=0; j<=i; j++) {
1115 fprintf(stderr, "%15.6f", H[i][j]);
1116 }
1117 fputc('\n', stderr);
1118 }
1119 #endif
1120 if (sumgrad > 0.0) {
1121 /* heading in the right direction (uphill) */
1122 steplen = simple_slen(n, &ndelta, b, X, t, &f, cfunc, data,
1123 sumgrad, fmax, &fcount, minimize);
1124 fdiff = fabs(fmax - f);
1125 if (iter > 1 || fdiff > 0) {
1126 done = fdiff <= reltol * (fabs(fmax) + reltol);
1127 #if BFGS_DEBUG
1128 fprintf(stderr, "convergence test: LHS=%g, RHS=%g; done=%d\n",
1129 fdiff, reltol * (fabs(fmax) + reltol), done);
1130 #endif
1131 }
1132
1133 /* prepare to stop if relative change is small enough */
1134 if (done) {
1135 ndelta = 0;
1136 fmax = f;
1137 }
1138
1139 if (ndelta > 0) {
1140 /* making progress */
1141 #if BFGS_DEBUG
1142 fprintf(stderr, "making progress, ndelta = %d\n", ndelta);
1143 #endif
1144 fmax = f;
1145 optim_gradcall(gradfunc, b, g, n, cfunc, data, minimize);
1146 #if BFGS_DEBUG > 1
1147 fprintf(stderr, "new gradient:\n");
1148 for (i=0; i<n; i++) {
1149 fprintf(stderr, "%15.6f", g[i]);
1150 }
1151 fputc('\n', stderr);
1152 #endif
1153 gcount++;
1154 iter++;
1155 D1 = 0.0;
1156 for (i=0; i<n; i++) {
1157 t[i] *= steplen;
1158 c[i] -= g[i];
1159 D1 += t[i] * c[i];
1160 }
1161 #if BFGS_DEBUG
1162 fprintf(stderr, "D1 = %g\n", D1);
1163 #endif
1164 if (D1 > 0.0) {
1165 D2 = 0.0;
1166 for (i=0; i<n; i++) {
1167 s = 0.0;
1168 for (j=0; j<=i; j++) {
1169 s += H[i][j] * c[j];
1170 }
1171 for (j=i+1; j<n; j++) {
1172 s += H[j][i] * c[j];
1173 }
1174 X[i] = s;
1175 D2 += s * c[i];
1176 }
1177 D2 = 1.0 + D2 / D1;
1178 for (i=0; i<n; i++) {
1179 for (j=0; j<=i; j++) {
1180 H[i][j] += (D2 * t[i]*t[j] - X[i]*t[j] - t[i]*X[j]) / D1;
1181 }
1182 }
1183 #if BFGS_DEBUG
1184 fprintf(stderr, "D2 = %g\n", D2);
1185 #endif
1186 } else {
1187 /* D1 <= 0.0 */
1188 ilast = gcount;
1189 }
1190 } else if (ilast < gcount) {
1191 ndelta = n;
1192 ilast = gcount;
1193 }
1194 } else if (sumgrad == 0.0) {
1195 #if 0
1196 fprintf(stderr, "gradient is exactly zero!\n");
1197 #endif
1198 break;
1199 } else {
1200 /* heading in the wrong direction */
1201 if (ilast == gcount) {
1202 /* we just did a reset, so don't reset again; instead set
1203 ndelta = 0 so that we exit the main loop
1204 */
1205 ndelta = 0;
1206 if (gcount == 1) {
1207 err = (broken_gradient(g, n))? E_NAN : E_NOCONV;
1208 }
1209 } else {
1210 /* reset for another attempt */
1211 ilast = gcount;
1212 ndelta = n;
1213 }
1214 }
1215
1216 if (iter >= maxit) {
1217 break;
1218 }
1219
1220 if (gcount - ilast > 2 * n) {
1221 /* periodic restart of curvature computation */
1222 ilast = gcount;
1223 }
1224
1225 } while (ndelta > 0 || ilast < gcount);
1226
1227 #if BFGS_DEBUG
1228 fprintf(stderr, "terminated: fmax=%g, ndelta=%d, ilast=%d, gcount=%d\n",
1229 fmax, ndelta, ilast, gcount);
1230 fprintf(stderr, "gradnorm = %g, vs gradmax = %g\n", gradnorm, gradmax);
1231 #endif
1232
1233 if (iter >= maxit) {
1234 gretl_errmsg_sprintf(_("Reached the maximum iterations (%d)"), maxit);
1235 err = E_NOCONV;
1236 } else if (gradnorm > gradmax) {
1237 gretl_errmsg_sprintf(_("Norm of gradient %g exceeds maximum of %g"),
1238 gradnorm, gradmax);
1239 err = E_NOCONV;
1240 } else if (fmax < f0) {
1241 /* allow a small sloppiness factor here? */
1242 double rdiff;
1243
1244 rdiff = (f0 == 0.0)? -fmax : fabs((f0 - fmax) / f0);
1245 if (rdiff > 1.0e-12) {
1246 fprintf(stderr, "failed to match initial value of objective function:\n"
1247 " f0=%.18g, fmax=%.18g\n", f0, fmax);
1248 err = E_NOCONV;
1249 }
1250 }
1251
1252 if (!err && gradnorm > GRAD_TOLER) {
1253 gretl_warnmsg_sprintf(_("norm of gradient = %g"), gradnorm);
1254 set_gretl_warning(W_GRADIENT);
1255 }
1256
1257 skipcalc:
1258
1259 /* particularly relevant for iterated GMM: increment,
1260 don't just set, these two counts
1261 */
1262 *fncount += fcount;
1263 *grcount += gcount;
1264
1265 if (verbose) {
1266 print_iter_info(-1, f, crittype, n, b, g, steplen, prn);
1267 /* pputc(prn, '\n'); */
1268 }
1269
1270 bailout:
1271
1272 free(wspace);
1273 free_triangular_array(H, n);
1274
1275 #if BFGS_DEBUG
1276 fprintf(stderr, "BFGS_max: returning %d\n", err);
1277 #endif
1278
1279 return err;
1280 }
1281
1282 /* Note: we need this because the original L-BFGS-B code is
1283 set up as a minimizer. We could get rid of it if anyone
1284 has the strength to go into lbfgsb.c (ex Fortran) and make
1285 the necessary adjustments.
1286 */
1287
reverse_gradient(double * g,int n)1288 static void reverse_gradient (double *g, int n)
1289 {
1290 int i;
1291
1292 for (i=0; i<n; i++) {
1293 if (!na(g[i])) {
1294 g[i] = -g[i];
1295 }
1296 }
1297 }
1298
transcribe_lbfgs_bounds(const gretl_matrix * m,int nparm,int * nbd,double * l,double * u)1299 static int transcribe_lbfgs_bounds (const gretl_matrix *m,
1300 int nparm, int *nbd,
1301 double *l, double *u)
1302 {
1303 double h = libset_get_double(CONV_HUGE);
1304 int i, j, c = gretl_matrix_cols(m);
1305 int err = 0;
1306
1307 if (c != 3) {
1308 fprintf(stderr, "lbfgs_bounds: matrix should have 3 cols\n");
1309 return E_INVARG;
1310 }
1311
1312 for (i=0; i<nparm; i++) {
1313 /* mark as unbounded */
1314 nbd[i] = 0;
1315 }
1316
1317 for (i=0; i<m->rows && !err; i++) {
1318 j = (int) gretl_matrix_get(m, i, 0);
1319 if (j < 1 || j > nparm) {
1320 fprintf(stderr, "lbfgs_bounds: out-of-bounds index %d\n", j);
1321 err = E_INVARG;
1322 } else {
1323 j--; /* convert to zero-based */
1324 l[j] = gretl_matrix_get(m, i, 1);
1325 u[j] = gretl_matrix_get(m, i, 2);
1326 if (l[j] > u[j]) {
1327 err = E_INVARG;
1328 } else if (l[j] != -h && u[j] != h) {
1329 /* both lower and upper bounds */
1330 nbd[j] = 2;
1331 } else if (l[j] != -h) {
1332 /* lower bound only */
1333 nbd[j] = 1;
1334 } else if (u[j] != h) {
1335 /* upper bound only */
1336 nbd[j] = 3;
1337 }
1338 }
1339 }
1340
1341 return err;
1342 }
1343
LBFGS_max(double * b,int n,int maxit,double reltol,int * fncount,int * grcount,BFGS_CRIT_FUNC cfunc,int crittype,BFGS_GRAD_FUNC gradfunc,BFGS_COMBO_FUNC combfunc,void * data,const gretl_matrix * bounds,gretlopt opt,PRN * prn)1344 int LBFGS_max (double *b, int n,
1345 int maxit, double reltol,
1346 int *fncount, int *grcount,
1347 BFGS_CRIT_FUNC cfunc, int crittype,
1348 BFGS_GRAD_FUNC gradfunc,
1349 BFGS_COMBO_FUNC combfunc,
1350 void *data,
1351 const gretl_matrix *bounds,
1352 gretlopt opt,
1353 PRN *prn)
1354 {
1355 double *wspace = NULL;
1356 int *ispace = NULL;
1357 double *g, *l, *u, *wa;
1358 int *iwa, *nbd;
1359 int i, m, dim;
1360 char task[60];
1361 char csave[60];
1362 double f, pgtol;
1363 double factr;
1364 double gradmax;
1365 double dsave[29];
1366 int isave[44];
1367 int lsave[4];
1368 int iter, ibak = 0;
1369 int show_activity = 0;
1370 int maximize;
1371 int verbskip, verbose = (opt & OPT_V);
1372 int err = 0;
1373
1374 maximize = (crittype != C_SSR) && !(opt & OPT_I);
1375
1376 *fncount = *grcount = 0;
1377
1378 optim_get_user_values(b, n, &maxit, &reltol, &gradmax, opt, prn);
1379
1380 /*
1381 m: the number of corrections used in the limited memory matrix.
1382 It is not altered by the routine. Values of m < 3 are not
1383 recommended, and large values of m can result in excessive
1384 computing time. The range 3 <= m <= 20 is recommended.
1385
1386 Was initially set to 5 (then 10, then 8; and 8 is the default).
1387 */
1388 m = libset_get_int(LBFGS_MEM);
1389
1390 dim = (2*m+5)*n + 11*m*m + 8*m; /* for wa */
1391 dim += 3*n; /* for g, l and u */
1392
1393 wspace = malloc(dim * sizeof *wspace);
1394 ispace = malloc(4*n * sizeof *ispace);
1395
1396 if (wspace == NULL || ispace == NULL) {
1397 err = E_ALLOC;
1398 goto bailout;
1399 }
1400
1401 g = wspace;
1402 l = g + n;
1403 u = l + n;
1404 wa = u + n;
1405
1406 nbd = ispace;
1407 iwa = nbd + n;
1408
1409 verbskip = libset_get_int(BFGS_VERBSKIP);
1410 show_activity = show_activity_func_installed();
1411
1412 if (gradfunc == NULL && combfunc == NULL) {
1413 gradfunc = numeric_gradient;
1414 }
1415
1416 /* Gradient convergence criterion (currently unused --
1417 we use reltol instead) */
1418 pgtol = 0.0;
1419
1420 /* tol = (factr * macheps) => factr = tol/macheps */
1421 factr = reltol / pow(2.0, -52);
1422
1423 if (!gretl_is_null_matrix(bounds)) {
1424 /* Handle specified bounds on the parameters */
1425 err = transcribe_lbfgs_bounds(bounds, n, nbd, l, u);
1426 if (err) {
1427 goto bailout;
1428 }
1429 } else {
1430 /* By default we just set all parameters to be
1431 less than some ridiculously large number */
1432 for (i=0; i<n; i++) {
1433 nbd[i] = 3; /* case 3: upper bound only */
1434 u[i] = DBL_MAX / 100;
1435 }
1436 }
1437
1438 /* Start the iteration by initializing @task */
1439 strcpy(task, "START");
1440
1441 while (1) {
1442 /* Call the L-BFGS-B code */
1443 setulb_(&n, &m, b, l, u, nbd, &f, g, &factr, &pgtol, wa, iwa,
1444 task, csave, lsave, isave, dsave);
1445
1446 iter = isave[29] + 1;
1447
1448 if (!strncmp(task, "FG", 2)) {
1449 /* Compute function value, f */
1450 if (combfunc != NULL) {
1451 f = combfunc(b, g, n, data);
1452 } else {
1453 f = cfunc(b, data);
1454 }
1455 if (!na(f)) {
1456 if (maximize) f = -f;
1457 } else if (*fncount == 0) {
1458 fprintf(stderr, "initial value of f is not finite\n");
1459 err = E_DATA;
1460 break;
1461 }
1462 *fncount += 1;
1463 if (combfunc == NULL) {
1464 /* Compute gradient, g */
1465 gradfunc(b, g, n, cfunc, data);
1466 }
1467 if (maximize) {
1468 reverse_gradient(g, n);
1469 }
1470 *grcount += 1;
1471 } else if (!strncmp(task, "NEW_X", 5)) {
1472 /* The optimizer has produced a new set of parameter values */
1473 if (isave[33] >= maxit) {
1474 strcpy(task, "STOP: TOTAL NO. of f AND g "
1475 "EVALUATIONS EXCEEDS LIMIT");
1476 err = E_NOCONV;
1477 break;
1478 }
1479 } else {
1480 if (strncmp(task, "CONVER", 6)) {
1481 fprintf(stderr, "%s\n", task);
1482 }
1483 break;
1484 }
1485
1486 if (bfgs_print_iter(verbose, verbskip, iter)) {
1487 if (iter != ibak) {
1488 double steplen = (iter == 1)? NADBL : dsave[13];
1489
1490 if (maximize) reverse_gradient(g, n);
1491 print_iter_info(iter, -f, crittype, n, b, g, steplen, prn);
1492 if (maximize) reverse_gradient(g, n);
1493 }
1494 ibak = iter;
1495 }
1496
1497 if (show_activity && (iter % 10 == 0)) {
1498 show_activity_callback();
1499 }
1500 }
1501
1502 if (!err && crittype == C_GMM) {
1503 /* finalize GMM computations */
1504 f = cfunc(b, data);
1505 }
1506
1507 if (opt & OPT_V) {
1508 if (maximize) reverse_gradient(g, n);
1509 print_iter_info(-1, -f, crittype, n, b, g, dsave[13], prn);
1510 pputc(prn, '\n');
1511 }
1512
1513 bailout:
1514
1515 free(wspace);
1516 free(ispace);
1517
1518 return err;
1519 }
1520
1521 /**
1522 * BFGS_max:
1523 * @b: array of adjustable coefficients.
1524 * @n: number elements in array @b.
1525 * @maxit: the maximum number of iterations to allow.
1526 * @reltol: relative tolerance for terminating iteration.
1527 * @fncount: location to receive count of function evaluations.
1528 * @grcount: location to receive count of gradient evaluations.
1529 * @cfunc: pointer to function used to calculate maximand.
1530 * @crittype: code for type of the maximand/minimand: should
1531 * be %C_LOGLIK, %C_GMM or %C_OTHER. Used only in printing
1532 * iteration info.
1533 * @gradfunc: pointer to function used to calculate the
1534 * gradient, or %NULL for default numerical calculation.
1535 * @data: pointer that will be passed as the last
1536 * parameter to the callback functions @cfunc and @gradfunc.
1537 * @A0: initial approximation to the inverse of the Hessian
1538 * (or %NULL to use identity matrix)
1539 * @opt: may contain %OPT_V for verbose operation, %OPT_L to
1540 * force use of L-BFGS-B.
1541 * @prn: printing struct (or %NULL). Only used if @opt
1542 * includes %OPT_V.
1543 *
1544 * Obtains the set of values for @b which jointly maximize the
1545 * criterion value as calculated by @cfunc. By default uses the BFGS
1546 * variable-metric method (based on Pascal code in J. C. Nash,
1547 * "Compact Numerical Methods for Computers," 2nd edition, converted
1548 * by p2c then re-crafted by B. D. Ripley for gnu R; revised for
1549 * gretl by Allin Cottrell and Jack Lucchetti). Alternatively,
1550 * if OPT_L is given, uses the L-BFGS-B method (limited memory
1551 * BFGS), based on Lbfgsb.3.0 by Ciyou Zhu, Richard Byrd, Jorge
1552 * Nocedal and Jose Luis Morales.
1553 *
1554 * Returns: 0 on successful completion, non-zero error code
1555 * on error.
1556 */
1557
BFGS_max(double * b,int n,int maxit,double reltol,int * fncount,int * grcount,BFGS_CRIT_FUNC cfunc,int crittype,BFGS_GRAD_FUNC gradfunc,void * data,const gretl_matrix * A0,gretlopt opt,PRN * prn)1558 int BFGS_max (double *b, int n, int maxit, double reltol,
1559 int *fncount, int *grcount, BFGS_CRIT_FUNC cfunc,
1560 int crittype, BFGS_GRAD_FUNC gradfunc, void *data,
1561 const gretl_matrix *A0, gretlopt opt, PRN *prn)
1562 {
1563 int ret, wnum;
1564
1565 gretl_iteration_push();
1566
1567 if ((opt & OPT_L) || libset_get_bool(USE_LBFGS)) {
1568 ret = LBFGS_max(b, n, maxit, reltol,
1569 fncount, grcount, cfunc,
1570 crittype, gradfunc, NULL, data,
1571 NULL, opt, prn);
1572 } else {
1573 ret = BFGS_orig(b, n, maxit, reltol,
1574 fncount, grcount, cfunc,
1575 crittype, gradfunc, data,
1576 A0, opt, prn);
1577 }
1578
1579 gretl_iteration_pop();
1580
1581 wnum = check_gretl_warning();
1582 if (wnum != W_GRADIENT) {
1583 /* suppress expected numerical warnings */
1584 set_gretl_warning(0);
1585 }
1586
1587 return ret;
1588 }
1589
1590 /* constrained L_BFGS-B */
1591
BFGS_cmax(double * b,int n,int maxit,double reltol,int * fncount,int * grcount,BFGS_CRIT_FUNC cfunc,int crittype,BFGS_GRAD_FUNC gradfunc,void * data,const gretl_matrix * bounds,gretlopt opt,PRN * prn)1592 static int BFGS_cmax (double *b, int n,
1593 int maxit, double reltol,
1594 int *fncount, int *grcount,
1595 BFGS_CRIT_FUNC cfunc, int crittype,
1596 BFGS_GRAD_FUNC gradfunc,
1597 void *data,
1598 const gretl_matrix *bounds,
1599 gretlopt opt, PRN *prn)
1600 {
1601 int ret, wnum;
1602
1603 gretl_iteration_push();
1604
1605 ret = LBFGS_max(b, n, maxit, reltol,
1606 fncount, grcount, cfunc,
1607 crittype, gradfunc, NULL, data,
1608 bounds, opt, prn);
1609
1610 gretl_iteration_pop();
1611
1612 wnum = check_gretl_warning();
1613 if (wnum != W_GRADIENT) {
1614 /* suppress expected numerical warnings */
1615 set_gretl_warning(0);
1616 }
1617
1618 return ret;
1619 }
1620
1621 /* user-level access to BFGS, NR and fdjac */
1622
1623 typedef struct umax_ umax;
1624
1625 struct umax_ {
1626 GretlType gentype; /* GRETL_TYPE_DOUBLE or GRETL_TYPE_MATRIX */
1627 char *pxname; /* name of scalar parameter value */
1628 gretl_matrix *b; /* parameter vector */
1629 gretl_matrix *g; /* gradient vector */
1630 gretl_matrix *h; /* hessian matrix */
1631 int ncoeff; /* number of coefficients */
1632 GENERATOR *gf; /* for generating scalar or matrix result */
1633 GENERATOR *gg; /* for generating gradient */
1634 GENERATOR *gh; /* for generating Hessian */
1635 double fx_out; /* function double value */
1636 gretl_matrix *fm_out; /* function matrix value */
1637 char gmname[VNAMELEN]; /* name of user-defined gradient vector */
1638 char hmname[VNAMELEN]; /* name of user-defined Hessian matrix */
1639 DATASET *dset; /* dataset */
1640 PRN *prn; /* optional printing struct */
1641 };
1642
umax_new(GretlType t)1643 static umax *umax_new (GretlType t)
1644 {
1645 umax *u = malloc(sizeof *u);
1646
1647 if (u != NULL) {
1648 u->gentype = t;
1649 u->pxname = NULL;
1650 u->b = NULL;
1651 u->g = NULL;
1652 u->h = NULL;
1653 u->ncoeff = 0;
1654 u->gf = NULL;
1655 u->gg = NULL;
1656 u->gh = NULL;
1657 u->fx_out = NADBL;
1658 u->fm_out = NULL;
1659 u->gmname[0] = '\0';
1660 u->hmname[0] = '\0';
1661 u->dset = NULL;
1662 u->prn = NULL;
1663 }
1664
1665 return u;
1666 }
1667
umax_unset_no_replace_flag(umax * u)1668 static void umax_unset_no_replace_flag (umax *u)
1669 {
1670 user_var *uv = get_user_var_by_data(u->b);
1671
1672 if (uv != NULL) {
1673 user_var_unset_flag(uv, UV_NOREPL);
1674 }
1675 }
1676
umax_destroy(umax * u)1677 static void umax_destroy (umax *u)
1678 {
1679 if (u->dset != NULL) {
1680 /* drop any private "$" series created */
1681 dataset_drop_listed_variables(NULL, u->dset, NULL, NULL);
1682 }
1683
1684 umax_unset_no_replace_flag(u);
1685 user_var_delete_by_name("$umax", NULL);
1686 free(u->pxname);
1687
1688 destroy_genr(u->gf);
1689 destroy_genr(u->gg);
1690 destroy_genr(u->gh);
1691
1692 free(u);
1693 }
1694
1695 /* user-defined optimizer: get the criterion value */
1696
user_get_criterion(const double * b,void * p)1697 static double user_get_criterion (const double *b, void *p)
1698 {
1699 umax *u = (umax *) p;
1700 double x = NADBL;
1701 int i, t, err;
1702
1703 for (i=0; i<u->ncoeff; i++) {
1704 u->b->val[i] = b[i];
1705 }
1706
1707 err = execute_genr(u->gf, u->dset, u->prn);
1708
1709 if (err) {
1710 return NADBL;
1711 }
1712
1713 t = genr_get_output_type(u->gf);
1714
1715 if (t == GRETL_TYPE_DOUBLE) {
1716 x = genr_get_output_scalar(u->gf);
1717 } else if (t == GRETL_TYPE_MATRIX) {
1718 gretl_matrix *m = genr_get_output_matrix(u->gf);
1719
1720 if (gretl_matrix_is_scalar(m)) {
1721 x = m->val[0];
1722 } else {
1723 err = E_TYPES;
1724 }
1725 } else {
1726 err = E_TYPES;
1727 }
1728
1729 u->fx_out = x;
1730
1731 return x;
1732 }
1733
user_get_criterion2(double b,void * p)1734 static double user_get_criterion2 (double b, void *p)
1735 {
1736 umax *u = (umax *) p;
1737 double x = NADBL;
1738 int t, err;
1739
1740 gretl_scalar_set_value(u->pxname, b);
1741 err = execute_genr(u->gf, u->dset, u->prn);
1742
1743 if (err) {
1744 return NADBL;
1745 }
1746
1747 t = genr_get_output_type(u->gf);
1748
1749 if (t == GRETL_TYPE_DOUBLE) {
1750 x = genr_get_output_scalar(u->gf);
1751 } else if (t == GRETL_TYPE_MATRIX) {
1752 gretl_matrix *m = genr_get_output_matrix(u->gf);
1753
1754 if (gretl_matrix_is_scalar(m)) {
1755 x = m->val[0];
1756 } else {
1757 err = E_TYPES;
1758 }
1759 } else {
1760 err = E_TYPES;
1761 }
1762
1763 u->fx_out = x;
1764
1765 return x;
1766 }
1767
1768 /* user-defined optimizer: get the gradient, if specified */
1769
user_get_gradient(double * b,double * g,int k,BFGS_CRIT_FUNC func,void * p)1770 static int user_get_gradient (double *b, double *g, int k,
1771 BFGS_CRIT_FUNC func, void *p)
1772 {
1773 umax *u = (umax *) p;
1774 gretl_matrix *ug;
1775 int i, err;
1776
1777 for (i=0; i<k; i++) {
1778 u->b->val[i] = b[i];
1779 }
1780
1781 err = execute_genr(u->gg, u->dset, u->prn);
1782
1783 if (err) {
1784 return err;
1785 }
1786
1787 ug = get_matrix_by_name(u->gmname);
1788
1789 if (ug == NULL) {
1790 err = E_UNKVAR;
1791 } else if (gretl_vector_get_length(ug) != k) {
1792 err = E_NONCONF;
1793 } else {
1794 for (i=0; i<k; i++) {
1795 g[i] = ug->val[i];
1796 }
1797 }
1798
1799 return err;
1800 }
1801
1802 /* user-defined optimizer: get the hessian, if specified */
1803
user_get_hessian(double * b,gretl_matrix * H,void * p)1804 static int user_get_hessian (double *b, gretl_matrix *H,
1805 void *p)
1806 {
1807 umax *u = (umax *) p;
1808 gretl_matrix *uH;
1809 int k = H->rows;
1810 int i, err;
1811
1812 for (i=0; i<k; i++) {
1813 u->b->val[i] = b[i];
1814 }
1815
1816 err = execute_genr(u->gh, u->dset, u->prn);
1817
1818 if (err) {
1819 return err;
1820 }
1821
1822 uH = get_matrix_by_name(u->hmname);
1823
1824 if (uH == NULL) {
1825 err = E_UNKVAR;
1826 } else if (uH->rows != k || uH->cols != k) {
1827 err = E_NONCONF;
1828 } else {
1829 gretl_matrix_copy_values(H, uH);
1830 }
1831
1832 return err;
1833 }
1834
1835 /* parse the name of the user gradient matrix (vector) or
1836 Hessian out of the associated function call, where it
1837 must be the first argument, given in pointer form
1838 */
1839
optimizer_get_matrix_name(const char * fncall,char * name)1840 int optimizer_get_matrix_name (const char *fncall, char *name)
1841 {
1842 const char *s = strchr(fncall, '(');
1843 int n, err = 0;
1844
1845 if (s == NULL) {
1846 err = E_DATA;
1847 } else {
1848 s++;
1849 s += strspn(s, " ");
1850 if (*s != '&') {
1851 err = E_TYPES;
1852 } else {
1853 s++;
1854 n = gretl_namechar_spn(s);
1855 if (n >= VNAMELEN) {
1856 err = E_DATA;
1857 } else {
1858 strncat(name, s, n);
1859 }
1860 }
1861 }
1862
1863 return err;
1864 }
1865
check_optimizer_scalar_parm(umax * u,const char * s)1866 static int check_optimizer_scalar_parm (umax *u, const char *s)
1867 {
1868 int n = gretl_namechar_spn(s);
1869 int err = 0;
1870
1871 if (n > 0 && n < VNAMELEN) {
1872 char vname[VNAMELEN];
1873
1874 *vname = '\0';
1875 strncat(vname, s, n);
1876 if (!gretl_is_scalar(vname)) {
1877 err = gretl_scalar_add(vname, NADBL);
1878 }
1879 if (!err) {
1880 u->pxname = gretl_strdup(vname);
1881 }
1882 } else if (n >= VNAMELEN) {
1883 err = E_INVARG;
1884 }
1885
1886 return err;
1887 }
1888
1889 /* Ensure that we can find the specified callback function,
1890 and that it cannot replace/move its param-vector argument,
1891 given by u->b.
1892 */
1893
check_optimizer_callback(umax * u,const char * fncall)1894 static int check_optimizer_callback (umax *u, const char *fncall)
1895 {
1896 int n = strcspn(fncall, "(");
1897 int err = 0;
1898
1899 if (n > 0 && n < FN_NAMELEN) {
1900 char fname[FN_NAMELEN];
1901 user_var *uvar = NULL;
1902 ufunc *ufun;
1903
1904 *fname = '\0';
1905 strncat(fname, fncall, n);
1906 ufun = get_user_function_by_name(fname);
1907 if (u->b == NULL) {
1908 check_optimizer_scalar_parm(u, fncall + n + 1);
1909 } else {
1910 uvar = get_user_var_by_data(u->b);
1911 }
1912 if (ufun != NULL && uvar != NULL) {
1913 user_var_set_flag(uvar, UV_NOREPL);
1914 }
1915 } else if (n >= FN_NAMELEN) {
1916 err = E_INVARG;
1917 }
1918
1919 return err;
1920 }
1921
user_gen_setup(umax * u,const char * fncall,const char * gradcall,const char * hesscall,DATASET * dset)1922 static int user_gen_setup (umax *u,
1923 const char *fncall,
1924 const char *gradcall,
1925 const char *hesscall,
1926 DATASET *dset)
1927 {
1928 gchar *formula;
1929 int err;
1930
1931 err = check_optimizer_callback(u, fncall);
1932 if (!err && gradcall != NULL) {
1933 err = check_optimizer_callback(u, gradcall);
1934 }
1935 if (!err && hesscall != NULL) {
1936 err = check_optimizer_callback(u, hesscall);
1937 }
1938 if (err) {
1939 return err;
1940 }
1941
1942 formula = g_strdup_printf("$umax=%s", fncall);
1943 u->gf = genr_compile(formula, dset, u->gentype, OPT_P,
1944 u->prn, &err);
1945
1946 if (!err && gradcall != NULL) {
1947 /* process gradient formula */
1948 err = optimizer_get_matrix_name(gradcall, u->gmname);
1949 if (!err) {
1950 u->gg = genr_compile(gradcall, dset, GRETL_TYPE_ANY,
1951 OPT_P | OPT_O, u->prn, &err);
1952 }
1953 }
1954
1955 if (!err && hesscall != NULL) {
1956 /* process Hessian formula */
1957 err = optimizer_get_matrix_name(hesscall, u->hmname);
1958 if (!err) {
1959 u->gh = genr_compile(hesscall, dset, GRETL_TYPE_ANY,
1960 OPT_P | OPT_O, u->prn, &err);
1961 }
1962 }
1963
1964 if (!err) {
1965 u->dset = dset;
1966 u->fm_out = genr_get_output_matrix(u->gf);
1967 } else {
1968 umax_unset_no_replace_flag(u);
1969 destroy_genr(u->gf);
1970 destroy_genr(u->gg);
1971 u->gf = u->gg = NULL;
1972 }
1973
1974 g_free(formula);
1975
1976 return err;
1977 }
1978
user_BFGS(gretl_matrix * b,const char * fncall,const char * gradcall,DATASET * dset,const gretl_matrix * bounds,int minimize,PRN * prn,int * err)1979 double user_BFGS (gretl_matrix *b,
1980 const char *fncall,
1981 const char *gradcall,
1982 DATASET *dset,
1983 const gretl_matrix *bounds,
1984 int minimize, PRN *prn,
1985 int *err)
1986 {
1987 umax *u;
1988 gretlopt opt = OPT_NONE;
1989 int maxit = BFGS_MAXITER_DEFAULT;
1990 int verbose, fcount = 0, gcount = 0;
1991 double tol;
1992 double ret = NADBL;
1993
1994 u = umax_new(GRETL_TYPE_DOUBLE);
1995 if (u == NULL) {
1996 *err = E_ALLOC;
1997 return ret;
1998 }
1999
2000 u->ncoeff = gretl_vector_get_length(b);
2001 if (u->ncoeff == 0) {
2002 *err = E_DATA;
2003 goto bailout;
2004 }
2005
2006 u->b = b;
2007 u->prn = prn; /* placement of this? */
2008
2009 *err = user_gen_setup(u, fncall, gradcall, NULL, dset);
2010 if (*err) {
2011 return NADBL;
2012 }
2013
2014 tol = libset_get_double(BFGS_TOLER);
2015 verbose = libset_get_int(MAX_VERBOSE);
2016
2017 if (verbose) {
2018 opt |= OPT_V;
2019 }
2020
2021 if (minimize) {
2022 opt |= OPT_I;
2023 }
2024
2025 if (bounds != NULL) {
2026 *err = BFGS_cmax(b->val, u->ncoeff,
2027 maxit, tol, &fcount, &gcount,
2028 user_get_criterion, C_OTHER,
2029 (u->gg == NULL)? NULL : user_get_gradient,
2030 u, bounds, opt, prn);
2031 } else {
2032 *err = BFGS_max(b->val, u->ncoeff,
2033 maxit, tol, &fcount, &gcount,
2034 user_get_criterion, C_OTHER,
2035 (u->gg == NULL)? NULL : user_get_gradient,
2036 u, NULL, opt, prn);
2037 }
2038
2039 if (fcount > 0 && (verbose || !gretl_looping())) {
2040 pprintf(prn, _("Function evaluations: %d\n"), fcount);
2041 pprintf(prn, _("Evaluations of gradient: %d\n"), gcount);
2042 }
2043
2044 if (!*err) {
2045 ret = u->fx_out;
2046 }
2047
2048 bailout:
2049
2050 umax_destroy(u);
2051
2052 return ret;
2053 }
2054
user_NR(gretl_matrix * b,const char * fncall,const char * gradcall,const char * hesscall,DATASET * dset,int minimize,PRN * prn,int * err)2055 double user_NR (gretl_matrix *b,
2056 const char *fncall,
2057 const char *gradcall,
2058 const char *hesscall,
2059 DATASET *dset,
2060 int minimize,
2061 PRN *prn, int *err)
2062 {
2063 umax *u;
2064 double crittol = 1.0e-7;
2065 double gradtol = 1.0e-7;
2066 gretlopt opt = OPT_NONE;
2067 int maxit = 100;
2068 int iters = 0;
2069 double ret = NADBL;
2070
2071 u = umax_new(GRETL_TYPE_DOUBLE);
2072 if (u == NULL) {
2073 *err = E_ALLOC;
2074 return ret;
2075 }
2076
2077 u->ncoeff = gretl_vector_get_length(b);
2078 if (u->ncoeff == 0) {
2079 *err = E_DATA;
2080 goto bailout;
2081 }
2082
2083 u->b = b;
2084
2085 *err = user_gen_setup(u, fncall, gradcall, hesscall, dset);
2086 if (*err) {
2087 fprintf(stderr, "user_NR: failed on user_gen_setup\n");
2088 return NADBL;
2089 }
2090
2091 if (libset_get_int(MAX_VERBOSE)) {
2092 opt |= OPT_V;
2093 }
2094
2095 if (minimize) {
2096 opt |= OPT_I;
2097 }
2098
2099 u->prn = prn; /* 2015-03-10: this was conditional on OPT_V */
2100
2101 *err = newton_raphson_max(b->val, u->ncoeff, maxit,
2102 crittol, gradtol,
2103 &iters, C_OTHER,
2104 user_get_criterion,
2105 (u->gg == NULL)? NULL : user_get_gradient,
2106 (u->gh == NULL)? NULL : user_get_hessian,
2107 u, opt, prn);
2108
2109 if (!*err) {
2110 ret = u->fx_out;
2111 }
2112
2113 bailout:
2114
2115 umax_destroy(u);
2116
2117 return ret;
2118 }
2119
deriv_free_optimize(MaxMethod method,gretl_matrix * b,const char * fncall,int maxit,double tol,int minimize,DATASET * dset,PRN * prn,int * err)2120 double deriv_free_optimize (MaxMethod method,
2121 gretl_matrix *b,
2122 const char *fncall,
2123 int maxit,
2124 double tol,
2125 int minimize,
2126 DATASET *dset,
2127 PRN *prn, int *err)
2128 {
2129 umax *u;
2130 gretlopt opt = OPT_NONE;
2131 double ret = NADBL;
2132
2133 if (b->is_complex) {
2134 *err = E_CMPLX;
2135 return ret;
2136 }
2137
2138 u = umax_new(GRETL_TYPE_DOUBLE);
2139 if (u == NULL) {
2140 *err = E_ALLOC;
2141 return ret;
2142 }
2143
2144 u->ncoeff = gretl_vector_get_length(b);
2145 if (u->ncoeff == 0 || (method == ROOT_FIND && u->ncoeff != 2)) {
2146 *err = E_INVARG;
2147 goto bailout;
2148 }
2149
2150 if (method != ROOT_FIND) {
2151 u->b = b;
2152 }
2153
2154 *err = user_gen_setup(u, fncall, NULL, NULL, dset);
2155 if (*err) {
2156 return NADBL;
2157 }
2158
2159 if (libset_get_int(MAX_VERBOSE)) {
2160 opt = OPT_V;
2161 u->prn = prn;
2162 }
2163
2164 if (minimize) {
2165 opt |= OPT_I;
2166 }
2167
2168 if (method == SIMANN_MAX) {
2169 *err = gretl_simann(b->val, u->ncoeff, maxit,
2170 user_get_criterion, u,
2171 opt, prn);
2172 } else if (method == NM_MAX) {
2173 *err = gretl_amoeba(b->val, u->ncoeff, maxit,
2174 user_get_criterion, u,
2175 opt, prn);
2176 } else if (method == GSS_MAX) {
2177 int iters = 0;
2178
2179 *err = gretl_gss(b->val, tol, &iters,
2180 user_get_criterion, u,
2181 opt, prn);
2182 } else if (method == ROOT_FIND) {
2183 *err = gretl_fzero(b->val, tol,
2184 user_get_criterion2, u,
2185 &ret, opt, prn);
2186 }
2187
2188 if (!*err && method != ROOT_FIND) {
2189 ret = user_get_criterion(b->val, u);
2190 }
2191
2192 bailout:
2193
2194 umax_destroy(u);
2195
2196 return ret;
2197 }
2198
2199 #define JAC_DEBUG 0
2200
user_calc_fvec(int m,int n,double * x,double * fvec,int * iflag,void * p)2201 static int user_calc_fvec (int m, int n, double *x, double *fvec,
2202 int *iflag, void *p)
2203 {
2204 umax *u = (umax *) p;
2205 gretl_matrix *v;
2206 int i, err;
2207
2208 for (i=0; i<n; i++) {
2209 u->b->val[i] = x[i];
2210 }
2211
2212 #if JAC_DEBUG
2213 gretl_matrix_print(u->b, "user_calc_fvec: u->b");
2214 #endif
2215
2216 err = execute_genr(u->gf, u->dset, u->prn);
2217 if (err) {
2218 fprintf(stderr, "execute_genr: err = %d\n", err);
2219 }
2220
2221 if (err) {
2222 *iflag = -1;
2223 return 0;
2224 }
2225
2226 v = genr_get_output_matrix(u->gf);
2227
2228 #if JAC_DEBUG
2229 gretl_matrix_print(v, "matrix from u->f");
2230 #endif
2231
2232 if (v == NULL || gretl_vector_get_length(v) != m) {
2233 fprintf(stderr, "user_calc_fvec: got bad matrix\n");
2234 *iflag = -1;
2235 } else {
2236 for (i=0; i<m; i++) {
2237 fvec[i] = v->val[i];
2238 }
2239 }
2240
2241 return 0;
2242 }
2243
fdjac_allocate(int m,int n,gretl_matrix ** J,double ** w,double ** f)2244 static int fdjac_allocate (int m, int n,
2245 gretl_matrix **J,
2246 double **w, double **f)
2247 {
2248 *J = gretl_matrix_alloc(m, n);
2249 if (*J == NULL) {
2250 return E_ALLOC;
2251 }
2252
2253 *w = malloc(m * sizeof **w);
2254 *f = malloc(m * sizeof **f);
2255
2256 if (*w == NULL || *f == NULL) {
2257 return E_ALLOC;
2258 }
2259
2260 return 0;
2261 }
2262
user_fdjac(gretl_matrix * theta,const char * fncall,double eps,DATASET * dset,int * err)2263 gretl_matrix *user_fdjac (gretl_matrix *theta, const char *fncall,
2264 double eps, DATASET *dset, int *err)
2265 {
2266 umax *u;
2267 gretl_matrix *J = NULL;
2268 int m, n, nnf = 0;
2269 int iflag = 0;
2270 double *wa = NULL;
2271 double *fvec = NULL;
2272 int i;
2273
2274 *err = 0;
2275
2276 u = umax_new(GRETL_TYPE_MATRIX);
2277 if (u == NULL) {
2278 *err = E_ALLOC;
2279 return NULL;
2280 }
2281
2282 n = gretl_vector_get_length(theta);
2283 if (n == 0) {
2284 fprintf(stderr, "fdjac: gretl_vector_get_length gave %d for theta\n",
2285 n);
2286 *err = E_DATA;
2287 return NULL;
2288 }
2289
2290 u->b = theta;
2291 u->ncoeff = n;
2292
2293 *err = user_gen_setup(u, fncall, NULL, NULL, dset);
2294 if (*err) {
2295 fprintf(stderr, "fdjac: error %d from user_gen_setup\n", *err);
2296 goto bailout;
2297 }
2298
2299 if (u->fm_out == NULL) {
2300 fprintf(stderr, "fdjac: u.fm_out is NULL\n");
2301 *err = E_DATA; /* FIXME */
2302 goto bailout;
2303 }
2304
2305 m = gretl_vector_get_length(u->fm_out);
2306 if (m == 0) {
2307 *err = E_DATA;
2308 goto bailout;
2309 }
2310
2311 *err = fdjac_allocate(m, n, &J, &wa, &fvec);
2312 if (*err) {
2313 goto bailout;
2314 }
2315
2316 for (i=0; i<m; i++) {
2317 fvec[i] = u->fm_out->val[i];
2318 if (na(fvec[i])) {
2319 nnf++;
2320 }
2321 }
2322
2323 if (nnf > 0) {
2324 gretl_errmsg_sprintf("fdjac: got %d non-finite value(s) on input",
2325 nnf);
2326 *err = E_DATA;
2327 } else {
2328 int quality = libset_get_int(FDJAC_QUAL);
2329
2330 fdjac2_(user_calc_fvec, m, n, quality, theta->val, fvec, J->val,
2331 m, &iflag, eps, wa, u);
2332 }
2333
2334 bailout:
2335
2336 free(wa);
2337 free(fvec);
2338
2339 if (*err) {
2340 gretl_matrix_free(J);
2341 J = NULL;
2342 }
2343
2344 umax_destroy(u);
2345
2346 return J;
2347 }
2348
user_numhess(gretl_matrix * b,const char * fncall,double d,DATASET * dset,int * err)2349 gretl_matrix *user_numhess (gretl_matrix *b, const char *fncall,
2350 double d, DATASET *dset, int *err)
2351 {
2352 gretl_matrix *H = NULL;
2353 struct uhess_data uh = {0};
2354 gchar *formula = NULL;
2355 int n;
2356
2357 if (get_user_var_by_data(b) == NULL) {
2358 fprintf(stderr, "numhess: b must be a named matrix\n");
2359 *err = E_DATA;
2360 return NULL;
2361 }
2362
2363 n = gretl_vector_get_length(b);
2364 if (n == 0) {
2365 fprintf(stderr, "numhess: gretl_vector_get_length gave %d for b\n", n);
2366 *err = E_DATA;
2367 return NULL;
2368 }
2369
2370 if (!*err) {
2371 formula = g_strdup_printf("$umax=%s", fncall);
2372 uh.genr = genr_compile(formula, dset, GRETL_TYPE_DOUBLE, OPT_P,
2373 NULL, err);
2374 }
2375
2376 if (*err) {
2377 fprintf(stderr, "numhess: error %d from genr_compile\n", *err);
2378 } else {
2379 H = gretl_zero_matrix_new(n, n);
2380 if (H == NULL) {
2381 *err = E_ALLOC;
2382 }
2383 }
2384
2385 if (!*err) {
2386 uh.dset = dset;
2387 *err = numerical_hessian(b->val, H, uhess_callback,
2388 &uh, 0, d);
2389 }
2390
2391 g_free(formula);
2392 user_var_delete_by_name("$umax", NULL);
2393 destroy_genr(uh.genr);
2394
2395 if (*err && H != NULL) {
2396 gretl_matrix_free(H);
2397 H = NULL;
2398 }
2399
2400 return H;
2401 }
2402
2403 /* Below: Newton-Raphson code, starting with a few
2404 auxiliary functions */
2405
broken_matrix(const gretl_matrix * m)2406 static int broken_matrix (const gretl_matrix *m)
2407 {
2408 int i, n = m->rows * m->cols;
2409
2410 for (i=0; i<n; i++) {
2411 if (na(m->val[i])) {
2412 return 1;
2413 }
2414 }
2415
2416 return 0;
2417 }
2418
copy_to(double * targ,const double * src,int n)2419 static void copy_to (double *targ, const double *src, int n)
2420 {
2421 int i;
2422
2423 for (i=0; i<n; i++) {
2424 targ[i] = src[i];
2425 }
2426 }
2427
copy_plus(double * targ,const double * src,double step,const double * a,int n)2428 static void copy_plus (double *targ, const double *src,
2429 double step, const double *a, int n)
2430 {
2431 int i;
2432
2433 for (i=0; i<n; i++) {
2434 targ[i] = src[i] + step * a[i];
2435 }
2436 }
2437
scalar_xpx(const gretl_matrix * m)2438 static double scalar_xpx (const gretl_matrix *m)
2439 {
2440 double xpx = 0.0;
2441 int i;
2442
2443 for (i=0; i<m->rows; i++) {
2444 xpx += m->val[i] * m->val[i];
2445 }
2446
2447 return xpx;
2448 }
2449
2450 enum {
2451 GRADTOL_MET = 1,
2452 CRITTOL_MET,
2453 STEPMIN_MET
2454 };
2455
print_NR_status(int status,double crittol,double gradtol,double sumgrad,PRN * prn)2456 static void print_NR_status (int status, double crittol, double gradtol,
2457 double sumgrad, PRN *prn)
2458 {
2459 int msgs = gretl_messages_on();
2460
2461 if (status == GRADTOL_MET) {
2462 if (msgs) {
2463 pprintf(prn, _("Gradient within tolerance (%g)\n"), gradtol);
2464 }
2465 } else if (status == CRITTOL_MET) {
2466 if (msgs) {
2467 pprintf(prn, _("Successive criterion values within tolerance (%g)\n"),
2468 crittol);
2469 }
2470 } else if (status == STEPMIN_MET) {
2471 if (sumgrad > 0) {
2472 pprintf(prn, _("Warning: couldn't improve criterion (gradient = %g)\n"),
2473 sumgrad);
2474 } else {
2475 pprintf(prn, _("Warning: couldn't improve criterion\n"));
2476 }
2477 }
2478 }
2479
2480 /*
2481 The strategy here may be simplistic, but appears to be effective in
2482 quite a few cases: If the (negative) Hessian is not pd, we try to
2483 nudge it towards positive definiteness without losing too much
2484 information on curvature by downsizing the off-diagonal elements of
2485 H. In practice, we use
2486
2487 C = \lambda H + (1-lambda) diag(H)
2488
2489 where lambda is reasonably close to 1. Note that, if lambda was 0,
2490 a NR iteration would just amount to an iteration of the simple
2491 gradient method (on a scaled version of the coefficients).
2492 Hopefully, a few of those should be able to "tow us away" from the
2493 non-pd region. In desperate cases, we use the a diagonal matrix
2494 with the absolute values of H_{i,i} plus one.
2495 */
2496
NR_invert_hessian(gretl_matrix * H,const gretl_matrix * Hcpy)2497 static int NR_invert_hessian (gretl_matrix *H, const gretl_matrix *Hcpy)
2498 {
2499 double hii, hmin = 1.0e-28; /* was 1.0e-20 */
2500 int i, j, n = H->rows;
2501 int restore = 0;
2502 double x;
2503 int err = 0;
2504
2505 /* first, check if all the elements along the diagonal are
2506 numerically positive
2507 */
2508 for (i=0; i<n && !err; i++) {
2509 hii = gretl_matrix_get(H, i, i);
2510 if (hii < hmin) {
2511 err = 1;
2512 break;
2513 }
2514 }
2515
2516 if (err) {
2517 fprintf(stderr, "NR_invert_hessian: non-positive "
2518 "diagonal (H(%d,%d) = %g)\n", i+1, i+1, hii);
2519 } else {
2520 err = gretl_invert_symmetric_matrix(H);
2521
2522 if (err == E_NOTPD) {
2523 double lambda = 1.0;
2524 int s;
2525
2526 for (s=0; lambda > 0.1 && err; s++) {
2527 lambda *= 0.8;
2528 fprintf(stderr, "newton hessian fixup: round %d, lambda=%g\n",
2529 s, lambda);
2530 /* restore the original H */
2531 gretl_matrix_copy_values(H, Hcpy);
2532 for (i=0; i<n; i++) {
2533 for (j=0; j<i; j++) {
2534 x = lambda * gretl_matrix_get(H, i, j);
2535 gretl_matrix_set(H, i, j, x);
2536 gretl_matrix_set(H, j, i, x);
2537 }
2538 }
2539 err = gretl_invert_symmetric_matrix(H);
2540 }
2541 restore = (err != 0);
2542 }
2543 }
2544
2545 if (err) {
2546 fprintf(stderr, "NR_invert_hessian: major surgery needed\n");
2547 if (restore) {
2548 gretl_matrix_copy_values(H, Hcpy);
2549 }
2550 for (i=0; i<n; i++) {
2551 for (j=0; j<n; j++) {
2552 x = (i==j) ? 1/(1 + fabs(gretl_matrix_get(H, i, j))): 0;
2553 gretl_matrix_set(H, i, j, x);
2554 }
2555 }
2556 }
2557
2558 return 0;
2559 }
2560
2561 /**
2562 * newton_raphson_max:
2563 * @b: array of adjustable coefficients.
2564 * @n: number elements in array @b.
2565 * @maxit: the maximum number of iterations to allow.
2566 * @crittol: tolerance for terminating iteration, in terms of
2567 * the change in the criterion.
2568 * @gradtol: tolerance for terminating iteration, in terms of
2569 * the gradient.
2570 * @itercount: location to receive count of iterations.
2571 * @crittype: code for type of the maximand/minimand: should
2572 * be %C_LOGLIK, %C_GMM or %C_OTHER. Used only in printing
2573 * iteration info.
2574 * @cfunc: pointer to function used to calculate maximand.
2575 * @gradfunc: pointer to function used to calculate the
2576 * gradient, or %NULL for default numerical calculation.
2577 * @hessfunc: pointer to function used to calculate the
2578 * Hessian.
2579 * @data: pointer that will be passed as the last
2580 * parameter to the callback functions @cfunc, @gradfunc
2581 * and @hessfunc.
2582 * @opt: may contain %OPT_V for verbose operation.
2583 * @prn: printing struct (or %NULL). Only used if @opt
2584 * includes %OPT_V.
2585 *
2586 * The functions @cfunc (computes the criterion, usually a
2587 * loglikelihood) and @gradfunc (score, provides an updated
2588 * estimate of the gradient in its second argument) are just as in
2589 * BFGS_max above.
2590 *
2591 * The @hessfunc callback should compute the negative Hessian,
2592 * _not_ inverted; newton_raphson_max takes care of the inversion,
2593 * with a routine for fixing up the matrix if it's not positive
2594 * definite. If @hessfunc is NULL we fall back on a numerical
2595 * approximation to the Hessian.
2596 *
2597 * Returns: 0 on successful completion, non-zero error code
2598 * on error.
2599 */
2600
newton_raphson_max(double * b,int n,int maxit,double crittol,double gradtol,int * itercount,int crittype,BFGS_CRIT_FUNC cfunc,BFGS_GRAD_FUNC gradfunc,HESS_FUNC hessfunc,void * data,gretlopt opt,PRN * prn)2601 int newton_raphson_max (double *b, int n, int maxit,
2602 double crittol, double gradtol,
2603 int *itercount, int crittype,
2604 BFGS_CRIT_FUNC cfunc,
2605 BFGS_GRAD_FUNC gradfunc,
2606 HESS_FUNC hessfunc,
2607 void *data, gretlopt opt,
2608 PRN *prn)
2609 {
2610 BFGS_GRAD_FUNC realgrad = NULL;
2611 int verbose = (opt & OPT_V);
2612 int minimize = (opt & OPT_I);
2613 double stepmin = 1.0e-6;
2614 gretl_matrix_block *B;
2615 gretl_matrix *H0, *H1;
2616 gretl_matrix *g, *a;
2617 double *b0, *b1;
2618 double f0, f1, sumgrad = 0;
2619 double steplen = 1.0;
2620 int status = 0;
2621 int iter = 0;
2622 int err = 0;
2623
2624 b0 = malloc(2 * n * sizeof *b0);
2625 if (b0 == NULL) {
2626 return E_ALLOC;
2627 }
2628
2629 B = gretl_matrix_block_new(&H0, n, n,
2630 &H1, n, n,
2631 &g, n, 1,
2632 &a, n, 1,
2633 NULL);
2634 if (B == NULL) {
2635 free(b0);
2636 return E_ALLOC;
2637 }
2638
2639 if (gradfunc == NULL) {
2640 gradfunc = numeric_gradient;
2641 } else {
2642 realgrad = gradfunc;
2643 }
2644
2645 /* needs some work */
2646 optim_get_user_values(b, n, NULL, NULL, NULL, opt, prn);
2647
2648 b1 = b0 + n;
2649 copy_to(b1, b, n);
2650
2651 f1 = optim_fncall(cfunc, b1, data, minimize);
2652 if (na(f1)) {
2653 gretl_errmsg_set(_("Initial value of objective function is not finite"));
2654 err = E_NAN;
2655 }
2656
2657 if (!err) {
2658 err = optim_gradcall(gradfunc, b, g->val, n, cfunc, data, minimize);
2659 if (err) {
2660 fprintf(stderr, "newton_raphson_max: err = %d from %s\n", err,
2661 realgrad ? "supplied gradfunc" : "numeric_gradient");
2662 }
2663 }
2664
2665 if (!err) {
2666 if (hessfunc != NULL) {
2667 err = hessfunc(b, H1, data);
2668 } else {
2669 err = NR_fallback_hessian(b, H1, realgrad, cfunc, data);
2670 }
2671 if (!err) {
2672 if (minimize) {
2673 gretl_matrix_multiply_by_scalar(H1, -1.0);
2674 }
2675 gretl_matrix_copy_values(H0, H1);
2676 err = NR_invert_hessian(H1, H0);
2677 }
2678 }
2679
2680 gretl_iteration_push();
2681
2682 while (status == 0 && !err) {
2683 iter++;
2684 steplen = 1.0;
2685 f0 = f1;
2686
2687 copy_to(b0, b1, n);
2688
2689 if (broken_matrix(g)) {
2690 fprintf(stderr, "NA in gradient\n");
2691 err = E_NAN;
2692 break;
2693 }
2694
2695 gretl_matrix_copy_values(H0, H1);
2696 if (broken_matrix(H0)) {
2697 fprintf(stderr, "NA in Hessian\n");
2698 err = E_NAN;
2699 break;
2700 }
2701
2702 /* apply quadratic approximation */
2703 gretl_matrix_multiply(H0, g, a);
2704 copy_plus(b1, b0, steplen, a->val, n);
2705 f1 = optim_fncall(cfunc, b1, data, minimize);
2706
2707 while (na(f1) || ((f1 < f0) && (steplen > stepmin))) {
2708 /* try smaller step */
2709 steplen /= 2.0;
2710 copy_plus(b1, b0, steplen, a->val, n);
2711 f1 = optim_fncall(cfunc, b1, data, minimize);
2712 }
2713
2714 if (verbose) {
2715 print_iter_info(iter, f1, crittype, n, b1, g->val,
2716 steplen, prn);
2717 }
2718
2719 err = optim_gradcall(gradfunc, b1, g->val, n, cfunc, data,
2720 minimize);
2721
2722 if (err || broken_matrix(g)) {
2723 err = (err == 0)? E_NAN : err;
2724 break;
2725 }
2726
2727 if (hessfunc != NULL) {
2728 err = hessfunc(b1, H1, data);
2729 } else {
2730 err = NR_fallback_hessian(b1, H1, realgrad, cfunc, data);
2731 }
2732
2733 if (err || broken_matrix(H1)) {
2734 err = (err == 0)? E_NAN : err;
2735 break;
2736 }
2737
2738 if (!err) {
2739 if (minimize) {
2740 gretl_matrix_multiply_by_scalar(H1, -1.0);
2741 }
2742 gretl_matrix_copy_values(H0, H1);
2743 err = NR_invert_hessian(H1, H0);
2744 if (err) {
2745 break;
2746 }
2747 }
2748
2749 sumgrad = sqrt(scalar_xpx(g));
2750
2751 if (steplen < stepmin) {
2752 status = STEPMIN_MET;
2753 } else if (iter > maxit) {
2754 err = E_NOCONV;
2755 } else if (sumgrad < gradtol) {
2756 status = GRADTOL_MET;
2757 } else if (f1 - f0 < crittol) {
2758 status = CRITTOL_MET;
2759 }
2760 }
2761
2762 gretl_iteration_pop();
2763
2764 if (verbose) {
2765 print_iter_info(-1, f1, crittype, n, b1, g->val,
2766 steplen, prn);
2767 pputc(prn, '\n');
2768 }
2769
2770 *itercount = iter;
2771
2772 if (!err) {
2773 copy_to(b, b1, n);
2774 if (prn != NULL) {
2775 print_NR_status(status, crittol, gradtol, sumgrad, prn);
2776 }
2777 }
2778
2779 free(b0);
2780 gretl_matrix_block_destroy(B);
2781
2782 return err;
2783 }
2784
simann_call(BFGS_CRIT_FUNC cfunc,double * b,void * data,int minimize)2785 static double simann_call (BFGS_CRIT_FUNC cfunc,
2786 double *b, void *data,
2787 int minimize)
2788 {
2789 double ret = cfunc(b, data);
2790
2791 return na(ret) ? NADBL : minimize ? -ret : ret;
2792 }
2793
2794 /**
2795 * gretl_simann:
2796 * @theta: parameter array.
2797 * @n: length of @theta.
2798 * @maxit: the maximum number of iterations to perform.
2799 * @cfunc: the function to be maximized.
2800 * @data: pointer to be passed to the @cfunc callback.
2801 * @opt: may include %OPT_V for verbose operation.
2802 * @prn: printing struct, or NULL.
2803 *
2804 * Simulated annealing: can help to improve the initialization
2805 * of @theta for numerical optimization. On exit the value of
2806 * @theta is set to the func-best point in case of improvement,
2807 * otherwise to the last point visited.
2808 *
2809 * Returns: 0 on success, non-zero code on error.
2810 */
2811
gretl_simann(double * theta,int n,int maxit,BFGS_CRIT_FUNC cfunc,void * data,gretlopt opt,PRN * prn)2812 int gretl_simann (double *theta, int n, int maxit,
2813 BFGS_CRIT_FUNC cfunc, void *data,
2814 gretlopt opt, PRN *prn)
2815 {
2816 gretl_matrix b;
2817 gretl_matrix *b0 = NULL;
2818 gretl_matrix *b1 = NULL;
2819 gretl_matrix *bstar = NULL;
2820 gretl_matrix *d = NULL;
2821 double f0, f1;
2822 double fbest, fworst;
2823 double Temp = 1.0;
2824 double radius = 1.0;
2825 int improved = 0;
2826 int minimize;
2827 int i, err = 0;
2828
2829 if (maxit <= 0) {
2830 maxit = 1024;
2831 }
2832
2833 /* maximize by default, but minimize if OPT_I is given */
2834 minimize = (opt & OPT_I)? 1 : 0;
2835
2836 gretl_matrix_init_full(&b, n, 1, theta);
2837
2838 b0 = gretl_matrix_copy(&b);
2839 b1 = gretl_matrix_copy(&b);
2840 bstar = gretl_matrix_copy(&b);
2841 d = gretl_column_vector_alloc(n);
2842
2843 if (b0 == NULL || b1 == NULL || bstar == NULL || d == NULL) {
2844 err = E_ALLOC;
2845 goto bailout;
2846 }
2847
2848 f0 = fbest = fworst = simann_call(cfunc, b.val, data, minimize);
2849
2850 if (opt & OPT_V) {
2851 pprintf(prn, "\nSimulated annealing: initial function value = %.8g\n",
2852 f0);
2853 }
2854
2855 gretl_iteration_push();
2856
2857 /* Question: should the initial radius be a function of the scale
2858 of the initial parameter vector?
2859 */
2860
2861 for (i=0; i<maxit; i++) {
2862 gretl_matrix_random_fill(d, D_NORMAL);
2863 gretl_matrix_multiply_by_scalar(d, radius);
2864 gretl_matrix_add_to(b1, d);
2865 f1 = simann_call(cfunc, b1->val, data, minimize);
2866
2867 if (!na(f1) && (f1 > f0 || gretl_rand_01() < Temp)) {
2868 /* jump to the new point */
2869 f0 = f1;
2870 gretl_matrix_copy_values(b0, b1);
2871 if (f0 > fbest) {
2872 fbest = f0;
2873 gretl_matrix_copy_values(bstar, b0);
2874 if (opt & OPT_V) {
2875 if (!improved) {
2876 pprintf(prn, "\n%6s %12s %12s %12s\n",
2877 "iter", "temp", "radius", "fbest");
2878 }
2879 pprintf(prn, "%6d %#12.6g %#12.6g %#12.6g\n",
2880 i, Temp, radius, fbest);
2881 }
2882 improved = 1;
2883 } else if (f0 < fworst) {
2884 fworst = f0;
2885 }
2886 } else {
2887 /* revert to where we were */
2888 gretl_matrix_copy_values(b1, b0);
2889 f1 = f0;
2890 }
2891
2892 Temp *= 0.999;
2893 radius *= 0.9999;
2894 }
2895
2896 gretl_iteration_pop();
2897
2898 if (improved) {
2899 /* use the best point */
2900 gretl_matrix_copy_values(&b, bstar);
2901 } else {
2902 /* use the last point */
2903 gretl_matrix_copy_values(&b, b0);
2904 }
2905
2906 if (improved) {
2907 if (opt & OPT_V) pputc(prn, '\n');
2908 } else {
2909 pprintf(prn, "No improvement found in %d iterations\n\n", maxit);
2910 }
2911
2912 if (fbest - fworst < 1.0e-9) {
2913 pprintf(prn, "*** warning: surface seems to be flat\n");
2914 }
2915
2916 bailout:
2917
2918 gretl_matrix_free(b0);
2919 gretl_matrix_free(b1);
2920 gretl_matrix_free(bstar);
2921 gretl_matrix_free(d);
2922
2923 return err;
2924 }
2925
2926 /*
2927 nelder_mead: this is based closely on the nelmin function as written
2928 in C by John Burkardt; see
2929 http://people.sc.fsu.edu/~jburkardt/c_src/asa047
2930 It is converted to a maximizer, and modified for use with the
2931 gretl library.
2932
2933 Burkardt's code is distributed under the GNU LGPL license, and was
2934 last modified on 28 October 2010. It draws on original Fortran code
2935 by R. O'Neill, for which see "Algorithm AS 47: Function Minimization
2936 Using a Simplex Procedure", Journal of the Royal Statistical
2937 Society, Series C (Applied Statistics), Vol. 20, No. 3, 1971.
2938 */
2939
nm_call(BFGS_CRIT_FUNC cfunc,double * b,void * data,int * ncalls,int minimize)2940 static double nm_call (BFGS_CRIT_FUNC cfunc,
2941 double *b, void *data,
2942 int *ncalls, int minimize)
2943 {
2944 double ret = cfunc(b, data);
2945
2946 *ncalls += 1;
2947
2948 return minimize ? ret : na(ret) ? ret : -ret;
2949 }
2950
2951 static int
nelder_mead(BFGS_CRIT_FUNC cfunc,int n,double start[],double xmin[],double * ynewlo,double reqmin,double step[],int maxcalls,int * ncalls,int * nresets,void * data,gretlopt opt,PRN * prn)2952 nelder_mead (BFGS_CRIT_FUNC cfunc, int n, double start[],
2953 double xmin[], double *ynewlo, double reqmin,
2954 double step[], int maxcalls, int *ncalls, int *nresets,
2955 void *data, gretlopt opt, PRN *prn)
2956 {
2957 gretl_matrix *pmat = NULL;
2958 double ccoeff = 0.5;
2959 double ecoeff = 2.0;
2960 double rcoeff = 1.0;
2961 double eps = 0.001;
2962 double del = 1.0;
2963 double *wspace;
2964 double *p;
2965 double *p2star;
2966 double *pbar;
2967 double *pstar;
2968 double *y;
2969 double rq, x, z;
2970 double ylo, ystar, y2star;
2971 /* frequency of convergence check */
2972 int konvge = 10;
2973 int i, ihi, ilo;
2974 int l, j, jcount;
2975 int outer, inner;
2976 int getmin;
2977 int err = 0;
2978
2979 /* use a gretl_matrix in case we want to print it */
2980 pmat = gretl_matrix_alloc(n, n + 1);
2981 wspace = malloc((4*n + 1) * sizeof *wspace);
2982
2983 if (pmat == NULL || wspace == NULL) {
2984 gretl_matrix_free(pmat);
2985 free(wspace);
2986 return E_ALLOC;
2987 }
2988
2989 p = pmat->val;
2990 pstar = wspace;
2991 p2star = pstar + n;
2992 pbar = p2star + n;
2993 y = pbar + n;
2994
2995 *ncalls = *nresets = 0;
2996 jcount = konvge;
2997 rq = reqmin * n;
2998
2999 /* maximize by default, but minimize if OPT_I is given */
3000 getmin = (opt & OPT_I)? 1 : 0;
3001
3002 gretl_iteration_push();
3003
3004 for (outer=1; ; outer++) {
3005 for (i=0; i<n; i++) {
3006 p[i+n*n] = start[i];
3007 }
3008 y[n] = nm_call(cfunc, start, data, ncalls, getmin);
3009
3010 if (opt & OPT_V) {
3011 if (outer == 1) {
3012 pprintf(prn, "\nOuter iteration %d: function value = %#g\n",
3013 outer, y[n]);
3014 } else {
3015 pprintf(prn, "Outer iteration %d (reset)\n", outer);
3016 }
3017 }
3018
3019 /* construct the simplex */
3020 for (j=0; j<n; j++) {
3021 x = start[j];
3022 start[j] += step[j] * del;
3023 for (i=0; i<n; i++) {
3024 p[i+j*n] = start[i];
3025 }
3026 y[j] = nm_call(cfunc, start, data, ncalls, getmin);
3027 start[j] = x;
3028 }
3029
3030 /* find the lowest y value */
3031 ylo = y[0];
3032 ilo = 0;
3033 for (i=1; i<=n; i++) {
3034 if (y[i] < ylo) {
3035 ylo = y[i];
3036 ilo = i;
3037 }
3038 }
3039
3040 for (inner=1; *ncalls < maxcalls; inner++) {
3041 *ynewlo = y[0];
3042 ihi = 0;
3043
3044 for (i=1; i<=n; i++) {
3045 if (*ynewlo < y[i]) {
3046 *ynewlo = y[i];
3047 ihi = i;
3048 }
3049 }
3050 /* calculate pbar, the centroid of the simplex */
3051 for (i=0; i<n; i++) {
3052 z = 0.0;
3053 for (j=0; j<=n; j++) {
3054 z += p[i+j*n];
3055 }
3056 z -= p[i+ihi*n];
3057 pbar[i] = z / n;
3058 }
3059
3060 /* reflection through the centroid */
3061 for (i=0; i<n; i++) {
3062 pstar[i] = pbar[i] + rcoeff * (pbar[i] - p[i+ihi*n]);
3063 }
3064 ystar = nm_call(cfunc, pstar, data, ncalls, getmin);
3065
3066 if ((opt & OPT_V) && (inner == 1 || inner % 10 == 0)) {
3067 pprintf(prn, " inner iter %3d: function value %#g\n",
3068 inner, ystar);
3069 }
3070
3071 if (ystar < ylo) {
3072 /* successful reflection, so extension */
3073 for (i=0; i<n; i++) {
3074 p2star[i] = pbar[i] + ecoeff * (pstar[i] - pbar[i]);
3075 }
3076 y2star = nm_call(cfunc, p2star, data, ncalls, getmin);
3077 /* check extension */
3078 if (ystar < y2star) {
3079 for (i=0; i<n; i++) {
3080 p[i+ihi*n] = pstar[i];
3081 }
3082 y[ihi] = ystar;
3083 } else {
3084 for (i=0; i<n; i++) {
3085 p[i+ihi*n] = p2star[i];
3086 }
3087 y[ihi] = y2star;
3088 }
3089 } else {
3090 l = 0;
3091 for (i=0; i<=n; i++) {
3092 if (ystar < y[i]) {
3093 l++;
3094 }
3095 }
3096 if (l > 1) {
3097 for (i=0; i<n; i++) {
3098 p[i+ihi*n] = pstar[i];
3099 }
3100 y[ihi] = ystar;
3101 } else if (l == 0) {
3102 for (i=0; i<n; i++) {
3103 p2star[i] = pbar[i] + ccoeff * (p[i+ihi*n] - pbar[i]);
3104 }
3105 y2star = nm_call(cfunc, p2star, data, ncalls, getmin);
3106 /* contract the whole simplex */
3107 if (y[ihi] < y2star) {
3108 for (j=0; j<=n; j++) {
3109 for (i=0; i<n; i++) {
3110 p[i+j*n] = (p[i+j*n] + p[i+ilo*n]) * 0.5;
3111 xmin[i] = p[i+j*n];
3112 }
3113 y[j] = nm_call(cfunc, xmin, data, ncalls, getmin);
3114 }
3115 ylo = y[0];
3116 ilo = 0;
3117 for (i=1; i<=n; i++) {
3118 if (y[i] < ylo) {
3119 ylo = y[i];
3120 ilo = i;
3121 }
3122 }
3123 continue;
3124 } else {
3125 for (i=0; i<n; i++) {
3126 p[i+ihi*n] = p2star[i];
3127 }
3128 y[ihi] = y2star;
3129 }
3130 } else if (l == 1) {
3131 for (i=0; i<n; i++) {
3132 p2star[i] = pbar[i] + ccoeff * (pstar[i] - pbar[i]);
3133 }
3134 y2star = nm_call(cfunc, p2star, data, ncalls, getmin);
3135 /* retain reflection? */
3136 if (y2star <= ystar) {
3137 for (i=0; i<n; i++) {
3138 p[i+ihi*n] = p2star[i];
3139 }
3140 y[ihi] = y2star;
3141 } else {
3142 for (i=0; i<n; i++) {
3143 p[i+ihi*n] = pstar[i];
3144 }
3145 y[ihi] = ystar;
3146 }
3147 }
3148 }
3149
3150 /* check if ylo improved */
3151 if (y[ihi] < ylo) {
3152 ylo = y[ihi];
3153 ilo = ihi;
3154 }
3155 jcount--;
3156
3157 if (jcount > 0) {
3158 continue;
3159 }
3160
3161 /* check to see if optimum reached */
3162 if (*ncalls <= maxcalls) {
3163 jcount = konvge;
3164 z = 0.0;
3165 for (i=0; i<=n; i++) {
3166 z += y[i];
3167 }
3168 x = z / (n+1);
3169 z = 0.0;
3170 for (i=0; i<=n; i++) {
3171 z += (y[i] - x) * (y[i] - x);
3172 }
3173 if (z <= rq) {
3174 break;
3175 }
3176 }
3177 }
3178
3179 /* check that ynewlo is a local minimum */
3180 for (i=0; i<n; i++) {
3181 xmin[i] = p[i+ilo*n];
3182 }
3183 *ynewlo = y[ilo];
3184
3185 if (*ncalls > maxcalls) {
3186 err = E_NOCONV;
3187 break;
3188 }
3189
3190 err = 0;
3191
3192 for (i=0; i<n; i++) {
3193 double xsave = xmin[i];
3194 double dx = step[i] * eps;
3195
3196 xmin[i] = xsave + dx;
3197 z = nm_call(cfunc, xmin, data, ncalls, getmin);
3198 if (z < *ynewlo) {
3199 err = E_NOCONV;
3200 break;
3201 }
3202 xmin[i] = xsave - dx;
3203 z = nm_call(cfunc, xmin, data, ncalls, getmin);
3204 if (z < *ynewlo) {
3205 err = E_NOCONV;
3206 break;
3207 }
3208 xmin[i] = xsave;
3209 }
3210
3211 if (err == 0) {
3212 if (opt & OPT_V) {
3213 double crit = getmin ? *ynewlo : -(*ynewlo);
3214
3215 pprintf(prn, "Found optimum %#g after %d function calls, "
3216 "%d resets\n\n", crit, *ncalls, *nresets);
3217 }
3218 break;
3219 }
3220
3221 /* prepare to restart */
3222 for (i=0; i<n; i++) {
3223 start[i] = xmin[i];
3224 }
3225 del = eps;
3226 *nresets += 1;
3227 }
3228
3229 gretl_iteration_pop();
3230
3231 gretl_matrix_free(pmat);
3232 free(wspace);
3233
3234 return err;
3235 }
3236
gretl_amoeba(double * theta,int n,int maxit,BFGS_CRIT_FUNC cfunc,void * data,gretlopt opt,PRN * prn)3237 int gretl_amoeba (double *theta, int n, int maxit,
3238 BFGS_CRIT_FUNC cfunc, void *data,
3239 gretlopt opt, PRN *prn)
3240 {
3241 int ncalls = 0;
3242 int nresets = 0;
3243 int maxcalls;
3244 double reqmin = 1.0e-12;
3245 double fval = 0.0;
3246 double *step;
3247 double *xmin;
3248 int i, err = 0;
3249
3250 step = malloc(n * sizeof *step);
3251 xmin = malloc(n * sizeof *xmin);
3252
3253 if (step == NULL || xmin == NULL) {
3254 free(step); free(xmin);
3255 return E_ALLOC;
3256 }
3257
3258 for (i=0; i<n; i++) {
3259 step[i] = 1.0;
3260 xmin[i] = 0.0;
3261 }
3262
3263 if (maxit < 0) {
3264 maxcalls = -maxit;
3265 opt |= OPT_F; /* fail on non-convergence */
3266 } else {
3267 maxcalls = maxit == 0 ? 2000 : maxit;
3268 }
3269
3270 err = nelder_mead(cfunc, n, theta, xmin, &fval, reqmin,
3271 step, maxcalls, &ncalls, &nresets,
3272 data, opt, prn);
3273
3274 fprintf(stderr, "asa047: fncalls=%d, err=%d\n", ncalls, err);
3275
3276 if (err == E_NOCONV && !(opt & OPT_F)) {
3277 /* tolerate non-convergence */
3278 err = 0;
3279 }
3280
3281 if (!err) {
3282 for (i=0; i<n; i++) {
3283 theta[i] = xmin[i];
3284 }
3285 }
3286
3287 free(step);
3288 free(xmin);
3289
3290 return err;
3291 }
3292
gretl_gss(double * theta,double tol,int * ic,BFGS_CRIT_FUNC cfunc,void * data,gretlopt opt,PRN * prn)3293 int gretl_gss (double *theta, double tol, int *ic,
3294 BFGS_CRIT_FUNC cfunc, void *data,
3295 gretlopt opt, PRN *prn)
3296 {
3297 double gr = (sqrt(5.0) + 1) / 2.0;
3298 double a = theta[1];
3299 double b = theta[2];
3300 double c = b - (b - a) / gr;
3301 double d = a + (b - a) / gr;
3302 double fc, fd;
3303 int minimize = (opt & OPT_I);
3304 int cond, iter = 1;
3305 int err = 0;
3306
3307 if (na(tol)) {
3308 tol = 1.0e-4; /* ?? */
3309 }
3310
3311 while (fabs(c - d) > tol) {
3312 theta[0] = c;
3313 fc = cfunc(theta, data);
3314 theta[0] = d;
3315 fd = cfunc(theta, data);
3316 if (opt & OPT_V) {
3317 pprintf(prn, "%d: bracket={%g,%g}, values={%g,%g}\n",
3318 iter, c, d, fc, fd);
3319 }
3320 if (na(fc) || na(fd)) {
3321 err = E_NAN;
3322 break;
3323 }
3324 cond = minimize ? fc < fd : fc > fd;
3325 if (cond) {
3326 b = d;
3327 } else {
3328 a = c;
3329 }
3330 /* recompute c and d to preserve precision */
3331 c = b - (b - a) / gr;
3332 d = a + (b - a) / gr;
3333 iter++;
3334 }
3335
3336 if (ic != NULL) {
3337 *ic = iter;
3338 }
3339
3340 if (!err) {
3341 /* record the optimum and the bracket */
3342 theta[0] = (b + a) / 2;
3343 theta[1] = a;
3344 theta[2] = b;
3345 }
3346
3347 return err;
3348 }
3349
sgn(double x)3350 static int sgn (double x)
3351 {
3352 return x == 0 ? 0 : x < 0 ? -1 : 1;
3353 }
3354
3355 /* Try to find a value for x1 which brackets a zero-crossing.
3356 Based on Octave's fzero.m but with a little extra stuff.
3357 */
3358
find_x1(double x0,double y0,double * py1,ZFUNC zfunc,void * data)3359 static double find_x1 (double x0, double y0, double *py1,
3360 ZFUNC zfunc, void *data)
3361 {
3362 double srch[] = {
3363 -0.01, 0.025, -0.05, 0.10, -0.25, 0.50,
3364 -1.01, 2.5, -5, 10, -50, 100, -500, 1000
3365 };
3366 double x1, y1, a = x0;
3367 int warnsave, negbad = 0;
3368 int i;
3369
3370 warnsave = libset_get_bool(WARNINGS);
3371 libset_set_bool(WARNINGS, 0);
3372
3373 if (fabs(x0) < 0.001) {
3374 a = (x0 == 0)? 0.1 : sgn(x0) * 0.1;
3375 }
3376
3377 errno = 0;
3378 *py1 = NADBL;
3379
3380 for (i=0; i<G_N_ELEMENTS(srch); i++) {
3381 x1 = a + a * srch[i];
3382 if (negbad && x1 < 0) {
3383 x1 = -x1;
3384 }
3385 y1 = zfunc(x1, data);
3386 if (na(y1)) {
3387 if (errno == EDOM && x1 < 0) {
3388 negbad = 1;
3389 }
3390 errno = 0;
3391 } else if (sgn(y1) * sgn(y0) <= 0) {
3392 /* found a candidate */
3393 *py1 = y1;
3394 break;
3395 }
3396 }
3397
3398 libset_set_bool(WARNINGS, warnsave);
3399
3400 return na(*py1) ? NADBL : x1;
3401 }
3402
gretl_fzero(double * bracket,double tol,ZFUNC zfunc,void * data,double * px,gretlopt opt,PRN * prn)3403 int gretl_fzero (double *bracket, double tol,
3404 ZFUNC zfunc, void *data, double *px,
3405 gretlopt opt, PRN *prn)
3406 {
3407 int MAXITER = 80;
3408 double ytol = 1.0e-14;
3409 double xtol = 1.0e-15;
3410 double y, y0, y1, y2;
3411 double x, x0, x1, x2;
3412 double dx, d0, d1;
3413 int i, err = 0;
3414
3415 x0 = bracket[0];
3416 x1 = bracket[1];
3417
3418 if (!na(tol)) {
3419 ytol = tol;
3420 }
3421 if (na(x0)) {
3422 /* exact zero is too risky as default */
3423 x0 = 0.107;
3424 }
3425
3426 y0 = zfunc(x0, data);
3427 if (na(y0)) {
3428 return E_NAN;
3429 }
3430 if (!na(x1)) {
3431 y1 = zfunc(x1, data);
3432 if (na(y1)) {
3433 return E_NAN;
3434 }
3435 } else {
3436 x1 = find_x1(x0, y0, &y1, zfunc, data);
3437 if (na(x1)) {
3438 return E_NOCONV;
3439 }
3440 }
3441
3442 if (y0 == 0) {
3443 *px = x0;
3444 return 0;
3445 } else if (y1 == 0) {
3446 *px = x1;
3447 return 0;
3448 } else if (y0 * y1 > 0) {
3449 return E_NOCONV;
3450 }
3451
3452 if (opt & OPT_V) {
3453 pprintf(prn, "Initial bracket {%#.6g, %#.6g}\n", x0, x1);
3454 }
3455
3456 for (i=0; i<MAXITER && !err; i++) {
3457 x2 = (x0 + x1) / 2;
3458 y2 = zfunc(x2, data);
3459 /* exponential interpolation of x */
3460 x = x2 + (x2-x0) * sgn(y0-y1)*y2 / sqrt(y2*y2 - y0*y1);
3461 d0 = fabs(x-x0);
3462 d1 = fabs(x-x1);
3463 dx = d0 < d1 ? d0 : d1;
3464 y = zfunc(x, data);
3465 if (opt & OPT_V) {
3466 pprintf(prn, "Iter %2d: f(%#.9g) = %g\n", i+1, x, y);
3467 }
3468 if (dx < xtol || fabs(y) < ytol) {
3469 break;
3470 }
3471 if (sgn(y2) != sgn(y)) {
3472 x0 = x2;
3473 y0 = y2;
3474 x1 = x;
3475 y1 = y;
3476 } else if (sgn(y1) != sgn(y)) {
3477 x0 = x;
3478 y0 = y;
3479 } else {
3480 x1 = x;
3481 y1 = y;
3482 }
3483 }
3484
3485 if (!err && fabs(y) > ytol) {
3486 x = NADBL;
3487 err = E_NOCONV;
3488 }
3489
3490 if (!err) {
3491 /* record the root */
3492 *px = x;
3493 }
3494
3495 return err;
3496 }
3497