예제 #1
0
        public static double[] Bracket(Func <double, double> function, double a, double b)
        {
            double xa;
            double xb;
            double xc;
            double fa;
            double fb;
            double fc;

            double GLIMIT = 100.0;
            double TINY   = 1.0e-20;

            xa = a;
            fa = function(xa);

            xb = b;
            fb = function(xb);

            if (fb > fa)
            {
                swap(ref xa, ref xb);
                swap(ref fa, ref fb);
            }

            xc = xb + MathTool.PHI * (xb - xa);
            fc = function(xc);

            double fu;

            while (fb > fc)
            {
                double r    = (xb - xa) * (fb - fc);
                double q    = (xb - xc) * (fb - fa);
                double u    = xb - ((xb - xc) * q - (xb - xa) * r) / (2.0 * MathTool.CopySign(Math.Max(Math.Abs(q - r), TINY), q - r));
                double ulim = xb + GLIMIT * (xc - xb);

                if ((xb - u) * (u - xc) > 0.0)
                {
                    fu = function(u);

                    if (fu < fc)
                    {
                        xa = xb;
                        fa = fb;

                        xb = u;
                        fb = fu;

                        return(new double[] { xa, fa, xb, fb, xc, fc });
                    }

                    if (fu > fb)
                    {
                        xc = u;
                        fc = fu;

                        return(new double[] { xa, fa, xb, fb, xc, fc });
                    }

                    u  = xc + MathTool.PHI * (xc - xb);
                    fu = function(u);
                }
                else
                {
                    if ((xc - u) * (u - ulim) > 0.0)
                    {
                        fu = function(u);

                        if (fu < fc)
                        {
                            shift(ref xb, ref xc, ref u, u + MathTool.PHI * (u - xc));
                            shift(ref fb, ref fc, ref fu, function(u));
                        }
                    }
                    else
                    {
                        if ((u - ulim) * (ulim - xc) >= 0.0)
                        {
                            u  = ulim;
                            fu = function(u);
                        }
                        else
                        {
                            u  = xc + MathTool.PHI * (xc - xb);
                            fu = function(u);
                        }
                    }
                }

                shift(ref xa, ref xb, ref xc, u);
                shift(ref fa, ref fb, ref fc, fu);
            }

            return(new double[] { xa, fa, xb, fb, xc, fc });
        }
예제 #2
0
            public Brent(Func <double, double> function, double xa, double xb, double xc, double tolerance)
            {
                const int    ITMAX = 100;
                const double CGOLD = 0.3819660;
                const double ZEPS  = 0.00001;// Double.Epsilon;// *1.0e-3;

                double a = (xa < xc ? xa : xc);
                double b = (xa > xc ? xa : xc);
                double d = 0.0;
                double e = 0.0;

                double u;
                double fu;

                double v  = xb;
                double fv = function(v);

                double w  = v;
                double fw = fv;

                double x  = v;
                double fx = fv;

                for (int i = 0; i < ITMAX; ++i)
                {
                    double xm   = 0.5 * (a + b);
                    double tol1 = tolerance * Math.Abs(x) + ZEPS;
                    double tol2 = 2.0 * tol1;

                    if (Math.Abs(x - xm) <= (tol2 - 0.5 * (b - a)))
                    {
                        xmin = x;
                        fmin = fx;

                        return;
                    }

                    if (Math.Abs(e) > tol1)
                    {
                        double r = (x - w) * (fx - fv);
                        double q = (x - v) * (fx - fw);
                        double p = (x - v) * q - (x - w) * r;

                        q = 2.0 * (q - r);

                        if (q > 0.0)
                        {
                            p = -p;
                        }

                        q = Math.Abs(q);
                        double etemp = e;
                        e = d;

                        if (Math.Abs(p) >= Math.Abs(0.5 * q * etemp) || p <= q * (a - x) || p >= q * (b - x))
                        {
                            d = CGOLD * (e = (x >= xm ? a - x : b - x));
                        }
                        else
                        {
                            d = p / q;
                            u = x + d;

                            if (u - a < tol2 || b - u < tol2)
                            {
                                d = MathTool.CopySign(tol1, xm - x);
                            }
                        }
                    }
                    else
                    {
                        d = CGOLD * (e = (x >= xm ? a - x : b - x));
                    }

                    u  = (Math.Abs(d) >= tol1 ? x + d : x + MathTool.CopySign(tol1, d));
                    fu = function(u);

                    if (fu <= fx)
                    {
                        if (u >= x)
                        {
                            a = x;
                        }
                        else
                        {
                            b = x;
                        }

                        shift(ref v, ref w, ref x, u);
                        shift(ref fv, ref fw, ref fx, fu);
                    }
                    else
                    {
                        if (u < x)
                        {
                            a = u;
                        }
                        else
                        {
                            b = u;
                        }

                        if (fu <= fw || w == x)
                        {
                            v  = w;
                            w  = u;
                            fv = fw;
                            fw = fu;
                        }
                        else
                        {
                            if (fu <= fv || v == x || v == w)
                            {
                                v  = u;
                                fv = fu;
                            }
                        }
                    }
                }

                //throw("Too many iterations in brent");
                xmin = double.NaN;
                fmin = double.NaN;
            }