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