Goodstein Sequences
Some theorems feel like magic tricks. Goodstein sequences are one of them: take any positive integer, apply a simple recursive rule, and watch the numbers explode - growing faster than exponentials, faster than towers of exponentials, faster than any primitive recursive function. The sequence appears to diverge to infinity.
Yet every Goodstein sequence terminates at zero. Always. And the twist… this fact cannot be proven using the standard axioms of arithmetic.
This post walks through the construction, implements it in Python, and sketches the ordinal-theoretic proof of termination.
The Construction
Goodstein sequences are built from hereditary base- notation, a way of writing numbers where the exponents themselves are also expanded.
Hereditary Base- Notation
In ordinary base-, we write numbers as sums of powers:
Hereditary notation goes further: every exponent is also written in base-, recursively, until all numbers in the expression are less than .
For example, in base :
But , so the hereditary form is:
Every positive integer has a unique hereditary base- representation for any .
The Goodstein Rule
The Goodstein sequence starting from proceeds as follows:
- Write in hereditary base-
- Replace every with (a “bump”)
- Subtract
- Repeat: write in hereditary base-, replace with , subtract
- Continue until you reach
At step , you’re working in base : write the number in hereditary base-, replace with , subtract .
Let’s implement this to see it in action.
Implementation
First, we need a data structure for hereditary representations. Each number is a sum of terms, where each term has a coefficient and an exponent (which is itself a hereditary representation):
from dataclasses import dataclass
@dataclass
class Term:
coeff: int # Coefficient (1 to base-1)
exp: list["Term"] # Exponent as hereditary representation
# A hereditary representation is a list of Terms
# Example: 2^(2^1) + 2^1 + 1 = [Term(1, [Term(1, [Term(1, [])])]),
# Term(1, [Term(1, [])]),
# Term(1, [])]
Converting a number to hereditary form:
def to_hereditary(n: int, base: int) -> list[Term]:
"""Convert n to hereditary base-b representation"""
if n == 0:
return []
terms = []
while n > 0:
# Find the largest power of base that fits
exp = 0
power = 1
while power * base <= n:
power *= base
exp += 1
# How many times does this power fit?
coeff = n // power
n = n % power
# Recursively convert the exponent
exp_hereditary = to_hereditary(exp, base)
terms.append(Term(coeff, exp_hereditary))
return terms
Evaluating a hereditary representation in a new base (after the “bump”):
def evaluate(terms: list[Term], base: int) -> int:
"""Evaluate hereditary representation in given base"""
total = 0
for term in terms:
if not term.exp: # Exponent is 0, so base^0 = 1
total += term.coeff
else:
exp_val = evaluate(term.exp, base)
total += term.coeff * (base ** exp_val)
return total
Now the Goodstein step - bump the base and subtract:
def goodstein_step(n: int, base: int) -> int:
"""One step: convert to hereditary base, bump to base+1, subtract 1"""
hereditary = to_hereditary(n, base)
bumped = evaluate(hereditary, base + 1)
return bumped - 1
And the full sequence generator:
def goodstein_sequence(start: int, max_steps: int = 100) -> list[int]:
"""Generate Goodstein sequence starting from n"""
seq = [start]
base = 2
while seq[-1] > 0 and len(seq) < max_steps:
seq.append(goodstein_step(seq[-1], base))
base += 1
return seq
A Complete Example:
Tracing through step by step:
Step 0: Start with in hereditary base-:
Step 1: Bump , then subtract:
Step 2: Write in hereditary base-:
Bump , subtract:
Step 3: Write in hereditary base-:
Bump has no effect. Subtract:
Steps 4-5: Continue subtracting: .
print(goodstein_sequence(3))
# [3, 3, 3, 2, 1, 0]
Six steps. Not too bad.
The Sequence
Now try :
seq = goodstein_sequence(4, max_steps=20)
print(seq)
# [4, 26, 41, 60, 83, 109, 139, 173, 211, 253, 299, 348, 401, 458, 519, 584, 653, 726, 803, 884]
It’s increasing. More steps:
seq = goodstein_sequence(4, max_steps=1000)
print(f"After 1000 steps: {seq[-1]}")
# After 1000 steps: 2352161
Still climbing. At step 10000, it reaches about 100 million. At step 1000000, it has 12 digits. The growth looks roughly quadratic in this phase.
But appearances deceive. The sequence does eventually terminate—after exactly:
That’s a number with over 121 million digits. The sequence grows to incomprehensible sizes before finally collapsing to zero.
Visualizing the Growth
A helper to print the hereditary form shows what’s happening structurally:
def format_hereditary(terms: list[Term], base: int) -> str:
"""Pretty-print hereditary representation"""
if not terms:
return "0"
parts = []
for term in terms:
if not term.exp: # base^0 = 1, so just the coefficient
parts.append(str(term.coeff))
elif term.exp == [Term(1, [])]: # base^1
if term.coeff == 1:
parts.append(str(base))
else:
parts.append(f"{term.coeff}·{base}")
else:
exp_str = format_hereditary(term.exp, base)
if term.coeff == 1:
parts.append(f"{base}^({exp_str})")
else:
parts.append(f"{term.coeff}·{base}^({exp_str})")
return " + ".join(parts)
Now we can watch the structure evolve:
def trace_goodstein(start: int, steps: int = 10):
"""Trace Goodstein sequence showing hereditary forms"""
n = start
base = 2
for step in range(steps):
if n == 0:
print(f"Step {step}: 0 - terminated!")
break
terms = to_hereditary(n, base)
form = format_hereditary(terms, base)
print(f"Step {step}: {n} = {form} (base {base})")
n = goodstein_step(n, base)
base += 1
trace_goodstein(4, steps=8)
Output:
Step 0: 4 = 2^(2) (base 2)
Step 1: 26 = 3^(3) + 2·3 + 2 (base 3)
Step 2: 41 = 4^(4) + 2·4 + 1 (base 4)
Step 3: 60 = 5^(5) + 2·5 (base 5)
Step 4: 83 = 6^(6) + 2·6 + 5 (base 6)
Step 5: 109 = 7^(7) + 2·7 + 4 (base 7)
Step 6: 139 = 8^(8) + 2·8 + 3 (base 8)
Step 7: 173 = 9^(9) + 2·9 + 2 (base 9)
Look at the pattern: where counts down. When hits zero, the term will start unwinding. Eventually the leading term will need to decompose - and that’s when things explode.
Why It Always Terminates
Despite the explosive growth, every Goodstein sequence reaches zero. The proof uses ordinal numbers - a generalization of natural numbers that extends into the transfinite.
The Key Idea: An Ordinal Shadow
At each step, we create a “shadow” of the current value by replacing the base with (the first infinite ordinal). This maps each Goodstein value to an ordinal below , where:
For example, when in hereditary base-, its ordinal shadow is:
The critical observation is that while the numerical values grow, the ordinal shadows strictly decrease.
Why? The base bump () doesn’t change the ordinal - stays . But subtracting always decreases the ordinal representation.
Tracing the ordinal shadows:
def to_ordinal_string(terms: list[Term]) -> str:
"""Convert hereditary representation to ordinal notation"""
if not terms:
return "0"
parts = []
for term in terms:
if not term.exp: # ω^0 = 1
parts.append(str(term.coeff))
elif term.exp == [Term(1, [])]: # ω^1 = ω
if term.coeff == 1:
parts.append("ω")
else:
parts.append(f"{term.coeff}ω")
else:
exp_str = to_ordinal_string(term.exp)
if term.coeff == 1:
parts.append(f"ω^({exp_str})")
else:
parts.append(f"{term.coeff}ω^({exp_str})")
return " + ".join(parts)
def trace_with_ordinals(start: int, steps: int = 8):
"""Show both value and ordinal shadow"""
n = start
base = 2
for step in range(steps):
if n == 0:
print(f"Step {step}: value = 0, ordinal = 0")
break
terms = to_hereditary(n, base)
ordinal = to_ordinal_string(terms)
print(f"Step {step}: value = {n}, ordinal = {ordinal}")
n = goodstein_step(n, base)
base += 1
trace_with_ordinals(4, steps=10)
Output:
Step 0: value = 4, ordinal = ω^(ω)
Step 1: value = 26, ordinal = ω^(ω) + 2ω + 2
Step 2: value = 41, ordinal = ω^(ω) + 2ω + 1
Step 3: value = 60, ordinal = ω^(ω) + 2ω
Step 4: value = 83, ordinal = ω^(ω) + ω + 5
Step 5: value = 109, ordinal = ω^(ω) + ω + 4
Step 6: value = 139, ordinal = ω^(ω) + ω + 3
Step 7: value = 173, ordinal = ω^(ω) + ω + 2
Step 8: value = 211, ordinal = ω^(ω) + ω + 1
Step 9: value = 253, ordinal = ω^(ω) + ω
Watch the ordinals: they’re counting down. The values explode (), but the ordinals decrease monotonically.
Why Ordinals Can’t Descend Forever
Ordinals have a crucial property: there are no infinite descending chains. Any strictly decreasing sequence of ordinals must be finite.
This is fundamentally different from integers, where we can descend forever in the negatives. Ordinals have a “floor” - you can’t go below zero.
So:
- Each Goodstein step decreases the ordinal shadow
- Ordinal sequences can’t decrease forever
- Therefore the sequence must reach ordinal
- When the ordinal is , the value is
Beyond Peano Arithmetic
The proof above uses induction on ordinals up to . This is called transfinite induction, and it’s more powerful than ordinary mathematical induction on natural numbers.
In 1982, Laurence Kirby and Jeff Paris proved something remarkable:
Goodstein’s theorem is unprovable in Peano Arithmetic.
Peano Arithmetic (PA) is the standard axiom system for natural numbers. It captures everything we normally think of as “arithmetic” - addition, multiplication, induction over natural numbers.
But PA can only do induction over . It cannot express or justify induction up to . Since that’s exactly what the proof requires, Goodstein’s theorem lies beyond PA’s reach.
This was a landmark result. Unlike Gödel’s incompleteness examples (which are self-referential and artificial), Goodstein’s theorem is a concrete, natural statement about integer sequences - yet it requires stepping outside arithmetic to prove.
Growth Rate Comparison
To appreciate how fast Goodstein sequences grow, compare them to familiar fast-growing functions:
| Function | Growth | Example |
|---|---|---|
| Polynomial | ||
| Exponential | Tower of height 1 | |
| Tower | Height | |
| Ackermann | Grows faster than any tower | |
| Goodstein | Beyond | Grows faster than Ackermann |
The Goodstein function (number of steps to termination) eventually dominates every primitive recursive function. It sits at level in the fast-growing hierarchy.
To put ‘s termination time in perspective:
| Quantity | Approximate size |
|---|---|
| Atoms in observable universe | |
| Planck times since Big Bang | |
| Steps for to terminate |
Conclusion
Goodstein sequences are a rare mathematical object - simple to define (hereditary base notation and subtraction), with explosive growth faster than any primitive recursive function, yet guaranteed to terminate via ordinal descent. And the termination proof requires transfinite induction to , placing it beyond Peano Arithmetic.
They reveal something profound about the foundations of mathematics: some true statements about natural numbers can only be proven by reasoning about infinite objects. The finite and the infinite are more entangled than naive intuition suggests.
Further Reading
- Goodstein’s theorem - the main theorem and proof sketch
- Fast-growing hierarchy - where Goodstein functions fit
- Goodstein sequence on Googology Wiki - for large number enthusiasts
References
- Goodstein, R. L. (1944). On the Restricted Ordinal Theorem. Journal of Symbolic Logic.
- Kirby, L. & Paris, J. (1982). Accessible Independence Results for Peano Arithmetic. Bulletin of the London Mathematical Society, 14, 285–293.
- Cichon, E. A. (1983). A Short Proof of Two Recently Discovered Independence Results Using Recursion Theoretic Methods. Proceedings of the AMS.