コード例 #1
0
ファイル: Solver1D.cs プロジェクト: zhangz/Highlander.Net
        /// <summary>
        /// This method returns the zero of the <see cref="IObjectiveFunction"/>
        /// <pramref name="objectiveFunction"/>, determined with the given accuracy.
        /// </summary>
        /// <remarks>
        /// <i>x</i> is considered a zero if <i>|f(x)| &lt; accuracy</i>.
        /// An initial guess must be supplied, as well as two values which
        /// must bracket the zero (i.e., either
        /// <i>f(x<sub>min</sub>) &gt; 0</i> &amp;&amp;
        /// <i>f(x<sub>max</sub>) &lt; 0</i>, or
        /// <i>f(x<sub>min</sub>) &lt; 0</i> &amp;&amp;
        /// <i>f(x<sub>max</sub>) &gt; 0</i> must be true).
        /// </remarks>
        /// <param name="objectiveFunction">The <see cref="IObjectiveFunction"/>.</param>
        /// <param name="xAccuracy">Given accuracy.</param>
        /// <param name="guess">Initial guess used to scan the range
        /// of the possible bracketing values.</param>
        /// <param name="xMin">Lower bracket.</param>
        /// <param name="xMax">Upper bracket.</param>
        /// <returns>The zero of the objective function.</returns>
        /// <exception cref="ApplicationException">
        /// Thrown when a bracket is not found after the maximum
        /// number of evaluations (see <see cref="MaxEvaluations"/>).
        /// </exception>
        public double Solve(IObjectiveFunction objectiveFunction, double xAccuracy,
                            double guess, double xMin, double xMax)
        {
            #region Check that input data is valid

            if (xMin >= xMax)
            {
                throw new ArgumentException($"Solver minimum bracket ({xMin}) must be below maximum bracket ({xMax}).");
            }
            if (LowerBoundEnforced && xMin < LowerBound)
            {
                throw new ArgumentException(
                          $"Solver minimum bracket ({xMin}) is less than lower bound ({LowerBound}).");
            }
            if (UpperBoundEnforced && xMax > _upperBound)
            {
                throw new ArgumentException(
                          $"Solver maximum bracket ({xMax}) is more than upper bound ({_upperBound}).");
            }
            // Check if the guess is within specified range (xMin, xMax)
            //
            if (guess < xMin)
            {
                throw new ApplicationException($"Solver guess ({guess}) is less than minimum bracket ({xMin}).");
            }
            if (guess > xMax)
            {
                throw new ApplicationException($"Solver guess ({guess}) is more than maximum bracket ({xMax}).");
            }

            #endregion

            XMin  = xMin;
            XMax  = xMax;
            FXMin = objectiveFunction.Value(xMin);
            if (Math.Abs(FXMin) < xAccuracy)
            {
                return(xMin);
            }
            FXMax = objectiveFunction.Value(xMax);
            if (Math.Abs(FXMax) < xAccuracy)
            {
                return(xMax);
            }
            EvaluationNumber = 2;
            if (FXMin * FXMax >= 0.0)
            {
                throw new ApplicationException(
                          $"Solver bounds must return different values with different signs; it returned {FXMin} and {FXMax}.");
            }
            Root = guess;
            return(SolveImpl(objectiveFunction, Math.Max(Math.Abs(xAccuracy), Double.Epsilon)));
        }
コード例 #2
0
 /// <summary>
 /// Overloaded constructor
 /// </summary>
 /// <param name="objective">A tour length objectiveulator object</param>
 /// <param name="initialSolution">An initial solution</param>
 /// <param name="swapPattern">A method for swapping the order of cities</param>
 public SteepestDecent(IObjectiveFunction objective, List<int> initialSolution, ICitySwapPattern swapMethod)
 {
     this.objective = objective;
     this.solution = initialSolution;
     this.currentTourLength = objective.Value(initialSolution);
     this.swapPattern = swapMethod;
 }
