Accord.Math.Optimization.BoundedBroydenFletcherGoldfarbShanno.dcstep C# (CSharp) Method

dcstep() static private method

static private dcstep ( double &stx, double &fx, double &dx, double &sty, double &fy, double &dy, double &stp, double fp, double dp, bool &brackt, double stpmin, double stpmax ) : void
stx double
fx double
dx double
sty double
fy double
dy double
stp double
fp double
dp double
brackt bool
stpmin double
stpmax double
return void
        internal static void dcstep(ref double stx, ref double fx, ref double dx,
            ref double sty, ref double fy, ref double dy, ref double stp,
            double fp, double dp, ref bool brackt, double stpmin, double stpmax)
        {

            double gamma = 0.0d;
            double p = 0.0d;
            double q = 0.0d;
            double r = 0.0d;
            double s = 0.0d;
            double sgnd = 0.0d;
            double stpc = 0.0d;
            double stpf = 0.0d;
            double stpq = 0.0d;
            double theta = 0.0d;
            sgnd = (dp * ((dx / System.Math.Abs(dx))));

            // 
            // c     First case: A higher function value. The minimum is bracketed. 
            // c     If the cubic step is closer to stx than the quadratic step, the 
            // c     cubic step is taken, otherwise the average of the cubic and 
            // c     quadratic steps is taken.
            // 

            if ((fp > fx))
            {
                theta = ((((3.0 * ((fx - fp))) / ((stp - stx))) + dx) + dp);

                s = Accord.Math.Tools.Max(System.Math.Abs(theta), System.Math.Abs(dx), System.Math.Abs(dp));

                gamma = (s * System.Math.Sqrt(((System.Math.Pow(((theta / s)), 2)) - (((dx / s)) * ((dp / s))))));
                if ((stp < stx))
                {
                    gamma = (-(gamma));
                }
                p = (((gamma - dx)) + theta);
                q = (((((gamma - dx)) + gamma)) + dp);
                r = (p / q);
                stpc = (stx + (r * ((stp - stx))));
                stpq = (stx + (((((dx / (((((fx - fp)) / ((stp - stx))) + dx)))) / 2.0)) * ((stp - stx))));

                if ((System.Math.Abs((stpc - stx)) < System.Math.Abs((stpq - stx))))
                {
                    stpf = stpc;
                }
                else
                {
                    stpf = (stpc + (((stpq - stpc)) / 2.0));
                }

                brackt = true;

                // 
                // c     Second case: A lower function value and derivatives of opposite 
                // c     sign. The minimum is bracketed. If the cubic step is farther from 
                // c     stp than the secant step, the cubic step is taken, otherwise the 

                // c     secant step is taken.
                // 
            }
            else if ((sgnd < 0.0))
            {
                theta = ((((3.0 * ((fx - fp))) / ((stp - stx))) + dx) + dp);
                s = Accord.Math.Tools.Max(System.Math.Abs(theta), System.Math.Abs(dx), System.Math.Abs(dp));
                gamma = (s * System.Math.Sqrt(((System.Math.Pow(((theta / s)), 2)) - (((dx / s)) * ((dp / s))))));

                if ((stp > stx))
                {
                    gamma = (-(gamma));
                }

                p = (((gamma - dp)) + theta);
                q = (((((gamma - dp)) + gamma)) + dx);
                r = (p / q);
                stpc = (stp + (r * ((stx - stp))));
                stpq = (stp + (((dp / ((dp - dx)))) * ((stx - stp))));

                if ((System.Math.Abs((stpc - stp)) > System.Math.Abs((stpq - stp))))
                {
                    stpf = stpc;
                }
                else
                {
                    stpf = stpq;
                }

                brackt = true;
                // 
                // c     Third case: A lower function value, derivatives of the same sign,

                // c     and the magnitude of the derivative decreases.
                // 
            }
            else if ((System.Math.Abs(dp) < System.Math.Abs(dx)))
            {
                // 
                // c        The cubic step is computed only if the cubic tends to infinity 
                // c        in the direction of the step or if the minimum of the cubic
                // c        is beyond stp. Otherwise the cubic step is defined to be the 
                // c        secant step.
                // 
                theta = ((((3.0 * ((fx - fp))) / ((stp - stx))) + dx) + dp);
                s = Accord.Math.Tools.Max(System.Math.Abs(theta), System.Math.Abs(dx), System.Math.Abs(dp));

                // 
                // c        The case gamma = 0 only arises if the cubic does not tend
                // c        to infinity in the direction of the step.
                // 
                gamma = (s * System.Math.Sqrt(System.Math.Max(0.0,
                    ((System.Math.Pow(((theta / s)), 2)) - (((dx / s)) * ((dp / s)))))));

                if ((stp > stx))
                {
                    gamma = (-(gamma));
                }

                p = (((gamma - dp)) + theta);
                q = (((gamma + ((dx - dp)))) + gamma);
                r = (p / q);

                if (((r < 0.0) && (gamma != 0.0)))
                {
                    stpc = (stp + (r * ((stx - stp))));
                }
                else if ((stp > stx))
                {
                    stpc = stpmax;
                }
                else
                {
                    stpc = stpmin;
                }

                stpq = (stp + (((dp / ((dp - dx)))) * ((stx - stp))));

                if (brackt)
                {
                    // 
                    // c           A minimizer has been bracketed. If the cubic step is 
                    // c           closer to stp than the secant step, the cubic step is 
                    // c           taken, otherwise the secant step is taken.
                    // 
                    if ((System.Math.Abs((stpc - stp)) < System.Math.Abs((stpq - stp))))
                    {
                        stpf = stpc;
                    }
                    else
                    {
                        stpf = stpq;
                    }
                    if ((stp > stx))
                    {
                        stpf = System.Math.Min((stp +
                            (0.6600000000000000310862446895043831318617 * ((sty - stp)))), stpf);
                    }
                    else
                    {
                        stpf = System.Math.Max((stp +
                            (0.6600000000000000310862446895043831318617 * ((sty - stp)))), stpf);
                    }
                }
                else
                {
                    // 
                    // c           A minimizer has not been bracketed. If the cubic step is 
                    // c           farther from stp than the secant step, the cubic step is 
                    // c           taken, otherwise the secant step is taken.
                    // 
                    if ((System.Math.Abs((stpc - stp)) > System.Math.Abs((stpq - stp))))
                    {
                        stpf = stpc;
                    }
                    else
                    {
                        stpf = stpq;
                    }
                    stpf = System.Math.Min(stpmax, stpf);
                    stpf = System.Math.Max(stpmin, stpf);
                }

                // 
                // c     Fourth case: A lower function value, derivatives of the same sign,
                // c     and the magnitude of the derivative does not decrease. If the 
                // c     minimum is not bracketed, the step is either stpmin or stpmax, 
                // c     otherwise the cubic step is taken.
                // 
            }
            else
            {
                if (brackt)
                {
                    theta = ((((3.0 * ((fp - fy))) / ((sty - stp))) + dy) + dp);
                    s = Accord.Math.Tools.Max(System.Math.Abs(theta), System.Math.Abs(dy), System.Math.Abs(dp));
                    gamma = (s * System.Math.Sqrt(((System.Math.Pow(((theta / s)), 2)) - (((dy / s)) * ((dp / s))))));

                    if ((stp > sty))
                    {
                        gamma = (-(gamma));
                    }

                    p = (((gamma - dp)) + theta);
                    q = (((((gamma - dp)) + gamma)) + dy);
                    r = (p / q);
                    stpc = (stp + (r * ((sty - stp))));
                    stpf = stpc;
                }
                else if ((stp > stx))
                {
                    stpf = stpmax;
                }
                else
                {
                    stpf = stpmin;
                }
            }

            // 
            // c     Update the interval which contains a minimizer.
            // 
            if ((fp > fx))
            {
                sty = stp;
                fy = fp;
                dy = dp;
            }
            else
            {
                if ((sgnd < 0.0))
                {
                    sty = stx;
                    fy = fx;
                    dy = dx;
                }
                stx = stp;
                fx = fp;
                dx = dp;
            }

            // 
            // c     Compute the new step.
            // 
            stp = stpf;
        }

