home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
ddjmag
/
ddj8603.arc
/
METRIC.MAR
< prev
next >
Wrap
Text File
|
1986-03-31
|
52KB
|
2,180 lines
/* GLOBAL.H 08/18/85
*
* Global include file for the Variable Metric Minimizer program.
*
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#define C80
/*
* remove the above line if you are not using C/80
*/
#ifdef C80
/*
* required for the Software Toolworks C/80 Version 3.0 compiler
*/
#define double float
#include "fprintf.h"
#include "scanf.h"
/*
* the following is the <math.h> for C/80
*/
float sin() , cos() , atan() , sqrt() , exp() ,
pow() , pow10() , ln() , log() , fabs() , atof() ;
#else
/*
* other compilers
*/
#include <stdio.h>
#include <math.h>
#include <ctype.h>
/*
* ctype.h may be needed for an isspace used in read.c
* some systems need it, some don't!
* check your math.h for fabs and atof declarations!
*/
#endif
double dot() ;
struct bound
{
int fl ;
double up ;
double lo ;
double mi ;
};
struct xydata
{
double x ;
double y ;
};
#define BOUND struct bound
#define DATA struct xydata
#define VECMAX 10
#define MATMAX VECMAX*VECMAX
#define NEPS 2
#define STDES 0
#define DFP 1
#define BFGS 2
#define ALLDONE -1
#define NEGEDM -3000
#define BADMIN -2000
#define BADLS -1000
#define MAXITERS 0
#define OK 0
#define EDM1 1000
#define EDM2 2000
#define TOOSML 3000
Listing TWO
/* VMM.C 11/04/85
*
* The main driver routine, function library routine
* and all library functions for vmm.
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#include "global.h"
#define DMAX 50 /* Size of experimental data array */
#define NFUN 3 /* Num of functions in function library */
/************************************************************************/
main()
{
static int nparam ; /* number of parameters */
static double const[VECMAX] ; /* constants used in function */
static double param[VECMAX] ; /* parameters to be found */
static double dstep[VECMAX] ; /* step sizes for derivatives */
static double epsilon[VECMAX];/* stopping criteria */
static BOUND limit[VECMAX] ; /* limits if constrained */
static char *pname[VECMAX] ;/* parameter names */
static double g0 ; /* expected value of minimum */
static int debug ; /* debug level, 0 if off */
static int itermin ; /* minimum number of iterations */
static int iterlim ; /* maximum number of iterations */
static int nreset ; /* reset y after this many iters*/
static DATA exp[DMAX] ; /* xy experimental data */
static int npoints ; /* number of data points */
static double *(*fun)() ; /* ptr to function to minimize */
static int iters ; /* number of iterations it took */
static int retcode ; /* return code from minimization*/
static double gmin ; /* the value at the minimum */
static int method ; /* method used to update y */
static int control ;
int i , j ;
for ( i=1 ; ; ++i )
{
raz ( &nparam , &itermin , &iterlim , &nreset , &debug ,
limit , dstep , param , &g0 , epsilon , &method ) ;
if( (control = reader ( &fun , const , &nparam , param ,
limit , dstep , pname , epsilon , &itermin ,
&iterlim , &nreset , &g0 , &debug , exp ,
&npoints , DMAX , &method)) == ALLDONE )
break ;
if ( control )
continue ;
if ( dfault ( nparam , &itermin , &iterlim , &nreset ,
epsilon , limit , dstep , debug ) )
continue ;
retcode = minim ( nparam , fun , param , dstep , limit ,
g0 , itermin , iterlim , epsilon , &gmin ,
&iters , debug , nreset , exp , npoints ,
const , method ) ;
printf("\t***************************\n") ;
printf("\t* results from dataset %2d *\n", i ) ;
printf("\t***************************\n") ;
printf("stopped after %1d iterations, ", iters ) ;
switch ( retcode )
{
case NEGEDM : printf("negative e.d.m.\n") ; break ;
case BADMIN : printf("new min > last min\n") ; break ;
case BADLS : printf("line search failed\n") ; break ;
case MAXITERS: printf("maximum iterations\n"); break ;
case EDM1 : printf("e.d.m. within tol.\n") ; break ;
case EDM2 : printf("e.d.m. within tol.\n") ; break ;
case TOOSML : printf("change too small\n") ; break ;
default : printf("unknown reason!!!\n") ; break ;
}
printf("value of the minimum was %11.4e\n", gmin ) ;
printf("parameter values at minimum:\n") ;
for (j=0 ; j<nparam ; ++j)
printf("%15s %11.4e\n" , pname[j] , param[j]);
printf("*********************************************\n") ;
}
}
/************************************************************************
* Function library. Note that NFUN is #defined at the top of this
* module.
*/
funlib ( funname , fun , np , nc , pname )
char funname[] ; /* name of function to be minimized */
int *fun ; /* address of function (non-portable) */
int *np ; /* number of parameters in the function */
int *nc ; /* number of constants in the function */
char *pname[] ; /* parameter names vector */
{
/*
* use funname to return fun and np, nc from a list
* for each new function in the library, you must:
* (1) declare the function "double" and link it in the load module
* (2) declare the function below under "functions available"
* (3) add an entry in the function table,including parameter names
* (4) add an entry in the switch table in the code
* (5) update the value of NFUN
*
* Available functions are:
*/
double cohen() ;
double sinus() ;
double rosen() ;
/*
* function table
*/
static struct
{
char *name ; /* function name in funname call */
int nnpp ; /* number of parameters in the function */
int nncc ; /* number of constants in the function */
char *ppnn[VECMAX]; /* list of names for the parameters */
} fctlib[NFUN] = {
/* 0 */ { "cohen" , 2, 0 , "alpha" , "beta" } ,
/* 1 */ { "sine" , 4, 0 , "P0" , "P1" , "P2" , "P3" } ,
/* 2 */ { "rosen" , 10, 5 , "x1" , "x2" , "x3" , "x4" , "x5" ,
"x6" , "x7" , "x8" , "x9" , "x10" }
} ;
int j, k;
for ( j=0 ; j<NFUN ; ++j )
if ( ! strcmp( funname , fctlib[j].name ) )
break ;
if (j==NFUN)
return( 1 ) ;
*np = fctlib[j].nnpp ;
*nc = fctlib[j].nncc ;
for (k=0 ; k < *np ; ++k)
pname[k] = fctlib[j].ppnn[k] ;
switch( j )
{
case 0 : *fun = cohen ; break ;
case 1 : *fun = sinus ; break ;
case 2 : *fun = rosen ; break ;
}
return( 0 ) ;
}
/************************************************************************/
double cohen ( const , xx , data , npoints , user )
double const[] ; /* vector of constants used by this fcn */
double xx[] ; /* the current values of the vector x */
DATA data[] ; /* dummy */
int npoints ; /* dummy */
int user ; /* dummy, reserved for each user! */
{
/*
* computes the function to be minimized
*
* this is the test function given in Cohen, page 280
* note that there are no constants for this fcn --
* the vector const is included for compatability with other fcns
*
* note program calls function with user = 0
*/
double t1 , t2 , t3 , t4 ;
t1 = (xx[1] - xx[0]*xx[0]) ;
t2 = t1 * t1 ;
t3 = (xx[0] * (1.0 - xx[1]) + 1.0) ;
t4 = t3 * t3 ;
return ( t2 + t4 ) ;
}
/************************************************************************/
double sinus ( const , xx , data , npoints , user )
double const[] ; /* vector of constants for this fcn */
double xx[] ; /* parameter vector */
DATA data[] ; /* data from file */
int npoints ; /* number of data points */
int user ; /* user parameter */
{
/*
* extract parameters for polynomial fit to sine function
*/
double t1 , t2 , t3 , t4 ;
int i;
for ( i=0 , t4 = 0.0 ; i<npoints ; i++ )
{
t1 = data[i].x * data[i].x ;
t2 = data[i].x *
(xx[0] + t1*(xx[1] + t1*(xx[2] + t1*xx[3]) )) ;
t3 = (data[i].y - t2)/data[i].y ;
t4 += t3 * t3 ;
}
return( t4 /= (double)(npoints-4) ) ;
}
/************************************************************************/
double rosen ( const , xx , data , npoints , user )
double const[] ; /* vector of constants used by this fcn */
double xx[] ; /* the current values of the vector x */
DATA data[] ; /* dummy */
int npoints ; /* dummy */
int user ; /* dummy, reserved for each user! */
{
/*
* Rosenbrock's test function
*/
double t1 , t2 , t3 ;
int l , m ;
for ( l=0 , m=0 , t3 = 0.0 ; l<10 ; l += 2 , ++m )
{
t1 = xx[l] ;
t2 = xx[l+1] ;
t3 += const[m]*(t2-t1*t1)*(t2-t1*t1) + (1.0-t1)*(1.0-t1) ;
}
return( t3 ) ;
}
/* LISTING THREE
* MINIM.C 11/04/85
*
* The main minimization routine
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#include "global.h"
/***************************************************************************/
minim ( n , fun , xextern , xstep , xlim , g0 , itermin , iterlim , epsilon ,
gmin , iters , debug , nreset , data , npoints , const , method )
int n ; /* number of parameters in the fit */
double (*fun)() ; /* pointer to the function to minimize */
double xextern[] ; /* vector containing the starting values of
the parameters; returns values at minimum */
double xstep[] ; /* step sizes on parameters for deriv calcs */
BOUND xlim[] ; /* limits on the vector x */
double g0 ; /* expected value of the minimum of the fcn */
int itermin ; /* minimum number of iterations */
int iterlim ; /* limit on the number of iterations */
double epsilon[] ; /* iteration control parameters */
double *gmin ; /* value of minimum for returned vector x */
int *iters ; /* number of iterations to converge */
int debug ; /* flag = 0 for no print, >0 for debug print */
int nreset ; /* reset limit for the y matrix */
DATA data[] ; /* the data */
int npoints ; /* number of data points */
double const[] ; /* vector of constants required by fcn */
int method ; /* update method for the matrix y */
{
/*
* variable metric minimization algorithm
* Reference (using DFP method) is: Numerical Analysis
* A.M. Cohen et. al.
* Halstead Press
* John Wiley and Sons
* 1973
* pages 276-280
* See also original papers by Fletcher and Powell
*/
int i , j , rc ;
static int ycount ; /* counter for resetting the Y matrix */
static double y[MATMAX] ; /* the Y matrix */
static double a[MATMAX] ; /* the A and B matrices are calculated to */
static double b[MATMAX] ; /* update the Y matrix at each iteration */
static double xintern[VECMAX];/* parameters in internal coordinates */
static double zint[VECMAX] ; /* gradients in internal coordinates */
static double znewi[VECMAX] ; /* same for the next iteration */
static double sigma[VECMAX] ; /* changes vector */
static double s[VECMAX] ; /* changes direction vector */
static double xi[VECMAX] ; /* change in gradient vector between */
* iterations */
static double xold[VECMAX] ; /* holds previous values of x */
static double alpha ; /* change scaling parameter */
static double g ; /* value of fcn for a given vector x */
static double gnew ; /* likewise for the next iteration */
double dot() ;
/*
* get started
*/
g = (*fun)( const , xextern , data , npoints , 0 ) ;
gozinta( n , xintern , xextern , xlim ) ;
derivs ( n , fun , xintern , xstep , xlim , zint , data ,
npoints , const , debug);
/*
* main loop
*/
for ( i = 1 , ycount = nreset ; i <= iterlim ; ++i , ++ycount )
{
if (ycount == nreset)
{
reset( n , y );
ycount = 0 ;
}
if (debug)
{
printf("\t\t++++++++++++++++++++++\n") ;
printf("\t\t+ Begin iteration %2d +\n", i ) ;
printf("\t\t++++++++++++++++++++++\n") ;
printf("external parameter values are:\n") ;
vout( n , xextern ) ;
printf("internal parameter values are:\n") ;
vout( n , xintern ) ;
printf("internal gradient vector is:\n") ;
vout( n , zint ) ;
printf("approximate inverse hessian matrix is:\n") ;
mout( n , y ) ;
printf("the current minimum is --->%11.4e<---\n", g ) ;
}
matvec ( n , y , zint , s ) ;
for (j=0 ; j<n ; ++j)
{
xold[j] = xintern[j] ;
s[j] *= -1.0 ;
}
if (debug>1)
{
printf("vector s is:\n"); vout( n , s ) ;
}
/*
* do line search and quit if it fails
* line search was successful if getalpha returns OK ( zero )
*/
if ( rc = getalpha ( n , fun , xintern , xstep , xlim , zint ,
s , g ,g0 , &alpha , debug , data , npoints , const ) )
break ;
/*
* update parameters
*/
for (j=0 ; j<n ; ++j)
{
sigma[j] = alpha * s[j] ;
xintern[j] += sigma[j];
}
if (debug>1)
{
printf("vector sigma is:\n") ; vout( n , sigma ) ;
}
/*
* get values for next iteration
*/
gozouta ( n , xintern , xextern , xlim );
gnew = (*fun)( const , xextern , data , npoints , 0 ) ;
derivs (n , fun , xintern , xstep , xlim , znewi ,
data , npoints , const , debug ) ;
for (j=0 ; j<n ; ++j)
xi[j] = znewi[j] - zint[j] ;
if (debug>1)
{
printf("orthogonality satisfied to %11.4e\n",
dot ( n , znewi , sigma ) ) ;
printf("vector xi is:\n") ;
vout( n , xi ) ;
}
/*
* decide whether to continue or not
* continue if decide returns OK ( zero )
*/
if ( rc = decide( g , gnew , n , znewi , sigma , y ,
epsilon , itermin , i , debug ) )
break ;
/*
* update all other quantities for the next pass
* three methods available:
* steepest descent (slowest and included only for completeness)
* Davidon Fletcher Powell (default, empirically the favorite)
* Broyden Fletcher Goldfarb Shanno (thought to be better by
* some)
* The method is selected by keyword on input.
*/
if ( method == STDES )
; /* nothing to do, y is not updated */
else if ( method == DFP )
{
dfpa ( n , sigma , xi , a , debug ) ;
dfpb ( n , y , xi , b , debug ) ;
gety ( n , a , b , y , debug ) ;
}
else if ( method == BFGS )
{
bfgsa ( n , y , sigma , xi , a , debug ) ;
bfgsb ( n , y , sigma , xi , b , debug ) ;
gety ( n , a , b , y , debug ) ;
}
for (j=0 ; j<n ; ++j)
zint[j] = znewi[j] ;
gozouta ( n , xintern , xextern , xlim ) ;
g = gnew ;
/*
* all done with this pass
*/
}
/*
* outside of the main loop here
*/
*iters = ( i > iterlim ) ? iterlim : i ;
/*
* first handle the case of abnormal exits
* these have returned rc negative above, from either getalpha or decide
*/
if ( rc < 0 )
{
for (j=0; j<n; ++j)
xintern[j] = xold[j] ;
gozouta ( n , xintern , xextern , xlim ) ;
*gmin = g ;
}
else
{
/*
* regular exit and fall through These represent positive or
* zero values of rc; zero means max iterations.
*/
gozouta ( n , xintern , xextern , xlim ) ;
*gmin = gnew ;
}
if (debug)
{
printf("\t\t++++++++++++++++++++++++\n") ;
printf("\t\t+ exiting minimization +\n") ;
printf("\t\t++++++++++++++++++++++++\n") ;
printf("\tnumber of iterations was: %11d\n",*iters) ;
printf("\t return code is: %11d\n",rc) ;
printf("\t minimum is: %11.4e\n", *gmin) ;
printf("best parameter values:\n") ;
vout( n , xextern ) ;
printf("last internal gradient vector:\n") ;
vout( n , znewi ) ;
}
return( rc ) ;
}
/* LISTING FOUR
* AUXL.C 11/04/85
*
* The line search and decision routines
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#include "global.h"
/************************************************************************/
getalpha ( n , fun , xx , xstep , xlim , z , s , g , g0 ,
alpha , debug , data , npoints , const )
int n ; /* number of parameters */
double (*fun)() ; /* pointer to the function to minimize */
double xx[] ; /* parameter vector */
double xstep[] ; /* stepsize for parameter derivative calcs */
BOUND xlim[] ; /* limits on parameters */
double z[] ; /* gradient vector */
double s[] ; /* changes direction vector */
double g ; /* value of fcn for the given vector xx */
double g0 ; /* expected value of the minimum of the fcn */
double *alpha ; /* scaling parameter we are trying to find */
int debug ; /* flag = 0 for no print, >0 for debug print */
DATA data[] ; /* the data */
int npoints ; /* number of data points */
double const[] ; /* constants vector needed by fcn */
{
/*
* find alpha according to Cohen, pp 279-280
*/
int i ;
static double u ; /* see Cohen */
static double eta ; /* see Cohen */
static double t[VECMAX] ; /* see Cohen */
static double text[VECMAX] ; /* same, in external coordinates */
static double zt[VECMAX] ; /* the z for fcn evaluated at x = t */
static double gt ; /* the g that results from fcn at */
/* x = t */
static double nu ; /* see Cohen */
static double d ; /* see Cohen */
static double w ; /* see Cohen */
static double temp1 ;
static double temp2 ;
if (debug>1) {
printf("\t\t+++++++++++++++++++++++++\n") ;
printf("\t\t+ line search procedure +\n") ;
printf("\t\t+++++++++++++++++++++++++\n") ;
}
u = dot ( n , z , s ) ;
eta = -2.0 * ( g - g0 ) / u ;
if (eta > 1.0)
eta = 1.0 ;
for (i=0 ; i<n ; ++i)
t[i] = xx[i] + eta * s[i] ;
gozouta ( n , t , text , xlim ) ;
gt = (*fun)( const , text , data , npoints , 0 ) ;
derivs ( n, fun, t, xstep, xlim, zt, data, npoints, const, debug );
nu = dot ( n , zt , s ) ;
if (debug>1)
{
printf("u and nu are: %11.4e %11.4e\n", u , nu ) ;
printf("g and gt are: %11.4e %11.4e\n", g , gt ) ;
printf("eta is: %11.4e\n", eta ) ;
if (debug>2)
{
printf("vector t is:\n") ;
vout( n , t ) ;
printf("vector zt is:\n") ;
vout( n , zt ) ;
}
}
d = 3*(g - gt)/eta + u + nu ;
if ( (temp1 = d*d) < (temp2 = u*nu) )
{
if (debug>1)
{
printf("cubic interpolation has failed, ") ;
printf("about to take sqrt of negative number!\n") ;
printf("d squared is %11.4e ", temp1 ) ;
printf("and u*nu is %11.4e\n", temp2 ) ;
printf("difference is %11.4e\n", temp1-temp2 ) ;
}
if ( u < 0.0 && nu < 0.0 && gt < g )
{
*alpha = eta ;
if (debug>1)
printf("return with alpha = eta\n") ;
return( OK ) ;
}
else
{
*alpha = 0.0 ;
if (debug>1)
printf("line search has failed\n") ;
return( BADLS ) ;
}
}
else
{
w = sqrt(temp1 - temp2) ;
*alpha = eta * ( 1.0 - (nu+w-d)/(nu-u+2.0*w) ) ;
if (debug>1)
printf("alpha returned is %11.4e\n", *alpha ) ;
return( OK ) ;
}
}
/***************************************************************************/
decide ( g , gnew , n , znewi , sigma , y ,
epsilon , itermin , iterations , debug )
double g ; /* old value of minimum */
double gnew ; /* new value of minimum */
int n ; /* number of parameters */
double znewi[] ; /* vector of new gradients */
double sigma[] ; /* change vector for parameters */
double y[] ; /* the transformation matrix */
double epsilon[] ; /* cutoff criteria vector */
int itermin ; /* minimum number of iterations */
int iterations ; /* current iteration number */
int debug ; /* debug flag */
{
/*
* makes the decision to continue iterating or not
* returns a zero if we want to keep going
* returns a positive number if we have a normal stopping reason
* returns a negative number if we have a catastrophic stopper
*/
static double edm ;
static double temp[VECMAX] ;
if (debug>1)
{
printf("\t\t+++++++++++++++++++++++++\n") ;
printf("\t\t+ decision making logic +\n") ;
printf("\t\t+++++++++++++++++++++++++\n") ;
printf("old minimum was: %11.4e, new minimum is %11.4e\n",
g , gnew ) ;
printf("ratio new/old is: %11.4e\n", gnew/g ) ;
}
/*
* exit if the new "minimum" is greater than or equal to the old minimum
*/
if (gnew >= g)
{
if (debug>1)
printf("STOP!!! new minimum is not lower!\n") ;
return( BADMIN ) ;
}
/*
* if the edm (estimated distance to the minimum) is negative we have
* a catastrophic problem and should stop
*/
matvec( n , y , znewi , temp ) ;
edm = dot( n , znewi , temp ) ;
if( edm < 0.0 )
{
if (debug>1)
printf("STOP!!! edm is negative = %11.4e\n", edm);
return( NEGEDM ) ;
}
/*
* now look at normal exits if the minimum number of iterations has
* been accomplished
*/
if (iterations < itermin) {
if (debug>1) printf("-->keep going, too few iterations\n") ;
return( OK ) ;
}
/*
* edm test: two ways to calculate, stop if either satisfies
*/
if (edm < epsilon[0])
{
if (debug>1)
printf("STOP, close enough, edm = %11.4e\n", edm);
return( EDM1 ) ;
}
edm = dot( n , sigma , sigma ) ;
if (edm < epsilon[0])
{
if (debug>1)
printf("STOP, close enough, edm = %11.4e\n", edm);
return( EDM2 ) ;
}
/*
* % change in g less than "something" means that approach is too slow
*/
if ( g-gnew < epsilon[1]*g )
{
if (debug>1)
printf("STOP, too slow, fractional change = %11.4e\n",
(g-gnew)/g ) ;
return( TOOSML ) ;
}
/*
* fall through case
* note that case of maximum number of iterations is handled in the
* calling program
*/
if (debug>1)
printf("--->keep going, no stoppers found...\n") ;
return( OK ) ;
}
/* LISTING FIVE
* UP.C 11/04/85
*
* Routines for updating the matrix y
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#include "global.h"
/*-----------------------------------------------------------------*/
dfpa ( n , sigma , xi , a , debug )
int n ; /* number of parameters */
double *sigma ; /* changes vector */
double *xi ; /* change in gradient vector */
double *a ; /* the result */
int debug ; /* flag = 0 for no print, >0 for debug print */
{
/*
* Compute the matrix A which is used to correct Y
* Davidon Fletcher Powell method
*/
int i ;
double norm ;
double *t ;
t = a ;
cross( n , sigma , sigma , a ) ;
norm = 1.0 / dot( n , sigma , xi ) ;
i = n*n ;
while( i-- )
*a++ *= norm ;
if (debug>1)
{
printf("AAAAA correcting matrix AAAAA is:\n") ;
mout( n , t ) ;
}
}
/*-----------------------------------------------------------------*/
dfpb ( n , y , xi , b , debug )
int n ; /* number of parameters */
double *y ; /* current Y matrix */
double *xi ; /* change in gradient vector */
double *b ; /* the result */
int debug ; /* flag = 0 if no print, >0 for debug print */
{
/*
* compute the matrix B which is used to update Y
* Davidon Fletcher Powell method
*/
int i ;
static double temp[VECMAX] ;
double *t ;
double norm ;
t = b ;
matvec( n , y , xi , temp ) ;
norm = - 1.0 / dot( n , temp , xi ) ;
cross( n , temp , temp , b ) ;
i = n*n ;
while( i-- )
*b++ *= norm ;
if (debug>1)
{
printf("BBBBB correcting matrix BBBBB is:\n") ;
mout( n , t ) ;
}
}
/*-----------------------------------------------------------------*/
bfgsa ( n , y , sigma , xi , a , debug )
int n ; /* number of parameters */
double *y ; /* current Y matrix */
double *sigma ; /* changes vector */
double *xi ; /* change in gradient vector */
double *a ; /* the result */
int debug ; /* flag = 0 for no print, >0 for debug print */
{
/*
* compute the matrix A which is used to correct Y
* Broyden Fletcher Goldfarb Shanno method
*/
int i , j ;
static double temp[VECMAX] ;
static double tmpa[MATMAX] ;
double norm ;
norm = 1.0 / dot ( n , sigma , xi ) ;
matvec( n , y , xi , temp ) ;
for (j=0 ; j<n ; ++j)
temp[j] = sigma[j] - temp[j] ;
cross( n , temp , sigma , tmpa ) ;
cross( n , sigma , temp , a ) ;
i = n*n ;
for (j=0 ; j<i ; ++j)
a[j] = norm * ( a[j] + tmpa[j] ) ;
if (debug>1)
{
printf("AAAAA correcting matrix AAAAA is:\n") ;
mout( n , a ) ;
}
}
/*-----------------------------------------------------------------*/
bfgsb ( n , y , sigma , xi , b , debug )
int n ; /* number of parameters */
double *y ; /* current Y matrix */
double *sigma ; /* changes vector */
double *xi ; /* change in gradient vector */
double *b ; /* the result */
int debug ; /* flag = 0 if no print, >0 for debug print */
{
/*
* compute the matrix B which is used to update Y
* Broyden Fletcher Goldfarb Shanno method
*/
int i ;
static double temp[VECMAX] ;
double *t ;
double norm ;
t = b ;
norm = 1.0 / dot( n , sigma , xi ) ;
norm = - norm * norm ;
matvec( n , y , xi , temp ) ;
for (i=0 ; i<n ; ++i)
temp[i] = sigma[i] - temp[i] ;
norm *= dot( n , temp , xi ) ;
cross( n , sigma , sigma , b ) ;
i = n*n ;
while( i-- )
*b++ *= norm ;
if (debug>1)
{
printf("BBBBB correcting matrix BBBBB is:\n") ;
mout( n , t ) ;
}
}
/*-----------------------------------------------------------------*/
gety ( n , a , b , y , debug )
int n ;
double *a ;
double *b ;
double *y ;
int debug ;
{
/*
* use matrices A and B to correct Y
*/
int i ;
double *t ;
t = y ;
i = n*n ;
while( i-- )
*y++ += *a++ + *b++ ;
if (debug>1)
{
printf("YYYYY new matrix YYYYY is:\n") ;
mout( n , t ) ;
}
}
* LISTING SIX
* UTIL.C 11/04/85
*
* Contains miscellaneous routines needed for variable metric minimization
* program, including matrix and vector utilities
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#include "global.h"
#define INALINE 6
/*-----------------------------------------------------------------*/
gozinta( n , xintern , xextern , xlim )
int n ;
double xintern[] ;
double xextern[] ;
BOUND xlim[] ;
{
/*
* transform all external coordinates to internal coordinates
*/
int i ;
for ( i=0 ; i<n ; ++i )
tointern( i , xintern , xextern , xlim ) ;
}
/*-----------------------------------------------------------------*/
gozouta( n , xintern , xextern , xlim )
int n ;
double xintern[] ;
double xextern[] ;
BOUND xlim[] ;
{
/*
* transform all internal coordinates to external coordinates
*/
int i ;
for ( i=0 ; i<n ; ++i )
toextern( i , xintern , xextern , xlim ) ;
}
/*-----------------------------------------------------------------*/
tointern ( j , xintern , xextern , xlim )
int j ; /* parameter to transform */
double xintern[] ; /* internal coordinates */
double xextern[] ; /* external coordinates */
BOUND xlim[] ; /* limits on the parameters */
{
/*
* transform to unbounded "internal" coordinates used by
* minimization program.
*/
double y ;
if( xlim[j].fl )
{
if ( xlim[j].mi == 0.0 )
xintern[j] = xextern[j] ;
else
{
y = ( (xextern[j]-xlim[j].lo) / xlim[j].mi ) - 1.0 ;
xintern[j] = atan( y / sqrt( 1.0 - y*y ) ) ;
}
}
else
xintern[j] = xextern[j] ;
}
/*-----------------------------------------------------------------*/
toextern ( j , xintern , xextern , xlim )
int j ; /* parameter to transform */
double xintern[] ; /* internal coordinates */
double xextern[] ; /* external coordinates */
BOUND xlim[] ; /* limits on the parameters */
{
/*
* transforms to bounded "external" coordinates known to the real world
*/
if( xlim[j].fl )
xextern[j] = xlim[j].lo + xlim[j].mi *
( sin(xintern[j]) + 1.0 ) ;
else
xextern[j] = xintern[j] ;
}
/*-----------------------------------------------------------------*/
derivs ( n , fun , xintern , xstep , xlim , z , data , m , const , debug )
int n ; /* number of parameters */
double (*fun)() ; /* pointer to the function to minimize */
double xintern[] ; /* coordinates vector */
double xstep[] ; /* step size to take on each component */
BOUND xlim[] ; /* limit vector */
double z[] ; /* derivative vector */
DATA data[] ; /* the data */
int m ; /* number of data points */
double const[] ; /* constants required by fcn */
int debug ; /* debug flag */
{
/*
* compute the derivatives of the vector x using a simple
* finite difference.
*/
int i ;
static double xextern[VECMAX];/* throwaway vector in ext coords */
static double f1 , f2 ; /* values of fcn at +/- stepsize */
static double xtemp ;
static double eps ;
gozouta( n , xintern , xextern , xlim ) ;
for ( i=0 ; i<n ; ++i )
{
xtemp = xintern[i] ;
eps = fabs( xtemp ) * xstep[i] ;
xintern[i] = xtemp + eps ;
toextern( i , xintern , xextern , xlim ) ;
f1 = (*fun)( const , xextern , data , m , 0 ) ;
xintern[i] = xtemp - eps ;
toextern( i , xintern , xextern , xlim ) ;
f2 = (*fun)( const , xextern , data , m , 0 ) ;
z[i] = (f1 - f2) / ( 2.0 * eps ) ;
if (debug>2)
printf("i,f1,f2,step,deriv %d %12e %12e %12e %12e\n",
i, f1, f2, eps , z[i] ) ;
xintern[i] = xtemp ;
toextern( i , xintern , xextern , xlim ) ;
}
if (debug==2)
{
printf("derivatives are:\n");
vout( n , z ) ;
}
}
/*-----------------------------------------------------------------*/
raz ( nparam , itermin , iterlim , nreset , debug , limit , dstep ,
param , g0 , epsilon , method )
int *nparam ; /* number of parameters */
int *itermin ; /* minimum number of iterations */
int *iterlim ; /* maximum number of iterations */
int *nreset ; /* reset y after nreset iters */
int *debug ; /* debug flag */
BOUND limit[] ; /* limit vector */
double dstep[] ; /* step size for derivatives */
double param[] ; /* initial values of parameters */
double *g0 ; /* expected value of minimum */
double epsilon[] ; /* stopping criteria vector */
int *method ; /* update method for y */
{
/*
* reinitialize important parameters before reading, so that we
* can later test to see if they were set in the dataset
*/
int j ;
*debug = *nparam = *itermin = *iterlim = *nreset = 0 ;
*g0 = 0.0 ;
*method = DFP ;
for ( j=0 ; j<VECMAX ; ++j )
{
limit[j].fl = 0 ;
dstep[j] = 0.0 ;
epsilon[j] = 0.0 ;
param[j] = 0.0 ;
}
}
/*-----------------------------------------------------------------*/
dfault ( n , itermin , iterlim , nreset , epsilon , xlim , dstep , debug )
int n ; /* number of parameters */
int *itermin ; /* minimum number of iterations */
int *iterlim ; /* maximum number of iterations */
int *nreset ; /* reset y matrix after this many iters */
double epsilon[] ; /* stopping criteria vector */
BOUND xlim[] ; /* limit vector for parameters */
double dstep[] ; /* step sizes for derivative calc */
int debug ; /* flag for debug */
{
/*
* this routine sets defaults if parameters not set with input data
*/
int j ;
if (debug)
{
printf("\t\t+++++++++++++++++++\n") ;
printf("\t\t+ initializations +\n") ;
printf("\t\t+++++++++++++++++++\n") ;
}
/*
* check that the number of parameters has been set; fatal error if not!
*/
if ( !n )
return( -1 ) ;
/*
* set up other defaults as required -- these depend on knowing n
*/
if ( !*itermin )
*itermin = n ;
if ( !*iterlim )
*iterlim = 2*n ;
if ( !*nreset )
*nreset = (3*n)/2 ;
for (j=0 ; j<n ; ++j)
if (dstep[j] == 0.0)
dstep[j] = 0.01 ;
if (debug)
{
printf("min iters = %3d, max iters = %3d, ", *itermin ,
*iterlim ) ;
printf("reset y every %3d iterations\n", *nreset ) ;
printf("step sizes for derivatives:\n") ; vout( n , dstep ) ;
}
if ( epsilon[0] == 0.0 )
{
epsilon[0] = 1.0e-06 ;
epsilon[1] = 0.001 ;
if (debug) printf("epsilons set to defaults:\n") ;
}
else if (debug)
printf("epsilons from input data:\n") ;
if (debug)
vout( NEPS , epsilon ) ;
/*
* note that if you add other stopping criteria (more elements in
* the epsilon vector) you will have to modify this code
*
* the following defaults were set in raz and remain if not changed
* by the data read in reader:
* starting values of parameters: 0.0
* expected value of minimum: 0.0
* constrained/unconstrained: unconstrained (all)
* parameter names: blank
* updating method for y : Davidon-Fletcher-Powell (DFP)
*
* variables used for intern<-->extern conversions:
*/
for (j=0 ; j<n ; j++)
if (xlim[j].fl)
xlim[j].mi = (xlim[j].up - xlim[j].lo) / 2.0 ;
return( 0 ) ;
}
/*-----------------------------------------------------------------*/
vout ( n , a )
int n ;
double *a ;
{
/*
* output the floating point vector a with n components
* INALINE values to a line, indent succeeding lines appropriately
*/
praline( n , a , 0 ) ;
putchar('\n') ;
}
/*-----------------------------------------------------------------*/
praline( n , a , indent )
int n ;
double *a ;
int indent ;
{
/*
* print out as many lines as required, indenting as we go
*/
int i ;
if ( indent )
{
putchar('\n') ;
for ( i=indent ; i ; --i )
putchar(' ');
}
for ( i=INALINE ; i && n ; --i , --n )
printf("%11.4e " , *a++ ) ;
if ( !n )
return ;
praline( n , a , ++indent ) ;
}
/*-----------------------------------------------------------------*/
mout ( n , a )
int n ;
double *a ;
{
/*
* output the floating point matrix a with n by n components
*/
int i ;
double *p ;
for (i=n , p=a ; i ; --i , p += n )
vout( n , p ) ;
}
/*-----------------------------------------------------------------*/
double dot( n , a , b )
int n ;
double *a , *b ;
{
/*
* dot product of the vectors a and b, n components each
*/
double c ;
c = 0.0 ;
while( n-- )
c += *a++ * *b++ ;
return( c ) ;
}
/*-----------------------------------------------------------------*/
reset ( n , y )
int n ;
double *y ;
{
/*
* set the n by n matrix y equal to the identity matrix
*/
int i, j;
for( i = n-1, j = n ; i ; --i, j = n )
{
*y++ = 1.0 ;
while ( j-- )
*y++ = 0.0 ;
}
*y = 1.0 ;
}
/*-----------------------------------------------------------------*/
cross( n , v1 , v2 , m )
int n ;
double *v1 ;
double *v2 ;
double *m ;
{
/*
* product of two vectors of dimension n yielding an n by n matrix
*/
int i , j ;
double *p ;
for( i=n , p=v2 ; i ; --i , ++v1 , p=v2 )
for( j=n ; j ; --j )
*m++ = *v1 * *p++ ;
}
/*-----------------------------------------------------------------*/
matvec( n , m , v1 , v2 )
int n ;
double *m ;
double *v1 ;
double *v2 ;
{
/*
* product of an n by n matrix and a column vector with n components
* yielding a second n component vector: m * v1 = v2
*/
int i , j ;
double *p ;
for ( i=n , p=v1 ; i ; --i , ++v2 , p=v1 )
for ( j=n , *v2=0.0 ; j ; --j )
*v2 += *m++ * *p++ ;
}
/* LISTING SEVEN
* READ.C 12/05/85
*
* reads standard input to get appropriate parameters
* echoes the data as it is read
* (c) Copyright 1985, Billybob Software. All rights reserved.
* This program may be reproduced for personal, non-profit use only.
*/
#include "global.h"
#define LEN 130
#define MAXKEY 19
#define DEBUGON if (*debug)
#define LF putchar('\n')
/************************************************************************/
reader ( fun , const , nparam , param , limit , dstep , pname ,
epsilon , itermin , iterlim , nreset , g0 , debug ,
data , npoints , npmax , method )
int *fun ; /* address of function (non-portable) */
double const[] ; /* values of constants used in fcn */
int *nparam ; /* number of parameters to be found by fitting */
double param[] ; /* starting values of parameters */
BOUND limit[] ; /* on-off flag, upper and lower limits */
double dstep[] ; /* step sizes used to calculate derivatives */
char *pname[] ; /* parameter names */
double epsilon[] ; /* vector of stopping criteria for iteration */
int *itermin ; /* minimum number of iterations required */
int *iterlim ; /* maximum number of iterations allowed */
int *nreset ; /* # of iters to reset y matrix */
double *g0; /* expected value of minimum */
int *debug ; /* debug mode */
DATA data[] ; /* data from input file */
int *npoints ; /* number of data points */
int npmax ; /* maximum number of data points allowed */
int *method ; /* dfp or bfgs updating method */
{
int nconst ; /* number of constants used in fcn */
char instring[LEN] ;
char *restofline ;
char *firstword ;
static char funname[] = " " ;
static char *key[MAXKEY] =
{
"bfgs" , /* 0 */
"constants" , /* 1 */
"debug" , /* 2 */
"derivsteps" , /* 3 */
"dfp" , /* 4 */
"end" , /* 5 */
"epsilons" , /* 6 */
"exmin" , /* 7 */
"funname" , /* 8 */
"iterlim" , /* 9 */
"itermin" , /* 10 */
"limitflags" , /* 11 */
"lowerlimits" , /* 12 */
"newdata" , /* 13 */
"next" , /* 14 */
"pstart" , /* 15 */
"reset" , /* 16 */
"sd" , /* 17 */
"upperlimits" /* 18 */
} ;
/*
* note above order; keywords are tested below in same order...
* remember this when adding keywords!
*/
int i , j , ncmd , ncom , bad ;
#ifdef C80
int chan ;
#else
FILE *chan ;
FILE *fopen() ;
char *fgets() ;
#endif
/*
* loop until a "next" or "end" command is picked up
*/
ncmd = ncom = bad = 0 ;
for (;;)
{
#ifdef C80
if ( ! getline( instring , LEN ) )
return( ALLDONE ) ;
printf("%s\n", instring) ;
/*
* C-80 library routine getline returns the line stored into
* "instring" with the null at the end, but with the '\n'
* stripped off.
*/
#else
if (fgets( instring , LEN , stdin ) == NULL)
return(ALLDONE);
printf("%s", instring) ;
#endif
restofline = instring ;
getnext( &restofline , &firstword ) ;
for ( j=0 ; j<MAXKEY ; ++j )
if ( ! strcmp( firstword , key[j] ) )
break ;
switch (j)
{
/* bfgs */
case 0:
++ncmd ;
DEBUGON printf("bfgs update requested\n") ;
*method = BFGS ;
break ;
/* constants */
case 1:
++ncmd ;
DEBUGON printf("%d constants in %s:\n", nconst ,
funname );
for (i=0 ; i < nconst ; ++i)
{
getnext( &restofline , &firstword ) ;
if( check( firstword ) )
{
++bad;
break;
}
const[i] = (double) atof( firstword ) ;
DEBUGON printf("%e ", const[i]);
}
DEBUGON LF;
break ;
/* debug */
case 2:
++ncmd ;
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
*debug = atoi( firstword ) ;
DEBUGON printf("debug level is %d\n", *debug);
break ;
/* derivsteps */
case 3:
++ncmd ;
DEBUGON printf("derivsteps are:\n");
for (i=0 ; i < *nparam ; ++i)
{
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
dstep[i] = (double) atof( firstword ) ;
DEBUGON printf("%e ", dstep[i]);
}
DEBUGON LF;
break ;
/* dfp */
case 4:
++ncmd ;
DEBUGON printf("dfp update requested\n") ;
*method = DFP ;
break ;
/* end */
case 5:
DEBUGON printf("end of all data\n") ;
return( ALLDONE ) ;
/* epsilons */
case 6:
++ncmd ;
DEBUGON printf("%d epsilons for cutoffs:\n",
NEPS );
for (i=0 ; i < NEPS ; ++i)
{
getnext( &restofline , &firstword ) ;
if( check( firstword ) )
{
++bad;
break;
}
epsilon[i] = (double) atof( firstword );
DEBUGON printf("%e ", epsilon[i]);
}
DEBUGON LF;
break ;
/* exmin */
case 7:
++ncmd ;
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
*g0 = (double) atof( firstword ) ;
DEBUGON printf("expected minimum is %11.4e\n", *g0);
break ;
/* funname */
case 8:
++ncmd ;
getnext( &restofline , &firstword ) ;
if( check( firstword ) )
{
++bad;
break;
}
strcpy( funname , firstword ) ;
DEBUGON printf("function to minimize is %s\n",
funname ) ;
if ( funlib( funname, fun, nparam, &nconst, pname))
{
DEBUGON printf("function not in library!\n") ;
++bad ;
}
break ;
/* iterlim */
case 9:
++ncmd ;
getnext( &restofline , &firstword ) ;
if( check( firstword ))
{
++bad;
break;
}
*iterlim = atoi( firstword ) ;
DEBUGON printf("iterlim is %d\n", *iterlim);
break ;
/* itermin */
case 10:
++ncmd ;
getnext( &restofline , &firstword ) ;
if( check( firstword ) )
{
++bad;
break;
}
*itermin = atoi( firstword ) ;
DEBUGON printf("itermin is %d\n", *itermin);
break ;
/* limitflags */
case 11:
++ncmd ;
DEBUGON printf("limitflags are:\n") ;
for (i=0 ; i < *nparam ; ++i)
{
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
limit[i].fl = atoi( firstword ) ;
DEBUGON printf("%d ", limit[i].fl);
}
DEBUGON LF;
break ;
/* lowerlimits */
case 12:
++ncmd ;
DEBUGON printf("lowerlimits are:\n") ;
for (i=0 ; i < *nparam ; ++i)
{
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
limit[i].lo = (double) atof( firstword ) ;
DEBUGON printf("%e ", limit[i].lo);
}
DEBUGON LF;
break ;
/* newdata */
case 13:
++ncmd ;
getnext( &restofline , &firstword ) ;
DEBUGON printf("datafile requested was %s\n" ,
firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
chan = fopen( firstword , "r");
if ( !chan )
{
printf("datafile can't be opened!\n") ;
return( ALLDONE ) ;
}
fscanf( chan , "%d" , npoints ) ;
DEBUGON printf("%d datapoints in file\n", *npoints);
if (*npoints > npmax)
{
++bad ;
printf("more data than allowed!\n") ;
printf("%d datapoints in file\n", *npoints);
printf("%d points allowed for\n", npmax ) ;
break ;
}
for (i=0 ; i<*npoints ; ++i)
{
#ifdef C80
fscanf(chan, "%f %f", &data[i].x, &data[i].y);
#else
fscanf(chan,"%lf %lf",&data[i].x, &data[i].y);
#endif
DEBUGON printf("%3d %f %f\n" , i+1 ,
data[i].x , data[i].y ) ;
}
fclose( chan ) ;
break ;
/* next */
case 14:
++ncmd ;
DEBUGON printf("end of this data set\n");
printf("%2d command lines read\n", ncmd) ;
printf("%2d comment lines read\n", ncom) ;
if( ! *nparam )
++bad ;
return( bad ) ;
/* pstart */
case 15:
++ncmd ;
DEBUGON printf("starting values are:\n" ) ;
for (i=0 ; i < *nparam ; ++i)
{
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
param[i] = (double) atof( firstword ) ;
DEBUGON printf("%e ", param[i]);
}
DEBUGON LF;
break ;
/* reset */
case 16:
++ncmd ;
getnext( &restofline , &firstword ) ;
if( check( firstword ) )
{
++bad;
break;
}
*nreset = atoi( firstword ) ;
DEBUGON printf("reset is %d\n", *nreset);
break ;
/* sd */
case 17:
++ncmd ;
DEBUGON printf("steepest descent update requested\n") ;
*method = STDES ;
break ;
/* upperlimits */
case 18:
++ncmd ;
DEBUGON printf("upperlimits are:\n");
for (i=0 ; i < *nparam ; ++i)
{
getnext( &restofline , &firstword ) ;
if ( check( firstword ) )
{
++bad;
break;
}
limit[i].up = (double) atof( firstword ) ;
DEBUGON printf("%e ", limit[i].up);
}
DEBUGON LF;
break ;
/*
* anything else is a comment; throw away and go
* to next line.
*/
default:
++ncom ;
DEBUGON printf("***%s*** taken as comment\n",
firstword ) ;
}
}
}
/*************************************************************************/
getnext( string , next )
char **string ;
char **next ;
{
/*
* splits the input string "string" into two pieces:
* "next" contains the first word with no leading or trailing blanks
* "string" then contains the rest of the line
*/
int length ;
char *p ;
length = strlen( p = *string ) ;
while( length-- > 0 && isspace( *p++ ) )
;
*next = --p ;
while( length-- >= 0 && !isspace( *++p ) )
;
*p = '\0' ;
*string = ++p ;
}
/*************************************************************************/
check( string )
char *string ;
{
/*
* checks if a string starts with a blank
* if the string was obtained with getnext, this means the string
* is blank unconditionally report this error
*/
if ( ! *string )
{
printf("Unexpected blank encountered!\n") ;
return( 1 ) ;
}
else
return( 0 ) ;
}
LISTING EIGHT
Test input for the VMM program
File name is "a1.dat"
Sample input using the Cohen function
Demonstrates using the limit flags and detail debug printout
funname cohen
pstart 1.0 1.0
limitflags 1 1
lowerlimits 0.5 0.75
upperlimits 2.0 3.0
iterlim 10
debug 2
next
This case tests a function which uses "experimental" data
Note the non-default epsilons for this case
funname sine
pstart 1.57 -0.65 0.08 -0.005
epsilons 1.0e-14 1.0e-6
newdata b:sine.dat
iterlim 12
reset 8
debug 1
next
The following cases use the Rosenbrock function
These correspond to the benchmarks...
Case 1
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 100. 100. 100. 100. 100.
sd
next
Case 2
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 10. 10. 10. 10. 10.
sd
next
Case 3
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 1. 1. 1. 1. 1.
sd
next
Case 4
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 100. 100. 100. 100. 100.
sd
next
Case 5
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 10. 10. 10. 10. 10.
sd
next
Case 6
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 1. 1. 1. 1. 1.
sd
next
Case 7
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 100. 100. 100. 100. 100.
dfp
reset 5
next
Case 8
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 10. 10. 10. 10. 10.
dfp
reset 5
next
Case 9
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 1. 1. 1. 1. 1.
dfp
reset 5
next
Case 10
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 100. 100. 100. 100. 100.
dfp
reset 5
next
Case 11
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 10. 10. 10. 10. 10.
dfp
reset 5
next
Case 12
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 1. 1. 1. 1. 1.
dfp
reset 5
next
Case 13
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 100. 100. 100. 100. 100.
bfgs
reset 5
next
Case 14
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 10. 10. 10. 10. 10.
bfgs
reset 5
next
Case 15
funname rosen
pstart -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0 -1.2 1.0
constants 1. 1. 1. 1. 1.
bfgs
reset 5
next
Case 16
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 100. 100. 100. 100. 100.
bfgs
reset 5
next
Case 17
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 10. 10. 10. 10. 10.
bfgs
reset 5
next
Case 18
funname rosen
pstart 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8 1.2 0.8
constants 1. 1. 1. 1. 1.
bfgs
reset 5
next
end
/* LISTING NINE
* The way it is done in vmm
* This works and will be portable
* so long as addresses are the
* same size as ints.
* Fine on 16 bit systems with "small
* model" e.g. 64K programs
*/
#define double float
#include "fprintf.h"
#include "scanf.h"
/*---------------------------------*/
main()
{
double *(*fun)() ;
double a , b ;
while(1) {
readit( &fun , &a , &b ) ;
doit( fun , a , b ) ;
}
}
/*----------------------------------*/
readit( fun , a , b )
int *fun ;
double *a ;
double *b ;
{
char string[10] ;
scanf("%s %f %f", string , a , b ) ;
funlib( fun , string ) ;
}
/*------------------------------------*/
funlib( fun , string )
int *fun ;
char string[] ;
{
double sum() ;
double mul() ;
if ( !strcmp( string, "add" ) ) *fun = sum ;
else if ( !strcmp( string, "mul" ) ) *fun = mul ;
else exit(0);
}
/*---------------------------------------*/
doit( fun , a , b )
double (*fun)() ;
double a ;
double b ;
{
double g ;
g = (*fun)( a , b ) ;
printf("%f is the result\n" , g ) ;
}
/*----------------------------------------*/
double sum( a , b )
double a ;
double b ;
{
printf("%f + %f = %f\n" , a , b , a+b ) ;
return( a + b ) ;
}
/*----------------------------------------*/
double mul( a , b )
double a ;
double b ;
{
printf("%f * %f = %f\n" , a , b , a*b ) ;
return( a * b ) ;
}
/* LISTING TEN
* The correct and most portable way to pass an object which is a
* pointer to a function
*/
#include <stdio.h>
/*---------------------------------*/
main()
{
double (*fun)() ; /* fun is a pointer to a function
* which returns a double
*/
double (*readit())() ; /* readit is a function that
* returns a pointer to a function
* that returns a double
*/
double a , b ;
while(1) {
fun = readit( &a , &b ) ;
doit( fun , a , b ) ;
}
}
/*----------------------------------*/
double (*readit( a , b ))() /* note position of arguments */
double *a ;
double *b ;
{
double (*fun)() ;
double (*funlib())() ; /* funlib is a function which
* returns a pointer to a function
* which returns a double
*/
char string[10] ;
scanf("%s %lf %lf", string , a , b ) ;
fun = funlib( string ) ;
return( fun ) ;
}
/*------------------------------------*/
double (*funlib( string ))() /* note position of arguments */
char string[] ;
{
double (*fun)() ;
double sum() ;
double mul() ;
if ( !strcmp( string, "add" ) )
fun = sum ;
else if ( !strcmp( string, "mul" ) )
fun = mul ;
else
exit(0);
return( fun ) ;
}
/*---------------------------------------*/
doit( fun , a , b )
double (*fun)() ;
double a ;
double b ;
{
double g ;
g = (*fun)( a , b ) ;
printf("%f is the result\n" , g ) ;
}
/*----------------------------------------*/
double sum( a , b )
double a ;
double b ;
{
printf("%f + %f = %f\n" , a , b , a+b ) ;
return( a + b ) ;
}
/*----------------------------------------*/
double mul( a , b )
double a ;
double b ;
{
printf("%f * %f = %f\n" , a , b , a*b ) ;
return( a * b ) ;
}
*END OF LISTINGS