public void ZetaIntegrals() { // By expanding 1/(1-x) = 1 + x + x^2 + ... and integrating term-by-term // it's easy to show that this integral is \zeta(d) Func <IList <double>, double> f = delegate(IList <double> x) { double p = 1.0; for (int i = 0; i < x.Count; i++) { p *= x[i]; } return(1.0 / (1.0 - p)); }; // \zeta(1) is infinite, so skip d=1 for (int d = 2; d <= 10; d++) { Console.WriteLine(d); IntegrationResult result = MultiFunctionMath.Integrate(f, UnitCube(d)); Console.WriteLine("{0} ({1}) {2}", result.Value, result.Precision, AdvancedMath.RiemannZeta(d)); Assert.IsTrue(TestUtilities.IsNearlyEqual(result.Value, AdvancedMath.RiemannZeta(d), new EvaluationSettings() { AbsolutePrecision = 2.0 * result.Precision })); } }
public void GoldsteinPrice() { // Goldstein-Price has a valley with a complicated shape and a global minimum value of 3 at (0,-1). // It also has local minima, so we have to start close to this minimum if we expect to end at it. Func <IList <double>, double> fGoldsteinPrice = (IList <double> v) => { double x = v[0]; double y = v[1]; return( (1 + MoreMath.Pow(x + y + 1, 2) * (19 - 14 * x + 3 * x * x - 14 * y + 6 * x * y + 6 * y * y)) * (30 + MoreMath.Pow(2 * x - 3 * y, 2) * (18 - 32 * x + 12 * x * x + 48 * y - 36 * x * y + 27 * y * y)) ); }; ColumnVector start = new ColumnVector(0.5, -0.5); MultiExtremum min = MultiFunctionMath.FindLocalMinimum(fGoldsteinPrice, start); Console.WriteLine(min.EvaluationCount); Console.WriteLine(min.Value); Assert.IsTrue(min.Dimension == 2); Assert.IsTrue(TestUtilities.IsNearlyEqual(min.Value, 3.0)); Assert.IsTrue(TestUtilities.IsNearlyEqual(min.Location, new ColumnVector(0.0, -1.0), Math.Sqrt(TestUtilities.TargetPrecision))); MultiExtremum min2 = MultiFunctionMath.FindGlobalMinimum(fGoldsteinPrice, new Interval[] { Interval.FromEndpoints(-2.0, 2.0), Interval.FromEndpoints(-2.0, 2.0) }); Assert.IsTrue(min2.Dimension == 2); Assert.IsTrue(TestUtilities.IsNearlyEqual(min2.Value, 3.0, new EvaluationSettings() { AbsolutePrecision = min2.Precision })); //Assert.IsTrue(TestUtilities.IsNearlyEqual(min2.Location, new ColumnVector(0.0, -1.0), Math.Sqrt(TestUtilities.TargetPrecision))); }
public void MultiRootExtendedRosenbock() { Random rng = new Random(1); // dimension must be even for this one for (int d = 2; d <= 10; d += 2) { Func <IReadOnlyList <double>, IReadOnlyList <double> > f = delegate(IReadOnlyList <double> u) { double[] v = new double[d]; for (int k = 0; k < d / 2; k++) { v[2 * k] = 1.0 - u[2 * k + 1]; v[2 * k + 1] = 10.0 * (u[2 * k] - MoreMath.Pow(u[2 * k + 1], 2)); } return(v); }; ColumnVector x = MultiFunctionMath.FindZero(f, GetRandomStartingVector(rng, d)); // the solution is (1, 1, ..., 1) for (int i = 0; i < d; i++) { Assert.IsTrue(TestUtilities.IsNearlyEqual(x[i], 1.0)); } // and of course the function should evaluate to zero IReadOnlyList <double> y = f(x); for (int i = 0; i < d; i++) { Assert.IsTrue(Math.Abs(y[i]) < TestUtilities.TargetPrecision); } } }
public void SteinmetzVolume() { // Steinmetz solid is intersection of unit cylinders along all axes. This is another hard-edged integral. Analytic values are known for d=2-5. // http://www.math.illinois.edu/~hildebr/ugresearch/cylinder-spring2013report.pdf // http://www.math.uiuc.edu/~hildebr/igl/nvolumes-fall2012report.pdf EvaluationSettings settings = new EvaluationSettings() { EvaluationBudget = 1000000, RelativePrecision = 1.0E-2 }; for (int d = 2; d <= 5; d++) { IntegrationResult v1 = MultiFunctionMath.Integrate((IList <double> x) => { for (int i = 0; i < d; i++) { double s = 0.0; for (int j = 0; j < d; j++) { if (j != i) { s += x[j] * x[j]; } } if (s > 1.0) { return(0.0); } } return(1.0); }, SymmetricUnitCube(d), settings); double v2 = 0.0; switch (d) { case 2: // trivial square v2 = 4.0; break; case 3: v2 = 16.0 - 8.0 * Math.Sqrt(2.0); break; case 4: v2 = 48.0 * (Math.PI / 4.0 - Math.Atan(Math.Sqrt(2.0)) / Math.Sqrt(2.0)); break; case 5: v2 = 256.0 * (Math.PI / 12.0 - Math.Atan(1.0 / (2.0 * Math.Sqrt(2.0))) / Math.Sqrt(2.0)); break; } Console.WriteLine("{0} {1} {2}", d, v1.Value, v2); Assert.IsTrue(TestUtilities.IsNearlyEqual(v1.Value, v2, new EvaluationSettings() { AbsolutePrecision = 4.0 * v1.Precision })); } }
public void MinimizeQuadratic1D() { Func <IList <double>, double> f = (IList <double> x) => 1.0 + MoreMath.Sqr(x[0] - 3.0); MultiExtremum m = MultiFunctionMath.FindLocalMinimum(f, new double[] { 1.0 }); Assert.IsTrue(TestUtilities.IsNearlyEqual(1.0, m.Value)); }
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 MinimizePerturbedQuadratic2D() { int count = 0; MultiExtremumSettings s = new MultiExtremumSettings() { EvaluationBudget = 100, RelativePrecision = 1.0E-10, Listener = r => { count++; } }; Func <IReadOnlyList <double>, double> f = (IReadOnlyList <double> x) => 1.0 + 2.0 * MoreMath.Sqr(x[0] - 3.0) + 4.0 * (x[0] - 3.0) * (x[1] - 5.0) + 6.0 * MoreMath.Sqr(x[1] - 5.0) + 7.0 * MoreMath.Pow(x[0] - 3.0, 4) + 8.0 * MoreMath.Pow(x[1] - 5.0, 4); MultiExtremum m = MultiFunctionMath.FindLocalMinimum(f, new double[] { 1.0, 1.0 }, s); Assert.IsTrue(m.EvaluationCount <= s.EvaluationBudget); Assert.IsTrue(m.Dimension == 2); Assert.IsTrue(TestUtilities.IsNearlyEqual(m.Value, 1.0, s)); Assert.IsTrue(TestUtilities.IsNearlyEqual(m.Location, new ColumnVector(3.0, 5.0), new EvaluationSettings() { RelativePrecision = Math.Sqrt(s.RelativePrecision) })); Assert.IsTrue(count > 0); }
public void OdeLorenz() { double sigma = 10.0; double beta = 8.0 / 3.0; double rho = 28.0; Func <double, IReadOnlyList <double>, IReadOnlyList <double> > rhs = (double t, IReadOnlyList <double> u) => new ColumnVector( sigma * (u[1] - u[0]), u[0] * (rho - u[2]) - u[1], u[0] * u[1] - beta * u[2] ); MultiOdeSettings settings = new MultiOdeSettings() { RelativePrecision = 1.0E-8, EvaluationBudget = 10000 }; ColumnVector u0 = new ColumnVector(1.0, 1.0, 1.0); MultiOdeResult result = MultiFunctionMath.IntegrateOde(rhs, 0.0, u0, 10.0, settings); Console.WriteLine(result.EvaluationCount); // Is there anything we can assert? There is no analytic solution or conserved quantity. }
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 })); } }
public void OdeLRC() { double L = 1.0; double R = 1.0; double C = 1.0; Func <double, IList <double>, IList <double> > rhs = (double x, IList <double> y) => { double q = y[0]; double qp = y[1]; return(new double[] { qp, (0.0 - q / C - R * qp) / L }); }; double q0 = 1.0; double qp0 = 0.0; double t0 = 2.0 * L / R; double w0 = Math.Sqrt(1.0 / (L * C) - 1.0 / (t0 * t0)); double t = 1.0; double sc = (q0 * Math.Cos(w0 * t) + (qp0 + q0 / t0) / w0 * Math.Sin(w0 * t)) * Math.Exp(-t / t0); Console.WriteLine(sc); IList <double> s = MultiFunctionMath.SolveOde(rhs, 0.0, new double[] { q0, qp0 }, t).Y; Console.WriteLine(s[0]); }
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 Interval watsonWidth = Interval.FromEndpoints(0.0, Math.PI); Interval[] watsonBox = new Interval[] { watsonWidth, watsonWidth, watsonWidth }; Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 - Math.Cos(x[0]) * Math.Cos(x[1]) * Math.Cos(x[2])), watsonBox ).Estimate.ConfidenceInterval(0.99).ClosedContains( MoreMath.Pow(AdvancedMath.Gamma(1.0 / 4.0), 4) / 4.0 ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <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 ).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( (IReadOnlyList <double> x) => 1.0 / (3.0 - Math.Cos(x[0]) - Math.Cos(x[1]) - Math.Cos(x[2])), watsonBox ).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 SeperableIntegrals() { // Integrates \Pi_{j=0}^{d-1} \int_0^1 \! dx \, x_j^j = \Pi_{j=0}^{d-1} \frac{1}{j+1} = \frac{1}{d!} // This is a simple test of a seperable integral Func <IReadOnlyList <double>, double> f = delegate(IReadOnlyList <double> x) { double y = 1.0; for (int j = 0; j < x.Count; j++) { y *= MoreMath.Pow(x[j], j); } return(y); }; for (int d = 1; d <= 10; d++) { Console.WriteLine(d); // Result gets very small, so rely on relative rather than absolute precision. IntegrationSettings s = new IntegrationSettings() { AbsolutePrecision = 0, RelativePrecision = Math.Pow(10.0, -(6.0 - d / 2.0)) }; IntegrationResult r = MultiFunctionMath.Integrate(f, UnitCube(d), s); Assert.IsTrue(r.Estimate.ConfidenceInterval(0.95).ClosedContains(1.0 / AdvancedIntegerMath.Factorial(d))); } }
public void SeperableIntegrals() { // Integrates \Pi_{j=0}^{d-1} \int_0^1 \! dx \, x_j^j = \Pi_{j=0}^{d-1} \frac{1}{j+1} = \frac{1}{d!} // This is a simple test of a seperable integral Func <IList <double>, double> f = delegate(IList <double> x) { double y = 1.0; for (int j = 0; j < x.Count; j++) { y *= MoreMath.Pow(x[j], j); } return(y); }; for (int d = 1; d <= 10; d++) { Console.WriteLine(d); IntegrationResult r = MultiFunctionMath.Integrate(f, UnitCube(d)); Console.WriteLine("{0}: {1} ({2}) ?= {3}", r.EvaluationCount, r.Value, r.Precision, 1.0 / AdvancedIntegerMath.Factorial(d)); Assert.IsTrue(TestUtilities.IsNearlyEqual( r.Value, 1.0 / AdvancedIntegerMath.Factorial(d), new EvaluationSettings() { AbsolutePrecision = 2.0 * r.Precision } )); } }
public void Perm() { Func <IList <double>, double> fPerm = (IList <double> x) => { double s = 0.0; for (int i = 1; i <= x.Count; i++) { double t = 0.0; for (int j = 0; j < x.Count; j++) { t += (j + 1) * (MoreMath.Pow(x[j], i) - 1.0 / MoreMath.Pow(j + 1, i)); } s += MoreMath.Sqr(t); } return(s); }; int n = 4; ColumnVector start = new ColumnVector(n); MultiExtremum minimum = MultiFunctionMath.FindLocalMinimum(fPerm, start); Console.WriteLine(minimum.EvaluationCount); Console.WriteLine(minimum.Value); for (int i = 0; i < minimum.Dimension; i++) { Console.WriteLine(minimum.Location[i]); } }
public void Beale() { // Beale is a very interesting function. // The only local minimum is at (3,1/2) where the function value is 0. // But along the lines (0,+\infty) and (-\infty,1) the function value decreases toward 0 at infinity. // From the point of view of a local minimizer those are perfectly valid downhill directions and // if the minimzer gets caught in them it will move toward infinity until its evaluation budget is // exhausted. Starting from y > 0 will probably keep us safe, or we can do bounded optimization. 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]); ColumnVector start = new ColumnVector(2.0, 1.0); MultiExtremum min = MultiFunctionMath.FindLocalMinimum(fBeale, start); Console.WriteLine(min.EvaluationCount); Console.WriteLine(min.Value); ColumnVector solution = new ColumnVector(3.0, 0.5); Assert.IsTrue(min.Dimension == 2); Assert.IsTrue(TestUtilities.IsNearlyEqual(min.Value, 0.0, new EvaluationSettings() { AbsolutePrecision = min.Precision })); Assert.IsTrue(TestUtilities.IsNearlyEqual(min.Location, solution, Math.Sqrt(TestUtilities.TargetPrecision))); }
public void OdeSine2() { Func <double, IList <double>, IList <double> > f2 = (double x, IList <double> y) => new double[] { -y[0] }; double[] y0 = new double[] { 0.0 }; double[] yp0 = new double[] { 1.0 }; ColumnVector z = MultiFunctionMath.SolveConservativeOde(f2, 0.0, y0, yp0, 5.0); }
/// <summary> /// Performs a linear logistic regression analysis. /// </summary> /// <param name="outputIndex">The index of the column to predict.</param> /// <returns></returns> /// <remarks>Logistic linear regression is suited to situations where multiple input variables, either continuous or binary indicators, are used to predict /// the value of a binary output variable. Like a linear regression, a logistic linear regression tries to find a model that predicts the output variable using /// a linear combination of input variables. Unlike a simple linear regression, the model does not assume that this linear /// function predicts the output directly; instead it assumes that this function value is then fed into a logit link function, which /// maps the real numbers into the interval (0, 1), and interprets the value of this link function as the probability of obtaining success value /// for the output variable.</remarks> /// <exception cref="InvalidOperationException">The column to be predicted contains values other than 0 and 1.</exception> /// <exception cref="InsufficientDataException">There are not more rows in the sample than columns.</exception> public FitResult LogisticLinearRegression(int outputIndex) { if ((outputIndex < 0) || (outputIndex >= this.Dimension)) { throw new ArgumentOutOfRangeException("outputIndex"); } if (this.Count <= this.Dimension) { throw new InsufficientDataException(); } // Define the log likelihood as a function of the parameter set Func <IList <double>, double> logLikelihood = (IList <double> a) => { double L = 0.0; for (int k = 0; k < this.Count; k++) { double z = 0.0; for (int i = 0; i < this.storage.Length; i++) { if (i == outputIndex) { z += a[i]; } else { z += a[i] * this.storage[i][k]; } } double ez = Math.Exp(z); double y = this.storage[outputIndex][k]; if (y == 0.0) { L -= Math.Log(1.0 + ez); } else if (y == 1.0) { L -= Math.Log(1.0 + 1.0 / ez); } else { throw new InvalidOperationException(); } } return(L); }; double[] start = new double[this.Dimension]; //for (int i = 0; i < start.Length; i++) { // if (i != outputIndex) start[i] = this.TwoColumns(i, outputIndex).Covariance / this.Column(i).Variance / this.Column(outputIndex).Variance; //} MultiExtremum maximum = MultiFunctionMath.FindLocalMaximum(logLikelihood, start); FitResult result = new FitResult(maximum.Location, maximum.HessianMatrix.CholeskyDecomposition().Inverse(), null); return(result); }
public void OdeLotkaVolterra() { // Lotka/Volterra equations are a non-linear predator-prey model. // \dot{x} = A x + B x y // \dot{y} = -C y + D x y // See http://mathworld.wolfram.com/Lotka-VolterraEquations.html // It can be shown solutions are always periodic (but not sinusoidal, and // often with phase shift between x and y). // Equilibria are x, y = C/D, A /B (and 0, 0). // If started positive, x and y never go negative. // A conserved quantity is: - D x + C log x - B y + A log y // Period of equations linearized around equilibrium is 2 \pi / \sqrt{AC}. // Can also be used to model chemical reaction rates. double A = 1.5; // Prey growth rate double B = 1.0; double C = 3.0; // Predator death rate double D = 1.0; // Try A = 20, B = 1, C = 30, D = 1, X = 8, Y = 12, T = 1 // Try A = 1.5, B = 1 C = 3, D = 1, X = 10, Y = 5, T = 10 Func <double, IReadOnlyList <double>, IReadOnlyList <double> > rhs = (double t, IReadOnlyList <double> p) => new double[] { A *p[0] - B * p[0] * p[1], -C *p[1] + D * p[0] * p[1] }; Func <IList <double>, double> conservedQuantity = (IList <double> p) => - D * p[0] + C * Math.Log(p[0]) - B * p[1] + A * Math.Log(p[1]); ColumnVector p0 = new ColumnVector(10.0, 5.0); double L0 = conservedQuantity(p0); // Set up a handler that verifies conservation and positivity MultiOdeSettings settings = new MultiOdeSettings() { Listener = (MultiOdeResult rr) => { double L = conservedQuantity(rr.Y); Assert.IsTrue(rr.Y[0] > 0.0); Assert.IsTrue(rr.Y[1] > 0.0); Assert.IsTrue(TestUtilities.IsNearlyEqual(L, L0, rr.Settings)); } }; // Estimate period double T = 2.0 * Math.PI / Math.Sqrt(A * C); // Integrate over a few estimated periods MultiOdeResult result = MultiFunctionMath.IntegrateOde(rhs, 0.0, p0, 3.0 * T, settings); Console.WriteLine(result.EvaluationCount); }
public static void IntegrateOde() { Func <double, double, double> rhs = (x, y) => - x * y; OdeResult sln = FunctionMath.IntegrateOde(rhs, 0.0, 1.0, 2.0); Console.WriteLine($"Numeric solution y({sln.X}) = {sln.Y}."); Console.WriteLine($"Required {sln.EvaluationCount} evaluations."); Console.WriteLine($"Analytic solution y({sln.X}) = {Math.Exp(-MoreMath.Sqr(sln.X) / 2.0)}"); // Lotka-Volterra equations double A = 0.1; double B = 0.02; double C = 0.4; double D = 0.02; Func <double, IReadOnlyList <double>, IReadOnlyList <double> > lkRhs = (t, y) => { return(new double[] { A *y[0] - B * y[0] * y[1], D *y[0] * y[1] - C * y[1] }); }; MultiOdeSettings lkSettings = new MultiOdeSettings() { Listener = r => { Console.WriteLine($"t={r.X} rabbits={r.Y[0]}, foxes={r.Y[1]}"); } }; MultiFunctionMath.IntegrateOde(lkRhs, 0.0, new double[] { 20.0, 10.0 }, 50.0, lkSettings); Func <double, IReadOnlyList <double>, IReadOnlyList <double> > rhs1 = (x, u) => { return(new double[] { u[1], -u[0] }); }; MultiOdeSettings settings1 = new MultiOdeSettings() { EvaluationBudget = 100000 }; MultiOdeResult result1 = MultiFunctionMath.IntegrateOde( rhs1, 0.0, new double[] { 0.0, 1.0 }, 500.0, settings1 ); double s1 = MoreMath.Sqr(result1.Y[0]) + MoreMath.Sqr(result1.Y[1]); Console.WriteLine($"y({result1.X}) = {result1.Y[0]}, (y)^2 + (y')^2 = {s1}"); Console.WriteLine($"Required {result1.EvaluationCount} evaluations."); Func <double, double, double> rhs2 = (x, y) => - y; OdeSettings settings2 = new OdeSettings() { EvaluationBudget = 100000 }; OdeResult result2 = FunctionMath.IntegrateConservativeOde( rhs2, 0.0, 0.0, 1.0, 500.0, settings2 ); double s2 = MoreMath.Sqr(result2.Y) + MoreMath.Sqr(result2.YPrime); Console.WriteLine($"y({result2.X}) = {result2.Y}, (y)^2 + (y')^2 = {s2}"); Console.WriteLine($"Required {result2.EvaluationCount} evaluations"); Console.WriteLine(MoreMath.Sin(500.0)); }
internal NonlinearRegressionResult( IReadOnlyList <double> x, IReadOnlyList <double> y, Func <IReadOnlyList <double>, double, double> function, IReadOnlyList <double> start, IReadOnlyList <string> names) { Debug.Assert(x != null); Debug.Assert(y != null); Debug.Assert(function != null); Debug.Assert(start != null); Debug.Assert(names != null); Debug.Assert(x.Count == y.Count); Debug.Assert(start.Count > 0); Debug.Assert(names.Count == start.Count); int n = x.Count; int d = start.Count; if (n <= d) { throw new InsufficientDataException(); } MultiExtremum min = MultiFunctionMath.FindLocalMinimum((IReadOnlyList <double> a) => { double ss = 0.0; for (int i = 0; i < n; i++) { double r = y[i] - function(a, x[i]); ss += r * r; } return(ss); }, start); CholeskyDecomposition cholesky = min.HessianMatrix.CholeskyDecomposition(); if (cholesky == null) { throw new DivideByZeroException(); } b = min.Location; C = cholesky.Inverse(); C = (2.0 * min.Value / (n - d)) * C; sumOfSquaredResiduals = 0.0; residuals = new List <double>(n); for (int i = 0; i < n; i++) { double z = y[i] - function(b, x[i]); sumOfSquaredResiduals += z * z; residuals.Add(z); } this.names = names; this.function = function; }
public double BoxIntegralB(int d, int r, IntegrationSettings settings) { return(MultiFunctionMath.Integrate((IReadOnlyList <double> x) => { double s = 0.0; for (int k = 0; k < d; k++) { s += x[k] * x[k]; } return (Math.Pow(s, r / 2.0)); }, UnitCube(d), settings).Value); }
private IntegrationResult RambleIntegral(int d, int s, IntegrationSettings settings) { return(MultiFunctionMath.Integrate((IReadOnlyList <double> x) => { Complex z = 0.0; for (int k = 0; k < d; k++) { z += ComplexMath.Exp(2.0 * Math.PI * Complex.I * x[k]); } return (MoreMath.Pow(ComplexMath.Abs(z), s)); }, UnitCube(d), settings)); }
public double BoxIntegralD(int d, int r, EvaluationSettings settings) { return(MultiFunctionMath.Integrate((IList <double> x) => { double s = 0.0; for (int k = 0; k < d; k++) { double z = x[k] - x[k + d]; s += z * z; } return (Math.Pow(s, r / 2.0)); }, UnitCube(2 * d), settings).Value); }
public void UnitSquareIntegrals() { // http://mathworld.wolfram.com/UnitSquareIntegral.html has a long list of integrals over the unit square. // Many are taken from Guillera and Sondow, // "Double Integrals and Infinite Products for Some Classical Constants Via Analytic Continuations of Lerch's Transcendent.", // 16 June 2005. (http://arxiv.org/abs/math.NT/0506319) Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 - x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( AdvancedMath.RiemannZeta(2.0) ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => - Math.Log(x[0] * x[1]) / (1.0 - x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( 2.0 * AdvancedMath.RiemannZeta(3.0) ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => (x[0] - 1.0) / (1.0 - x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( AdvancedMath.EulerGamma ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => (x[0] - 1.0) / (1.0 + x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( Math.Log(4.0 / Math.PI) ) ); Assert.IsTrue( MultiFunctionMath.Integrate( (IReadOnlyList <double> x) => 1.0 / (1.0 + MoreMath.Sqr(x[0] * x[1])), UnitCube(2) ).Estimate.ConfidenceInterval(0.95).ClosedContains( AdvancedMath.Catalan ) ); }
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 OdeCatenary() { // The equation of a catenary is // \frac{d^2 y}{dx^2} = \sqrt{1.0 + \left(\frac{dy}{dx}\right)^2} // with y(0) = 1 and y'(0) = 0 and solution y = \cosh(x) Func <double, IReadOnlyList <double>, IReadOnlyList <double> > rhs = (double t, IReadOnlyList <double> y) => new double[] { y[1], MoreMath.Hypot(1.0, y[1]) }; MultiOdeResult result = MultiFunctionMath.IntegrateOde(rhs, 0.0, new double[] { 1.0, 0.0 }, 2.0); Assert.IsTrue(TestUtilities.IsNearlyEqual(result.Y[0], Math.Cosh(2.0))); }
public void DoubleIntegrals() { // At http://mathworld.wolfram.com/DoubleIntegral.html, Mathworld // lists a few double integrals with known values that we take as // tests. // One of the integrals listed there is just the zeta integral for d=2 // which we do above, so we omit it here. // Because these are non-ocsilatory and have relatively low // dimension, we can demand fairly high accuracy. IntegrationResult i1 = MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (1.0 - x[0] * x[0] * x[1] * x[1]), UnitCube(2) ); Console.WriteLine("{0} ({1})", i1.Value, i1.Precision); Assert.IsTrue(TestUtilities.IsNearlyEqual(i1.Value, Math.PI * Math.PI / 8.0, new EvaluationSettings() { AbsolutePrecision = 2.0 * i1.Precision })); //Assert.IsTrue(i1.Estimate.ConfidenceInterval(0.99).ClosedContains(Math.PI * Math.PI / 8.0)); IntegrationResult i2 = MultiFunctionMath.Integrate( (IList <double> x) => 1.0 / (x[0] + x[1]) / Math.Sqrt((1.0 - x[0]) * (1.0 - x[1])), UnitCube(2), new EvaluationSettings() { RelativePrecision = 1.0E-5, EvaluationBudget = 1000000 } ); Console.WriteLine("{0} ({1})", i2.Value, i2.Precision); Assert.IsTrue(TestUtilities.IsNearlyEqual(i2.Value, 4.0 * AdvancedMath.Catalan, new EvaluationSettings() { AbsolutePrecision = 2.0 * i2.Precision })); // For higher precision demands on this integral, we start getting Infinity +/- NaN for estimate and never terminate, look into this. IntegrationResult i3 = MultiFunctionMath.Integrate( (IList <double> x) => (x[0] - 1.0) / (1.0 - x[0] * x[1]) / Math.Log(x[0] * x[1]), UnitCube(2) ); Console.WriteLine("{0} ({1})", i3.Value, i3.Precision); Assert.IsTrue(TestUtilities.IsNearlyEqual(i3.Value, AdvancedMath.EulerGamma, new EvaluationSettings() { AbsolutePrecision = 2.0 * i3.Precision })); }
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 })); } }
public void OdeOrbit() { // This is a simple Keplerian orbit. // Hull (1972) constructed initial conditions that guarantee a given orbital eccentricity // and a period of 2 \pi with unit masses and unit gravitational constant. Func <double, IList <double>, IList <double> > rhs = (double t, IList <double> r) => { double d = MoreMath.Hypot(r[0], r[1]); double d3 = MoreMath.Pow(d, 3); return(new double[] { -r[0] / d3, -r[1] / d3 }); }; EvaluationSettings settings = new EvaluationSettings() { RelativePrecision = 1.0E-12, AbsolutePrecision = 1.0E-24, EvaluationBudget = 10000 }; settings.UpdateHandler = (EvaluationResult a) => { OdeResult <IList <double> > b = (OdeResult <IList <double> >)a; Console.WriteLine("{0} {1}", b.EvaluationCount, b.X); }; //double e = 0.5; foreach (double e in TestUtilities.GenerateUniformRealValues(0.0, 1.0, 8)) { Console.WriteLine("e = {0}", e); ColumnVector r0 = new ColumnVector(1.0 - e, 0.0); ColumnVector rp0 = new ColumnVector(0.0, Math.Sqrt((1.0 + e) / (1.0 - e))); settings.UpdateHandler = (EvaluationResult a) => { OdeResult <IList <double> > b = (OdeResult <IList <double> >)a; Console.WriteLine(" {0} {1}", b.EvaluationCount, b.X); Console.WriteLine(" {0} ?= {1}", OrbitEnergy(b.Y, b.YPrime), OrbitEnergy(r0, rp0)); Assert.IsTrue(TestUtilities.IsNearlyEqual(OrbitAngularMomentum(b.Y, b.YPrime), OrbitAngularMomentum(r0, rp0), settings)); Assert.IsTrue(TestUtilities.IsNearlyEqual(OrbitEnergy(b.Y, b.YPrime), OrbitEnergy(r0, rp0), new EvaluationSettings() { RelativePrecision = 2.0E-12 })); }; ColumnVector r1 = MultiFunctionMath.SolveConservativeOde(rhs, 0.0, r0, rp0, 2.0 * Math.PI, settings); // The Assert.IsTrue(TestUtilities.IsNearlyEqual(r0, r1, new EvaluationSettings() { RelativePrecision = 1.0E-9 })); } }
public void GaussianIntegrals() { Random rng = new Random(1); for (int d = 2; d < 8; d++) { 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 <IReadOnlyList <double>, double> f = (IReadOnlyList <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); } // These are difficult integrals; demand reduced precision. IntegrationSettings settings = new IntegrationSettings() { RelativePrecision = Math.Pow(10.0, -(4.0 - d / 2.0)) }; IntegrationResult I = MultiFunctionMath.Integrate(f, volume, settings); // Compare to the analytic result Assert.IsTrue(I.Estimate.ConfidenceInterval(0.95).ClosedContains(Math.Sqrt(MoreMath.Pow(Math.PI, d) / detA))); } }