Пример #1
0
        //public double lastXx = 1.0;
        private double[] LineMinimize(IDiffFunction function, double[] initial, double[] direction)
        {
            // make a 1-dim function along the direction line
            // THIS IS A HACK (but it's the NRiC peoples' hack)
            CGMinimizer.OneDimDiffFunction oneDim = new CGMinimizer.OneDimDiffFunction(function, initial, direction);
            // do a 1-dim line min on this function
            //Double Ax = new Double(0.0);
            //Double Xx = new Double(1.0);
            //Double Bx = new Double(0.0);
            // bracket the extreme pt
            double guess = 0.01;

            //log.info("Current "+oneDim.valueAt(0)+" nudge "+(oneDim.smallestZeroPositiveLocation()*1e-2)+" "+oneDim.valueAt(oneDim.smallestZeroPositiveLocation()*1e-5));
            if (!silent)
            {
                log.Info("[");
            }
            CGMinimizer.Triple bracketing = Mnbrak(new CGMinimizer.Triple(0, guess, 0), oneDim);
            if (!silent)
            {
                log.Info("]");
            }
            double ax = bracketing.a;
            double xx = bracketing.b;
            double bx = bracketing.c;

            //lastXx = xx;
            // CHECK FOR END OF WORLD
            if (!(ax <= xx && xx <= bx) && !(bx <= xx && xx <= ax))
            {
                log.Info("Bad bracket order!");
            }
            //log.info("Bracketing found: "+arrayToString(oneDim.vectorOf(ax),3)+" "+arrayToString(oneDim.vectorOf(xx),3)+" "+arrayToString(oneDim.vectorOf(bx),3));
            // find the extreme pt
            if (!silent)
            {
                log.Info("<");
            }
            double xmin = Dbrent(oneDim, ax, xx, bx);

            if (!silent)
            {
                log.Info(">");
            }
            // return the full vector
            //log.info("Went "+xmin+" during lineMinimize");
            return(oneDim.VectorOf(xmin));
        }
Пример #2
0
        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);
        }
Пример #3
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));
        }