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