1 /* minimize - minimization for Bayes routines in XLISP-STAT and S */
2 /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
3 /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
4 /* You may give out copies of this software; for conditions see the */
5 /* file COPYING included with this distribution. */
8 * Nonlinear optimization modules adapted from Dennis and Schnabel,
9 * "Numerical Methods for Unconstrained Optimization and Nonlinear
16 #define PRINTSTR(s) printf(s)
20 void (*ffun
)(), (*gfun
)();
21 double f
, typf
, new_f
;
22 double crit
, new_crit
;
23 double *x
, *new_x
, *sx
, *delf
, *new_delf
, *qnstep
, *F
;
24 double **hessf
, **H
, **L
, **new_delg
;
25 double gradtol
, steptol
, maxstep
;
26 int itncount
, itnlimit
, maxtaken
, consecmax
, retcode
, termcode
;
27 int use_line_search
, verbose
, values_supplied
, change_sign
;
32 extern double macheps();
35 extern double choldecomp();
36 static void eval_gradient(Iteration
*);
37 static void eval_next_gradient(Iteration
*);
41 This is a little more advanced section on functions, but is very useful. Take this for example:
42 int applyeqn(int F(int), int max, int min) {
50 What does this function do if we call it with applyeqn(square(x),
51 y, z);? What happens is that the int F(int) is a reference to the
52 function that is passed in as a parameter. Thus inside applyeqn where
53 there is a call to F, it actually is a call to square! This is very
54 useful if we have one set function, but wish to vary the input
55 according to a particular function. So if we had a different function
56 called cube we could change how we call applyeqn by calling the
57 function by applyeqn(cube(x), y, z);. */
60 /************************************************************************/
62 /** Definitions and Globals **/
64 /************************************************************************/
70 # define INIT_GRAD_FRAC .001
71 # define CONSEC_MAX_LIMIT 5
73 # define MAX_STEP_FACTOR 1000
74 # define GRADTOL_POWER 1.0 / 3.0
75 # define STEPTOL_POWER 2.0 / 3.0
78 # define USE_SEARCH TRUE
80 typedef double **RMatrix
, *RVector
;
83 static char *termcodes
[] = {"not yet terminated",
84 "gradient size is less than gradient tolerance",
85 "step size is less than step tolerance",
86 "no satisfactory step found in backtracking",
87 "iteration limit exceeded",
88 "maximum size step taken 5 iterations in a row"};
90 /************************************************************************/
92 /** Utility Functions **/
94 /************************************************************************/
96 static double Max(a
, b
)
99 return(a
> b
? a
: b
);
102 static double Min(a
, b
)
105 return(a
> b
? b
: a
);
108 /************************************************************************/
110 /** Cholesky Solving Functions **/
112 /************************************************************************/
115 /* solve Ly = b for y */
117 lsolve(size_t n
, double *b
, double **L
, double *y
)
121 for (i
= 0; i
< n
; i
++) {
123 for (j
= 0; j
< i
; j
++) y
[i
] -= L
[i
][j
] * y
[j
];
124 if (L
[i
][i
] != 0) y
[i
] /= L
[i
][i
];
128 /* solve (L^T)x = y for x */
130 ltsolve(size_t n
, double *y
, double **L
, double *x
)
134 for (i
= n
- 1; i
>= 0; i
--) {
136 for (j
= i
+ 1; j
< n
; j
++) x
[i
] -= L
[j
][i
] * x
[j
];
137 if (L
[i
][i
] != 0) x
[i
] /= L
[i
][i
];
141 /* solve (L L^T) s = -g for s */
144 double *g
, double **L
,
155 for (i
= 0; i
< n
; i
++) s
[i
] = -s
[i
];
159 modelhess(size_t n
, double *sx
, double **H
, double **L
, double *diagadd
)
162 double sqrteps
, maxdiag
, mindiag
, maxoff
, maxoffl
, maxposdiag
, mu
,
163 maxadd
, maxev
, minev
, offrow
, sdd
;
165 /* scale H on both sides with sx */
166 for (i
= 0; i
< n
; i
++)
167 for (j
= 0; j
< n
; j
++) H
[i
][j
] /= sx
[i
] * sx
[j
];
170 * find mu to add to diagonal so no diagonal elements are negative
171 * and largest diagonal dominates largest off diagonal element in H
173 sqrteps
= sqrt(macheps());
174 for (maxdiag
= H
[0][0], i
= 1; i
< n
; i
++)
175 maxdiag
= Max(maxdiag
, H
[i
][i
]);
176 for (mindiag
= H
[0][0], i
= 1; i
< n
; i
++)
177 mindiag
= Min(mindiag
, H
[i
][i
]);
178 maxposdiag
= Max(0.0, maxdiag
);
180 if (mindiag
<= sqrteps
* maxposdiag
) {
181 mu
= 2 * (maxposdiag
- mindiag
) * sqrteps
- mindiag
;
187 for (maxoff
= fabs(H
[0][1]), i
= 0; i
< n
; i
++)
188 for (j
= i
+ 1; j
< n
; j
++)
189 maxoff
= Max(maxoff
, fabs(H
[i
][j
]));
193 if (maxoff
* (1 + 2 * sqrteps
) > maxdiag
) {
194 mu
+= (maxoff
- maxdiag
) + 2 * sqrteps
* maxoff
;
195 maxdiag
= maxoff
* (1 + 2 * sqrteps
);
198 if (maxdiag
== 0.0) {
203 if (mu
> 0) for (i
= 0; i
< n
; i
++) H
[i
][i
] += mu
;
205 maxoffl
= sqrt(Max(maxdiag
, maxoff
/ n
));
208 * compute the perturbed Cholesky decomposition
210 for (i
= 0; i
< n
; i
++)
211 for (j
= 0; j
< n
; j
++) L
[i
][j
] = H
[i
][j
];
212 choldecomp(L
, n
, maxoffl
, &maxadd
);
215 * add something to diagonal, if needed, to make positive definite
216 * and recompute factorization
221 for (i
= 0; i
< n
; i
++) {
222 for (offrow
= 0.0, j
= 0; j
< n
; j
++)
223 if (i
!= j
) offrow
+= fabs(H
[i
][j
]);
224 maxev
= Max(maxev
, H
[i
][i
] + offrow
);
225 minev
= Min(minev
, H
[i
][i
] - offrow
);
227 sdd
= (maxev
- minev
) * sqrteps
- minev
;
229 mu
= Min(maxadd
, sdd
);
230 for (i
= 0; i
< n
; i
++) H
[i
][i
] += mu
;
231 for (i
= 0; i
< n
; i
++)
232 for (j
= 0; j
< n
; j
++) L
[i
][j
] = H
[i
][j
];
233 choldecomp(L
, n
, maxoffl
, &maxadd
);
238 /* unscale H and L */
239 for (i
= 0; i
< n
; i
++)
240 for (j
= 0; j
< n
; j
++) {
241 H
[i
][j
] *= sx
[i
] * sx
[j
];
246 /************************************************************************/
248 /** Stopping Criteria **/
250 /************************************************************************/
253 gradsize(Iteration
*iter
, int new)
256 double size
, term
, crit
, typf
;
257 double *x
, *delf
, *sx
;
259 n
= iter
->n
+ iter
->k
;
264 delf
= (new) ? iter
->new_delf
: iter
->delf
;
266 for (i
= 0, size
= 0.0; i
< n
; i
++) {
267 term
= fabs(delf
[i
]) * Max(x
[i
], 1.0 / sx
[i
]) / Max(fabs(crit
), typf
);
268 size
= Max(size
, term
);
274 incrsize(Iteration
*iter
)
278 double *x
, *new_x
, *sx
;
281 n
= iter
->n
+ iter
->k
;
285 for (i
= 0, size
= 0.0; i
< n
; i
++) {
286 term
= fabs(x
[i
] - new_x
[i
]) / Max(fabs(x
[i
]), 1.0 / sx
[i
]);
287 size
= Max(size
, term
);
292 static int /* AJR:TESTME guess! */
293 stoptest0(Iteration
*iter
)
297 if (gradsize(iter
, FALSE
) <= INIT_GRAD_FRAC
* iter
->gradtol
)
299 else iter
->termcode
= 0;
301 return(iter
->termcode
);
305 stoptest(Iteration
*iter
)
307 int termcode
, retcode
, itncount
, itnlimit
, maxtaken
, consecmax
;
308 double gradtol
, steptol
;
310 retcode
= iter
->retcode
;
311 gradtol
= iter
->gradtol
;
312 steptol
= iter
->steptol
;
313 itncount
= iter
->itncount
;
314 itnlimit
= iter
->itnlimit
;
315 maxtaken
= iter
->maxtaken
;
316 consecmax
= iter
->consecmax
;
319 if (retcode
== 1) termcode
= 3;
320 else if (gradsize(iter
, TRUE
) <= gradtol
) termcode
= 1;
321 else if (incrsize(iter
) <= steptol
) termcode
= 2;
322 else if (itncount
>= itnlimit
) termcode
= 4;
325 if (consecmax
>= CONSEC_MAX_LIMIT
) termcode
= 5;
329 iter
->consecmax
= consecmax
;
330 iter
->termcode
= termcode
;
335 /************************************************************************/
337 /** Function and Derivative Evaluation **/
339 /************************************************************************/
342 eval_funval(Iteration
*iter
)
346 (*(iter
->ffun
))(iter
->x
, &iter
->f
, nil
, nil
);
347 if (iter
->k
== 0) iter
->crit
= iter
->f
;
350 for (i
= 0, iter
->crit
= 0.0; i
< iter
->n
+ iter
->k
; i
++)
351 iter
->crit
+= 0.5 * pow(fabs(iter
->delf
[i
]), 2.0);
356 eval_next_funval(Iteration
*iter
)
360 (*(iter
->ffun
))(iter
->new_x
, &iter
->new_f
, nil
, nil
);
361 if (iter
->k
== 0) iter
->new_crit
= iter
->new_f
;
363 eval_next_gradient(iter
);
364 for (i
= 0, iter
->new_crit
= 0.0; i
< iter
->n
+ iter
->k
; i
++)
365 iter
->new_crit
+= 0.5 * pow(fabs(iter
->new_delf
[i
]), 2.0);
370 eval_gradient(Iteration
*iter
)
377 (*(iter
->ffun
))(iter
->x
, nil
, iter
->delf
, nil
);
379 (*(iter
->gfun
))(iter
->x
, iter
->delf
+ n
, nil
, nil
);
380 (*(iter
->gfun
))(iter
->x
, nil
, iter
->new_delg
, nil
);
381 for (i
= 0; i
< n
; i
++) {
382 for (j
= 0; j
< k
; j
++)
383 iter
->delf
[i
] += iter
->x
[n
+ j
] * iter
->new_delg
[j
][i
];
384 for (j
= 0; j
< k
; j
++) {
385 iter
->hessf
[n
+ j
][i
] = iter
->new_delg
[j
][i
];
386 iter
->hessf
[i
][n
+ j
] = iter
->new_delg
[j
][i
];
393 eval_next_gradient(Iteration
*iter
)
399 (*(iter
->ffun
))(iter
->new_x
, nil
, iter
->new_delf
, nil
);
401 (*(iter
->gfun
))(iter
->new_x
, iter
->new_delf
+ n
, nil
, nil
);
402 (*(iter
->gfun
))(iter
->new_x
, nil
, iter
->new_delg
, nil
);
403 for (i
= 0; i
< n
; i
++) {
404 for (j
= 0; j
< k
; j
++)
405 iter
->new_delf
[i
] += iter
->new_x
[n
+ j
] * iter
->new_delg
[j
][i
];
410 static void eval_hessian(Iteration
*iter
)
416 (*(iter
->ffun
))(iter
->x
, nil
, nil
, iter
->hessf
);
417 for (i
= n
; i
< n
+ k
; i
++)
418 for (j
= n
; j
< n
+ k
; j
++) iter
->hessf
[i
][j
] = 0.0;
421 /************************************************************************/
423 /** Backtracking Line Search **/
425 /************************************************************************/
428 linesearch(Iteration
*iter
)
431 double newtlen
, maxstep
, initslope
, rellength
, lambda
, minlambda
,
432 lambdatemp
, lambdaprev
, a
, b
, disc
, critprev
, f1
, f2
, a11
, a12
, a21
, a22
,
434 double *qnstep
, *delf
, *x
, *new_x
, *sx
;
436 n
= iter
->n
+ iter
->k
;
437 if (! iter
->use_line_search
) {
438 iter
->maxtaken
= FALSE
;
439 for (i
= 0; i
< n
; i
++)
440 iter
->new_x
[i
] = iter
->x
[i
] + iter
->qnstep
[i
];
441 eval_next_funval(iter
);
445 qnstep
= iter
->qnstep
;
446 maxstep
= iter
->maxstep
;
447 delf
= (iter
->k
== 0) ? iter
->delf
: iter
->F
;
452 iter
->maxtaken
= FALSE
;
455 for (i
= 0, newtlen
= 0.0; i
< n
; i
++)
456 newtlen
+= pow(sx
[i
] * qnstep
[i
], 2.0);
457 newtlen
= sqrt(newtlen
);
459 if (newtlen
> maxstep
) {
460 for (i
= 0; i
< n
; i
++) qnstep
[i
] *= (maxstep
/ newtlen
);
464 for (i
= 0, initslope
= 0.0; i
< n
; i
++) initslope
+= delf
[i
] * qnstep
[i
];
466 for (i
= 0, rellength
= 0.0; i
< n
; i
++)
467 rellength
= Max(rellength
, fabs(qnstep
[i
]) / Max(fabs(x
[i
]), 1.0 / sx
[i
]));
469 minlambda
= (rellength
== 0.0) ? 2.0 : iter
->steptol
/ rellength
;
472 lambdaprev
= 1.0; /* to make compilers happy */
473 critprev
= 1.0; /* to make compilers happy */
474 while (iter
->retcode
> 1) {
475 for (i
= 0; i
< n
; i
++) new_x
[i
] = x
[i
] + lambda
* qnstep
[i
];
476 eval_next_funval(iter
);
477 if (iter
->new_crit
<= iter
->crit
+ ALPHA
* lambda
* initslope
) {
479 if (lambda
== 1.0 && newtlen
> 0.99 * maxstep
) iter
->maxtaken
= TRUE
;
481 else if (lambda
< minlambda
) {
483 iter
->new_crit
= iter
->crit
;
484 for (i
= 0; i
< n
; i
++) new_x
[i
] = x
[i
];
487 if (lambda
== 1.0) { /* first backtrack, quadratic fit */
488 lambdatemp
= - initslope
489 / (2 * (iter
->new_crit
- iter
->crit
- initslope
));
491 else { /* all subsequent backtracks, cubic fit */
492 del
= lambda
- lambdaprev
;
493 f1
= iter
->new_crit
- iter
->crit
- lambda
* initslope
;
494 f2
= critprev
- iter
->crit
- lambdaprev
* initslope
;
495 a11
= 1.0 / (lambda
* lambda
);
496 a12
= -1.0 / (lambdaprev
* lambdaprev
);
497 a21
= -lambdaprev
* a11
;
499 a
= (a11
* f1
+ a12
* f2
) / del
;
500 b
= (a21
* f1
+ a22
* f2
) / del
;
501 disc
= b
* b
- 3 * a
* initslope
;
502 if (a
== 0) { /* cubic is a quadratic */
503 lambdatemp
= - initslope
/ (2 * b
);
505 else { /* legitimate cubic */
506 lambdatemp
= (-b
+ sqrt(disc
)) / (3 * a
);
508 lambdatemp
= Min(lambdatemp
, 0.5 * lambda
);
511 critprev
= iter
->new_crit
;
512 lambda
= Max(0.1 * lambda
, lambdatemp
);
513 if (iter
->verbose
> 0) {
514 sprintf(buf
, "Backtracking: lambda = %g\n", lambda
);
522 /************************************************************************/
524 /** Status Printing Functions **/
526 /************************************************************************/
529 print_header(Iteration
*iter
)
531 if (iter
->verbose
> 0) {
532 sprintf(buf
, "Iteration %d.\n", iter
->itncount
);
538 print_status(Iteration
*iter
)
542 if (iter
->verbose
> 0) {
543 sprintf(buf
, "Criterion value = %g\n",
544 (iter
->change_sign
) ? -iter
->crit
: iter
->crit
);
546 if (iter
->verbose
> 1) {
547 PRINTSTR("Location = <");
548 for (i
= 0; i
< iter
->n
+ iter
->k
; i
++) {
549 sprintf(buf
, (i
< iter
->n
+ iter
->k
- 1) ? "%g " : "%g>\n", iter
->x
[i
]);
553 if (iter
->verbose
> 2) {
554 PRINTSTR("Gradient = <");
555 for (i
= 0; i
< iter
->n
+ iter
->k
; i
++) {
556 sprintf(buf
, (i
< iter
->n
+ iter
->k
- 1) ? "%g " : "%g>\n",
557 (iter
->change_sign
) ? -iter
->delf
[i
] : iter
->delf
[i
]);
561 if (iter
->verbose
> 3) {
562 PRINTSTR("Hessian:\n");
563 for (i
= 0; i
< iter
->n
+ iter
->k
; i
++) {
564 for (j
= 0; j
< iter
->n
+ iter
->k
; j
++) {
565 sprintf(buf
, (j
< iter
->n
+ iter
->k
- 1) ? "%g " : "%g\n",
566 (iter
->change_sign
) ? -iter
->hessf
[i
][j
] : iter
->hessf
[i
][j
]);
572 if (iter
->termcode
!= 0 && iter
->verbose
> 0) {
573 sprintf(buf
, "Reason for termination: %s.\n", termcodes
[iter
->termcode
]);
578 /************************************************************************/
580 /** Iteration Driver **/
582 /************************************************************************/
585 findqnstep(Iteration
*iter
)
590 modelhess(iter
->n
, iter
->sx
, iter
->hessf
, iter
->L
, &iter
->diagadd
);
591 cholsolve(iter
->n
, iter
->delf
, iter
->L
, iter
->qnstep
);
594 N
= iter
->n
+ iter
->k
;
595 for (i
= 0; i
< N
; i
++) {
596 for (l
= 0, iter
->F
[i
] = 0.0; l
< N
; l
++)
597 iter
->F
[i
] += iter
->hessf
[i
][l
] * iter
->delf
[l
];
598 for (j
= 0; j
< N
; j
++)
599 for (l
= 0, iter
->H
[i
][j
] = 0.0; l
< N
; l
++)
600 iter
->H
[i
][j
] += iter
->hessf
[i
][l
] * iter
->hessf
[j
][l
];
602 modelhess(N
, iter
->sx
, iter
->H
, iter
->L
, &iter
->diagadd
);
603 cholsolve(N
, iter
->F
, iter
->L
, iter
->qnstep
);
607 static void iterupdate(Iteration
*iter
)
613 iter
->f
= iter
->new_f
;
614 iter
->crit
= iter
->new_crit
;
615 for (i
= 0; i
< n
+ k
; i
++) {
616 iter
->x
[i
] = iter
->new_x
[i
];
617 iter
->delf
[i
] = iter
->new_delf
[i
];
619 for (i
= 0; i
< k
; i
++) {
620 for (j
= 0; j
< n
; j
++) {
621 iter
->hessf
[n
+ i
][j
] = iter
->new_delg
[i
][j
];
622 iter
->hessf
[j
][n
+ i
] = iter
->new_delg
[i
][j
];
628 mindriver(Iteration
*iter
)
633 if (! iter
->values_supplied
) {
635 if (iter
->k
== 0) eval_gradient(iter
);
642 while (iter
->termcode
== 0) {
647 if (iter
->k
== 0) eval_next_gradient(iter
);
655 /************************************************************************/
657 /** External Interface Routines **/
659 /************************************************************************/
661 static Iteration myiter
;
664 minworkspacesize(size_t n
, size_t k
)
668 /* x, new_x, sx, delf, new_delf, qnstep and F */
669 size
= 7 * sizeof(double) * (n
+ k
);
672 size
+= 3 * (sizeof(double *) * (n
+ k
)
673 + sizeof(double) * (n
+ k
) * (n
+ k
));
675 /* delg and new_delg */
676 size
+= 2 * (sizeof(double *) * k
+ sizeof(double) * n
* k
);
682 minresultstring(int code
)
684 if (code
<= 0) return("bad input data");
685 else if (code
<= 5) return(termcodes
[code
]);
686 else return("unknown return code");
690 minsetup(size_t n
, size_t k
,
691 void (*ffun
)(), void (*gfun
)(),
692 double *x
, double typf
, double *typx
, char *work
)
693 /* int (*ffun)(), (*gfun)();*/
695 Iteration
*iter
= &myiter
;
704 iter
->ffun
= ffun
; /* FIXME:AJR */
707 iter
->x
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
708 iter
->new_x
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
709 iter
->sx
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
710 iter
->delf
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
711 iter
->new_delf
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
712 iter
->qnstep
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
713 iter
->F
= (double *) work
; work
+= sizeof(double) * (n
+ k
);
714 for (i
= 0; i
< n
; i
++) {
716 iter
->sx
[i
] = (typx
!= nil
&& typx
[i
] > 0.0) ? 1.0 / typx
[i
] : 1.0;
718 for (i
= 0; i
< k
; i
++) {
719 iter
->x
[n
+ i
] = x
[n
+ i
];
720 iter
->sx
[n
+ i
] = 1.0;
723 iter
->hessf
= (double **) work
; work
+= sizeof(double *) * (n
+ k
);
724 for (i
= 0; i
< n
+ k
; i
++) {
725 iter
->hessf
[i
] = (double *) work
;
726 work
+= sizeof(double) * (n
+ k
);
728 for (i
= 0; i
< n
+ k
; i
++)
729 for (j
= 0; j
< n
+ k
; j
++) iter
->hessf
[i
][j
] = 0.0;
730 iter
->L
= (double **) work
; work
+= sizeof(double *) * (n
+ k
);
731 for (i
= 0; i
< n
+ k
; i
++) {
732 iter
->L
[i
] = (double *) work
;
733 work
+= sizeof(double) * (n
+ k
);
735 iter
->H
= (double **) work
; work
+= sizeof(double *) * (n
+ k
);
736 for (i
= 0; i
< n
+ k
; i
++) {
737 iter
->H
[i
] = (double *) work
;
738 work
+= sizeof(double) * (n
+ k
);
741 iter
->new_delg
= (k
> 0) ? (double **) work
: nil
;
742 work
+= sizeof(double *) * k
;
743 for (i
= 0; i
< k
; i
++) {
744 iter
->new_delg
[i
] = (double *) work
;
745 work
+= sizeof(double) * n
;
748 iter
->typf
= (typf
> 0.0) ? typf
: 1.0;
750 iter
->verbose
= VERBOSE
;
751 iter
->use_line_search
= USE_SEARCH
;
753 iter
->itnlimit
= ITNLIMIT
;
754 iter
->gradtol
= pow(macheps(), GRADTOL_POWER
);
755 iter
->steptol
= pow(macheps(), STEPTOL_POWER
);
756 for (i
= 0, nx0
= 0.0, ntypx
= 0.0; i
< iter
->n
; i
++) {
757 nx0
+= fabs(iter
->new_x
[i
] / iter
->sx
[i
]);
758 ntypx
+= fabs(1.0 / iter
->sx
[i
]);
760 iter
->maxstep
= MAX_STEP_FACTOR
* Max(nx0
, ntypx
);
761 iter
->values_supplied
= FALSE
;
765 minsetoptions(double gradtol
, double steptol
, double maxstep
,
766 int itnlimit
, int verbose
, int use_search
, int change_sign
)
768 Iteration
*iter
= &myiter
;
770 if (gradtol
> 0.0) iter
->gradtol
= gradtol
;
771 if (steptol
> 0.0) iter
->steptol
= steptol
;
772 if (maxstep
> 0.0) iter
->maxstep
= maxstep
;
773 if (itnlimit
>= 0) iter
->itnlimit
= itnlimit
;
774 if (verbose
>= 0) iter
->verbose
= verbose
;
775 iter
->use_line_search
= use_search
;
776 iter
->change_sign
= change_sign
;
780 minsupplyvalues(double f
, double *delf
, double **hessf
,
781 double *g
, double **delg
)
783 Iteration
*iter
= &myiter
;
790 for (i
= 0; i
< n
; i
++) {
791 iter
->delf
[i
] = delf
[i
];
792 for (j
= 0; j
< k
; j
++)
793 iter
->delf
[i
] += iter
->x
[n
+ j
] * delg
[j
][i
];
794 for (j
= 0; j
< n
; j
++) iter
->hessf
[i
][j
] = hessf
[i
][j
];
796 for (i
= 0; i
< k
; i
++) {
797 iter
->delf
[n
+ i
] = g
[i
];
798 for (j
= 0; j
< n
; j
++) {
799 iter
->hessf
[n
+ i
][j
] = delg
[i
][j
];
800 iter
->hessf
[j
][n
+ i
] = delg
[i
][j
];
803 if (k
== 0) iter
->crit
= f
;
805 for (i
= 0, iter
->crit
= 0.0; i
< n
+ k
; i
++)
806 iter
->crit
+= 0.5 * pow(fabs(iter
->delf
[i
]), 2.0);
808 iter
->values_supplied
= TRUE
;
818 minresults(double *x
, double *pf
, double *pcrit
, double *delf
, double **hessf
,
819 double *g
, double **delg
, int *pcount
, int *ptermcode
, double *diagadd
)
821 Iteration
*iter
= &myiter
;
827 if (pf
!= nil
) *pf
= iter
->f
;
828 if (pcrit
!= nil
) *pcrit
= iter
->crit
;
829 for (i
= 0; i
< n
; i
++) {
830 if (x
!= nil
) x
[i
] = iter
->x
[i
];
831 if (delf
!= nil
) delf
[i
] = iter
->delf
[i
];
832 for (j
= 0; j
< n
; j
++) if (hessf
!= nil
) hessf
[i
][j
] = iter
->hessf
[i
][j
];
834 for (i
= 0; i
< k
; i
++) {
835 if (x
!= nil
) x
[n
+ i
] = iter
->x
[n
+ i
];
836 if (g
!= nil
) g
[i
] = iter
->delf
[n
+ i
];
837 for (j
= 0; j
< n
; j
++)
838 if (delg
!= nil
) delg
[i
][j
] = iter
->hessf
[n
+ i
][j
];
840 if (pcount
!= nil
) *pcount
= iter
->itncount
;
841 if (ptermcode
!= nil
) *ptermcode
= iter
->termcode
;
842 if (diagadd
!= nil
) *diagadd
= iter
->diagadd
;
846 double pdlogdet(int n
, double **H
)
849 double logdet
, maxadd
;
851 choldecomp(H
, n
, 0.0, &maxadd
);
852 for (i
= 0, logdet
= 0.0; i
< n
; i
++) logdet
+= 2.0 * log(H
[i
][i
]);
860 return amount added to make pos definite
862 scaling for constraints
864 alternate global strategies
866 callback function for verbose mode