示例#1
0
        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)));
        }
示例#3
0
        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);
                }
            }
        }
示例#4
0
        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.
        }
示例#7
0
        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);
        }
示例#8
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
                }));
            }
        }
示例#10
0
        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]);
        }
示例#11
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)
                    )
                );
        }
示例#12
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)));
            }
        }
示例#13
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 <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)));
        }
示例#16
0
        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);
        }
示例#17
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);
        }
示例#18
0
        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);
        }
示例#19
0
        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;
        }
示例#21
0
 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);
 }
示例#22
0
 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));
 }
示例#23
0
 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);
 }
示例#24
0
        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)
                }));
            }
        }
示例#26
0
        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)));
        }
示例#27
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
            }));
        }
示例#28
0
        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
                }));
            }
        }
示例#29
0
        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
                }));
            }
        }
示例#30
0
        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)));
            }
        }