/// <summary>
        /// Isolates a root within a given interval.
        /// </summary>
        /// <param name="f">The function whoose zero is sought.</param>
        /// <param name="bracket">An interval bracketing the root.</param>
        /// <returns>An ordinate within the bracket at which the function has a zero.</returns>
        /// <exception cref="InvalidOperationException">The function does not change sign across the given interval.</exception>
        public static double FindZero(Func<double, double> f, Interval bracket)
        {
            if (f == null) throw new ArgumentNullException("f");

            double x1 = bracket.LeftEndpoint;
            double x2 = bracket.RightEndpoint;
            double f1 = f(x1);
            double f2 = f(x2);

            // make sure the bracket points really do bracket a root
            if (Math.Sign(f1) == Math.Sign(f2)) throw new InvalidOperationException();

            return (FindZero(f, x1, f1, x2, f2));
        }
        public void Ackley()
        {
            // Ackley's function has many local minima, and a global minimum at (0, 0) -> 0.

            Func<IList<double>, double> function = (IList<double> x) => {
                double s = 0.0;
                double c = 0.0;
                for (int i = 0; i < x.Count; i++) {
                    s += x[i] * x[i];
                    c += Math.Cos(2.0 * Math.PI * x[i]);
                }
                return (-20.0 * Math.Exp(-0.2 * Math.Sqrt(s / x.Count)) - Math.Exp(c / x.Count) + 20.0 + Math.E);
            };

            EvaluationSettings settings = new EvaluationSettings() { AbsolutePrecision = 1.0E-8, EvaluationBudget = 10000000 };

            for (int n = 2; n < 16; n = (int) Math.Round(AdvancedMath.GoldenRatio * n)) {
                Console.WriteLine("n={0}", n);

                Interval[] box = new Interval[n];
                for (int i = 0; i < box.Length; i++) box[i] = Interval.FromEndpoints(-32.0, 32.0);

                MultiExtremum minimum = MultiFunctionMath.FindGlobalMinimum(function, box, settings);

                Console.WriteLine(minimum.EvaluationCount);
                Console.WriteLine(minimum.Value);
                foreach (double coordinate in minimum.Location) Console.WriteLine(coordinate);

                Assert.IsTrue(minimum.Dimension == n);

                Assert.IsTrue(TestUtilities.IsNearlyEqual(minimum.Value, 0.0, new EvaluationSettings() { AbsolutePrecision = 2.0 * minimum.Precision }));

                ColumnVector solution = new ColumnVector(n);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(minimum.Location, solution, new EvaluationSettings() { AbsolutePrecision = 2.0 * Math.Sqrt(minimum.Precision) }));

            }
        }
        public void PackCirclesInCircle()
        {
            // Put n points into the unit circle. Place them so as to maximize the minimum distance between them.
            // http://en.wikipedia.org/wiki/Circle_packing_in_a_circle, http://hydra.nat.uni-magdeburg.de/packing/csq/csq.html
            // This can also be ecoded via a box constraint if we use polar coordinates.
            // In that case, 0 < r < 1 and -\pi < \theta < +\pi are the coordinate bounds.

            double[] solutions = {
                Double.NaN,
                Double.NaN,
                2.0, /* uniformly along edge, i.e. opposite sides */
                Math.Sqrt(3.0), /* uniformly along edge, i.e. triangle */
                Math.Sqrt(2.0), /* uniformly along edge, i.e. square */
                Math.Sqrt(2.0 / (1.0 + 1.0 / Math.Sqrt(5.0))), /* uniformly along edge, i.e. pentagon */
                1.0, /* uniformly along edge, i.e. hexagon */
                1.0, /* six uniformly along edge plus one in center */
                2.0 * Math.Sin(Math.PI / 7.0),
                Math.Sqrt(2.0 / (2.0 + Math.Sqrt(2.0))),
                0.710978235561246550830725976904,
                2.0 * Math.Sin(Math.PI / 9.0)
            };

            for (int n = 2; n < 8; n++)
            {
                // We have a problem with n = 5. Chooses to put one in middle and others at 90 degree angles around it instead of distributing uniformly along edge.
                if (n == 5) continue;

                Console.WriteLine(n);

                // We assume that the point r=1, t=0 exists and encode only the remaining n-1 points in a 2(n-1)-length vector.

                Func<IList<double>, double> f = (IList<double> u) => {
                    double sMin = Double.MaxValue;
                    for (int i = 0; i < (n - 1); i++) {
                        double ri = u[2 * i];
                        double ti = u[2 * i + 1];
                        double xi = ri * Math.Cos(ti);
                        double yi = ri * Math.Sin(ti);
                        for (int j = 0; j < i; j++) {
                            double rj = u[2 * j];
                            double tj = u[2 * j + 1];
                            double xj = rj * Math.Cos(tj);
                            double yj = rj * Math.Sin(tj);
                            double s = MoreMath.Hypot(xi - xj, yi - yj);
                            if (s < sMin) sMin = s;
                        }
                        // also compare distance to fixed point (1, 0)
                        double s1 = MoreMath.Hypot(xi - 1.0, yi);
                        if (s1 < sMin) sMin = s1;
                    }
                    return (sMin);
                };

                Interval[] box = new Interval[2 * (n - 1)];
                for (int i = 0; i < (n - 1); i++) {
                    box[2 * i] = Interval.FromEndpoints(0.0, 1.0);
                    box[2 * i + 1] = Interval.FromEndpoints(-Math.PI, Math.PI);
                }

                MultiExtremum maxmimum = MultiFunctionMath.FindGlobalMaximum(f, box);

                Console.WriteLine(maxmimum.EvaluationCount);
                Console.WriteLine("{0} {1}", maxmimum.Value, maxmimum.Precision);
                for (int i = 0; i < (n - 1); i++) Console.WriteLine("{0} {1}", maxmimum.Location[2 * i], maxmimum.Location[2 * i + 1]);
                Assert.IsTrue(maxmimum.Dimension == 2 * (n - 1));
                Assert.IsTrue(TestUtilities.IsNearlyEqual(maxmimum.Value, solutions[n], new EvaluationSettings() { AbsolutePrecision = 2.0 * maxmimum.Precision }));

            }
        }
        public void Griewank()
        {
            // See http://mathworld.wolfram.com/GriewankFunction.html

            for (int n = 2; n < 8; n++) {

                Console.WriteLine(n);

                Func<IList<double>, double> function = (IList<double> x) => {
                    double s = 0.0;
                    double p = 1.0;
                    for (int i = 0; i < x.Count; i++) {
                        s += MoreMath.Sqr(x[i]);
                        p *= Math.Cos(x[i] / Math.Sqrt(i + 1.0));
                    }
                    return (1.0 + s / 4000.0 - p);
                };

                Interval[] box = new Interval[n];
                for (int i = 0; i < n; i++) box[i] = Interval.FromEndpoints(-100.0, 100.0);

                EvaluationSettings settings = new EvaluationSettings() { AbsolutePrecision = 1.0E-6, EvaluationBudget = 1000000 };

                MultiExtremum minimum = MultiFunctionMath.FindGlobalMinimum(function, box, settings);

                Console.WriteLine(minimum.Dimension);
                Console.WriteLine(minimum.EvaluationCount);
                Console.WriteLine("{0} ({1}) ?= 0.0", minimum.Value, minimum.Precision);
                Console.WriteLine("{0} {1} ...", minimum.Location[0], minimum.Location[1]);

                // We usually find the minimum at 0, but sometimes land a valley or two over.

            }
        }
        public void EasomGlobal()
        {
            Func<IList<double>, double> function = (IList<double> x) => Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Exp(-(MoreMath.Sqr(x[0] - Math.PI) + MoreMath.Sqr(x[1] - Math.PI)));
            IList<Interval> box = new Interval[] { Interval.FromEndpoints(-10.0, 10.0), Interval.FromEndpoints(-10.0, 10.0) };

            MultiExtremum maximum = MultiFunctionMath.FindGlobalMaximum(function, box);

            Console.WriteLine(maximum.EvaluationCount);
            Console.WriteLine(maximum.Value);

            Assert.IsTrue(TestUtilities.IsNearlyEqual(maximum.Value, 1.0, new EvaluationSettings() { AbsolutePrecision = 2.0 * maximum.Precision }));
            Assert.IsTrue(TestUtilities.IsNearlyEqual(maximum.Location, new ColumnVector(Math.PI, Math.PI), new EvaluationSettings { AbsolutePrecision = 2.0 * Math.Sqrt(maximum.Precision) }));
        }
        public void Bukin()
        {
            // Burkin has a narrow valley, not aligned with any axis, punctuated with many tiny "wells" along its bottom.
            // The deepest well is at (-10,1)-> 0.
            Func<IList<double>, double> function = (IList<double> x) => 100.0 * Math.Sqrt(Math.Abs(x[1] - 0.01 * x[0] * x[0])) + 0.01 * Math.Abs(x[0] + 10.0);

            IList<Interval> box = new Interval[] { Interval.FromEndpoints(-15.0, 0.0), Interval.FromEndpoints(-3.0, 3.0) };

            EvaluationSettings settings = new EvaluationSettings() { RelativePrecision = 0.0, AbsolutePrecision = 1.0E-4, EvaluationBudget = 1000000 };
            /*
            settings.Update += (object result) => {
                MultiExtremum e = (MultiExtremum) result;
                Console.WriteLine("After {0} evaluations, best value {1}", e.EvaluationCount, e.Value);
            };
            */
            MultiExtremum minimum = MultiFunctionMath.FindGlobalMinimum(function, box, settings);

            Console.WriteLine(minimum.EvaluationCount);
            Console.WriteLine("{0} ({1})", minimum.Value, minimum.Precision);
            Console.WriteLine("{0} {1}", minimum.Location[0], minimum.Location[1]);

            // We do not end up finding the global minimum.
        }
        public void TammesGlobal()
        {
            double[] tammesSolutions = new double[] { Double.NaN, Double.NaN, 2.0, Math.Sqrt(3.0), Math.Sqrt(8.0 / 3.0), Math.Sqrt(2.0), Math.Sqrt(2.0) };

            for (int n = 2; n < 8; n++) {
                Console.WriteLine("n = {0}", n);

                // Define a function that returns the minimum distance between points
                Func<IList<double>, double> f = (IList<double> u) => {
                    // add a point at 0,0
                    double[] v = new double[2 * n];
                    u.CopyTo(v, 0);

                    double dmin = Double.PositiveInfinity;

                    // iterate over all distinct pairs of points
                    for (int i = 0; i < n; i++) {
                        for (int j = 0; j < i; j++) {
                            // compute the chord length between points i and j
                            double dx = Math.Cos(v[2 * j]) * Math.Cos(v[2 * j + 1]) - Math.Cos(v[2 * i]) * Math.Cos(v[2 * i + 1]);
                            double dy = Math.Cos(v[2 * j]) * Math.Sin(v[2 * j + 1]) - Math.Cos(v[2 * i]) * Math.Sin(v[2 * i + 1]);
                            double dz = Math.Sin(v[2 * j]) - Math.Sin(v[2 * i]);
                            double d = Math.Sqrt(dx * dx + dy * dy + dz * dz);
                            if (d < dmin) dmin = d;
                        }
                    }

                    return (dmin);
                };

                /*
                // Start with a random arrangement
                Random r = new Random(1001110000);
                double[] start = new double[2 * n];
                for (int i = 0; i < n; i++) {
                    start[2 * i] = -Math.PI + 2.0 * r.NextDouble() * Math.PI;
                    start[2 * i + 1] = Math.Asin(2.0 * r.NextDouble() - 1.0);
                }

                // Maximize the minimum distance
                MultiExtremum maximum = MultiFunctionMath.FindLocalMinimum(f, start);
                */

                Interval[] limits = new Interval[2 * (n - 1)];
                for (int i = 0; i < (n - 1); i++) {
                    limits[2 * i] = Interval.FromEndpoints(-Math.PI, +Math.PI);
                    limits[2 * i + 1] = Interval.FromEndpoints(-Math.PI / 2.0, +Math.PI / 2.0);
                }
                MultiExtremum maximum = MultiFunctionMath.FindGlobalMaximum(f, limits);

                Console.WriteLine(maximum.EvaluationCount);
                Console.WriteLine("{0} ({1})", maximum.Value, maximum.Precision);

                Assert.IsTrue(maximum.Dimension == 2 * (n - 1));

                if (n < tammesSolutions.Length) Assert.IsTrue(TestUtilities.IsNearlyEqual(maximum.Value, tammesSolutions[n], new EvaluationSettings() { AbsolutePrecision = 2.0 * maximum.Precision }));

            }
        }
        public void WatsonIntegrals()
        {
            // Watson defined and analytically integrated three complicated triple integrals related to random walks in three dimension
            // See http://mathworld.wolfram.com/WatsonsTripleIntegrals.html

            // These integrals are difficult, so up the budget to about 1,000,000 and reduce the target accuracy to about 10^{-4}
            EvaluationSettings settings = new EvaluationSettings() { RelativePrecision = 1.0E-4, EvaluationBudget = 1000000 };

            Interval watsonWidth = Interval.FromEndpoints(0.0, Math.PI);
            Interval[] watsonBox = new Interval[] { watsonWidth, watsonWidth, watsonWidth };

            Assert.IsTrue(
                MultiFunctionMath.Integrate(
                    (IList<double> x) => 1.0 / (1.0 - Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Cos(x[2])), watsonBox, settings
                ).Estimate.ConfidenceInterval(0.99).ClosedContains(
                    MoreMath.Pow(AdvancedMath.Gamma(1.0 / 4.0), 4) / 4.0
                )
            );

            Assert.IsTrue(
                MultiFunctionMath.Integrate(
                    (IList<double> x) => 1.0 / (3.0 - Math.Cos(x[0]) * Math.Cos(x[1]) - Math.Cos(x[1]) * Math.Cos(x[2]) - Math.Cos(x[0]) * Math.Cos(x[2])), watsonBox, settings
                ).Estimate.ConfidenceInterval(0.99).ClosedContains(
                    3.0 * MoreMath.Pow(AdvancedMath.Gamma(1.0 / 3.0), 6) / Math.Pow(2.0, 14.0 / 3.0) / Math.PI
                )
            );

            Assert.IsTrue(
                MultiFunctionMath.Integrate(
                    (IList<double> x) => 1.0 / (3.0 - Math.Cos(x[0]) - Math.Cos(x[1]) - Math.Cos(x[2])), watsonBox, settings
                ).Estimate.ConfidenceInterval(0.99).ClosedContains(
                    Math.Sqrt(6.0) / 96.0 * AdvancedMath.Gamma(1.0 / 24.0) * AdvancedMath.Gamma(5.0 / 24.0) * AdvancedMath.Gamma(7.0 / 24.0) * AdvancedMath.Gamma(11.0 / 24.0)
                )
            );
        }
        public void IsingIntegrals()
        {
            // See http://www.davidhbailey.com/dhbpapers/ising.pdf.

            EvaluationSettings settings = new EvaluationSettings() { RelativePrecision = 1.0E-3, EvaluationBudget = 1000000 };

            int d = 4;
            Interval[] volume = new Interval[d];
            for (int i = 0; i < volume.Length; i++) {
                volume[i] = Interval.FromEndpoints(0.0, Double.PositiveInfinity);
            }

            IntegrationResult r = MultiFunctionMath.Integrate((IList<double> x) => {
                double p = 1.0;
                double q = 0.0;
                for (int i = 0; i < x.Count; i++) {
                    double u = x[i];
                    double v = 1.0 / u;
                    q += (u + v);
                    p *= v;
                }
                return (p / MoreMath.Sqr(q));
            }, volume, settings);
            double c = 4.0 / AdvancedIntegerMath.Factorial(d);
            Console.WriteLine("{0} {1}", c * r.Estimate, r.EvaluationCount);

            Console.WriteLine(7.0 * AdvancedMath.RiemannZeta(3.0) / 12.0);

            Assert.IsTrue((c * r.Estimate).ConfidenceInterval(0.99).ClosedContains(7.0 * AdvancedMath.RiemannZeta(3.0) / 12.0));
        }
 // Returns a d-dimensional unit cube [0,1]^d
 public Interval[] UnitCube(int d)
 {
     Interval[] box = new Interval[d];
     for (int j = 0; j < d; j++) {
         box[j] = Interval.FromEndpoints(0.0, 1.0);
     }
     return (box);
 }
        public void GaussianIntegrals()
        {
            Random rng = new Random(1);
            for (int d = 2; d < 4; d++) {
                if (d == 4 || d == 5 || d == 6) continue;
                Console.WriteLine(d);

                // Create a symmetric matrix
                SymmetricMatrix A = new SymmetricMatrix(d);
                for (int r = 0; r < d; r++) {
                    for (int c = 0; c < r; c++) {
                        A[r, c] = rng.NextDouble();
                    }
                    // Ensure it is positive definite by diagonal dominance
                    A[r, r] = r + 1.0;
                }

                // Compute its determinant, which appears in the analytic value of the integral
                CholeskyDecomposition CD = A.CholeskyDecomposition();
                double detA = CD.Determinant();

                // Compute the integral
                Func<IList<double>, double> f = (IList<double> x) => {
                    ColumnVector v = new ColumnVector(x);
                    double s = v.Transpose() * (A * v);
                    return (Math.Exp(-s));
                };

                Interval[] volume = new Interval[d];
                for (int i = 0; i < d; i++) volume[i] = Interval.FromEndpoints(Double.NegativeInfinity, Double.PositiveInfinity);

                IntegrationResult I = MultiFunctionMath.Integrate(f, volume);

                // Compare to the analytic result
                Console.WriteLine("{0} ({1}) {2}", I.Value, I.Precision, Math.Sqrt(MoreMath.Pow(Math.PI, d) / detA));
                Assert.IsTrue(TestUtilities.IsNearlyEqual(I.Value, Math.Sqrt(MoreMath.Pow(Math.PI, d) / detA), new EvaluationSettings() { AbsolutePrecision = 2.0 * I.Precision }));
            }
        }
 /// <summary>
 /// Maximizes a function on the given interval.
 /// </summary>
 /// <param name="f">The function.</param>
 /// <param name="r">The interval.</param>
 /// <returns>The maximum.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="f"/> is null.</exception>
 /// <exception cref="NonconvergenceException">More than the maximum allowed number of function evaluations occured without a minimum being determined.</exception>
 public static Extremum FindMaximum(Func<double, double> f, Interval r)
 {
     return (FindMaximum(f, r, DefaultExtremaSettings));
 }
 /// <summary>
 /// Minimizes a function on the given interval, subject to the given evaluation settings.
 /// </summary>
 /// <param name="f">The function.</param>
 /// <param name="r">The interval.</param>
 /// <param name="settings">The settings used when searching for the minimum.</param>
 /// <returns>The minimum.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="f"/> is null or <paramref name="settings"/> is null.</exception>
 /// <exception cref="NonconvergenceException">More than the maximum allowed number of function evaluations occured without a minimum being determined to the prescribed precision.</exception>
 /// <remarks>
 /// <para>When you supply <paramref name="settings"/>, note that the supplied <see cref="EvaluationSettings.RelativePrecision"/> and <see cref="EvaluationSettings.AbsolutePrecision"/>
 /// values refer to argument (i.e. x) values, not function (i.e. f) values. Note also that, for typical functions, the best attainable relative precision is of the order of the
 /// square root of machine precision (about 10<sup>-7</sup>), i.e. half the number of digits in a <see cref="Double"/>. This is because to identify an extremum we need to resolve changes
 /// in the function value, and near an extremum  &#x3B4;f &#x223C; (&#x3B4;x)<sup>2</sup>, so changes in the function value &#x3B4;f &#x223C; &#x3B5; correspond to changes in the
 /// argument value &#x3B4;x &#x223C; &#x221A;&#x3B5;. If you supply zero values for both precision settings, the method will adaptively approximate the best attainable precision for
 /// the supplied function and locate the extremum to that resolution. This is our suggested practice unless you know that you require a less precise determination.</para>
 /// </remarks>
 public static Extremum FindMinimum(Func<double, double> f, Interval r, EvaluationSettings settings)
 {
     if (f == null) throw new ArgumentNullException("f");
     if (settings == null) throw new ArgumentNullException("settings");
     return (FindMinimum(new Functor(f), r.LeftEndpoint, r.RightEndpoint, settings));
 }
        public void PackCirclesInSquare()
        {
            // Put n points into the unit square. Place them so as to maximize the minimum distance between them.
            // See http://en.wikipedia.org/wiki/Circle_packing_in_a_square, http://hydra.nat.uni-magdeburg.de/packing/csq/csq.html
            // This is a great test problem because it is simple to understand, hard to solve,
            // solutions are known/proven for many n, and it covers many dimensions.

            double[] solutions = new double[] {
                Double.NaN,
                Double.NaN,
                Math.Sqrt(2.0), /* at opposite corners */
                Math.Sqrt(6.0) - Math.Sqrt(2.0),
                1.0, /* at each corner */
                Math.Sqrt(2.0) / 2.0 /* at each corner and in center */,
                Math.Sqrt(13.0) / 6.0,
                4.0 - 2.0 * Math.Sqrt(3.0),
                (Math.Sqrt(6.0) - Math.Sqrt(2.0)) / 2.0,
                1.0 / 2.0, /* 3 X 3 grid */
                0.421279543983903432768821760651,
                0.398207310236844165221512929748,
                Math.Sqrt(34.0) / 15.0,
                0.366096007696425085295389370603,
                2.0 / (4.0 + Math.Sqrt(3.0)),
                2.0 / (Math.Sqrt(6.0) + 2.0 + Math.Sqrt(2.0)),
                1.0 / 3.0
            };

            //int n = 11;
            for (int n = 2; n < 8; n++)
            {

                Console.WriteLine("n={0}", n);

                Func<IList<double>, double> function = (IList<double> x) => {
                    // Intrepret coordinates as (x_1, y_1, x_2, y_2, \cdots, x_n, y_n)
                    // Iterate over all pairs of points, finding smallest distance betwen any pair of points.
                    double sMin = Double.MaxValue;
                    for (int i = 0; i < n; i++) {
                        for (int j = 0; j < i; j++) {
                            double s = MoreMath.Hypot(x[2 * i] - x[2 * j], x[2 * i + 1] - x[2 * j + 1]);
                            if (s < sMin) sMin = s;
                        }
                    }
                    return (sMin);
                };

                IList<Interval> box = new Interval[2 * n];
                for (int i = 0; i < box.Count; i++) box[i] = Interval.FromEndpoints(0.0, 1.0);

                EvaluationSettings settings = new EvaluationSettings() { RelativePrecision = 1.0E-4, AbsolutePrecision = 1.0E-6, EvaluationBudget = 10000000 };

                MultiExtremum maximum = MultiFunctionMath.FindGlobalMaximum(function, box, settings);

                Console.WriteLine(maximum.EvaluationCount);
                Console.WriteLine("{0} {1}", solutions[n], maximum.Value);

                Assert.IsTrue(maximum.Dimension == 2 * n);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(maximum.Value, solutions[n], new EvaluationSettings() { AbsolutePrecision = 2.0 * maximum.Precision }));

            }
        }
 public TestIntegral (Func<double, double> f, Interval r, double I) {
     this.Integrand = f;
     this.Range = r;
     this.Result = I;
 }
        public void PackSpheresInCube()
        {
            // See http://www.combinatorics.org/ojs/index.php/eljc/article/download/v11i1r33/pdf

            double[] solutions = new double[] {
                Double.NaN,
                Double.NaN,
                Math.Sqrt(3.0), /* opposite corners */
                Math.Sqrt(2.0), /* three non-adjacent corners*/
                Math.Sqrt(2.0), /* on opposite faces in opposite corners */
                Math.Sqrt(5.0) / 2.0,
                3.0 * Math.Sqrt(2.0) / 4.0,
                Math.Sqrt(2.0 / 3.0 * (8.0 + Math.Sqrt(3.0) - 2.0 * Math.Sqrt(10.0 + 4.0 * Math.Sqrt(3.0)))),
                1.0, /* in each corner */
                Math.Sqrt(3.0) / 2.0, /* in each corner and at center */
                3.0 / 4.0,
                0.710116382462,
                0.707106806467,
                1.0 / Math.Sqrt(2.0),
                1.0 / Math.Sqrt(2.0),
                5.0 / 8.0
            };

            //int n = 11;
            for (int n = 2; n < 8; n++)
            {

                Func<IList<double>, double> function = (IList<double> x) => {
                    // Intrepret coordinates as (x_1, y_1, z_1, x_2, y_2, z_2, \cdots, x_n, y_n, z_n)
                    // Iterate over all pairs of points, finding smallest distance betwen any pair of points.
                    double sMin = Double.MaxValue;
                    for (int i = 0; i < n; i++) {
                        for (int j = 0; j < i; j++) {
                            double s = Math.Sqrt(
                                MoreMath.Sqr(x[3 * i] - x[3 * j]) +
                                MoreMath.Sqr(x[3 * i + 1] - x[3 * j + 1]) +
                                MoreMath.Sqr(x[3 * i + 2] - x[3 * j + 2])
                            );
                            if (s < sMin) sMin = s;
                        }
                    }
                    return (sMin);
                };

                IList<Interval> box = new Interval[3 * n];
                for (int i = 0; i < box.Count; i++) box[i] = Interval.FromEndpoints(0.0, 1.0);

                MultiExtremum maximum = MultiFunctionMath.FindGlobalMaximum(function, box);

                Console.WriteLine(maximum.EvaluationCount);
                Console.WriteLine("{0} {1} ({2})", solutions[n], maximum.Value, maximum.Precision);

                Assert.IsTrue(maximum.Dimension == 3 * n);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(maximum.Value, solutions[n], new EvaluationSettings() { AbsolutePrecision = 2.0 * maximum.Precision }));

            }
        }
 public TestExtremum(Func<double, double> function, Interval interval, double location, double value, double curvature)
 {
     this.Function = function;
     this.Interval = interval;
     this.Location = location;
     this.Value = value;
     this.Curvature = curvature;
 }
        public void Schwefel()
        {
            // Test over [-500,500], minimum at (420.969,...) -> -418.983*d, many local minima

            Func<IList<double>, double> function = (IList<double> x) => {
                double s = 0.0;
                for (int i = 0; i < x.Count; i++) {
                    s += x[i] * Math.Sin(Math.Sqrt(Math.Abs(x[i])));
                }
                return (-s);
            };

            for (int n = 2; n < 32; n = (int) Math.Round(AdvancedMath.GoldenRatio * n)) {
                Console.WriteLine("n={0}", n);

                Interval[] box = new Interval[n];
                for (int i = 0; i < box.Length; i++) box[i] = Interval.FromEndpoints(-500.0, 500.0);

                MultiExtremum minimum = MultiFunctionMath.FindGlobalMinimum(function, box);

                Assert.IsTrue(minimum.Dimension == n);

                Console.WriteLine(minimum.EvaluationCount);
                Console.WriteLine("{0} ({1}) ?= {2}", minimum.Value, minimum.Precision, -418.983 * n);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(minimum.Value, -418.983 * n, new EvaluationSettings() { AbsolutePrecision = minimum.Precision }));

                foreach (double coordinate in minimum.Location) Console.WriteLine(coordinate);
                ColumnVector solution = new ColumnVector(n);
                solution.Fill((int i, int j) => 420.969);
                Assert.IsTrue(TestUtilities.IsNearlyEqual(minimum.Location, solution, new EvaluationSettings() { RelativePrecision = 2.0 * Math.Sqrt(Math.Abs(minimum.Precision / minimum.Value)) }));
            }
        }
        public void STA()
        {
            // Has local minimum when any coordinate is at one of two values, global when all coordinates at one of them.
            Func<IList<double>, double> fStyblinskiTang = (IList<double> x) => {
                double fst = 0.0;
                for (int i = 0; i < x.Count; i++) {
                    double x1 = x[i];
                    double x2 = MoreMath.Sqr(x1);
                    fst += x2 * (x2 - 16.0) + 5.0 * x1;
                }
                return (fst / 2.0);
            };

            // Asymptotic "minima" at infinity, and (3,1/2)->0
            Func<IList<double>, double> fBeale = (IList<double> x) =>
                MoreMath.Sqr(1.5 - x[0] + x[0] * x[1]) +
                MoreMath.Sqr(2.25 - x[0] + x[0] * x[1] * x[1]) +
                MoreMath.Sqr(2.625 - x[0] + x[0] * x[1] * x[1] * x[1]);

            Func<IList<double>, double> fEggholder = (IList<double> x) => {
                double y47 = x[1] + 47.0;
                return(-y47 * Math.Sin(Math.Sqrt(Math.Abs(y47 + x[0] / 2.0))) - x[0] * Math.Sin(Math.Sqrt(Math.Abs(x[0] - y47))));
            };

            // Many local minima, global minimum at (0,0)->0
            Func<IList<double>, double> fAckley = (IList<double> x) => {
                double s = 0.0;
                double c = 0.0;
                for (int i = 0; i < x.Count; i++) {
                    s += x[i] * x[i];
                    c += Math.Cos(2.0 * Math.PI * x[i]);
                }
                return (-20.0 * Math.Exp(-0.2 * Math.Sqrt(s / x.Count)) - Math.Exp(c / x.Count) + 20.0 + Math.E);
            };

            // Burkin has a narrow valley, not aligned with any axis, punctuated with many tiny "wells" along its bottom.
            // The deepest well is at (-10,1)-> 0.
            Func<IList<double>, double> fBurkin = (IList<double> x) => 100.0 * Math.Sqrt(Math.Abs(x[1] - 0.01 * x[0] * x[0])) + 0.01 * Math.Abs(x[0] + 10.0);

            Func<IList<double>, double> threeHumpCamel = (IList<double> x) => {
                double x2 = x[0] * x[0];
                return (2.0 * x2 - 1.05 * x2 * x2 + x2 * x2 * x2 / 6.0 + (x[0] + x[1]) * x[1]);
            };

            // Easom has many lobal extra ripples and then a deep but narrow global minimum at (\pi, \pi) -> -1
            Func<IList<double>, double> fEasom = (IList<double> x) => -Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Exp(-(MoreMath.Sqr(x[0] - Math.PI) + MoreMath.Sqr(x[1] - Math.PI)));

            // Test over [-500,500], minimum at (420.969,...) -> -418.983*d, many local minima
            Func<IList<double>, double> fSchwefel = (IList<double> x) => {
                double s = 0.0;
                for (int i = 0; i < x.Count; i++) {
                    s += x[i] * Math.Sin(Math.Sqrt(Math.Abs(x[i])));
                }
                return (-s);
            };

            Func<IList<double>, double> function = fSchwefel;

            int n = 4;

            ColumnVector start = new ColumnVector(n);
            //for (int i = 0; i < start.Dimension; i++) start[i] = 1.0;

            Interval[] box = new Interval[n];
            for (int i = 0; i < box.Length; i++) {
                box[i] = Interval.FromEndpoints(-500.0, 500.0);
            }
            //box[0] = Interval.FromEndpoints(-15.0, -5.0);
            //box[1] = Interval.FromEndpoints(-3.0, 3.0);

            MultiFunctionMath.FindGlobalMinimum(function, box);
            //MultiFunctionMath.FindExtremum_Amobea(fStyblinskiTang, start, new EvaluationSettings() { RelativePrecision = 1.0E-10, AbsolutePrecision = 1.0E-12, EvaluationBudget = 1000 });
        }
        public void ThompsonGlobal()
        {
            for (int n = 2; n < 8; n++)
            {
                Console.WriteLine("n={0}", n);

                Func<IList<double>, double> f = GetThompsonFunction(n);

                Interval[] box = new Interval[2 * (n - 1)];
                for (int i = 0; i < (n - 1); i++) {
                    box[2 * i] = Interval.FromEndpoints(-Math.PI, Math.PI);
                    box[2 * i + 1] = Interval.FromEndpoints(-Math.PI / 2.0, Math.PI / 2.0);
                }

                MultiExtremum minimum = MultiFunctionMath.FindGlobalMinimum(f, box);

                Console.WriteLine(minimum.EvaluationCount);
                Console.WriteLine("{0} ({1})", minimum.Value, minimum.Precision);
                for (int i = 0; i < (n - 1); i++) {
                    Console.WriteLine("{0} {1}", minimum.Location[2 * i], minimum.Location[2 * i + 1]);
                }
                Console.WriteLine("0.0 0.0");

                Assert.IsTrue(minimum.Dimension == 2 * (n - 1));
                Assert.IsTrue(TestUtilities.IsNearlyEqual(minimum.Value, thompsonSolutions[n], new EvaluationSettings() { AbsolutePrecision = 2.0 * minimum.Precision }));

            }
        }