コード例 #3
0
        /// <summary>
        /// Implementation of the actual code to search for the zeroes of
        /// the <see cref="IObjectiveFunction"/>.
        /// </summary>
        /// <remarks>
        /// It assumes that:
        /// <list type="bullet">
        /// <item>
        ///   <description>
        ///		<see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/> form a valid bracket;
        ///	  </description>
        /// </item>
        /// <item>
        ///   <description>
        ///     <see cref="Solver1D.FXMin"/> and <see cref="Solver1D.FXMax"/> contain the values of the
        ///		function in <see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/>;
        ///	  </description>
        /// </item>
        /// <item>
        ///   <description>
        ///     <see cref="Solver1D.Root"/> was initialized to a valid initial guess.
        ///	  </description>
        /// </item>
        /// </list>
        /// </remarks>
        /// <param name="objectiveFunction">The <see cref="IObjectiveFunction"/>.</param>
        /// <param name="xAccuracy">Given accuracy.</param>
        /// <returns>The zero of the objective function.</returns>
        /// <exception cref="ApplicationException">
        /// Thrown when a bracket is not found after the maximum
        /// number of evaluations (see <see cref="Solver1D.MaxEvaluations"/>).
        /// </exception>
        protected override double SolveImpl(IObjectiveFunction objectiveFunction,
                                            double xAccuracy)
        {
            // Orient the search so that f>0 lies at root_+dx
            double dx;

            if (FXMin < 0.0)
            {
                dx   = XMax - XMin;
                Root = XMin;
            }
            else
            {
                dx   = XMin - XMax;
                Root = XMax;
            }
            while (EvaluationNumber++ < MaxEvaluations)
            {
                dx /= 2.0;
                double xMid = Root + dx;
                double fMid = objectiveFunction.Value(xMid);
                if (fMid <= 0.0)
                {
                    Root = xMid;
                }
                if (Math.Abs(dx) < xAccuracy || fMid == 0.0)
                {
                    return(Root);
                }
            }
            throw new ApplicationException("SlvMaxEval");
        }
コード例 #4
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="objective">A tour length objectiveulator object</param>
 /// <param name="initialSolution">An initial solution</param>
 public OrdinaryDecent(IObjectiveFunction objective, List<int> initialSolution)
 {
     this.objective = objective;
     this.solution = initialSolution;
     this.currentTourLength = objective.Value(initialSolution);
     this.swapPattern = new TwoCitySwapPattern(initialSolution);
 }
コード例 #5
0
 /// <summary>
 /// Implementation of the actual code to search for the zeroes of
 /// the <see cref="IObjectiveFunction"/>.
 /// </summary>
 /// <remarks>
 /// It assumes that:
 /// <list type="bullet">
 /// <item>
 ///   <description>
 ///		<see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/> form a valid bracket;
 ///	  </description>
 /// </item>
 /// <item>
 ///   <description>
 ///     <see cref="Solver1D.FXMin"/> and <see cref="Solver1D.FXMax"/> contain the values of the
 ///		function in <see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/>;
 ///	  </description>
 /// </item>
 /// <item>
 ///   <description>
 ///     <see cref="Solver1D.Root"/> was initialized to a valid initial guess.
 ///	  </description>
 /// </item>
 /// </list>
 /// </remarks>
 /// <param name="objectiveFunction">The <see cref="IObjectiveFunction"/>.</param>
 /// <param name="xAccuracy">Given accuracy.</param>
 /// <returns>The zero of the objective function.</returns>
 /// <exception cref="ApplicationException">
 /// Thrown when a bracket is not found after the maximum
 /// number of evaluations (see <see cref="Solver1D.MaxEvaluations"/>).
 /// </exception>
 /// <exception cref="NotImplementedException">
 /// Thrown by the <see cref="ObjectiveFunction"/> base class
 /// when the function's derivative has not been implemented.
 /// </exception>
 protected override double SolveImpl(IObjectiveFunction objectiveFunction,
                                     double xAccuracy)
 {
     while (EvaluationNumber++ < MaxEvaluations)
     {
         double froot  = objectiveFunction.Value(Root);
         double dfroot = objectiveFunction.Derivative(Root);
         double dx     = froot / dfroot;
         Root -= dx;
         // jumped out of brackets, switch to NewtonSafe
         if ((XMin - Root) * (Root - XMax) < 0.0)
         {
             ISolver1D newtonSafe = new NewtonSafe();
             newtonSafe.MaxEvaluations -= EvaluationNumber;
             return(newtonSafe.Solve(objectiveFunction, xAccuracy,
                                     Root + dx, XMin, XMax));
         }
         if (Math.Abs(dx) < xAccuracy)
         {
             return(Root);
         }
     }
     throw new ApplicationException("SlvMaxEval");
 }
