home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
applications
/
xlispstat
/
src
/
src2.lzh
/
XLisp-Stat
/
minimize.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-09
|
25KB
|
884 lines
/* 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