private static double Dbrent(CGMinimizer.OneDimDiffFunction function, double ax, double bx, double cx) { // constants bool dbVerbose = false; int Itmax = 100; double Tol = 1.0e-4; double d = 0.0; double e = 0.0; double a = (ax < cx ? ax : cx); double b = (ax > cx ? ax : cx); double x = bx; double v = bx; double w = bx; double fx = function.ValueAt(x); double fv = fx; double fw = fx; double dx = function.DerivativeAt(x); double dv = dx; double dw = dx; for (int iteration = 0; iteration < Itmax; iteration++) { //log.info("dbrent "+iteration+" x "+x+" fx "+fx); double xm = 0.5 * (a + b); double tol1 = Tol * Fabs(x); double tol2 = 2.0 * tol1; if (Fabs(x - xm) <= (tol2 - 0.5 * (b - a))) { return(x); } double u; if (Fabs(e) > tol1) { double d1 = 2.0 * (b - a); double d2 = d1; if (dw != dx) { d1 = (w - x) * dx / (dx - dw); } if (dv != dx) { d2 = (v - x) * dx / (dx - dv); } double u1 = x + d1; double u2 = x + d2; bool ok1 = ((a - u1) * (u1 - b) > 0.0 && dx * d1 <= 0.0); bool ok2 = ((a - u2) * (u2 - b) > 0.0 && dx * d2 <= 0.0); double olde = e; e = d; if (ok1 || ok2) { if (ok1 && ok2) { d = (Fabs(d1) < Fabs(d2) ? d1 : d2); } else { if (ok1) { d = d1; } else { d = d2; } } if (Fabs(d) <= Fabs(0.5 * olde)) { u = x + d; if (u - a < tol2 || b - u < tol2) { d = Sign(tol1, xm - x); } } else { e = (dx >= 0.0 ? a - x : b - x); d = 0.5 * e; } } else { e = (dx >= 0.0 ? a - x : b - x); d = 0.5 * e; } } else { e = (dx >= 0.0 ? a - x : b - x); d = 0.5 * e; } double fu; if (Fabs(d) >= tol1) { u = x + d; fu = function.ValueAt(u); } else { u = x + Sign(tol1, d); fu = function.ValueAt(u); if (fu > fx) { return(x); } } double du = function.DerivativeAt(u); if (fu <= fx) { if (u >= x) { a = x; } else { b = x; } v = w; fv = fw; dv = dw; w = x; fw = fx; dw = dx; x = u; fx = fu; dx = du; } else { if (u < x) { a = u; } else { b = u; } if (fu <= fw || w == x) { v = w; fv = fw; dv = dw; w = u; fw = fu; dw = du; } else { if (fu < fv || v == x || v == w) { v = u; fv = fu; dv = du; } } } } // dan's addition: if (fx < function.ValueAt(0.0)) { return(x); } return(0.0); }
// end class OneDimDiffFunction // constants private static CGMinimizer.Triple Mnbrak(CGMinimizer.Triple abc, CGMinimizer.OneDimDiffFunction function) { // inputs double ax = abc.a; double fa = function.ValueAt(ax); double bx = abc.b; double fb = function.ValueAt(bx); if (fb > fa) { // swap double temp = fa; fa = fb; fb = temp; temp = ax; ax = bx; bx = temp; } // guess cx double cx = bx + Gold * (bx - ax); double fc = function.ValueAt(cx); // loop until we get a bracket while (fb > fc) { double r = (bx - ax) * (fb - fc); double q = (bx - cx) * (fb - fa); double u = bx - ((bx - cx) * q - (bx - ax) * r) / (2.0 * Sign(Fmax(Fabs(q - r), Tiny), q - r)); double fu; double ulim = bx + Glimit * (cx - bx); if ((bx - u) * (u - cx) > 0.0) { fu = function.ValueAt(u); if (fu < fc) { //Ax = new Double(bx); //Bx = new Double(u); //Cx = new Double(cx); //log.info("\nReturning3: a="+bx+" ("+fb+") b="+u+"("+fu+") c="+cx+" ("+fc+")"); return(new CGMinimizer.Triple(bx, u, cx)); } else { if (fu > fb) { //Cx = new Double(u); //Ax = new Double(ax); //Bx = new Double(bx); //log.info("\nReturning2: a="+ax+" ("+fa+") b="+bx+"("+fb+") c="+u+" ("+fu+")"); return(new CGMinimizer.Triple(ax, bx, u)); } } u = cx + Gold * (cx - bx); fu = function.ValueAt(u); } else { if ((cx - u) * (u - ulim) > 0.0) { fu = function.ValueAt(u); if (fu < fc) { bx = cx; cx = u; u = cx + Gold * (cx - bx); fb = fc; fc = fu; fu = function.ValueAt(u); } } else { if ((u - ulim) * (ulim - cx) >= 0.0) { u = ulim; fu = function.ValueAt(u); } else { u = cx + Gold * (cx - bx); fu = function.ValueAt(u); } } } ax = bx; bx = cx; cx = u; fa = fb; fb = fc; fc = fu; } //log.info("\nReturning: a="+ax+" ("+fa+") b="+bx+"("+fb+") c="+cx+" ("+fc+")"); return(new CGMinimizer.Triple(ax, bx, cx)); }