/* optmn.c optimize n parameters to achieve a minimum of a function */ /* the double precision function y = f(double x[]) */ /* srchn does a coarse global search to find initial values */ #include "optmn.h" #include #include void optmn(int n, /* number of parameters */ double x[], /* initial and returned optimum */ double *y, /* returned value of function */ double yfinal, /* stop when y < yfinal */ int maxcnt, /* maximum number of steps */ double tol, /* relative tolerance on step */ double step[], /* start and returned step size */ double xmin[], /* minimum value for each x */ double xmax[], /* maximum value for each x */ double (*f)(double x[]) ) /* function to be evaluated */ { double dx[100], xl[100], xh[100], xb[100], xp[100]; double dxv[100], dv; double v1, vxl, vxh; /* initial, -dx, +dx value of y */ double vb, vp; /* best, pivot value of y */ int best, i, j, k, mstep, noimp; int debug = 0; int cnt = 0; v1 =f(x); /* initial evaluation */ noimp = 1; /* check for no improvement */ while(1) /* coming in with cnt==0 gets return each iteration */ { /* v1 and x are available */ vb = v1; /* best value of y */ for(i=0; ixmax[i]) x[i] = xmax[i]; vxh=f(x); if(vxh v1 && vxh < v1) || (vxh < v1 && vxh < vxl)) { dxv[i] = +dx[i]; noimp = 0; } else if((vxl < v1 && vxh > v1) || (vxl < v1 && vxl < vxh)) { dxv[i] = -dx[i]; noimp = 0; } else step[i] = step[i]*0.7071; } /* have each delta */ if(debug) { printf("cnt=%d, v1=%g, vb=%g \n", cnt, v1, vb); for(j=0; j maxcnt) goto done; if(noimp) continue; /* step size reduced, end while */ dv = 0.0; for(i=0; ixmax[i]) xl[i] = xmax[i]; xh[i] = x[i] + dxv[i]; if(xh[i]>xmax[i]) xh[i] = xmax[i]; if(xh[i] v1 && vxh < v1) || (vxh < v1 && vxh < vxl)) { noimp = 0; v1 = vxh; vb = vxh; /* best value of y */ for(j=0; j v1) || (vxl < v1 && vxl < vxh)) { noimp = 0; v1 = vxl; vb = vxl; /* best value of y */ for(j=0; jmaxcnt) goto done; } /* loop on expand/contract search along preferred direction */ /* end this iteration, test for finish */ v1 = vb; for(i=0; i maxcnt) break; } /* end while */ done: *y = v1; } /* end optmn */ void srchn(int n, /* number of parameters */ double x[], /* returned best found */ double *y, /* returned value of function */ int maxcnt, /* maximum steps each dimension */ double xmin[], /* minimum value for each x */ double xmax[], /* maximum value for each x */ double (*f)(double x[]) ) /* function to be evaluated */ { double dx[100]; /* step size for each parameter */ double step[100]; /* stem number for each parameter */ double xbest[100]; /* best values of x */ double ybest; /* best value of y */ int i, j, k, mymax; int debug = 0; double yy; /* check input */ if(maxcnt<3) maxcnt=3; /* two ends and middle of each parameter */ if(n>6 && maxcnt>3) maxcnt=3; if(n==6 && maxcnt>4) maxcnt=4; if(n==5 && maxcnt>10) maxcnt=10; if(n==4 && maxcnt>20) maxcnt=20; if(n==3 && maxcnt>200) maxcnt=200; mymax = 1; for(i=0; i