/* nonlinear optimization using simplex method developed by Nelder and Mead simplex method minimizes an object function this method requires no derivative information */ #include #include #include #include "opt.h" #define Debug 0 #define Static static #define SKIPTIME 100 /* print interval for debugging */ static int nvar; static dbl (*objective)(); static dbl **simp, *fvalue; static int ih, is, il; static dbl *xcentroid; static dbl fmean, fvar; static dbl *xreflect, *xcontract, *xexpand; static dbl freflect, fcontract, fexpand; static dbl al = 1, bt = 0.5, gm = 2; static void fprint_simplex(FILE *fd) { int i; for (i=0; i<=nvar; i++) { vectorfprint(fd, nvar, simp[i]); } } static void fprint_points(FILE *fd) { fprintf(fd, "----- xh xs and xl -----\n"); vectorfprint(fd, nvar, simp[ih]); vectorfprint(fd, nvar, simp[is]); vectorfprint(fd, nvar, simp[il]); fprintf(fd, "----- xcentroid -----\n"); vectorfprint(fd, nvar, xcentroid); } static void fprint_generated_points(FILE *fd) { fprintf(fd, "----- xreflect xcontract xexpand -----\n"); vectorfprint(fd, nvar, xreflect); vectorfprint(fd, nvar, xcontract); vectorfprint(fd, nvar, xexpand); fprintf(fd, "freflect %lf fcontract %lf fexpand %lf\n", freflect, fcontract, fexpand); } static void initialize() { int i; simp = alloc(dbl *, nvar+1); for (i=0; i<=nvar; i++) { simp[i] = alloc(dbl, nvar); } fvalue = alloc(dbl, nvar+1); xcentroid = alloc(dbl, nvar); xreflect = alloc(dbl, nvar); xcontract = alloc(dbl, nvar); xexpand = alloc(dbl, nvar); } static void initial_simplex(dbl *xinit, dbl length) { int i, j; dbl a, d1, d2, *v; a = nvar + 1; d1 = (sqrt(a) + nvar - 1)/sqrt(2.00)/nvar; d2 = (sqrt(a) - 1)/sqrt(2.00)/nvar; v = simp[0]; for (j=0; j fvalue[1]) { ih = 0; is = il = 1; } else { ih = 1; is = il = 0; } /* fprintf(stderr, "%d %d %d\n", ih, is, il); */ for (i=2; i<=nvar; i++) { if (fvalue[i] > fvalue[ih]) { is = ih; ih = i; } else if (fvalue[i] > fvalue[is]) { is = i; } else if (fvalue[i] < fvalue[il]) { il = i; } /* fprintf(stderr, "%d %d %d\n", ih, is, il); */ } } static void compute_xcentroid() { int i, j; dbl *x; for (j=0; j= fvalue[il]) { vectorcopy(nvar, simp[ih], xreflect); fvalue[ih] = freflect; } else { expansion(); if (fexpand < fvalue[il]) { vectorcopy(nvar, simp[ih], xexpand); fvalue[ih] = fexpand; } else { vectorcopy(nvar, simp[ih], xreflect); fvalue[ih] = freflect; } } } else { if (freflect < fvalue[ih]) { vectorcopy(nvar, simp[ih], xreflect); fvalue[ih] = freflect; } contraction(); if (fcontract < fvalue[ih]) { vectorcopy(nvar, simp[ih], xcontract); fvalue[ih] = fcontract; } else { for (i=0; i<=nvar; i++) { if (i == il) continue; vectoradd(nvar, simp[i], simp[i], simp[il]); scalarvector(nvar, simp[i], 0.50, simp[i]); fvalue[i] = (*objective)(nvar, simp[i]); } } } #if Debug /* fprintf(stderr, "%d : min = %lf\n", count, fvalue[il]); */ #endif } vectorcopy(nvar, xinit, simp[il]); *fopt = fvalue[il]; return stat; }