/// <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 δf ∼ (δx)<sup>2</sup>, so changes in the function value δf ∼ ε correspond to changes in the /// argument value δx ∼ √ε. 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 })); } }
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); } }