コード例 #6
0
        /// <summary>
        /// Implementation of the actual code to search for the zeroes of
        /// the <see cref="IObjectiveFunction"/>.
        /// </summary>
        /// <remarks>
        /// It assumes that:
        /// <list type="bullet">
        /// <item>
        ///   <description>
        ///		<see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/> form a valid bracket;
        ///	  </description>
        /// </item>
        /// <item>
        ///   <description>
        ///     <see cref="Solver1D.FXMin"/> and <see cref="Solver1D.FXMax"/> contain the values of the
        ///		function in <see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/>;
        ///	  </description>
        /// </item>
        /// <item>
        ///   <description>
        ///     <see cref="Solver1D.Root"/> was initialized to a valid initial guess.
        ///	  </description>
        /// </item>
        /// </list>
        /// </remarks>
        /// <param name="objectiveFunction">The <see cref="IObjectiveFunction"/>.</param>
        /// <param name="xAccuracy">Given accuracy.</param>
        /// <returns>The zero of the objective function.</returns>
        /// <exception cref="ApplicationException">
        /// Thrown when a bracket is not found after the maximum
        /// number of evaluations (see <see cref="Solver1D.MaxEvaluations"/>).
        /// </exception>
        /// <exception cref="NotImplementedException">
        /// Thrown by the <see cref="ObjectiveFunction"/> base class
        /// when the function's derivative has not been implemented.
        /// </exception>
        protected override double SolveImpl(IObjectiveFunction objectiveFunction,
                                            double xAccuracy)
        {
            // Orient the search so that f(xl) < 0
            double xh, xl;

            if (FXMin < 0.0)
            {
                xl = XMin; xh = XMax;
            }
            else
            {
                xh = XMin; xl = XMax;
            }

            // the "stepsize before last"
            double dxold = XMax - XMin;
            // it was dxold=QL_FABS(_xMax_-_xMin_); in Numerical Recipes
            // here (_xMax_-_xMin_ > 0) is verified in the constructor
            // and the last step
            double dx     = dxold;
            double froot  = objectiveFunction.Value(Root);
            double dfroot = objectiveFunction.Derivative(Root);

            // the objectiveFunction throws  System.NotImplementedException
            while (++EvaluationNumber < MaxEvaluations)
            {
                // Bisect if (out of range || not decreasing fast enough)
                if ((((Root - xh) * dfroot - froot) * ((Root - xl) * dfroot - froot) > 0.0) ||
                    (Math.Abs(2.0 * froot) > Math.Abs(dxold * dfroot)))
                {
                    dxold = dx;
                    dx    = (xh - xl) / 2.0;
                    Root  = xl + dx;
                }
                else
                {
                    dxold = dx;
                    dx    = froot / dfroot;
                    Root -= dx;
                }
                // Convergence criterion
                if (Math.Abs(dx) < xAccuracy)
                {
                    return(Root);
                }

                froot  = objectiveFunction.Value(Root);
                dfroot = objectiveFunction.Derivative(Root);

                if (froot < 0.0)
                {
                    xl = Root;
                }
                else
                {
                    xh = Root;
                }
            }
            throw new ApplicationException(String.Format(
                                               "SlvMaxEval")
                                           );
        }
