[Home] [Puzzles & Projects] [Delphi Techniques] [Math Topics] [Library] [Utilities]

 Given any set of distinct objects, how many ways can it be split into subsets? Such a division is called a set partition. More formally, a set partition of a set of distinct objects, S, is a set of disjoint subsets whose union is S. For example, the set {a,b,c} can be partitioned in 5 ways:
A set with 4 members can be partitioned in 15 ways, 5 members in 52 ways, etc. The number of ways that a set can be partitioned is it's Bell number. Named after Eric T. Bell, the mathematician who first studied the numbers in depth. As a matter of curiosity, the Bell number for a set with N members, B(N), is the sum of the number of ways that it can be partitioned into 1, 2, 3, ... N subsets. The number of ways that a set of size N can be partitioned into K subsets, denoted S_{2}(N,K), has also been named  "Stirling numbers of the second kind". So, in general B(N)=Sum_{k=1 to N} S_{2}(N,k). For example: B(3) = S_{2}(3,1) + S_{2}(3,2) + S_{2}(3,3) = 1 + 3 + 1 = 5. Stirling numbers of the first kind, S_{1}(N,k), by the way, represent the number of permutations of N objects that contain exactly k cycles. A cycle describes the way that permutations are generated from the original ordered set  a topic we'll save for another day. The program here generates a few (up to 1000) partitions for any set size from 2 to 25. It will also generate and display the Bell number and the Stirling 2 numbers for any set in this range. Generating partitionsThe idea of a restricted growth function is key to generating the partition themselves. The restricted growth array, RG, is a set of zero based indices specifying to which partition each element of the set belongs. For set size 4, for example RG=[0,0,0,0] defines the single set partition {1,2,3,4} , RG=[0,1,1,0] represents {1,4},{2,3} , etc. The RG array values have the characteristic that for each i, RG[i]<=1+max(RG[0], RG[1]... RG[i1]). So [0,0,0,2] is not a valid RG array for example. Procedure GetNextRG in unit USetPartition does the job of generating RG values in this program. Procedure GetNextPartition calls GetNextRG to get the values used to generate the actual partition records. Generating Bell numbers (number of partitions)The number of partitions increases rapidly with set size  more than a billion for 15 items  so it's not practical to count the number of ways by actually generating them. There is a recursive definition for Stirling numbers of the second type, therefore we can sum these as described above to get the Bell number. Above 10 members, the recursive definition time can become long unless you have a fast computer. The original PartitionCount procedure remains in commented form in the downloaded code, for reference. The Stirling2 function can be called to see the distribution of partition subset sizes for any set size (again for large set sizes and older computers, this may take a few minutes). The alternative method is based on a Bell triangle description found at http://www.pballew.net/Bellno.html. with this construction algorithm "The numbers can be constructed by using the Bell Triangle, a name suggested to Martin Gardner by Jeffrey Shallit. Start with a row with the number 1. Afterward each row begins with the last number of the previous row and continues to the right adding each number to the number above it to get the next number in the row." Sure enough it works and it is fast. The program will generate Bell numbers up to the limit of the 64 bit integer type, about set size 25. May 8, 2006: A small fix was made today to handle the partitioning of a single element set. Of course, there is only one partition, the element itself, but the TPartition class should return it, and now it does.

[Feedback] [Newsletters (subscribe/view)] [About me]Copyright © 20002013, Gary Darby
All rights reserved.
