/// <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"); }
/// <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") ); }