コード例 #7
0
        /// <summary>
        /// Solves for unconstrained problems, using a gradient descendent.
        /// </summary>
        /// <param name="initialGuess">The vector initial guess.</param>
        /// <param name="gradientTolerance">The gradient tolerance set per default to 1e-8.</param>
        /// <param name="maxIteration">The number of iteration used, set per default 1000.</param>
        /// <returns>The minimization result, <see cref="MinimizationResult"/>.</returns>
        internal MinimizationResult UnconstrainedMinimizer(Vector initialGuess, double gradientTolerance = 1e-8, int maxIteration = 1000)
        {
            Vector x0      = new Vector(initialGuess);
            int    n       = x0.Count;
            double f0      = _objectiveFunction.Value(x0);
            double f1      = 0.0;
            Vector x1      = null;
            Vector s       = null;
            string message = string.Empty;

            if (double.IsNaN(f0))
            {
                throw new Exception("Unconstrained Minimizer: f(x0) is a NaN!");
            }

            gradientTolerance = Math.Max(gradientTolerance, GSharkMath.Epsilon);
            Matrix H1        = Matrix.Identity(n);
            int    iteration = 0;
            Vector g0        = _objectiveFunction.Gradient(x0);

            while (iteration < maxIteration)
            {
                if (g0.Any(val => double.IsNaN(val) || double.IsInfinity(val)))
                {
                    message = "Gradient has Infinity or NaN.";
                    break;
                }
                Vector step = Vector.Reverse(g0 * H1);
                if (step.Any(val => double.IsNaN(val) || double.IsInfinity(val)))
                {
                    message = "Search direction has Infinity or NaN";
                    break;
                }

                double lengthStep = step.Length();
                if (lengthStep < gradientTolerance)
                {
                    message = "Newton step smaller than tolerance.";
                    break;
                }

                double t   = 1.0;
                double df0 = Vector.Dot(g0, step);

                // Line search.
                while (iteration < maxIteration)
                {
                    if (t * lengthStep < gradientTolerance)
                    {
                        break;
                    }

                    s  = step * t;
                    x1 = x0 + s;
                    f1 = _objectiveFunction.Value(x1);

                    if (f1 - f0 >= 0.1 * t * df0 || double.IsNaN(f1))
                    {
                        t *= 0.5;
                        iteration++;
                        continue;
                    }

                    break;
                }

                if (t * lengthStep < gradientTolerance)
                {
                    message = "Line search step size smaller than gradient tolerance.";
                    break;
                }
                if (iteration > maxIteration)
                {
                    message = "ParameterB iteration reached during line search.";
                    break;
                }

                Vector g1 = _objectiveFunction.Gradient(x1);
                Vector y  = g1 - g0;
                double ys = Vector.Dot(y, s);
                Vector Hy = y * H1;

                Matrix T0 = Tensor(s, s);
                Matrix T1 = Tensor(Hy, s);
                Matrix T2 = Tensor(s, Hy);

                H1 = (H1 + (T0 * (ys + Vector.Dot(y, Hy)) / (ys * ys))) - (T1 + T2) / ys;
                x0 = x1;
                f0 = f1;
                g0 = g1;
                iteration++;
            }

            return(new MinimizationResult(x0, f0, g0, H1, iteration, message));
        }
