home *** CD-ROM | disk | FTP | other *** search
- /* minimize - minimization for Bayes routines in XLISP-STAT and S */
- /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
- /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
- /* You may give out copies of this software; for conditions see the */
- /* file COPYING included with this distribution. */
-
- /*
- * Nonlinear optimization modules adapted from Dennis and Schnabel,
- * "Numerical Methods for Unconstrained Optimization and Nonlinear
- * Equations."
- */
-
- #include <stdio.h>
- #include "xlisp.h"
- #include "osdef.h"
- #ifdef ANSI
- #include "xlproto.h"
- #include "xlsproto.h"
- #else
- #include "xlfun.h"
- #include "xlsfun.h"
- #endif ANSI
-
- #ifdef ANSI
- double gradsize(Iteration *,int),incrsize(Iteration *);
- int stoptest0(Iteration *),stoptest(Iteration *);
- void cholsolve(int,RVector,RMatrix,RVector),
- lsolve(int,RVector,RMatrix,RVector),
- ltsolve(int,RVector,RMatrix,RVector),
- modelhess(int,RVector,RMatrix,RMatrix,double *),
- eval_funval(Iteration *),eval_next_funval(Iteration *),
- eval_gradient(Iteration *),eval_next_gradient(Iteration *),
- eval_hessian(Iteration *),linesearch(Iteration *),
- print_header(Iteration *),print_status(Iteration *),
- findqnstep(Iteration *),iterupdate(Iteration *),
- mindriver(Iteration *);
- #else
- double gradsize(),incrsize();
- int stoptest0(),stoptest();
- void cholsolve(),lsolve(),ltsolve(),modelhess(),eval_funval(),eval_next_funval(),
- eval_gradient(),eval_next_gradient(),eval_hessian(),linesearch(),
- print_header(),print_status(),findqnstep(),iterupdate(),mindriver);
- #endif ANSI
-
- #ifdef SBAYES
- /*# include <math.h>*/
- static char buf[200];
- #define PRINTSTR(s) printf(s)
- #else
- /*# include "xmath.h"*/
- extern char buf[];
- #define PRINTSTR(s) stdputstr(s)
- #endif SBAYES
-
- /************************************************************************/
- /** **/
- /** Definitions and Globals **/
- /** **/
- /************************************************************************/
-
- # define nil 0L
- # define FALSE 0
- # define TRUE 1
-
- # define INIT_GRAD_FRAC .001
- # define CONSEC_MAX_LIMIT 5
- # define ALPHA .0001
- # define MAX_STEP_FACTOR 1000
- # define GRADTOL_POWER 1.0 / 3.0
- # define STEPTOL_POWER 2.0 / 3.0
- # define ITNLIMIT 100
- # define VERBOSE 0
- # define USE_SEARCH TRUE
-
- typedef double **RMatrix, *RVector;
-
- typedef struct {
- int n, k;
- #ifdef ANSI
- int (*ffun)(RVector,double *,RVector,RMatrix),
- (*gfun)(RVector,RVector,RMatrix,RMatrix);
- #else
- int (*ffun)(), (*gfun)();
- #endif ANSI
- double f, typf, new_f;
- double crit, new_crit;
- RVector x, new_x, sx, delf, new_delf, qnstep, F;
- RMatrix hessf, H, L, new_delg;
- double gradtol, steptol, maxstep;
- int itncount, itnlimit, maxtaken, consecmax, retcode, termcode;
- int use_line_search, verbose, values_supplied, change_sign;
- double diagadd;
- } Iteration;
-
- static char *termcodes[] = {"not yet terminated",
- "gradient size is less than gradient tolerance",
- "step size is less than step tolerance",
- "no satisfactory step found in backtracking",
- "iteration limit exceeded",
- "maximum size step taken 5 iterations in a row"};
-
- /************************************************************************/
- /** **/
- /** Utility Functions **/
- /** **/
- /************************************************************************/
- /*
- static double Max(a, b) macros in xlsdef.h JKL
- double a, b;
- {
- return(a > b ? a : b);
- }
-
- static double Min(a, b)
- double a, b;
- {
- return(a > b ? b : a);
- }
- */
- /************************************************************************/
- /** **/
- /** Cholesky Solving Functions **/
- /** **/
- /************************************************************************/
-
- /* solve (L L^T) s = -g for s */
- static void cholsolve(n, g, L, s)
- int n;
- RVector g, s;
- RMatrix L;
- {
- int i;
-
- /* solve Ly = g */
- lsolve(n, g, L, s);
-
- /* solve L^Ts = y */
- ltsolve(n, s, L, s);
-
- for (i = 0; i < n; i++) s[i] = -s[i];
- }
-
- /* solve Ly = b for y */
- static void lsolve(n, b, L, y)
- int n;
- RVector b, y;
- RMatrix L;
- {
- int i, j;
-
- for (i = 0; i < n; i++) {
- y[i] = b[i];
- for (j = 0; j < i; j++) y[i] -= L[i][j] * y[j];
- if (L[i][i] != 0) y[i] /= L[i][i];
- }
- }
-
- /* solve (L^T)x = y for x */
- static void ltsolve(n, y, L, x)
- int n;
- RVector y, x;
- RMatrix L;
- {
- int i, j;
-
- for (i = n - 1; i >= 0; i--) {
- x[i] = y[i];
- for (j = i + 1; j < n; j++) x[i] -= L[j][i] * x[j];
- if (L[i][i] != 0) x[i] /= L[i][i];
- }
- }
-
- static void modelhess(n, sx, H, L, diagadd)
- int n;
- RVector sx;
- RMatrix H, L;
- double *diagadd;
- {
- int i, j;
- double sqrteps, maxdiag, mindiag, maxoff, maxoffl, maxposdiag, mu,
- maxadd, maxev, minev, offrow, sdd;
-
- /* scale H on both sides with sx */
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++) H[i][j] /= sx[i] * sx[j];
-
- /*
- * find mu to add to diagonal so no diagonal elements are negative
- * and largest diagonal dominates largest off diagonal element in H
- */
- sqrteps = sqrt(macheps());
- for (maxdiag = H[0][0], i = 1; i < n; i++)
- maxdiag = Max(maxdiag, H[i][i]);
- for (mindiag = H[0][0], i = 1; i < n; i++)
- mindiag = Min(mindiag, H[i][i]);
- maxposdiag = Max(0.0, maxdiag);
-
- if (mindiag <= sqrteps * maxposdiag) {
- mu = 2 * (maxposdiag - mindiag) * sqrteps - mindiag;
- maxdiag += mu;
- }
- else mu = 0.0;
-
- if (n > 1) {
- for (maxoff = fabs(H[0][1]), i = 0; i < n; i++)
- for (j = i + 1; j < n; j++)
- maxoff = Max(maxoff, fabs(H[i][j]));
- }
- else maxoff = 0.0;
-
- if (maxoff * (1 + 2 * sqrteps) > maxdiag) {
- mu += (maxoff - maxdiag) + 2 * sqrteps * maxoff;
- maxdiag = maxoff * (1 + 2 * sqrteps);
- }
-
- if (maxdiag == 0.0) {
- mu = 1;
- maxdiag = 1;
- }
-
- if (mu > 0) for (i = 0; i < n; i++) H[i][i] += mu;
-
- maxoffl = sqrt(Max(maxdiag, maxoff / n));
-
- /*
- * compute the perturbed Cholesky decomposition
- */
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++) L[i][j] = H[i][j];
- choldecomp(L, n, maxoffl, &maxadd);
-
- /*
- * add something to diagonal, if needed, to make positive definite
- * and recompute factorization
- */
- if (maxadd > 0) {
- maxev = H[0][0];
- minev = H[0][0];
- for (i = 0; i < n; i++) {
- for (offrow = 0.0, j = 0; j < n; j++)
- if (i != j) offrow += fabs(H[i][j]);
- maxev = Max(maxev, H[i][i] + offrow);
- minev = Min(minev, H[i][i] - offrow);
- }
- sdd = (maxev - minev) * sqrteps - minev;
- sdd = Max(sdd, 0.0);
- mu = Min(maxadd, sdd);
- for (i = 0; i < n; i++) H[i][i] += mu;
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++) L[i][j] = H[i][j];
- choldecomp(L, n, maxoffl, &maxadd);
- *diagadd = mu;
- }
- else *diagadd = 0.0;
-
- /* unscale H and L */
- for (i = 0; i < n; i++)
- for (j = 0; j < n; j++) {
- H[i][j] *= sx[i] * sx[j];
- L[i][j] *= sx[i];
- }
- }
-
- /************************************************************************/
- /** **/
- /** Stopping Criteria **/
- /** **/
- /************************************************************************/
-
- static double gradsize(iter, new)
- Iteration *iter;
- int new;
- {
- int n, i;
- double size, term, crit, typf;
- RVector x, delf, sx;
-
- n = iter->n + iter->k;
- crit = iter->crit;
- typf = iter->typf;
- x = iter->x;
- sx = iter->sx;
- delf = (new) ? iter->new_delf : iter->delf;
-
- for (i = 0, size = 0.0; i < n; i++) {
- term = fabs(delf[i]) * Max(x[i], 1.0 / sx[i]) / Max(fabs(crit), typf);
- size = Max(size, term);
- }
- return(size);
- }
-
- static double incrsize(iter)
- Iteration *iter;
- {
- int n, i;
- double size, term;
- RVector x, new_x, sx;
-
- new_x = iter->new_x;
- n = iter->n + iter->k;
- x = iter->x;
- sx = iter->sx;
-
- for (i = 0, size = 0.0; i < n; i++) {
- term = fabs(x[i] - new_x[i]) / Max(fabs(x[i]), 1.0 / sx[i]);
- size = Max(size, term);
- }
- return(size);
- }
-
- static int stoptest0(iter)
- Iteration *iter;
- {
- iter->consecmax = 0;
-
- if (gradsize(iter, FALSE) <= INIT_GRAD_FRAC * iter->gradtol)
- iter->termcode = 1;
- else iter->termcode = 0;
-
- return(iter->termcode);
- }
-
- static int stoptest(iter)
- Iteration *iter;
- {
- int termcode, retcode, itncount, itnlimit, maxtaken, consecmax;
- double gradtol, steptol;
-
- retcode = iter->retcode;
- gradtol = iter->gradtol;
- steptol = iter->steptol;
- itncount = iter->itncount;
- itnlimit = iter->itnlimit;
- maxtaken = iter->maxtaken;
- consecmax = iter->consecmax;
-
- termcode = 0;
- if (retcode == 1) termcode = 3;
- else if (gradsize(iter, TRUE) <= gradtol) termcode = 1;
- else if (incrsize(iter) <= steptol) termcode = 2;
- else if (itncount >= itnlimit) termcode = 4;
- else if (maxtaken) {
- consecmax++;
- if (consecmax >= CONSEC_MAX_LIMIT) termcode = 5;
- }
- else consecmax = 0;
-
- iter->consecmax = consecmax;
- iter->termcode = termcode;
-
- return(termcode);
- }
-
- /************************************************************************/
- /** **/
- /** Function and Derivative Evaluation **/
- /** **/
- /************************************************************************/
-
- static void eval_funval(iter)
- Iteration *iter;
- {
- int i;
-
- (*(iter->ffun))(iter->x, &iter->f, nil, nil);
- if (iter->k == 0) iter->crit = iter->f;
- else {
- eval_gradient(iter);
- for (i = 0, iter->crit = 0.0; i < iter->n + iter->k; i++)
- iter->crit += 0.5 * pow(fabs(iter->delf[i]), 2.0);
- }
- }
-
- static void eval_next_funval(iter)
- Iteration *iter;
- {
- int i;
-
- (*(iter->ffun))(iter->new_x, &iter->new_f, nil, nil);
- if (iter->k == 0) iter->new_crit = iter->new_f;
- else {
- eval_next_gradient(iter);
- for (i = 0, iter->new_crit = 0.0; i < iter->n + iter->k; i++)
- iter->new_crit += 0.5 * pow(fabs(iter->new_delf[i]), 2.0);
- }
- }
-
- static void eval_gradient(iter)
- Iteration *iter;
- {
- int i, j, n, k;
-
- n = iter->n;
- k = iter->k;
-
- (*(iter->ffun))(iter->x, nil, iter->delf, nil);
- if (k > 0) {
- (*(iter->gfun))(iter->x, iter->delf + n, nil, nil);
- (*(iter->gfun))(iter->x, nil, iter->new_delg, nil);
- for (i = 0; i < n; i++) {
- for (j = 0; j < k; j++)
- iter->delf[i] += iter->x[n + j] * iter->new_delg[j][i];
- for (j = 0; j < k; j++) {
- iter->hessf[n + j][i] = iter->new_delg[j][i];
- iter->hessf[i][n + j] = iter->new_delg[j][i];
- }
- }
- }
- }
-
- static void eval_next_gradient(iter)
- Iteration *iter;
- {
- int i, j, n, k;
-
- n = iter->n;
- k = iter->k;
- (*(iter->ffun))(iter->new_x, nil, iter->new_delf, nil);
- if (k > 0) {
- (*(iter->gfun))(iter->new_x, iter->new_delf + n, nil, nil);
- (*(iter->gfun))(iter->new_x, nil, iter->new_delg, nil);
- for (i = 0; i < n; i++) {
- for (j = 0; j < k; j++)
- iter->new_delf[i] += iter->new_x[n + j] * iter->new_delg[j][i];
- }
- }
- }
-
- static void eval_hessian(iter)
- Iteration *iter;
- {
- int i, j, n, k;
-
- n = iter->n;
- k = iter->k;
- (*(iter->ffun))(iter->x, nil, nil, iter->hessf);
- for (i = n; i < n + k; i++)
- for (j = n; j < n + k; j++) iter->hessf[i][j] = 0.0;
- }
-
- /************************************************************************/
- /** **/
- /** Backtracking Line Search **/
- /** **/
- /************************************************************************/
-
- static void linesearch(iter)
- Iteration *iter;
- {
- int i, n;
- double newtlen, maxstep, initslope, rellength, lambda, minlambda,
- lambdatemp, lambdaprev, a, b, disc, critprev, f1, f2, a11, a12, a21, a22,
- del;
- RVector qnstep, delf, x, new_x, sx;
-
- n = iter->n + iter->k;
- if (! iter->use_line_search) {
- iter->maxtaken = FALSE;
- for (i = 0; i < n; i++)
- iter->new_x[i] = iter->x[i] + iter->qnstep[i];
- eval_next_funval(iter);
- iter->retcode = 0;
- }
- else{
- qnstep = iter->qnstep;
- maxstep = iter->maxstep;
- delf = (iter->k == 0) ? iter->delf : iter->F;
- x = iter->x;
- new_x = iter->new_x;
- sx = iter->sx;
-
- iter->maxtaken = FALSE;
- iter->retcode = 2;
-
- for (i = 0, newtlen = 0.0; i < n; i++)
- newtlen += pow(sx[i] * qnstep[i], 2.0);
- newtlen = sqrt(newtlen);
-
- if (newtlen > maxstep) {
- for (i = 0; i < n; i++) qnstep[i] *= (maxstep / newtlen);
- newtlen = maxstep;
- }
-
- for (i = 0, initslope = 0.0; i < n; i++) initslope += delf[i] * qnstep[i];
-
- for (i = 0, rellength = 0.0; i < n; i++)
- rellength = Max(rellength, fabs(qnstep[i]) / Max(fabs(x[i]), 1.0 / sx[i]));
-
- minlambda = (rellength == 0.0) ? 2.0 : iter->steptol / rellength;
-
- lambda = 1.0;
- lambdaprev = 1.0; /* to make compilers happy */
- critprev = 1.0; /* to make compilers happy */
- while (iter->retcode > 1) {
- for (i = 0; i < n; i++) new_x[i] = x[i] + lambda * qnstep[i];
- eval_next_funval(iter);
- if (iter->new_crit <= iter->crit + ALPHA * lambda * initslope) {
- iter->retcode = 0;
- if (lambda == 1.0 && newtlen > 0.99 * maxstep) iter->maxtaken = TRUE;
- }
- else if (lambda < minlambda) {
- iter->retcode = 1;
- iter->new_crit = iter->crit;
- for (i = 0; i < n; i++) new_x[i] = x[i];
- }
- else {
- if (lambda == 1.0) { /* first backtrack, quadratic fit */
- lambdatemp = - initslope
- / (2 * (iter->new_crit - iter->crit - initslope));
- }
- else { /* all subsequent backtracks, cubic fit */
- del = lambda - lambdaprev;
- f1 = iter->new_crit - iter->crit - lambda * initslope;
- f2 = critprev - iter->crit - lambdaprev * initslope;
- a11 = 1.0 / (lambda * lambda);
- a12 = -1.0 / (lambdaprev * lambdaprev);
- a21 = -lambdaprev * a11;
- a22 = -lambda * a12;
- a = (a11 * f1 + a12 * f2) / del;
- b = (a21 * f1 + a22 * f2) / del;
- disc = b * b - 3 * a * initslope;
- if (a == 0) { /* cubic is a quadratic */
- lambdatemp = - initslope / (2 * b);
- }
- else { /* legitimate cubic */
- lambdatemp = (-b + sqrt(disc)) / (3 * a);
- }
- lambdatemp = Min(lambdatemp, 0.5 * lambda);
- }
- lambdaprev = lambda;
- critprev = iter->new_crit;
- lambda = Max(0.1 * lambda, lambdatemp);
- if (iter->verbose > 0) {
- sprintf(buf, "Backtracking: lambda = %g\n", lambda);
- PRINTSTR(buf);
- }
- }
- }
- }
- }
-
- /************************************************************************/
- /** **/
- /** Status Printing Functions **/
- /** **/
- /************************************************************************/
-
- static void print_header(iter)
- Iteration *iter;
- {
- if (iter->verbose > 0) {
- sprintf(buf, "Iteration %d.\n", iter->itncount);
- PRINTSTR(buf);
- }
- }
-
- static void print_status(iter)
- Iteration *iter;
- {
- int i, j;
-
- if (iter->verbose > 0) {
- sprintf(buf, "Criterion value = %g\n",
- (iter->change_sign) ? -iter->crit : iter->crit);
- PRINTSTR(buf);
- if (iter->verbose > 1) {
- PRINTSTR("Location = <");
- for (i = 0; i < iter->n + iter->k; i++) {
- sprintf(buf, (i < iter->n + iter->k - 1) ? "%g " : "%g>\n", iter->x[i]);
- PRINTSTR(buf);
- }
- }
- if (iter->verbose > 2) {
- PRINTSTR("Gradient = <");
- for (i = 0; i < iter->n + iter->k; i++) {
- sprintf(buf, (i < iter->n + iter->k - 1) ? "%g " : "%g>\n",
- (iter->change_sign) ? -iter->delf[i] : iter->delf[i]);
- PRINTSTR(buf);
- }
- }
- if (iter->verbose > 3) {
- PRINTSTR("Hessian:\n");
- for (i = 0; i < iter->n + iter->k; i++) {
- for (j = 0; j < iter->n + iter->k; j++) {
- sprintf(buf, (j < iter->n + iter->k - 1) ? "%g " : "%g\n",
- (iter->change_sign) ? -iter->hessf[i][j] : iter->hessf[i][j]);
- PRINTSTR(buf);
- }
- }
- }
- }
- if (iter->termcode != 0 && iter->verbose > 0) {
- sprintf(buf, "Reason for termination: %s.\n", termcodes[iter->termcode]);
- PRINTSTR(buf);
- }
- }
-
- /************************************************************************/
- /** **/
- /** Iteration Driver **/
- /** **/
- /************************************************************************/
-
- static void findqnstep(iter)
- Iteration *iter;
- {
- int i, j, N, l;
-
- if (iter->k == 0) {
- modelhess(iter->n, iter->sx, iter->hessf, iter->L, &iter->diagadd);
- cholsolve(iter->n, iter->delf, iter->L, iter->qnstep);
- }
- else {
- N = iter->n + iter->k;
- for (i = 0; i < N; i++) {
- for (l = 0, iter->F[i] = 0.0; l < N; l++)
- iter->F[i] += iter->hessf[i][l] * iter->delf[l];
- for (j = 0; j < N; j++)
- for (l = 0, iter->H[i][j] = 0.0; l < N; l++)
- iter->H[i][j] += iter->hessf[i][l] * iter->hessf[j][l];
- }
- modelhess(N, iter->sx, iter->H, iter->L, &iter->diagadd);
- cholsolve(N, iter->F, iter->L, iter->qnstep);
- }
- }
-
- static void iterupdate(iter)
- Iteration *iter;
- {
- int i, j, n, k;
-
- n = iter->n;
- k = iter->k;
- iter->f = iter->new_f;
- iter->crit = iter->new_crit;
- for (i = 0; i < n + k; i++) {
- iter->x[i] = iter->new_x[i];
- iter->delf[i] = iter->new_delf[i];
- }
- for (i = 0; i < k; i++) {
- for (j = 0; j < n; j++) {
- iter->hessf[n + i][j] = iter->new_delg[i][j];
- iter->hessf[j][n + i] = iter->new_delg[i][j];
- }
- }
- }
-
- static void mindriver(iter)
- Iteration *iter;
- {
- iter->consecmax = 0;
- iter->itncount = 0;
- iter->termcode = 0;
- if (! iter->values_supplied) {
- eval_funval(iter);
- if (iter->k == 0) eval_gradient(iter);
- eval_hessian(iter);
- }
-
- stoptest0(iter);
- print_header(iter);
- print_status(iter);
- while (iter->termcode == 0) {
- iter->itncount++;
- print_header(iter);
- findqnstep(iter);
- linesearch(iter);
- if (iter->k == 0) eval_next_gradient(iter);
- stoptest(iter);
- iterupdate(iter);
- eval_hessian(iter);
- print_status(iter);
- }
- }
-
- /************************************************************************/
- /** **/
- /** External Interface Routines **/
- /** **/
- /************************************************************************/
-
- static Iteration myiter;
-
- int minworkspacesize(n, k)
- int n, k;
- {
- int size;
-
- /* x, new_x, sx, delf, new_delf, qnstep and F */
- size = 7 * sizeof(double) * (n + k);
-
- /* hessf, H and L */
- size += 3 * (sizeof(double *) * (n + k)
- + sizeof(double) * (n + k) * (n + k));
-
- /* delg and new_delg */
- size += 2 * (sizeof(double *) * k + sizeof(double) * n * k);
-
- return(size);
- }
-
- char *minresultstring(code)
- int code;
- {
- if (code <= 0) return("bad input data");
- else if (code <= 5) return(termcodes[code]);
- else return("unknown return code");
- }
-
- void minsetup(n, k, ffun, gfun, x, typf, typx, work)
- int n, k, (*ffun)(), (*gfun)();
- RVector x, typx;
- double typf;
- char *work;
- {
- Iteration *iter = &myiter;
- int i, j;
- double nx0, ntypx;
-
- n = (n > 0) ? n : 0;
- k = (k > 0) ? k : 0;
-
- iter->n = n;
- iter->k = k;
- iter->ffun = ffun;
- iter->gfun = gfun;
-
- iter->x = (RVector) work; work += sizeof(double) * (n + k);
- iter->new_x = (RVector) work; work += sizeof(double) * (n + k);
- iter->sx = (RVector) work; work += sizeof(double) * (n + k);
- iter->delf = (RVector) work; work += sizeof(double) * (n + k);
- iter->new_delf = (RVector) work; work += sizeof(double) * (n + k);
- iter->qnstep = (RVector) work; work += sizeof(double) * (n + k);
- iter->F = (RVector) work; work += sizeof(double) * (n + k);
- for (i = 0; i < n; i++) {
- iter->x[i] = x[i];
- iter->sx[i] = (typx != nil && typx[i] > 0.0) ? 1.0 / typx[i] : 1.0;
- }
- for (i = 0; i < k; i++) {
- iter->x[n + i] = x[n + i];
- iter->sx[n + i] = 1.0;
- }
-
- iter->hessf = (RMatrix) work; work += sizeof(double *) * (n + k);
- for (i = 0; i < n + k; i++) {
- iter->hessf[i] = (RVector) work;
- work += sizeof(double) * (n + k);
- }
- for (i = 0; i < n + k; i++)
- for (j = 0; j < n + k; j++) iter->hessf[i][j] = 0.0;
- iter->L = (RMatrix) work; work += sizeof(double *) * (n + k);
- for (i = 0; i < n + k; i++) {
- iter->L[i] = (RVector) work;
- work += sizeof(double) * (n + k);
- }
- iter->H = (RMatrix) work; work += sizeof(double *) * (n + k);
- for (i = 0; i < n + k; i++) {
- iter->H[i] = (RVector) work;
- work += sizeof(double) * (n + k);
- }
-
- iter->new_delg = (k > 0) ? (RMatrix) work : nil;
- work += sizeof(double *) * k;
- for (i = 0; i < k; i++) {
- iter->new_delg[i] = (RVector) work;
- work += sizeof(double) * n;
- }
-
- iter->typf = (typf > 0.0) ? typf : 1.0;
-
- iter->verbose = VERBOSE;
- iter->use_line_search = USE_SEARCH;
- iter->itncount = 0;
- iter->itnlimit = ITNLIMIT;
- iter->gradtol = pow(macheps(), GRADTOL_POWER);
- iter->steptol = pow(macheps(), STEPTOL_POWER);
- for (i = 0, nx0 = 0.0, ntypx = 0.0; i < iter->n; i++) {
- nx0 += fabs(iter->new_x[i] / iter->sx[i]);
- ntypx += fabs(1.0 / iter->sx[i]);
- }
- iter->maxstep = MAX_STEP_FACTOR * Max(nx0, ntypx);
- iter->values_supplied = FALSE;
- }
-
- void minsetoptions(gradtol, steptol, maxstep, itnlimit, verbose, use_search, change_sign)
- double gradtol, steptol, maxstep;
- int itnlimit, verbose, use_search, change_sign;
- {
- Iteration *iter = &myiter;
-
- if (gradtol > 0.0) iter->gradtol = gradtol;
- if (steptol > 0.0) iter->steptol = steptol;
- if (maxstep > 0.0) iter->maxstep = maxstep;
- if (itnlimit >= 0) iter->itnlimit = itnlimit;
- if (verbose >= 0) iter->verbose = verbose;
- iter->use_line_search = use_search;
- iter->change_sign = change_sign;
- }
-
- void minsupplyvalues(f, delf, hessf, g, delg)
- double f;
- RVector delf, g;
- RMatrix hessf, delg;
- {
- Iteration *iter = &myiter;
- int i, j, n, k;
-
- n = iter->n;
- k = iter->k;
-
- iter->f = f;
- for (i = 0; i < n; i++) {
- iter->delf[i] = delf[i];
- for (j = 0; j < k; j++)
- iter->delf[i] += iter->x[n + j] * delg[j][i];
- for (j = 0; j < n; j++) iter->hessf[i][j] = hessf[i][j];
- }
- for (i = 0; i < k; i++) {
- iter->delf[n + i] = g[i];
- for (j = 0; j < n; j++) {
- iter->hessf[n + i][j] = delg[i][j];
- iter->hessf[j][n + i] = delg[i][j];
- }
- }
- if (k == 0) iter->crit = f;
- else {
- for (i = 0, iter->crit = 0.0; i < n + k; i++)
- iter->crit += 0.5 * pow(fabs(iter->delf[i]), 2.0);
- }
- iter->values_supplied = TRUE;
- }
-
- void minimize() { mindriver(&myiter); }
-
- void minresults(x, pf, pcrit, delf, hessf, g, delg, pcount, ptermcode, diagadd)
- RVector x, delf, g;
- double *pf, *pcrit, *diagadd;
- RMatrix hessf, delg;
- int *pcount, *ptermcode;
- {
- Iteration *iter = &myiter;
- int i, j, n, k;
-
- n = iter->n;
- k = iter->k;
-
- if (pf != nil) *pf = iter->f;
- if (pcrit != nil) *pcrit = iter->crit;
- for (i = 0; i < n; i++) {
- if (x != nil) x[i] = iter->x[i];
- if (delf != nil) delf[i] = iter->delf[i];
- for (j = 0; j < n; j++) if (hessf != nil) hessf[i][j] = iter->hessf[i][j];
- }
- for (i = 0; i < k; i++) {
- if (x != nil) x[n + i] = iter->x[n + i];
- if (g != nil) g[i] = iter->delf[n + i];
- for (j = 0; j < n; j++)
- if (delg != nil) delg[i][j] = iter->hessf[n + i][j];
- }
- if (pcount != nil) *pcount = iter->itncount;
- if (ptermcode != nil) *ptermcode = iter->termcode;
- if (diagadd != nil) *diagadd = iter->diagadd;
- }
-
- #ifdef SBAYES
- double pdlogdet(n, H)
- int n;
- RMatrix H;
- {
- int i;
- double logdet, maxadd;
-
- choldecomp(H, n, 0.0, &maxadd);
- for (i = 0, logdet = 0.0; i < n; i++) logdet += 2.0 * log(H[i][i]);
- return(logdet);
- }
- #endif /* SBAYES */
- #ifdef TODO
- return amount added to make pos definite
- scaling for constraints
- alternate global strategies
- callback function for verbose mode
- #endif TODO
-