public void AssociatedLegendreOrthonormalityL() { // don't let l and m get too big, or numerical integration will fail due to heavily oscilatory behavior int[] ells = TestUtilities.GenerateIntegerValues(1, 10, 4); for (int ki = 0; ki < ells.Length; ki++) { int k = ells[ki]; for (int li = 0; li <= ki; li++) { int l = ells[li]; foreach (int m in TestUtilities.GenerateUniformIntegerValues(0, Math.Min(k, l), 4)) { Func <double, double> f = delegate(double x) { return(OrthogonalPolynomials.LegendreP(k, m, x) * OrthogonalPolynomials.LegendreP(l, m, x)); }; double I = FunctionMath.Integrate(f, Interval.FromEndpoints(-1.0, 1.0)); Console.WriteLine("k={0} l={1} m={2} I={3}", k, l, m, I); if (k == l) { Assert.IsTrue(TestUtilities.IsNearlyEqual( I, 2.0 / (2 * k + 1) * Math.Exp(AdvancedIntegerMath.LogFactorial(l + m) - AdvancedIntegerMath.LogFactorial(l - m)) )); } else { Assert.IsTrue(Math.Abs(I) < TestUtilities.TargetPrecision); } } } } }
public void JacobiIntegrals() { foreach (double k in TestUtilities.GenerateRealValues(1.0E-1, 1.0, 4)) { // DLMF 22.14.18 says // \int_{0}^{K(k)} \ln(\dn(t, k)) \, dt = \frac{1}{2} K(k) \ln k' double K = AdvancedMath.EllipticK(k); double k1 = Math.Sqrt(1.0 - k * k); double I1 = FunctionMath.Integrate( x => Math.Log(AdvancedMath.JacobiDn(x, k)), Interval.FromEndpoints(0.0, K) ); Assert.IsTrue(TestUtilities.IsNearlyEqual(I1, K / 2.0 * Math.Log(k1))); // If k is small, log(k1) is subject to cancellation error, so don't pick k too small. // It also gives values for the analogous integrals with \sn and \cn, // but their values involve K'(k), for which we don't have a method. // Mathworld (http://mathworld.wolfram.com/CompleteEllipticIntegraloftheSecondKind.html) says // \int_{0}^{K(k)} \dn^2(t, k) = E(k) double I2 = FunctionMath.Integrate( u => MoreMath.Sqr(AdvancedMath.JacobiDn(u, k)), Interval.FromEndpoints(0.0, K) ); Assert.IsTrue(TestUtilities.IsNearlyEqual(I2, AdvancedMath.EllipticE(k))); } }
// COrrel Making for Hybrid Method! public SymmetricMatrix MakeCorrel(int n, Grid grid) { //Correlation between Z , Z_1 and Z_2 //integrationCalcul Func <double, double> func = t => (double)Math.Pow((1 * grid.get_Step() - t), (H - 0.5)) * Math.Pow((2 * grid.get_Step() - t), (H - 0.5)); EvaluationSettings settings = new EvaluationSettings(); settings.AbsolutePrecision = 1.0E-9; settings.RelativePrecision = 0.0; IntegrationResult integresult = FunctionMath.Integrate(func, Meta.Numerics.Interval.FromEndpoints(0.0, grid.get_Step()), settings); #region Correlation Calcul (correl Matrix) SymmetricMatrix correl = new SymmetricMatrix(3); for (int i = 0; i < 3; i++) { correl[i, i] = 1.0; } double var_0 = (double)1 / n; double var_1 = (double)1 / (Math.Pow(n, 2 * (H - 0.5) + 1) * (2 * (H - 0.5) + 1)); double var_2 = (double)Math.Pow(2, 2 * (H - 0.5) + 1) / (Math.Pow(n, 2 * (H - 0.5) + 1) * (2 * (H - 0.5) + 1)); correl[1, 0] = (double)1 / (Math.Pow(n, H + 0.5) * (H + 0.5)) / (Math.Pow(var_0 * var_1, 0.5)); correl[2, 0] = (double)(Math.Pow(2, H + 0.5) - 1) / (Math.Pow(n, H + 0.5) * (H + 0.5)) / (Math.Pow(var_0 * var_2, 0.5)); correl[2, 1] = integresult.Value / (Math.Pow(var_2 * var_1, 0.5)); #endregion return(correl); }
public void DistributionVarianceIntegral() { foreach (ContinuousDistribution distribution in distributions) { double v = distribution.Variance; // Skip distributions with infinite variance if (Double.IsNaN(v) || Double.IsInfinity(v)) { continue; } // Skip beta distribution with enpoint singularities that cannot be numerically integrated if (distribution is BetaDistribution b && ((b.Alpha < 1.0) || (b.Beta < 1.0))) { continue; } // Determine target precision, which must be reduced for some cases where an integral singularity means that cannot achieve full precision double e = TestUtilities.TargetPrecision; GammaDistribution gammaDistribution = distribution as GammaDistribution; if ((gammaDistribution != null) && (gammaDistribution.Shape < 1.0)) { e = Math.Sqrt(e); } Func <double, double> f = delegate(double x) { double z = x - distribution.Mean; return(distribution.ProbabilityDensity(x) * z * z); }; double C2 = FunctionMath.Integrate(f, distribution.Support, new IntegrationSettings() { RelativePrecision = e, AbsolutePrecision = 0.0 }).Value; Assert.IsTrue(TestUtilities.IsNearlyEqual(C2, distribution.Variance, e)); } }
public void DistributionVarianceIntegral() { foreach (ContinuousDistribution distribution in distributions) { if (Double.IsNaN(distribution.Variance) || Double.IsInfinity(distribution.Variance)) { continue; } double e = TestUtilities.TargetPrecision; // since a Gamma distribution with \alpha < 1 has a power law singularity and numerical integration cannot achieve full precision with such a singularity, // we reduce our precision requirement in this case GammaDistribution gammaDistribution = distribution as GammaDistribution; if ((gammaDistribution != null) && (gammaDistribution.Shape < 1.0)) { e = Math.Sqrt(e); } Console.WriteLine(distribution.GetType().Name); Func <double, double> f = delegate(double x) { double z = x - distribution.Mean; return(distribution.ProbabilityDensity(x) * z * z); }; double C2 = FunctionMath.Integrate(f, distribution.Support, new IntegrationSettings() { RelativePrecision = e, AbsolutePrecision = 0.0 }).Value; Console.WriteLine(" {0} {1}", distribution.StandardDeviation, Math.Sqrt(C2)); Assert.IsTrue(TestUtilities.IsNearlyEqual(C2, distribution.Variance, e)); } }
public void DistributionRawMomentIntegral() { foreach (Distribution distribution in distributions) { // range of moments is about 3 to 30 foreach (int n in TestUtilities.GenerateIntegerValues(3, 30, 10)) { double M = distribution.Moment(n); if (Double.IsInfinity(M) || Double.IsNaN(M)) { continue; // don't try to do a non-convergent integral } Func <double, double> f = delegate(double x) { return(distribution.ProbabilityDensity(x) * Math.Pow(x, n)); }; try { double MI = FunctionMath.Integrate(f, distribution.Support); Console.WriteLine("{0} {1} {2} {3}", distribution.GetType().Name, n, M, MI); if (M == 0.0) { Assert.IsTrue(Math.Abs(MI) < TestUtilities.TargetPrecision); } else { Assert.IsTrue(TestUtilities.IsNearlyEqual(M, MI)); } } catch (NonconvergenceException) { Console.WriteLine("{0} {1} {2} NC", distribution.GetType().Name, n, M); } } } }
public void EllipticKIntegrals() { Interval i = Interval.FromEndpoints(0.0, 1.0); // http://mathworld.wolfram.com/CatalansConstant.html equation 37 Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate( k => AdvancedMath.EllipticK(k), Interval.FromEndpoints(0.0, 1.0)), 2.0 * AdvancedMath.Catalan )); Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate( k => AdvancedMath.EllipticK(k) * k, Interval.FromEndpoints(0.0, 1.0)), 1.0 )); Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate( k => AdvancedMath.EllipticK(k) / (1.0 + k), Interval.FromEndpoints(0.0, 1.0)), Math.PI * Math.PI / 8.0 )); }
public void HypergeometricIntegral() { // A&S 15.3.1 // F(a, b, c, x) = \frac{\Gamma(c)}{\Gamma(b) \Gamma(c - b)} // \int_{0}^{1} \! dt \, t^{b-1} (1 - t)^{c - b - 1} (1 - x t)^{-a} // Choose limits on a, b, c so that singularities of integrand are numerically integrable. foreach (double a in TestUtilities.GenerateRealValues(1.0, 10.0, 2)) { foreach (double b in TestUtilities.GenerateRealValues(0.6, 10.0, 2)) { foreach (double c in TestUtilities.GenerateRealValues(b + 0.6, 10.0, 2)) { foreach (double x in xs) { double I = FunctionMath.Integrate( t => Math.Pow(t, b - 1.0) * Math.Pow(1.0 - t, c - b - 1.0) * Math.Pow(1.0 - x * t, -a), Interval.FromEndpoints(0.0, 1.0) ); double B = AdvancedMath.Beta(b, c - b); Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Hypergeometric2F1(a, b, c, x), I / B)); } } } } }
public void DistributionMeanIntegral() { foreach (ContinuousDistribution distribution in distributions) { double mean = distribution.Mean; if (Double.IsNaN(mean) || Double.IsInfinity(mean)) { continue; } if (distribution is BetaDistribution b && ((b.Alpha < 1.0) || (b.Beta < 1.0))) { continue; } Func <double, double> f = delegate(double x) { return(distribution.ProbabilityDensity(x) * x); }; double M1 = FunctionMath.Integrate(f, distribution.Support); if (mean == 0.0) { Assert.IsTrue(Math.Abs(M1) <= TestUtilities.TargetPrecision); } else { Assert.IsTrue(TestUtilities.IsNearlyEqual(M1, distribution.Mean)); } } }
public void DistributionRawMomentIntegral() { foreach (ContinuousDistribution distribution in distributions) { foreach (int r in TestUtilities.GenerateIntegerValues(2, 32, 8)) { double M = distribution.RawMoment(r); if (Double.IsInfinity(M) || Double.IsNaN(M)) { continue; // don't try to do a non-convergent integral } Func <double, double> f = delegate(double x) { return(distribution.ProbabilityDensity(x) * Math.Pow(x, r)); }; try { IntegrationResult MI = FunctionMath.Integrate(f, distribution.Support); Console.WriteLine("{0} {1} {2} {3}", distribution.GetType().Name, r, M, MI); Assert.IsTrue(MI.Estimate.ConfidenceInterval(0.99).ClosedContains(M)); /* * if (M == 0.0) { * Assert.IsTrue(Math.Abs(MI) < TestUtilities.TargetPrecision); * } else { * Assert.IsTrue(TestUtilities.IsNearlyEqual(M, MI)); * } */ } catch (NonconvergenceException) { Console.WriteLine("{0} {1} {2} NC", distribution.GetType().Name, r, M); } } } }
public void EllipticKCatalanIntegral() { System.Diagnostics.Stopwatch timer = System.Diagnostics.Stopwatch.StartNew(); Interval i = Interval.FromEndpoints(0.0, 1.0); // http://mathworld.wolfram.com/CatalansConstant.html equation 37 Func <double, double> f1 = delegate(double k) { return(AdvancedMath.EllipticK(k)); }; Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(f1, i), 2.0 * AdvancedMath.Catalan )); Func <double, double> f2 = delegate(double k) { return(AdvancedMath.EllipticK(k) * k); }; Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(f2, i), 1.0 )); timer.Stop(); Console.WriteLine(timer.ElapsedTicks); }
/// <summary> /// Computes the expectation value of the given function. /// </summary> /// <param name="f">The function.</param> /// <returns>The expectation value of the function.</returns> /// <exception cref="ArgumentNullException"><paramref name="f"/> is <see langword="null"/>.</exception> public virtual double ExpectationValue(Func <double, double> f) { if (f == null) { throw new ArgumentNullException(nameof(f)); } return(FunctionMath.Integrate(x => f(x) * ProbabilityDensity(x), Support).Estimate.Value); }
public void IntegralE1Integral() { // A & S 5.1.33 Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(t => MoreMath.Sqr(AdvancedMath.IntegralE(1, t)), 0.0, Double.PositiveInfinity), 2.0 * Math.Log(2.0) )); }
public void DistributionProbabilityIntegral() { Random rng = new Random(1); // if integral is very small, we still want to get it very accurately IntegrationSettings settings = new IntegrationSettings() { AbsolutePrecision = 0.0 }; foreach (ContinuousDistribution distribution in distributions) { if (distribution is BetaDistribution b && ((b.Alpha < 1.0) || (b.Beta < 1.0))) { continue; } for (int i = 0; i < 4; i++) { double x; if (Double.IsNegativeInfinity(distribution.Support.LeftEndpoint) && Double.IsPositiveInfinity(distribution.Support.RightEndpoint)) { // pick an exponentially distributed random point with a random sign double y = rng.NextDouble(); x = -Math.Log(y); if (rng.NextDouble() < 0.5) { x = -x; } } else if (Double.IsPositiveInfinity(distribution.Support.RightEndpoint)) { // pick an exponentially distributed random point double y = rng.NextDouble(); x = distribution.Support.LeftEndpoint - Math.Log(y); } else { // pick a random point within the support x = distribution.Support.LeftEndpoint + rng.NextDouble() * distribution.Support.Width; } double P = FunctionMath.Integrate(distribution.ProbabilityDensity, Interval.FromEndpoints(distribution.Support.LeftEndpoint, x), settings).Value; double Q = FunctionMath.Integrate(distribution.ProbabilityDensity, Interval.FromEndpoints(x, distribution.Support.RightEndpoint), settings).Value; if (!TestUtilities.IsNearlyEqual(P + Q, 1.0)) { // the numerical integral for the triangular distribution can be inaccurate, because // its locally low-polynomial behavior fools the integration routine into thinking it need // not integrate as much near the inflection point as it must; this is a problem // of the integration routine (or arguably the integral), not the triangular distribution, // so skip it here continue; } Assert.IsTrue(TestUtilities.IsNearlyEqual(P, distribution.LeftProbability(x))); Assert.IsTrue(TestUtilities.IsNearlyEqual(Q, distribution.RightProbability(x))); } } }
public void IntegrateTestIntegrals() { for (int i = 0; i < integrals.Length; i++) { TestIntegral integral = integrals[i]; double result = FunctionMath.Integrate(integral.Integrand, integral.Range); Assert.IsTrue(TestUtilities.IsNearlyEqual(result, integral.Result)); } }
public void BesselWeberIntegral() { Func <double, double> f = delegate(double t) { return(Math.Exp(-t * t) * AdvancedMath.BesselJ(0, t) * t); }; Interval r = Interval.FromEndpoints(0.0, Double.PositiveInfinity); Assert.IsTrue(TestUtilities.IsNearlyEqual(FunctionMath.Integrate(f, r).Estimate.Value, Math.Exp(-1.0 / 4.0) / 2.0)); }
public void IntegralEiE1Integrals() { // Here are a couple unusual integrals involving both Ei and E1 // https://nvlpubs.nist.gov/nistpubs/jres/73B/jresv73Bn3p191_A1b.pdf Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(x => Math.Exp(-x) * AdvancedMath.IntegralE(1, x) * AdvancedMath.IntegralEi(x), 0.0, Double.PositiveInfinity), -Math.PI * Math.PI / 12.0 )); }
public virtual double ExpectationValue(Func <double, double> function) { if (function == null) { throw new ArgumentNullException(nameof(function)); } IntegrationResult result = FunctionMath.Integrate(x => function(x) * this.ProbabilityDensity(x), this.Support); return(result.Value); }
public void IntegralShiDefintion() { foreach (double x in TestUtilities.GenerateRealValues(1.0E-2, 1.0E1, 4)) { Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(t => Math.Sinh(t) / t, 0.0, x), AdvancedMath.IntegralShi(x) )); } }
public void BesselLipshitzIntegral() { // \int_{0}^{\infty} e^{-x} J_0(x) \, dx = \frac{1}{\sqrt{2}} Func <double, double> f = delegate(double t) { return(Math.Exp(-t) * AdvancedMath.BesselJ(0, t)); }; Interval r = Interval.FromEndpoints(0.0, Double.PositiveInfinity); Assert.IsTrue(TestUtilities.IsNearlyEqual(FunctionMath.Integrate(f, r).Estimate.Value, 1.0 / Math.Sqrt(2.0))); }
public void GammaIntegral() { foreach (double x in TestUtilities.GenerateRealValues(1.0, 1.0E2, 4)) { Func <double, double> f = delegate(double t) { return(Math.Pow(t, x - 1.0) * Math.Exp(-t)); }; Interval r = Interval.FromEndpoints(0.0, Double.PositiveInfinity); Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Gamma(x), FunctionMath.Integrate(f, r))); } }
public void Bug2() { // Integrate failed with a NullReference exception when all NaNs were returned. // Changed logic to ignore NaNs. Func <double, double> integrand = x => Double.NaN; IntegrationResult result = FunctionMath.Integrate(integrand, 0.0, 1.0); Assert.IsTrue(result.Estimate.Value == 0.0); }
public void SphericalBesselMomentIntegral() { // \int_0^{\infty} dx x^n j_{n+1}(x) = 1/(2n+1)!! // which follows from derivative formula // (https://math.stackexchange.com/questions/805379/integral-involving-the-spherical-bessel-function-of-the-first-kind-int-0) foreach (int n in TestUtilities.GenerateIntegerValues(4, 100, 4)) { IntegrationResult M = FunctionMath.Integrate(x => MoreMath.Pow(x, -n) * AdvancedMath.SphericalBesselJ(n + 1, x), 0.0, Double.PositiveInfinity); Assert.IsTrue(M.Estimate.ConfidenceInterval(0.95).ClosedContains(1.0 / AdvancedIntegerMath.DoubleFactorial(2 * n + 1))); } }
public void AiryAiIntegral() { // DLMF 9.10.11 Func <double, double> f = delegate(double t) { return(AdvancedMath.AiryAi(t)); }; Interval r = Interval.FromEndpoints(0.0, Double.PositiveInfinity); double I = FunctionMath.Integrate(f, r); Assert.IsTrue(TestUtilities.IsNearlyEqual(I, 1.0 / 3.0)); }
public void IntegralCinDefinition() { // To avoid cancellation error, near cos(x) ~ 1, use half-angle formula // 1 - \cos(x) = 2 \sin^2(x/2) foreach (double x in TestUtilities.GenerateRealValues(1.0E-2, 1.0E2, 8)) { Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(t => 2.0 * MoreMath.Sqr(MoreMath.Sin(t / 2.0)) / t, 0.0, x), AdvancedMath.IntegralCin(x) )); } }
public void PolynomialCalculus() { Polynomial p = Polynomial.FromCoefficients(4.0, -3.0, 2.0, -1.0); Polynomial i = p.Integrate(3.14159); double i1 = i.Evaluate(1.0) - i.Evaluate(0.0); double i2 = FunctionMath.Integrate(p.Evaluate, Interval.FromEndpoints(0.0, 1.0)); Assert.IsTrue(TestUtilities.IsNearlyEqual(i1, i2)); Polynomial id = i.Differentiate(); }
public void EllipticFIntegral() { foreach (double k in TestUtilities.GenerateRealValues(1.0E-2, 1.0, 8)) { foreach (double phi in TestUtilities.GenerateUniformRealValues(0.0, Math.PI / 2.0, 4)) { Assert.IsTrue(TestUtilities.IsNearlyEqual( FunctionMath.Integrate(t => AdvancedMath.EllipticF(t, k) / Math.Sqrt(1.0 - MoreMath.Pow(k * Math.Sin(t), 2)), Interval.FromEndpoints(0.0, phi)), MoreMath.Pow(AdvancedMath.EllipticF(phi, k), 2) / 2.0 )); } } }
public void AiryPowerIntegrals() { // Bernard Laurenzi, "Moment Integrals of Powers of Airy Functions", ZAMP 44 (1993) 891 double I2 = FunctionMath.Integrate(t => MoreMath.Pow(AdvancedMath.AiryAi(t), 2), 0.0, Double.PositiveInfinity); Assert.IsTrue(TestUtilities.IsNearlyEqual(I2, MoreMath.Sqr(AdvancedMath.Airy(0.0).FirstSolutionDerivative))); // I3 involves difference of 2F1 functions double I4 = FunctionMath.Integrate(t => MoreMath.Pow(AdvancedMath.AiryAi(t), 4), 0.0, Double.PositiveInfinity); Assert.IsTrue(TestUtilities.IsNearlyEqual(I4, Math.Log(3.0) / (24.0 * Math.PI * Math.PI))); }
public void IntegralEDefinition() { // A & S 5.1.4 foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 4)) { foreach (double x in TestUtilities.GenerateRealValues(1.0E-2, 10.0, 8)) { Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedMath.IntegralE(n, x), FunctionMath.Integrate(t => Math.Exp(-x * t) / MoreMath.Pow(t, n), 1.0, Double.PositiveInfinity) )); } } }
/// <summary> /// Returns the cumulative probability to the right of (above) the given point. /// </summary> /// <param name="x">The reference point.</param> /// <returns>The integrated probability Q(x) = 1 - P(x) to obtain a result above the reference point.</returns> /// <remarks> /// <para>In survival analysis, the right probability function is commonly called the survival function, because it gives the /// fraction of the population remaining after the given time.</para> /// <para>If you want a right-tailed probability, it is better to call this /// method directly instead of computing 1.0 - LeftProbability(x), because the /// latter will loose accuracy as P(x) gets close to 1. (In fact, in the far right tail /// where Q(x) < 1.0E-16, it will give 0.0, whereas this method is likely to give /// an accurate tiny value.)</para> /// </remarks> /// <seealso href="http://mathworld.wolfram.com/SurvivalFunction.html"/> /// <seealso href="https://en.wikipedia.org/wiki/Survival_function"/> public virtual double RightProbability(double x) { if (x <= Support.LeftEndpoint) { return(1.0); } else if (x >= Support.RightEndpoint) { return(0.0); } else { return(FunctionMath.Integrate(ProbabilityDensity, x, Support.RightEndpoint).Estimate.Value); } }