Usage Example

Example #1
0
        private unsafe ConjugateGradientCode cvsmod(ref double f, double[] s, ref double stp, ref int info,
                                                    ref int nfev, double[] wa, ref double dginit, ref double dgout)
        {
            int n = NumberOfVariables;

            double[] x = Solution;

            if (info == 1)
            {
                goto L321;
            }

            infoc = 1;

            if (stp <= 0) // Check the input parameters for errors
            {
                return(ConjugateGradientCode.StepSize);
            }

            // Compute the initial gradient in the search direction
            // and check that S is a descent direction.

            if (dginit >= 0)
            {
                throw new LineSearchFailedException(0, "The search direction is not a descent direction.");
            }

            // Initialize local variables
            brackt = false;
            stage1 = true;
            nfev   = 0;
            finit  = f;
            dgtest = ftol * dginit;
            width  = stpmax - stpmin;
            width1 = width / 0.5;

            for (int j = 0; j < x.Length; ++j)
            {
                wa[j] = x[j];
            }

            // The variables STX, FX, DGX contain the values of the step,
            //   function, and directional derivative at the best step.
            // The variables STY, FY, DGY contain the value of the step,
            //   function, and derivative at the other endpoint of the interval
            //   of uncertainty.
            // The variables STP, F, DG contain the values of the step,
            //   function, and derivative at the current step.

            stx = 0;
            fx  = finit;
            dgx = dginit;
            sty = 0;
            fy  = finit;
            dgy = dginit;


L30:        // Start of iteration.

            // Set the minimum and maximum steps to correspond
            // to the present interval of uncertainty.

            if (brackt)
            {
                stmin = Math.Min(stx, sty);
                stmax = Math.Max(stx, sty);
            }
            else
            {
                stmin = stx;
                stmax = stp + 4 * (stp - stx);
            }

            // Force the step to be within
            // the bounds STPMAX and STPMIN.

            stp = Math.Max(stp, stpmin);
            stp = Math.Min(stp, stpmax);

            // If an unusual termination is to occur then
            // let STP be the lowest point obtained so far.

            if (brackt && (stp <= stmin || stp >= stmax) || nfev >= maxfev - 1 ||
                infoc == 0 || brackt && stmax - stmin <= xtol * stmax)
            {
                stp = stx;
            }

            // Evaluate the function and gradient at STP
            // and compute the directional derivative.

            for (int j = 0; j < s.Length; ++j)
            {
                x[j] = wa[j] + stp * s[j];
            }

            // Fetch function and gradient
            f = Function(x);
            g = Gradient(x);

            info = 0;
            nfev++;
            dg2 = 0;

            for (int j = 0; j < g.Length; ++j)
            {
                dg2 += g[j] * s[j];
            }

            ftest1 = finit + stp * dgtest;

            if ((brackt && (stp <= stmin || stp >= stmax)) || infoc == 0)
            {
                return(ConjugateGradientCode.RoundingErrors);
            }

            if (stp == stpmax && f <= ftest1 && dg2 <= dgtest)
            {
                return(ConjugateGradientCode.StepHigh);
            }

            if (stp == stpmin && (f > ftest1 || dg2 >= dgtest))
            {
                return(ConjugateGradientCode.StepLow);
            }

            if (nfev >= maxfev)
            {
                return(ConjugateGradientCode.MaximumEvaluations);
            }

            if (brackt && stmax - stmin <= xtol * stmax)
            {
                return(ConjugateGradientCode.Precision);
            }


            // More's code has been modified so that at least one new
            //  function value is computed during the line search (enforcing
            //  at least one interpolation is not easy, since the code may
            //  override an interpolation)

            if (f <= ftest1 && Math.Abs(dg2) <= gtol * (-dginit) && nfev > 1)
            {
                info  = 1;
                dgout = dg2;
                return(ConjugateGradientCode.Success);
            }


L321:

            // In the first stage we seek a step for which the modified
            // function has a nonpositive value and nonnegative derivative.
            if (stage1 && f <= ftest1 && dg2 >= Math.Min(ftol, gtol) * dginit)
            {
                stage1 = false;
            }

            // A modified function is used to predict the step only if
            // we have not obtained a step for which the modified function
            // has a nonpositive function value and nonnegative derivative,
            // and if a lower function value has been obtained but the
            // decrease is not sufficient.

            if (stage1 && f <= fx && f > ftest1)
            {
                // Define the modified function and derivative values
                double fm   = f - stp * dgtest;
                double fxm  = fx - stx * dgtest;
                double fym  = fy - sty * dgtest;
                double dgm  = dg2 - dgtest;
                double dgxm = dgx - dgtest;
                double dgym = dgy - dgtest;

                // Call CSTEPM to update the interval of
                // uncertainty and to compute the new step.

                BoundedBroydenFletcherGoldfarbShanno.dcstep(ref stx, ref fxm, ref dgxm,
                                                            ref sty, ref fym, ref dgym, ref stp, fm, dgm, ref brackt, stpmin, stpmax);

                // Reset the function and gradient values for f.
                fx  = fxm + stx * dgtest;
                fy  = fym + sty * dgtest;
                dgx = dgxm + dgtest;
                dgy = dgym + dgtest;
            }
            else
            {
                // Call CSTEPM to update the interval of
                // uncertainty and to compute the new step.
                BoundedBroydenFletcherGoldfarbShanno.dcstep(ref stx, ref fx, ref dgx,
                                                            ref sty, ref fy, ref dgy, ref stp, f, dg2, ref brackt, stpmin, stpmax);
            }

            // Force a sufficient decrease in the
            // size of the interval of uncertainty.

            if (brackt)
            {
                if ((Math.Abs(sty - stx)) >= 0.66 * width1)
                {
                    stp = stx + 0.5 * (sty - stx);
                }

                width1 = width;
                width  = Math.Abs(sty - stx);
            }

            goto L30;
        }