// Substituting u = e^{-z}, the raw moment integral for the standard Gumbel distribution can be re-written as // M_r = \int_{0}^{\infty} \! e^{-u} ( - \log u )^r \, du // Koelbig, "On the Integral \int_{0}^{\infty} \!e^{-\mu t} t^{\nu - 1} \log^m t \, dt", Mathematics of Computation 41 (1983) 171 // derives formulas for integrals of this form. In particular, his equation (23) implies // M_j = \sum_{k=0}{j-1} \frac{(j-1)!}{k!} \hat{\zeta}(j-k) M_k // where \hat{\zeta}(n) = \zeta(n) s^n for n > 1 and m + \gamma s for n = 1. This expresses a given raw moment in terms // of all the lower raw moments, making computation of the rth moment O(r^2). internal override double[] RawMoments(int rMax) { // Create an array to hold the moments. double[] M = new double[rMax + 1]; M[0] = 1.0; if (rMax == 0) { return(M); } // Pre-compute the zeta-hat values, since we will use them repeatedly. double[] Z = new double[rMax + 1]; double sj = s; // tracks s^j Z[1] = m + s * AdvancedMath.EulerGamma; for (int j = 2; j < Z.Length; j++) { sj *= s; Z[j] = AdvancedMath.RiemannZeta(j) * sj; } // Compute higher moments in turn. for (int j = 1; j <= rMax; j++) { double sum = 0.0; for (int k = 0; k < j; k++) { sum += Z[j - k] * M[k] / AdvancedIntegerMath.Factorial(k); } M[j] = AdvancedIntegerMath.Factorial(j - 1) * sum; } return(M); }
public void StirlingNumber1SpecialCases() { Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(0, 0) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(1, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(1, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(2, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(2, 1) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(2, 2) == 1); foreach (int m in TestUtilities.GenerateIntegerValues(2, 100, 4)) { Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, 0) == 0); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, 1) == AdvancedIntegerMath.Factorial(m - 1)); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedIntegerMath.StirlingNumber1(m, 2), AdvancedIntegerMath.Factorial(m - 1) * AdvancedIntegerMath.HarmonicNumber(m - 1) )); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, m) == 1); Assert.IsTrue(AdvancedIntegerMath.StirlingNumber1(m, m - 1) == AdvancedIntegerMath.BinomialCoefficient(m, 2)); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedIntegerMath.StirlingNumber1(m, m - 2), (3 * m - 1) * AdvancedIntegerMath.BinomialCoefficient(m, 3) / 4 )); } }
private double DurbinMatrixPPrime(double w) { int k = (int)Math.Ceiling(w); double h = k - w; // compute derivative of H SquareMatrix DH = GetDurbinMatrixPrime(k, h); //PrintMatrix(DH); // compute powers of H SquareMatrix[] PowerH = new SquareMatrix[n]; PowerH[1] = GetDurbinMatrix(k, h); for (int i = 2; i < n; i++) { PowerH[i] = PowerH[1] * PowerH[i - 1]; } // use D(H^n) = (DH) H^(n-1) + H (DH) H^(n-2) + H^2 (DH) H^(n-3) + \cdots + H^(n-2) (DH) H + H^(n-1) (DH) SquareMatrix HnP = DH * PowerH[n - 1]; for (int i = 1; i < (n - 1); i++) { HnP += PowerH[i] * DH * PowerH[n - 1 - i]; } HnP += PowerH[n - 1] * DH; double f = AdvancedIntegerMath.Factorial(n - 1) / MoreMath.Pow(n, n - 2); return(f * HnP[0, 1]); }
public void PermutationCount() { foreach (int n in TestUtilities.GenerateIntegerValues(2, 8, 4)) { int totalCount = 0; int evenCount = 0; int derangementCount = 0; foreach (Permutation p in Permutation.Permutations(n)) { totalCount++; if (p.IsEven) { evenCount++; } if (p.IsDerangement) { derangementCount++; } } Assert.IsTrue(totalCount == (int)AdvancedIntegerMath.Factorial(n)); Assert.IsTrue(evenCount == totalCount / 2); //Assert.IsTrue(derangementCount == AdvancedIntegerMath.Subfactorial(n)); } }
public void FactorialRecurrence() { foreach (int n in TestUtilities.GenerateIntegerValues(1, 30, 5)) { Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedIntegerMath.Factorial(n), n * AdvancedIntegerMath.Factorial(n - 1))); } }
public void BesselModifiedBesselRelationship() { // This is a very interesting test because it relates (normal Bessel) J and (modified Bessel) I // I_{\nu}(x) = \sum_{k=0}^{\infty} J_{\nu + k}(x) \frac{x^k}{k!} // We want x not too big, so that \frac{x^k}{k!} converges, and x <~ \nu, so that J_{\nu+k} decreases rapidly foreach (double nu in TestUtilities.GenerateRealValues(0.1, 10.0, 4)) { foreach (double x in TestUtilities.GenerateRealValues(0.1, nu, 4)) { double I = 0.0; for (int k = 0; k < 100; k++) { double I_old = I; I += AdvancedMath.BesselJ(nu + k, x) * MoreMath.Pow(x, k) / AdvancedIntegerMath.Factorial(k); if (I == I_old) { goto Test; } } throw new NonconvergenceException(); Test: Assert.IsTrue(TestUtilities.IsNearlyEqual(I, AdvancedMath.ModifiedBesselI(nu, x))); } } }
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 } )); } }
/* * minValue: es el minimo de personas que llegan al andén * maxValue: es el máximo de personas que llegan al andén * personasPorMinuto: cantida de personas que llegan por minuto * cantidadEnHoras: tiempo en horas de la muestra de personas */ public static int Poisson(int minValue, int maxValue, int personasPorMinuto, int cantidadEnHoras) { double r1, r2, m, y, fx; int k, lambda, x; if ((personasPorMinuto <= 0) || (cantidadEnHoras <= 0)) { throw new System.ArgumentException("Valores incorrectos"); } k = personasPorMinuto; lambda = cantidadEnHoras; PoissonDistribution f = new PoissonDistribution(lambda); m = Math.Pow(k, k) / (Math.Exp(k) * AdvancedIntegerMath.Factorial(k)); Random r = new Random(); do { r1 = r.NextDouble(); r2 = r.NextDouble(); x = Convert.ToInt32(minValue + (maxValue - minValue) * r1); y = m * r2; fx = f.ProbabilityMass(Convert.ToInt32(k * r1)); } while (y < fx); return(x); }
private double DurbinMatrixPPrime(double t) { int k; double h; DecomposeInteger(t, out k, out h); // compute derivative of H SquareMatrix DH = GetDurbinMatrixPrime(k, h); // compute powers of H SquareMatrix[] PowerH = new SquareMatrix[n]; PowerH[1] = GetDurbinMatrix(k, h); for (int i = 2; i < n; i++) { PowerH[i] = PowerH[1] * PowerH[i - 1]; } // use D(H^n) = (DH) H^(n-1) + H (DH) H^(n-2) + H^2 (DH) H^(n-3) + \cdots + H^(n-2) (DH) H + H^(n-1) (DH) SquareMatrix HnP = DH * PowerH[n - 1]; for (int i = 1; i < (n - 1); i++) { HnP += PowerH[i] * DH * PowerH[n - 1 - i]; } HnP += PowerH[n - 1] * DH; double f = AdvancedIntegerMath.Factorial(n) / MoreMath.Pow(n, n); return(f * HnP[k - 1, k - 1]); }
public void FactorialSpecialCases() { Assert.IsTrue(AdvancedIntegerMath.Factorial(0) == 1); Assert.IsTrue(AdvancedIntegerMath.Factorial(1) == 1); Assert.IsTrue(AdvancedIntegerMath.Factorial(2) == 2); Assert.IsTrue(AdvancedIntegerMath.Factorial(3) == 6); Assert.IsTrue(AdvancedIntegerMath.Factorial(4) == 24); }
public void StirlingNumbers1RowSum() { foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 4)) { double sum = 0.0; foreach (double s in AdvancedIntegerMath.StirlingNumbers1(n)) { sum += s; } Assert.IsTrue(TestUtilities.IsNearlyEqual(sum, AdvancedIntegerMath.Factorial(n))); } }
public void PochammerSpecialIntegerArguments() { Assert.IsTrue(AdvancedMath.Pochhammer(0.0, 0) == 1.0); foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 6)) { Assert.IsTrue(AdvancedMath.Pochhammer(0.0, n) == 0.0); Assert.IsTrue(TestUtilities.IsNearlyEqual( AdvancedMath.Pochhammer(0.0, -n), (n % 2 == 0 ? 1.0 : -1.0) / AdvancedIntegerMath.Factorial(n) )); Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedMath.Pochhammer(1.0, n), AdvancedIntegerMath.Factorial(n))); } }
// Durbin derives a matrix result for the Kuiper statistic analogous to his result for the Kolmogorov-Smirnov that was used by Marsaglia. // In this case, if w = n V = k - h, H is k X k with entries of the form // { 0 1 0 0 0 } // { 0 1/1! 1 0 0 } // H = { 0 1/2! 1/1! 1 0 } // { 0 1/3! 1/2! 1/1! 1 } // { 0 (1-h^4)/4! (1-h^3)/3! (1-h^2)/2! (1-h)/1! } // and // P = \frac{n!}{n^{n-1}} \left( H^n \right)_{1,2} // Note there is no discontinuity at half-integer values of w in the Kuiper case. // See Durbin, "Distribution Theory for Tests Based on the Sample Distribution Function", 1973, p. 12-13, 35. private double DurbinMatrixP(double w) { int k = (int)Math.Ceiling(w); double h = k - w; SquareMatrix H = GetDurbinMatrix(k, h); SquareMatrix Hn = H.Power(n); //SquareMatrix Hn = MatrixPower(H, n); double f = AdvancedIntegerMath.Factorial(n - 1) / MoreMath.Pow(n, n - 2); return(f * Hn[0, 1]); }
// Durbin derived a matrix formulation, later programmed by Marsaglia, that gives P by taking matrix powers. // If t = n D = k - h, where k is an integer and h is a fraction, the matrix is (2k - 1) X (2k - 1) and takes the form: // { (1-h)/1! 1 0 0 0 } // { (1-h^2)/2! 1/1! 1 0 0 } // H = { (1-h^3)/3! 1/2! 1/1! 1 0 } // { (1-h^4)/4! 1/3! 1/2! 1/1! 1 } // { * (1-h^4)/4! (1-h^3)/3! (1-h^2)/2! (1-h)/1! } // The lower-left element is special and depends on the size of h: // 0 < h < 1/2: * = (1 - 2 h^m) / m! // 1/2 < h < 1: * = (1 - 2 h^m + (2h-1)^m)/ m! // Note the factor 2 in the first case and the additional term in the second case. The left probability is then given by // the middle element of H to the nth power: // P = \frac{n!}{n^n} \left( H^n \right)_{k,k} // Note that, for a given value of t, the matrix H does not depend on n; n dependence only enters as the power to which H is taken. // While astounding, the matrix method is clearly quite onerous. Because all the entries of H are positive, though, it is not subject to // the cancelation errors that makes the series solution practically useless in the region t < n/2. // See Durbin, "Distribution THeory for Tests Based on the Sample Distribution Function", 1973 and // Marsaglia, Tsand, & Wang, "Evaluating Kolmogorov's Distribution", Journal of Statistical Software 8 (2003) private double DurbinMatrixP(double t) { int k; double h; DecomposeInteger(t, out k, out h); SquareMatrix H = GetDurbinMatrix(k, h); SquareMatrix Hn = H.Power(n); double f = AdvancedIntegerMath.Factorial(n) / MoreMath.Pow(n, n); return(f * Hn[k - 1, k - 1]); }
public override double Cumulant(int r) { if (r < 0) { throw new ArgumentOutOfRangeException("r"); } else if (r == 0) { return(0.0); } else { return(MoreMath.Pow(2.0, r - 1) * AdvancedIntegerMath.Factorial(r - 1) * (nu + r * lambda)); } }
/// <inheritdoc /> public override double RawMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(1.0); } else { return(AdvancedIntegerMath.Factorial(r) * MoreMath.Pow(mu, r)); } }
/// <inheritdoc/> public override double CentralMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r % 2 == 0) { return(AdvancedIntegerMath.Factorial(r) * Math.Pow(b, r)); } else { return(0.0); } }
/// <inheritdoc /> public override double Cumulant(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(0.0); } else { return(MoreMath.Pow(2, r - 1) * AdvancedIntegerMath.Factorial(r - 1) * nu); } }
public void AssociatedLaguerreOrthonormality() { // don't let orders get too big, or (1) the Gamma function will overflow and (2) our integral will become highly oscilatory foreach (int n in TestUtilities.GenerateIntegerValues(1, 10, 3)) { foreach (int m in TestUtilities.GenerateIntegerValues(1, 10, 3)) { foreach (double a in TestUtilities.GenerateRealValues(0.1, 10.0, 5)) { //int n = 2; //int m = 4; //double a = 3.5; Console.WriteLine("n={0} m={1} a={2}", n, m, a); // evaluate the orthonormal integral Func <double, double> f = delegate(double x) { return(Math.Pow(x, a) * Math.Exp(-x) * OrthogonalPolynomials.LaguerreL(m, a, x) * OrthogonalPolynomials.LaguerreL(n, a, x) ); }; Interval r = Interval.FromEndpoints(0.0, Double.PositiveInfinity); // need to loosen default evaluation settings in order to get convergence in some of these cases // seems to have most convergence problems for large a IntegrationSettings e = new IntegrationSettings(); e.AbsolutePrecision = TestUtilities.TargetPrecision; e.RelativePrecision = TestUtilities.TargetPrecision; double I = FunctionMath.Integrate(f, r, e).Value; Console.WriteLine(I); // test for orthonormality if (n == m) { Assert.IsTrue(TestUtilities.IsNearlyEqual( I, AdvancedMath.Gamma(n + a + 1) / AdvancedIntegerMath.Factorial(n) )); } else { Assert.IsTrue(Math.Abs(I) < TestUtilities.TargetPrecision); } } } } }
private void FirstStepSeriesExpansion( out Complex wave, out Complex deriv ) { int MAX = 10; double[] A = new double[MAX]; double DebyeSum = 0; double dx = WaveVector_fm * StepSize_fm; double DK = DebyeMass_MeV / WaveVector_fm / Constants.HbarC_MeV_fm; double ZK = Potential_fm.AlphaEff * Param.QuarkMass_MeV / WaveVector_fm / Constants.HbarC_MeV_fm; double SK = DebyeMass_MeV == 0 ? 0 : SigmaEff_MeV / DebyeMass_MeV / Constants.HbarC_MeV_fm / WaveVector_fm / WaveVector_fm; A[0] = 1.0; A[1] = 0.5 * ZK / (Param.QuantumNumberL + 1.0); for (int j = 2; j < MAX; j++) { for (int k = 0; k <= j - 2; k++) { DebyeSum += Math.Pow(-DK, k) / AdvancedIntegerMath.Factorial(k) * (SK + DK * ZK / (k + 1.0)) * A[j - 2 - k]; } A[j] = (ZK * A[j - 1] - A[j - 2] - DebyeSum) / (j + 2.0 * Param.QuantumNumberL + 1.0) / j; } if (A[MAX - 1] * Math.Pow(dx, MAX - 1) > 1e-14) { throw new Exception("Last term is suspiciously large."); } double sum = 0; double dsum = 0; for (int j = 0; j < MAX; j++) { // x = WaveVector*Radius sum += A[j] * Math.Pow(dx, j + Param.QuantumNumberL + 1); dsum += (j + Param.QuantumNumberL + 1) * A[j] * Math.Pow(dx, j + Param.QuantumNumberL); } wave = new Complex(sum, 0); deriv = new Complex(dsum * WaveVector_fm, 0); // <- factor of WaveVector is important }
/// <inheritdoc/> public override double Cumulant(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(0.0); } else { // This expression for the cumulant appears in the Wikipedia article. return(MoreMath.Pow(2.0, r - 1) * (nu + r * lambda) * AdvancedIntegerMath.Factorial(r - 1)); } }
//[TestMethod] // Cancellation too bad to be useful public void BernoulliStirlingRelationship() { // This involves significant cancellation, so don't pick n too high foreach (int n in TestUtilities.GenerateIntegerValues(2, 16, 4)) { double S = 0.0; for (int k = 0; k <= n; k++) { double dS = AdvancedIntegerMath.Factorial(k) / (k + 1) * AdvancedIntegerMath.StirlingNumber2(n, k); if (k % 2 != 0) { dS = -dS; } S += dS; } Assert.IsTrue(TestUtilities.IsNearlyEqual(S, AdvancedIntegerMath.BernoulliNumber(n))); } }
/// <inheritdoc /> public override double CentralMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(1.0); } else if (r % 2 != 0) { return(0.0); } else { return(2.0 * AdvancedIntegerMath.Factorial(r) * AdvancedMath.DirichletEta(r) * MoreMath.Pow(s, r)); } }
/// <inheritdoc /> public override double ProbabilityMass(int k) { if (k < 0) { return(0.0); } else { // These are the same expression, but the form for small arguments is faster, // while the form for large arguments avoids overflow and cancellation errors. if (k < 16) { return(Math.Exp(-mu) * MoreMath.Pow(mu, k) / AdvancedIntegerMath.Factorial(k)); } else { return(Stirling.PoissonProbability(mu, k)); } } }
/// <inheritdoc /> public override double Cumulant(int r) { if (r < 0) { throw new ArgumentOutOfRangeException("r"); } else if (r == 0) { return(0.0); } else if (r == 1) { return(Mean); } else { double C = AdvancedIntegerMath.Factorial(r - 1) * AdvancedMath.RiemannZeta(r) * MoreMath.Pow(s, r); return(C); } }
// Faa di Bruno's formula expresses raw moments in terms of cumulants. // M_r = \sum_{m_1 + \cdots + m_k = r} \frac{r!}{m_1 \cdots m_k} K_1 \cdots K_k // That is: take all partitions of r. (E.g. for r = 4, thre are 5 partitions: 1 + 1 + 1 + 1 = 4, 1 + 1 + 2 = 4, 2 + 2 = 4, 1 + 3 = 4, and 4 = 4). // Each partition will contribute one term. Each appearance of an integer k in the partition will contribute one factor of the kth cumulant // to that term. (E.g. K_1^4, K_1^2 K_2, K_2^2, K_1 K_3, and K_4.) // Each term has a combinatoric factor of r! divided by the product of all the integers in the partition. (E.g. 1^4, 1^2 * 2, 2^2, 1 * 3, and 4.) internal static double CumulantToMoment(double[] K, int r, bool central) { Debug.Assert(K != null); Debug.Assert(r > 0); Debug.Assert(K.Length >= r); double M = 0.0; foreach (int[] partition in AdvancedIntegerMath.InternalPartitions(r)) { double dM = AdvancedIntegerMath.Factorial(r); int u = 0; // tracks the last observed partition member int m = 1; // tracks the multiplicity of the current partition member foreach (int v in partition) { // if we are computing central moments, ignore all terms with a factor of K_1 if (central && (v == 1)) { dM = 0.0; break; } if (v == u) { m++; } else { m = 1; } dM *= K[v] / AdvancedIntegerMath.Factorial(v) / m; u = v; } M += dM; } return(M); // This method of reading out a partition is a bit klunky. We really want to know the multiplicity of each element, // but that isn't straightforwardly available. In fact, this method will break if identical elements are not adjacent // in the array (e.g. 4 = 1 + 2 + 1 + 1). Would be nice to address this, perhaps by actually returning a multiplicity // representation of parititions. }
/// <inheritdoc /> public override double CentralMoment(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(1.0); } else if (r == 1) { return(0.0); } else { // Subfactorial !r, see http://mathworld.wolfram.com/Subfactorial.html for properties of subfactorial. // Most relevant for fast computation is (!r) = round[ r! / e ]. return(Math.Round(AdvancedIntegerMath.Factorial(r) / Math.E) * MoreMath.Pow(mu, r)); } }
/// <inheritdoc /> public override double ProbabilityMass(int k) { if (k < 0) { return(0.0); } else { // these are the same expression, but the form for small arguments is faster and the form for large arguments avoids overflow if (k < 16) { return(Math.Exp(-mu) * MoreMath.Pow(mu, k) / AdvancedIntegerMath.Factorial(k)); } else { return(Math.Exp( k * Math.Log(mu) - AdvancedIntegerMath.LogFactorial(k) - mu )); } } }
/// <inheritdoc /> public override double Cumulant(int r) { if (r < 0) { throw new ArgumentOutOfRangeException(nameof(r)); } else if (r == 0) { return(0.0); } else if (r == 1) { return(m); } else if (r % 2 != 0) { return(0.0); } else { return(2.0 * AdvancedIntegerMath.Factorial(r - 1) * AdvancedMath.RiemannZeta(r) * MoreMath.Pow(s, r)); } }
public void HermiteSum() { // accuracy of equality falls at high n because of cancelations among large terms for (int n = 0; n < 12; n++) { double sum = 0.0; for (int k = 0; k <= n; k++) { double term = AdvancedIntegerMath.BinomialCoefficient(n, k) * OrthogonalPolynomials.HermiteH(n, k); Console.WriteLine(" k={0}, term={1}", k, term); if ((n - k) % 2 == 0) { sum += term; } else { sum -= term; } } Console.WriteLine("n={0}, sum={1}", n, sum); Assert.IsTrue(TestUtilities.IsNearlyEqual(sum, Math.Pow(2, n) * AdvancedIntegerMath.Factorial(n))); } }