Example #1
0
        // 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.
        }