Beispiel #1
0
        /// <summary>
        /// Cubic interpolation routine from Nocedal and Wright
        /// </summary>
        /// <param name="a">first point, with value and derivative</param>
        /// <param name="b">second point, with value and derivative</param>
        /// <returns>local minimum of interpolating cubic polynomial</returns>
        private static Float CubicInterp(StepValueDeriv a, StepValueDeriv b)
        {
            Float t1    = a.Deriv + b.Deriv - 3 * (a.Value - b.Value) / (a.Step - b.Step);
            Float t2    = Math.Sign(b.Step - a.Step) * MathUtils.Sqrt(t1 * t1 - a.Deriv * b.Deriv);
            Float num   = b.Deriv + t2 - t1;
            Float denom = b.Deriv - a.Deriv + 2 * t2;

            return(b.Step - (b.Step - a.Step) * num / denom);
        }
Beispiel #2
0
        private Float FindMinimum(DiffFunc1D func, Float initValue, Float initDeriv)
        {
            Contracts.CheckParam(initDeriv < 0, nameof(initDeriv), "Cannot search in direction of ascent!");

            StepValueDeriv lo = new StepValueDeriv(func, 0, initValue, initDeriv);
            StepValueDeriv hi = new StepValueDeriv(func, _step);

            // bracket minimum
            while (hi.Deriv < 0)
            {
                Swap(ref lo, ref hi);
                if (lo.Step >= MaxStep)
                {
                    return(MaxStep);
                }
                hi.Step = lo.Step * 2;
            }

            Float window = 1;

            StepValueDeriv mid = new StepValueDeriv(func);

            for (int numSteps = 1; ; ++numSteps)
            {
                Float interp = CubicInterp(lo, hi);
                if (window <= MinWindow || numSteps == MaxNumSteps)
                {
                    return(interp);
                }

                // insure minimal progress to narrow interval
                Float minProgressStep = _minProgress * (hi.Step - lo.Step);
                Float maxMid          = hi.Step - minProgressStep;
                if (interp > maxMid)
                {
                    interp = maxMid;
                }
                Float minMid = lo.Step + minProgressStep;
                if (interp < minMid)
                {
                    interp = minMid;
                }

                mid.Step = interp;

                if (mid.Deriv == 0 || mid.Step == lo.Step || mid.Step == hi.Step)
                {
                    return(mid.Step);
                }

                if (mid.Deriv < 0)
                {
                    Swap(ref lo, ref mid);
                }
                else
                {
                    Swap(ref hi, ref mid);
                }

                if (lo.Step >= MaxStep)
                {
                    return(MaxStep);
                }

                window = (hi.Step - lo.Step) / hi.Step;
            }
        }