コード例 #8
0
ファイル: Solver1D.cs プロジェクト: zhangz/Highlander.Net
        /// <summary>
        /// This method returns the zero of the <see cref="IObjectiveFunction"/>
        /// <pramref name="objectiveFunction"/>, determined with the given accuracy.
        /// </summary>
        /// <remarks>
        /// <i>x</i> is considered a zero if <i>|f(x)| &lt; accuracy</i>.
        /// This method contains a bracketing routine to which an initial
        /// guess must be supplied as well as a step used to scan the range
        /// of the possible bracketing values.
        /// </remarks>
        /// <param name="objectiveFunction">The <see cref="ApplicationException"/>.</param>
        /// <param name="xAccuracy">Given accuracy.</param>
        /// <param name="guess">Initial guess used to scan the range
        /// of the possible bracketing values.</param>
        /// <param name="step">Initial step used to scan the range
        /// of the possible bracketing values.</param>
        /// <returns>The zero of the objective function.</returns>
        /// <exception cref="MaxEvaluations">
        /// Thrown when a bracket is not found after the maximum
        /// number of evaluations (see <see cref="IObjectiveFunction"/>).
        /// </exception>
        public double Solve(IObjectiveFunction objectiveFunction, double xAccuracy, double guess, double step)
        {
            const double growthFactor = 1.618;//golden ratio
            int          flipflop     = -1;

            Root  = guess;
            FXMax = objectiveFunction.Value(Root);
            // monotonically crescent bias, as in optionValue(volatility)
            if (Math.Abs(FXMax) <= xAccuracy)
            {
                return(Root);
            }
            if (FXMax > 0.0)
            {
                XMin  = EnforceBounds(Root - step);
                FXMin = objectiveFunction.Value(XMin);
                XMax  = Root;
            }
            else
            {
                XMin  = Root;
                FXMin = FXMax;
                XMax  = EnforceBounds(Root + step);
                FXMax = objectiveFunction.Value(XMax);
            }
            EvaluationNumber = 2;
            while (EvaluationNumber <= MaxEvaluations)
            {
                if (FXMin * FXMax <= 0.0)
                {
                    if (FXMin == 0.0)
                    {
                        return(XMin);
                    }
                    if (FXMax == 0.0)
                    {
                        return(XMax);
                    }
                    Root = (XMax + XMin) / 2.0;
                    // check whether we really want to pass epsilon
                    return(SolveImpl(objectiveFunction,
                                     Math.Max(Math.Abs(xAccuracy), Double.Epsilon)));
                }
                if (Math.Abs(FXMin) < Math.Abs(FXMax))
                {
                    XMin  = EnforceBounds(XMin + growthFactor * (XMin - XMax));
                    FXMin = objectiveFunction.Value(XMin);
                }
                else if (Math.Abs(FXMin) > Math.Abs(FXMax))
                {
                    XMax  = EnforceBounds(XMax + growthFactor * (XMax - XMin));
                    FXMax = objectiveFunction.Value(XMax);
                }
                else if (flipflop == -1)
                {
                    XMin  = EnforceBounds(XMin + growthFactor * (XMin - XMax));
                    FXMin = objectiveFunction.Value(XMin);
                    EvaluationNumber++;
                    flipflop = 1;
                }
                else if (flipflop == 1)
                {
                    XMax     = EnforceBounds(XMax + growthFactor * (XMax - XMin));
                    FXMax    = objectiveFunction.Value(XMax);
                    flipflop = -1;
                }
                EvaluationNumber++;
            }
            throw new ApplicationException($"Solver has exceeded its maximum iterations ({MaxEvaluations}).");
        }
