コード例 #1
0
        // 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);
        }
コード例 #2
0
        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
                                  ));
            }
        }
コード例 #3
0
        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]);
        }
コード例 #4
0
        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));
            }
        }
コード例 #5
0
 public void FactorialRecurrence()
 {
     foreach (int n in TestUtilities.GenerateIntegerValues(1, 30, 5))
     {
         Assert.IsTrue(TestUtilities.IsNearlyEqual(AdvancedIntegerMath.Factorial(n), n * AdvancedIntegerMath.Factorial(n - 1)));
     }
 }
コード例 #6
0
        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)));
                }
            }
        }
コード例 #7
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
                }
                                  ));
            }
        }
コード例 #8
0
        /*
         * 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);
        }
コード例 #9
0
        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]);
        }
コード例 #10
0
 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);
 }
コード例 #11
0
 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)));
     }
 }
コード例 #12
0
 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)));
     }
 }
コード例 #13
0
        // 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]);
        }
コード例 #14
0
        // 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]);
        }
コード例 #15
0
 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));
     }
 }
コード例 #16
0
 /// <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));
     }
 }
コード例 #17
0
 /// <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);
     }
 }
コード例 #18
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);
     }
 }
コード例 #19
0
        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);
                        }
                    }
                }
            }
        }
コード例 #20
0
        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
        }
コード例 #21
0
 /// <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));
     }
 }
コード例 #22
0
 //[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)));
     }
 }
コード例 #23
0
 /// <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));
     }
 }
コード例 #24
0
 /// <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));
         }
     }
 }
コード例 #25
0
 /// <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);
     }
 }
コード例 #26
0
ファイル: MomentMath.cs プロジェクト: zyzhu/metanumerics
        // 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.
        }
コード例 #27
0
 /// <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));
     }
 }
コード例 #28
0
 /// <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
                        ));
         }
     }
 }
コード例 #29
0
 /// <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));
     }
 }
コード例 #30
0
 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)));
     }
 }