General post
Composition of formal power series
Originally posted 2024-11-22
Last updated 2024-11-22
Background
Note: This is supplemental material originally meant to go with the meetup on classical methods for power series coefficient extraction. I wasn’t able to find a simple, sufficient, self-contained treatment of computational coefficient extraction for power series compositions using iterative methods, so hope this fills that void.1 Understanding integer compositions will make it easier to follow the “composition product terms” discussed below.2
Definition of power series composition
Let , where , , and are all formal power series. We want to compute the coefficients of , for all . Unfortunately, doing so efficiently (in space and time) is non-trivial. We’ll develop a solution by working with the original series definition and inspecting the coefficients that come out at each step. Start by writing
and expanding terms. We find that
Notice that this is a series that does not converge if (we require all coefficients to be finite; technically, to stabilize). Therefore, we conclude that we must have for the composition to converge. This immediately tells us that , since the only term that contributes a constant is the one with .
Computing coefficients by brute force
Using similar logic for expansion of the other factors, let’s compute a few coefficients, . Recall that , so we can start the inner sum at . Now, note that is essentially asking for the sum of all products such that . Obviously, each , but we also know that , so only positive indices actually contribute. Let’s put this in context of the total sum for the coefficient of interest:
Now it becomes clearer that each contributes one term for each (strong) -composition of .3 Each such integer composition corresponds to a certain product of coefficients of . For example, is a -composition of . It has parts and the product of the implied powers of is , since . Consequently this contributes to the coefficient after being multiplied by the outer coefficient .
Here are the first few coefficients fully expanded:
It may jump out at you that visiting each partition (which grows exponentially in ) and multiplying by its corresponding multinomial coefficient would be more efficient than visiting each composition (which grows exponentially in ). However, this obscures a natural recurrence relation which helps us actually compute the “efficiently”.4
Deriving a recurrence
Suppose we’re computing where . This will involve a sum of the form
where is precisely the sum-of-products of coefficients from that we’ve been discussing. In particular, it counts the coefficient products corresponding to each distinct -partition of . We want an explicit recurrence for .
Note that (there’s only one -composition of ) and (there’s only one -composition of ).
Now, consider the “composition product sum”, for . If you look at the row computing for a fixed , you can see that each composition product sum of parts builds off of the product sums of the rows of parts from some row before it. Specifically, consider the operation of prepending a given factor to any composition of for all valid . This generates all valid -composition products of . Moreover, since we’re prepending a factor to the each term in a given set of composition products (rather than, for example, replacing one of the previous factors with ), this has the effect of scaling the corresponding sub-composition by .
A concrete example will probably help this stick. Consider the -compositions of , i.e. the composition terms of the term that go into . If we choose as the first factor, then this leaves us with -compositions of . We read these off of the term of : . Similarly, we could have a first factor of by combining this with the -compositions of . As before, we read these off of the term of : . Putting these all together, we have the terms of the term of : . As desired, this matches exactly what we found by brute force under .
We now have our recurrence relation:
Note that the sum is over because we can only have valid -compositions of when . Thus we can only have -compositions of if .
Space and runtime
The recurrence shown above suggests a direct algorithm for computing each :
- Maintain a ragged array of coefficients computed so far.
- Bootstrap with .
- Compute as:
Note: Each implicit value of computed above should be stored in the array to avoid exponentially duplicated work.
If we’re computing coefficient , then we effectively have to compute all coefficients for , so we’re using storage space for the composition product sum array.5
At each step , the double sum costs us runtime, for a total of to get . While this could potentially work fine up to a few thousand (without many deeper levels of composition), it will quickly become unwieldy for larger . Unfortunately, I’m not aware of any good solutions in arbitrary precision. You seem to be stuck with lossy DFT-based solutions or asymptotic analysis.
Footnotes
-
I did, however see many references to advanced or impractical techniques such as those by Brent and Kung, as well as Bell polynomials and Faà di Bruno’s formula. ↩
-
Any time I use the phrase “integer composition”, this should be understood as a “strong integer composition”, since we do not allow zeros in this context. ↩
-
To see why, note that we’re taking an infinite multinomial raised to the power and, consequently, need to select terms in total whose powers of sum to , i.e., the power of interest. ↩
-
We will not be using FFT-based methods here because these increase the complexity and prerequisites dramatically, but also because the goal is to compute exact numbers in arbitrary precision. In particular, in the combinatorial classes we will be dealing with, the output coefficients are always intergral (except for some intermediate fractional coefficients as observed in function composition). ↩
-
We’re also using storage for the original s and s since these are reused while computing each sum. While it doesn’t affect the asymptotics, it does mean that you don’t get much benefit in a setting where the coefficients of and are streamed. ↩