Brent's root finding and minimization algorithms.

In numerical analysis, Brent's method is a complicated but popular root-finding algorithm combining the bisection method, the secant method and inverse quadratic interpolation. It has the reliability of bisection but it can be as quick as some of the less reliable methods. The idea is to use the secant method or inverse quadratic interpolation if possible, because they converge faster, but to fall back to the more robust bisection method if necessary. Brent's method is due to Richard Brent (1973) and builds on an earlier algorithm of Theodorus Dekker (1969).

The algorithms implemented in this class are based on the original C source code available in Netlib (http://www.netlib.org/c/brent.shar) by Oleg Keselyov, 1991.

References: R.P. Brent (1973). Algorithms for Minimization without Derivatives, Chapter 4. Prentice-Hall, Englewood Cliffs, NJ. ISBN 0-13-022335-2. Wikipedia contributors. "Brent's method." Wikipedia, The Free Encyclopedia. Wikipedia, The Free Encyclopedia, 11 May. 2012. Web. 22 Jun. 2012.

Пример #1
0
    private double brentMethod()
    {
        double guessVal = (Mathd.Sqrt(obj.parent.gravParam) * currentTime) / semiMajorAxis;

        //second two params are the min and max values the solver will search for, they are at this point total spitballing
        Accord.Math.Optimization.BrentSearch searcher = new Accord.Math.Optimization.BrentSearch(substitutionFunction, -2.0d * (guessVal + 20.0d), 2.0d * (guessVal + 20.0d));

        searcher.Tolerance = 0.0001;
        searcher.FindRoot();
        return(searcher.Solution);
    }
Пример #2
0
        public void ConstructorTest()
        {

            // Suppose we were given the function x³ + 2x² - 10x and 
            // we have to find its root, maximum and minimum inside 
            // the interval [-4,3]. First, we express this function
            // as a lambda expression:
            Func<double, double> function = x => x * x * x + 2 * x * x - 10 * x;

            // And now we can create the search algorithm:
            BrentSearch search = new BrentSearch(function, -4, 3);

            // Finally, we can query the information we need
            double max = search.Maximize();  // occurs at -2.61
            double min = search.Minimize();  // occurs at  1.27
            double root = search.FindRoot(); // occurs at  0.50

            Assert.AreEqual(-2.6103173042172645, max);
            Assert.AreEqual(1.2769840667540548, min);
            Assert.AreEqual(-0.5, root);
        }
        public static PointParamWithRayProjection ClosestPointToRay(this ICurve curve, PointDirection3 ray, double tol = 1e-9)
        {
            var bound = curve.Domain();
            int numOfRadius = 0;
            double[] radius = null;
            MathPoint location = null;

            var radiusResult = curve.FindMinimumRadius();
            var domain = new RangeDouble(curve.Domain());
            var tessTol = radiusResult.Radius/10;
            var closestPointOnEdge = Vector3.Zero;
            for (var i = 0; i < 1; i++)
            {
                var tessPoints = Sequences
                    .LinSpace(domain.Min, domain.Max, 100)
                    .Select(curve.PointParamAt).ToList();
                var edges = tessPoints.Buffer(2, 1).Where(buf => buf.Count == 2)
                    .ToList();

                var closestEdge
                    = edges
                        .Select(edge => new {edge, connection= MakeEdge(edge).ShortestEdgeJoining(ray, tol)})
                        .MinBy(o=>o.connection.LengthSquared)[0];

                var a = closestEdge.edge[0].T;
                var b = closestEdge.edge[1].T;
                domain = new RangeDouble(a, b);
                tessTol = tessTol/10;
            }

            Func<Vector3, Vector3> projectOnRay = p => (p - ray.Point).ProjectOn(ray.Direction) + ray.Point;

            var solver = new BrentSearch(t =>
            {
                var p = curve.PointAt(t);
                var proj = projectOnRay(p);
                return (p - proj).LengthSquared();
            }, domain.Min, domain.Max);
            solver.Minimize();
            var minT = solver.Solution;

            var pointParam = curve.PointParamAt(minT);
            return new PointParamWithRayProjection(pointParam, projectOnRay(pointParam.Point));
        }
 /// <summary>
 /// Should solve
 /// </summary>
 /// <param name="c"></param>
 /// <param name="t0"></param>
 /// <param name="distance"></param>
 /// <returns></returns>
 public static double PointAtDistanceFrom(this ICurve c, double t0, double distance)
 {
     Func<double, double> objFunc = t1 =>
     {
         var length3 = t0 < t1 ? c.GetLength3(t0, t1) : c.GetLength3(t1, t0);
         return length3 - Math.Abs(distance);
     };
     var domain = c.Domain();
     var min = distance < 0.0 ? 0.8*domain[0] : t0;
     var max = distance < 0.0 ? t0 : 1.2*domain[1];
     var solver = new BrentSearch(objFunc, min, max);
     solver.FindRoot();
     var sol = solver.Solution;
     return sol;
 }
        public static EdgeDistance ClosestDistanceBetweenTwoCurves(IMathUtility m,ICurve curve0, ICurve curve1)
        {
            var curveDomain = curve1.Domain();

            var solver = new BrentSearch
                (t =>
                {
                    var pt = curve1.PointAt(t);
                    return (curve0.ClosestPointOn(pt).Point - pt).Length();
                }
                , curveDomain[0]
                , curveDomain[1]
                );

            solver.Minimize();
            var param = solver.Solution;

            var pt1 = curve1.PointAt(param);
            var pt0 = curve0.ClosestPointOn(pt1).Point;
            var edge = new Edge3(pt1, pt0);
            return new EdgeDistance(edge, solver.Value);
        }