Exemple #21
0
        private void button1_Click(object sender, EventArgs e)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();

            ConsolaTB.Text     = "\nIniciando cálculos para el modelo de Mandl & Volek\n";
            progressBar1.Value = 0;

            double Qiny, hw, hr, CalVapor, Lv, por, densRoca, SGOil, calEspRoca, SatOil, Sw, densAgua, calEspAgua, espesor, difTermForm, condTermForm, tempVapor, tempYac, sor, Tiny;

            Qiny         = propiedades.Qiny;
            hw           = propiedades.hw;
            hr           = propiedades.hr;
            CalVapor     = propiedades.CalVapor;
            Lv           = propiedades.Lv;
            por          = propiedades.por;
            densRoca     = propiedades.densRoca;
            SGOil        = propiedades.SGOil;
            calEspRoca   = propiedades.calEspRoca;
            SatOil       = propiedades.SatOil;
            densAgua     = propiedades.densAgua;
            calEspAgua   = propiedades.calEspAgua;
            espesor      = propiedades.espesor;
            difTermForm  = propiedades.difTermForm;
            condTermForm = propiedades.condTermForm;
            tempVapor    = propiedades.tempVapor;
            tempYac      = propiedades.tempYac;
            sor          = propiedades.sor;
            Tiny         = propiedades.Tiny;
            Sw           = 1 - SatOil;

            bool Calculo = propiedades.Calculo;

            double capCalForm;

            if (!Calculo)
            {
                capCalForm = propiedades.capCalRoca;
                ConsolaTB.AppendText("\nCapacidad Calorífica de la Formación = " + capCalForm.ToString("F5") + " BTU/ft3-°F");
            }
            else
            {
                double densidadCrudo = SGOil * 62.4;
                double calEspCrudo   = 0.388 + (0.00045 * tempYac) / Math.Pow(propiedades.SGOil, 0.5);

                ConsolaTB.AppendText("\nLa capacidad calorífica será calculada\n");
                ConsolaTB.AppendText("\nCalor específico del crudo = " + calEspCrudo.ToString("F5"));

                capCalForm = (1 - por) * densRoca * calEspRoca + por * (densidadCrudo * calEspCrudo * SatOil + densAgua * calEspAgua * (Sw));
                ConsolaTB.AppendText("\nCap Calorífica Formación = " + capCalForm.ToString("F5") + " BTU/ft3-°F");
            }

            beta = Math.Pow(1 + (Lv * CalVapor / (calEspAgua * (tempVapor - tempYac))), -1);
            ConsolaTB.AppendText("\nParámetro Mandi & Volek= " + beta.ToString("F3"));

            MN.Interval inter = MN.Interval.FromEndpoints(0, 1);
            double      xi    = MN.Analysis.FunctionMath.FindZero(errorComp, inter);

            string erp = (100 * (MN.Functions.AdvancedMath.Erfc(xi) - beta) / MN.Functions.AdvancedMath.Erfc(xi)).ToString("F5");

            ConsolaTB.AppendText("\n% Error Xiterado vs Parámetro Mandi & Volek = " + erp);

            double tc = Math.Pow((xi * capCalForm * espesor * Math.Pow(difTermForm, 0.5)) / (2 * condTermForm), 2);

            ConsolaTB.AppendText("\nTiempo critico = " + tc.ToString("F3") + " horas");

            double Qi = (350.0 / 24.0) * Qiny * ((hw - hr) + CalVapor * Lv); //Tasa de inyección de calor

            ConsolaTB.AppendText("\nTasa de Inyección de Calor = " + Qi.ToString("F3") + " BTU/día\n");

            progressBar1.Value = 20;

            /* Comienzo de la corrida de calculos */


            DataTable caudales = OfficeHandler.createTable("Tiempo", "Caudal");

            double tiempo = 0;

            /*Calculo con Marx y Langhenheim */

            ConsolaTB.AppendText("\nCalculando tasas de flujo en región menor a Tc con Marx & Langhenheim:\n\n");

            while (tiempo < tc && tiempo < (Tiny * 24))
            {
                tiempo = tiempo + 24;

                double X = ((2 * propiedades.condTermForm) / (capCalForm * propiedades.espesor * Math.Pow(propiedades.difTermForm, 0.5))) * Math.Pow(tiempo, 0.5);

                double error = MN.Functions.AdvancedMath.Erfc(X);

                double q0 = 4.274 * (Qi * propiedades.por * (propiedades.SatOil - propiedades.sor) * error) / (capCalForm * (propiedades.tempVapor - propiedades.tempYac));

                ConsolaTB.AppendText("\nT=" + tiempo + " horas \t Q=" + q0.ToString("F3") + " BBL/dia");

                caudales.Rows.Add(tiempo, q0);
            }

            progressBar1.Value = 70;

            if (tiempo <= Tiny * 24)
            {
                ConsolaTB.AppendText("\n\nCalculando tasas de flujo en región mayor a Tc con Mandl & Volek: ");
            }

            while (tiempo <= Tiny * 24)
            {
                tiempo = tiempo + 24;
                double X = ((2 * propiedades.condTermForm) / (capCalForm * propiedades.espesor * Math.Pow(propiedades.difTermForm, 0.5))) * Math.Pow(tiempo, 0.5);

                double error = MN.Functions.AdvancedMath.Erfc(X);

                double t1 = 4.274 * (Qi * propiedades.por * (propiedades.SatOil - propiedades.sor)) / (capCalForm * (propiedades.tempVapor - propiedades.tempYac));

                double xdiff = Math.Pow(X, 2) - Math.Pow(MN.Functions.AdvancedMath.Erfc(xi), 2);

                double t2 = (1 - ((xdiff - 2) * Math.Pow(xdiff, 0.5) / (3 * Math.Pow(Math.PI, 0.5))) - ((xdiff - 3) / (6 * Math.Pow(Math.PI * xdiff, 0.5)))) * error;

                double t3 = ((1 / (3 * Math.PI)) * (xdiff - 2 + (Math.Pow(MN.Functions.AdvancedMath.Erfc(xi), 2) / 2 * Math.Pow(X, 2))) * Math.Pow(xdiff / X, 0.5)) - (beta / (2 * Math.Pow(Math.PI * xdiff, 0.5)));

                double q0 = t1 * (t2 + t3);

                ConsolaTB.AppendText("\nT=" + tiempo + " horas \t Q=" + q0.ToString("F3") + " BBL/dia");

                caudales.Rows.Add(tiempo, q0);
            }

            progressBar1.Value = 95;

            double Acumulado = 0;

            foreach (DataRow row in caudales.Rows)
            {
                Acumulado = Acumulado + Double.Parse(row["Caudal"].ToString());
            }

            watch.Stop();
            double elapsedMs = watch.ElapsedMilliseconds;

            ConsolaTB.AppendText("\n\nCálculos finalizados. \nTiempo total = " + propiedades.Tiny.ToString("F2") + " días\nAcumulado= " + Acumulado.ToString("F3") + " Barriles \nTiempo de calculo=" + elapsedMs / 1000 + " segundos");

            progressBar1.Value = 100;

            if (MessageBox.Show("Cálculos finalizados, ¿ Desea exportar a excel los resultados ?", "Cálculos finalizados", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
            {
                OfficeHandler.exportExcel(caudales);
            }
        }