private void CheckPartitions(int n)
        {
            // Some sets to make sure partition and conjugate only appear once.
            // Also tests equality, hash set.
            HashSet <IntegerPartition> set          = new HashSet <IntegerPartition>();
            HashSet <IntegerPartition> conjugateSet = new HashSet <IntegerPartition>();

            foreach (IntegerPartition partition in AdvancedIntegerMath.Partitions(n))
            {
                Assert.IsTrue(partition != null);

                // Values should add to number.
                int vCount = 0;
                foreach (int v in partition.Values)
                {
                    Assert.IsTrue(v > 0);
                    vCount += v;
                }
                Assert.IsTrue(vCount == n);

                // Elements should add to number.
                int eCount = 0;
                foreach (Element e in partition.Elements)
                {
                    Assert.IsTrue(e.Value > 0);
                    Assert.IsTrue(e.Multiplicity > 0);
                    eCount += e.Value * e.Multiplicity;
                }
                Assert.IsTrue(eCount == n);

                // Partition should be generated only once
                Assert.IsTrue(!set.Contains(partition));
                set.Add(partition);

                IntegerPartition conjugate = partition.Conjugate();

                // Conjugate values should add to same number
                int cCount = 0;
                foreach (int c in conjugate.Values)
                {
                    Assert.IsTrue(c > 0);
                    cCount += c;
                }
                Assert.IsTrue(cCount == n);

                // Conujate should be generated only once
                Assert.IsTrue(!conjugateSet.Contains(conjugate));
                conjugateSet.Add(conjugate);

                // Rank should fulfill inequality and be related to conjugate rank
                Assert.IsTrue((-n < partition.Rank) && (partition.Rank < n));
                Assert.IsTrue(conjugate.Rank == -partition.Rank);

                // Double-conjugating should return us to the original
                Assert.IsTrue(conjugate.Conjugate() == partition);
            }
        }
 public void IntegerPartitionCounts()
 {
     // these counts are from Table 21.5 of Abromowitz & Stegun
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(1)) == 1);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(2)) == 2);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(3)) == 3);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(4)) == 5);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(5)) == 7);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(6)) == 11);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(7)) == 15);
     Assert.IsTrue(CountValues(AdvancedIntegerMath.Partitions(8)) == 22);
 }
 public void IntegerPartitionSums()
 {
     foreach (int n in TestUtilities.GenerateIntegerValues(1, 100, 5))
     {
         foreach (int[] partition in AdvancedIntegerMath.Partitions(n))
         {
             int s = 0;
             foreach (int i in partition)
             {
                 s += i;
             }
             Assert.IsTrue(s == n);
         }
     }
 }
Example #4
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)
        {
            double M = 0.0;

            foreach (int[] partition in AdvancedIntegerMath.Partitions(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.
        }
 private long PartitionFunction(int n)
 {
     return(AdvancedIntegerMath.Partitions(n).LongCount());
 }