/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * This file is distributed subject to a Software License Agreement found * in the file LICENSE that is included with this distribution. \*************************************************************************/ /* $Log: onedoptimize.c,v $ Revision 1.7 2009/05/11 04:22:04 borland Fixed problems with one-dimensional parabolic optimization, so that it is now "guaranteed" to quit eventually. Revision 1.6 2004/04/07 02:01:10 borland OneDParabolicOptimization now keeps track of the best point and is guaranteed to return it. Revision 1.5 2004/01/24 18:18:07 borland Changed the meaning of the nEvalMax option, which was not actually used. It is now used as the maximum number of steps to take in one direction when the value is found to improve. Revision 1.4 2003/08/28 19:56:28 soliday Cleaned up some of the code. Revision 1.3 2002/08/14 16:18:59 soliday Added Open License Revision 1.2 2002/02/26 03:12:22 borland Added OneDParabolicOptimization, which used to reside in sddsnaff.c Revision 1.1 2001/07/23 16:38:47 borland New procedure by H. Shang. */ #include "mdb.h" #define DEFAULT_MAXEVALS 100 #define DEFAULT_MAXPASSES 5 long checkVariableLimits(double *x, double *xlo, double *xhi, long n); long OneDScanOptimize ( double *yReturn, double *xGuess, double *dxGuess, double *xLowerLimit, double *xUpperLimit, short *disable, long dimensions, double target, /* will return if any value is <= this */ double tolerance, /* <0 means fractional, >0 means absolute */ double (*func)(double *x, long *invalid), void (*report)(double ymin, double *xmin, long pass, long evals, long dims), long maxSteps, /* number of steps to try in good direction */ long maxDivisions, long maxRepeats, unsigned long flags) { static double *dxLocal = NULL; static long lastDimensions = 0; double yLast, dVector = 1, yNew,xLocal; long point, totalEvaluations = 0, isInvalid, repeats=0,divisions; long activeDimensions, direction, found=0, stepsTaken, decreaseSeen; double *divisor, *minimum, min; min=1e9; if (dimensions<=0) return(-3); if (disable) { activeDimensions = 0; for (direction=0; directionlastDimensions) { if (dxLocal) free(dxLocal); dxLocal = tmalloc(sizeof(*dxLocal)*activeDimensions); lastDimensions = activeDimensions; } divisor=(double*)malloc(sizeof(*divisor)*activeDimensions); minimum=(double*)malloc(sizeof(*minimum)*activeDimensions); for (point=0;point=xGuess[direction]) dxGuess[direction] = fabs(dxGuess[direction]); } if (xUpperLimit) { /* if start is at upper limit, make sure initial step is negative */ for (direction=0; directionxUpper || x1xUpper || x2f1) break; if (x1==x2) break; x0 = x1; f0 = f1; x1 = x2; f1 = f2; } if (x0>x2) { /* arrange in increasing order */ SWAP_DOUBLE(x0, x2); SWAP_DOUBLE(f0, f2); } /* now f0 > f1 and f2 > f1 */ for (cycle=0; cycle1e-6*scale && fabs(x3-x1)>1e-6*scale && fabs(x3-x2)>1e-6*scale) { /* evaluate at parabolic interpolation point */ failed = 0; f3 = maxFactor*(*func)(x3, &invalid); if (invalid) failed = 1; else { if (f3f0 && f3x1) { SWAP_DOUBLE(x0, x1); SWAP_DOUBLE(f0, f1); } } else failed = 1; } } #ifdef DEBUG if (!failed) fprintf(stderr, "Parabolic interpolation succeeded\n"); #endif if (failed) { long right, other; for (other=0; other<2; other++) { /* try dividing one of the intervals */ if (fabs(x0-x1)x1) { SWAP_DOUBLE(x0, x1); SWAP_DOUBLE(f0, f1); } break; } } #ifdef DEBUG fprintf(stderr, "Sectioning succeeded\n"); #endif } } #ifdef DEBUG fprintf(stderr, "Returning: x=%21.15e, y=%21.15e\n", xBest, maxFactor*fBest); #endif *yReturn = maxFactor*fBest; *xGuess = xBest; return 1; }