This is a continuation of my last note on polynomials as lists. Here, I'm going to talk about the concepts of generating functions and combinatorial species, which extend the ideas from those posts into a more coherent framework.
Combinatorics is concerned with counting instances of structures. "Structure" here is a very broad term. It can refer to anything from permutations, to multisets, to trees. The key thing to these structures is that their size can be talked about in a meaningful way: permutations may act on a given number of elements, multisets likewise, and trees can have a certain number of nodes. The driving idea of combinatorics is to take any one of these structures and determine "how many" there are of a given size. For example, there are possible permutations of elements.
The obvious way to do this is to just enumerate these structures manually. For example, the first few general trees are enumerated in the hand-drawn figure below.
The number of trees for each size grows as , but finding this manually becomes intractable as the size of the trees becomes larger. If I were to give you a few minutes to find how many trees there are of size , you definitely wouldn't be able to draw all 1,767,263,190 of them. You would, however, be able to use this closed-form expression to find the answer:
This will be proven later, but for now it's given. The idea here is that simple enumeration won't be enough to study combinatorial structures, so a more efficient approach is needed to gain any information about them. This approach was hinted at in the last post, Polynomials as Lists, where I introduced the idea of using sequences of numbers to create infinite polynomials, known as power series. This can be applied in enumerating combinatorial structures through a specialized kind of power series known as a generating function (GF). In that post I took the Fibonacci sequence, , and showed that its generating function is equal to
This was done by taking advantage of the recurrence relation that Fibonacci numbers have, , and using that on the lefthand side of the equality to find a functional equation that we solved to get the righthand side. A fundamental property of generating functions is that their singularities ultimately determine their coefficients. In the case of , the GF has two singularities which give an explicit formula for Fibonacci numbers:
If we were to apply this to the sequence of trees, we get the generating function for general tree structures.
Unfortunately, we're unable to get much further in our understanding of this structure since it doesn't have an "easy" recurrence scheme like the Fibonacci numbers. In order to do anything with this GF, we need to know more about what generating functions are and what they represent.
Let's start from the beginning and work our way towards "discovering" generating functions from scratch. We can start with the binomial theorem, which relies on a fairly straightforward combinatoric argument to prove.
It goes like this; the power on the lefthand side can be broken up into a product: . Taking a specific term from the expansion effectively means making choices between either or and multiplying those out in order. If you were to fix the number of choices of ahead of time to , then there are choices of (since they must add up to ) and there are exactly different terms of this type.
If we don't group the terms together like in the equation above, then we can more clearly see the structure that represents.
We get terms, each of which is a unique sequence of and with length . We can then say that "generates" n-length sequences of and . This is where I should make clear that and don't necessarily need to be interpreted as numbers. For instance, we can interpret these are actual letters as written. This may seem strange, since you cannot add or multiply letters in a literal sense. The level of abstraction we need comes from the notion of a combinatorial species.
A combinatorial species is roughly a set interpreted in the language of algebra. The "elements" are all written like , where addition represents a disjoint union in the language of sets. Multiplication corresponds to the cartesian product of two sets, or all possible pairs of elements from the two.
Going back to letters, we can say that the English alphabet is the combinatorial species, . Multiplication can be thought of as just "adding" one letter on the end of another to form a word. Then, for example, represents the combinatorial species of all 3-letter words. is the combinatorial species of two-letter words ending in f. The possibilities are endless.
We can take this further to ask about the combinatorial species of all sequences of (i.e. all possible words, no matter how long). This will be denoted as , and it is:
Here is included as the "empty" sequence of length , since . Other structures than sequences can be combinatorically specified. For example, given a set such as , all of its possible subsets (the powerset) may be obtained by:
Where is a stand-in for any member of the set . To see why this is, take . Then
Similarly, multisets may be generated by:
If it's not clear why this is, a multiset is a set that can have the same element more than once. Since multisets aren't ordered, then several sequences may represent the same multiset: , , and are three examples of such. Because ordering is arbitrary, we can set a fixed ordering, such as , that uniquely defines a multiset and is a member of this combinatorial class. This decomposes multisets into a product of sequences of a, b, and c, where a sequence of a single variable is the species . In this example, .
Some algebraic identities turn into observations from combinatorics. For example, the fact that a multiset may have either an even or an odd number of components results in the identity
Where the odd-numbered elements get one element "moved" into a powerset, resulting in a multiset with even numbers of elements. The combinatorial species for the latter is . This can be applied iteratively:
When is a combinatorial species with only one element (more on that soon), this translates into this interesting identity:
This captures the fact that every number can also be uniquely written as a sum of powers of 2 (i.e in binary).
Combinatorial species are close in form to generating functions. The dfference is that generating functions "equivocate" different elements of the same size. While the species of the alphabet is , its corresponding generating function is (here is an arbitrary variable). Since there are 26 letters in the English alphabet, the species has 26 elements of size 1 . What about ? It's the species of two-letter words of which there are possible combinations, so its corresponding GF is .
In general a generating function like the one above represents a combinatorial species with "empty" elements, elements of size 1, of size 2, and so on. This means that enumerating structures of a given size translates to finding the coefficients of the generating function of that structure, and vice-versa. This essentially repackages information about a structure into a single object.
The constructions above can be easily translated into generating functions:
If we just take a basic generating function like (one object of size 1), we get that . This is an interesting species because it can be interpreted as representing all natural numbers (there is exactly one element of each size). Likewise, is the GF for even numbers. is the GF for powers of (notice that the powerset of this GF is ).
We can build upon this a bit but won't stay for too long. One benefit to equating to the GF of natural numbers is that we can talk about compositions and partitions easily. A composition is a way of writing numbers as the sum of smaller numbers. Some of the compositions of are . This can be thought of as a sequence (here, order matters) of natural numbers (excluding 0), or:
So we immediately know how many compositions of there are, . We can also limit what numbers are used in compositions, so to find the compositions with only 1 and 2 used, we can look at sequences of the smaller generating function instead:
Which is the same as the generating function of the Fibonacci sequence from the beginning of the note, just "shifted over".
A partition is a composition where order no longer matters. It's generating function is then
While the coefficients of its power series can be calculated recursively, there's no non-recursive formula like what we found with the Fibonacci numbers. We can, however, find that the coefficients of approach:
We won't prove that now though. We can find interesting constructions and sequences by composing these functions, using restricted base classes, and so on, but can this be extended into recursion? Can a generating function reference itself as a base class? Let's go back to thinking about general trees.
A tree structure will always have a "root" node. Since we're counting the sizes of trees by the number of nodes they have, a tree may be broken up into it's size 1 root node and a sequence of smaller subtrees attached to the root node (the order/topology of the tree matters here). These subtrees are standalone trees themselves, since they contain a root and branches (subtrees) from that root. This "breaking down" process can continue indefinitely, or a root can simply terminate. The combinatorial species of trees is defined in terms of itself, since any member of the species is a node connected to subtrees, so .
Solving for is pretty straightforward. We have
Finding a closed-form formula for trees amounts to finding a series representation of this function. We may use the binomial theorem here on the term of interest:
Finding is the hard part. Here's what it looks like:
We can "fill in the gaps" on the last term:
So now we can write in simpler terms and start to march backwards
Which means that there are exactly general trees with nodes.