Skip to content
AI360Xpert
Beta

Generating Functions

Pack a whole sequence into one function the way a zip file packs folders: algebra on the package does counting for every entry at once.

One rational function x over 1 minus x minus x squared expands into the whole Fibonacci sequence 0 1 1 2 3 5, one coefficient per term
One rational function x over 1 minus x minus x squared expands into the whole Fibonacci sequence 0 1 1 2 3 5, one coefficient per term

Why Does This Exist?

Counting problems ask about whole sequences at once: how many binary strings of length nn avoid consecutive ones, for every nn? Answering term by term means solving infinitely many problems. A generating function folds the entire sequence into a single object

G(x)=a0+a1x+a2x2+a3x3+⋯G(x) = a_0 + a_1 x + a_2 x^2 + a_3 x^3 + \cdots

and then ordinary algebra on GG answers questions about all the ana_n simultaneously. A recurrence between sequence terms becomes an equation for GG; solving that equation and reading off coefficients solves the recurrence in closed form.

The same idea resurfaces wherever series do work: moment generating functions in probability package a distribution's moments the same way, and Taylor series are generating functions for a smooth function's derivatives. Learn the trick once here and both of those read as dialects.

The one idea you need first

A power series is a polynomial that never ends: coefficients ana_n attached to increasing powers of xx. Two series are equal exactly when all their coefficients match, so extracting information means reading coefficients. Adding series adds coefficients term by term; multiplying convolves them, which is why products of generating functions count combined choices.

Think of It Like This

A zip archive for sequences

A folder of a thousand text files is awkward to email, so you zip it into one archive. The archive is not the files, but every file is recoverable from it, and some operations (copying, checksumming) are easier on the single package.

A generating function is a zip archive for a sequence. The "files" are the terms a0,a1,a2,…a_0, a_1, a_2, \ldots and the "archive" is the function G(x)G(x). Adding archives merges file lists term by term. Differentiating shifts and reweights the contents. And just as you would never edit a photo by hex-editing its zip, you manipulate the sequence through the function, then unzip by reading coefficients at the end.

The analogy stops at convergence: a zip always opens, but a power series only represents its sequence where it converges, and formal manipulation outside that range can lie.

How It Actually Works

Start from a recurrence and let the series do the bookkeeping. The Fibonacci numbers F0=0F_0 = 0, F1=1F_1 = 1, Fn=Fn−1+Fn−2F_n = F_{n-1} + F_{n-2} have generating function F(x)=∑n≥0FnxnF(x) = \sum_{n \ge 0} F_n x^n. Multiply the recurrence by xnx^n and sum over n≥2n \ge 2:

∑n≥2Fnxn=∑n≥2Fn−1xn+∑n≥2Fn−2xn\sum_{n \ge 2} F_n x^n = \sum_{n \ge 2} F_{n-1} x^n + \sum_{n \ge 2} F_{n-2} x^n

The left side is F(x)−xF(x) - x (missing only the n=1n = 1 term xx). The first sum on the right is xF(x)x F(x) and the second is x2F(x)x^2 F(x). So F(x)−x=xF(x)+x2F(x)F(x) - x = xF(x) + x^2 F(x), giving the closed package:

F(x)=x1−x−x2F(x) = \frac{x}{1 - x - x^2}

Worked example

Expand the package by long division and watch the sequence emerge. Write (1−x−x2)(a0+a1x+a2x2+a3x3+a4x4+a5x5)=x(1 - x - x^2)(a_0 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4 + a_5 x^5) = x and match coefficients:

  • constant: a0=0a_0 = 0
  • xx: a1−a0=1a_1 - a_0 = 1, so a1=1a_1 = 1
  • x2x^2: a2−a1−a0=0a_2 - a_1 - a_0 = 0, so a2=1a_2 = 1
  • x3x^3: a3−a2−a1=0a_3 - a_2 - a_1 = 0, so a3=2a_3 = 2
  • x4x^4: a4−a3−a2=0a_4 - a_3 - a_2 = 0, so a4=3a_4 = 3
  • x5x^5: a5−a4−a3=0a_5 - a_4 - a_3 = 0, so a5=5a_5 = 5

Out comes 0,1,1,2,3,50, 1, 1, 2, 3, 5: Fibonacci, recovered from one rational function with no guessing. From here partial fractions lead to Binet's closed form, but the coefficient extraction above is already the whole method.

Code

The point is the check: rebuild the coefficients from the recurrence the algebra implies, and confirm they match.

def fib_from_package(n_terms: int) -> list[int]:    a = [0] * n_terms    for n in range(n_terms):        if n == 1:            a[n] = 1  # the lone x on the right hand side        elif n >= 2:            a[n] = a[n - 1] + a[n - 2]  # coefficient matching rule    return a

print(fib_from_package(6))  # -> [0, 1, 1, 2, 3, 5]

Watch Out For

Mixing up ordinary and exponential generating functions

Ordinary generating functions attach ana_n to xnx^n; exponential ones attach ana_n to xn/n!x^n / n!. The two packages answer different questions (unlabelled versus labelled structures) and their product rules differ. Using ordinary multiplication on exponential packages scrambles the counts. Check which convention your source uses before combining anything.

Manipulating where the series diverges

Formal algebra on G(x)G(x) is valid inside its radius of convergence; outside it, rearranging terms can produce any answer you like. When extracting asymptotics or evaluating at a point, confirm the point lies inside the disc first. The zip analogy breaks exactly here: every zip opens, but not every series converges.

The Quick Version

  • A generating function packs a whole sequence into one power series: G(x)=a0+a1x+⋯G(x) = a_0 + a_1 x + \cdots.
  • Recurrences between terms become solvable equations for the package function.
  • Fibonacci falls out of x/(1−x−x2)x / (1 - x - x^2): matching coefficients gives 0, 1, 1, 2, 3, 5.
  • Ordinary and exponential variants answer different counting questions; do not mix them.
  • Series algebra is only trustworthy inside the radius of convergence.