コード例 #9
0
ファイル: Brent.cs プロジェクト: zhangz/Highlander.Net
        /// <summary>
        /// Implementation of the actual code to search for the 0.0es of
        /// the <see cref="IObjectiveFunction"/>.
        /// </summary>
        /// <remarks>
        /// It assumes that:
        /// <list type="bullet">
        /// <item>
        ///   <description>
        ///		<see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/> form a valid bracket;
        ///	  </description>
        /// </item>
        /// <item>
        ///   <description>
        ///     <see cref="Solver1D.FXMin"/> and <see cref="Solver1D.FXMax"/> contain the values of the
        ///		function in <see cref="Solver1D.XMin"/> and <see cref="Solver1D.XMax"/>;
        ///	  </description>
        /// </item>
        /// <item>
        ///   <description>
        ///     <see cref="Solver1D.Root"/> was initialized to a valid initial guess.
        ///	  </description>
        /// </item>
        /// </list>
        /// </remarks>
        /// <param name="objectiveFunction">The <see cref="IObjectiveFunction"/>.</param>
        /// <param name="xAccuracy">Given accuracy.</param>
        /// <returns>The 0.0 of the objective function.</returns>
        /// <exception cref="ApplicationException">
        /// Thrown when a bracket is not found after the maximum
        /// number of evaluations (see <see cref="Solver1D.MaxEvaluations"/>).
        /// </exception>
        protected override double SolveImpl(IObjectiveFunction objectiveFunction, double xAccuracy)
        {
            // dummy assignements to avoid compiler warning
            //
            double d = 0.0;
            double e = 0.0;

            Root = XMax;
            double froot = FXMax;

            while (EvaluationNumber++ < MaxEvaluations)
            {
                if (froot > 0.0 && FXMax > 0.0 ||
                    froot < 0.0 && FXMax < 0.0)
                {
                    // Rename _xMin, root, _xMax and adjust bounding interval d
                    //
                    XMax  = XMin;
                    FXMax = FXMin;
                    e     = d = Root - XMin;
                }
                if (Math.Abs(FXMax) < Math.Abs(froot))
                {
                    XMin  = Root;
                    Root  = XMax;
                    XMax  = XMin;
                    FXMin = froot;
                    froot = FXMax;
                    FXMax = FXMin;
                }
                // Convergence check
                //
                double xAcc1 = 2.0 * Double.Epsilon * Math.Abs(Root) + 0.5 * xAccuracy;
                double xMid  = (XMax - Root) / 2.0;
                // Yield return value
                // (exit path)
                //
                if (Math.Abs(xMid) <= xAcc1 || froot == 0.0)
                {
                    return(Root);
                }
                if (Math.Abs(e) >= xAcc1 && Math.Abs(FXMin) > Math.Abs(froot))
                {
                    double p, q;
                    double s = froot / FXMin;  // Attempt inverse quadratic interpolation
                    if (XMin == XMax)
                    {
                        p = 2.0 * xMid * s;
                        q = 1.0 - s;
                    }
                    else
                    {
                        q = FXMin / FXMax;
                        double r = froot / FXMax;
                        p = s * (2.0 * xMid * q * (q - r) - (Root - XMin) * (r - 1.0));
                        q = (q - 1.0) * (r - 1.0) * (s - 1.0);
                    }
                    if (p > 0.0)
                    {
                        q = -q;           // Check whether in bounds
                    }
                    p = Math.Abs(p);
                    double min1 = 3.0 * xMid * q - Math.Abs(xAcc1 * q);
                    double min2 = Math.Abs(e * q);
                    if (2.0 * p < (min1 < min2 ? min1 : min2))
                    {
                        e = d;                // Accept interpolation
                        d = p / q;
                    }
                    else
                    {
                        d = xMid;  // Interpolation failed, use bisection
                        e = d;
                    }
                }
                else
                {
                    //  Bounds decreasing too slowly, use bisection
                    //
                    d = xMid;
                    e = d;
                }
                XMin  = Root;
                FXMin = froot;
                if (Math.Abs(d) > xAcc1)
                {
                    Root += d;
                }
                else
                {
                    Root += Math.Sign(xMid) * Math.Abs(xAcc1);
                }
                froot = objectiveFunction.Value(Root);
            }
            throw new ApplicationException("SlvMaxEval");
        }
コード例 #10
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="objective">A tour length objectiveulator object</param>
 /// <param name="initialSolution">An initial solution</param>
 public BruteForceSearch(IObjectiveFunction objective, List<int> initialSolution)
 {
     this.objective = objective;
     this.solution = initialSolution;
     this.currentTourLength = objective.Value(initialSolution);
 }