Skip to content
The Lumenary

Math laboratory

Euclid's numbers and induction formulas, checked

Factors 2*3*5*...*p + 1 for the first nine primes (30031 = 59 * 509 is not prime, but every factor is a new prime), and checks Gauss's sum formula and the sum of odd numbers for every n up to 10000, plus a fake theorem that fails at every n. Finite checks support the induction proofs in the lesson; they do not replace them.

Back to the labExact computationExhaustive finite check
Euclid's numbers and induction formulas, checkedPythonExact computationExhaustive finite checkComputationally tested
"""Euclid's numbers, and evidence versus proof for induction formulas.

Euclid's proof that there are infinitely many primes multiplies the primes of
a finite list and adds 1. The result N need not be prime itself - but every
prime factor of N is missing from the list. Here we factor N for the lists of
the first k primes, k = 1, ..., 9, and check that each factor is new.

Then we test two formulas proved by induction in the lesson,
1 + 2 + ... + n = n(n + 1)/2 and 1 + 3 + ... + (2n - 1) = n^2, for every n up
to 10 000, and a false claim whose inductive step works but whose base case
fails: "n^2 + n + 1 is even".

Runs unchanged in the browser (Pyodide) using only the standard library.
"""

from math import prod

def first_primes(k):
    """The first k primes."""
    primes = []
    n = 2
    while len(primes) < k:
        if all(n % p for p in primes if p * p <= n):
            primes.append(n)
        n += 1
    return primes

def factorize(n):
    """Prime factorisation of n >= 2 by trial division, as a sorted list."""
    if n < 2:
        raise ValueError("n must be at least 2")
    factors = []
    d = 2
    while d * d <= n:
        while n % d == 0:
            factors.append(d)
            n //= d
        d += 1
    if n > 1:
        factors.append(n)
    return factors

def euclid_number(primes):
    """The product of the given primes, plus one."""
    return prod(primes) + 1

def first_failure(claim, upto):
    """The least n in 0..upto with claim(n) false, or None."""
    for n in range(upto + 1):
        if not claim(n):
            return n
    return None

def step_difference(n):
    """(n+1)^2 + (n+1) + 1 minus n^2 + n + 1: always 2(n + 1), an even number,
    which is why "n^2 + n + 1 even" would pass from n to n + 1."""
    return ((n + 1) ** 2 + (n + 1) + 1) - (n * n + n + 1)

def running_check(term, closed_form, upto):
    """Check sum_{i < n} term(i) == closed_form(n) for n = 0..upto,
    accumulating the sum; return the first n where it fails, or None."""
    total = 0
    for n in range(upto + 1):
        if total != closed_form(n):
            return n
        total += term(n)
    return None

def main():
    print(" k  2*3*...*p_k + 1   factorisation           all factors new?")
    for k in range(1, 10):
        ps = first_primes(k)
        n = euclid_number(ps)
        fs = factorize(n)
        shown = " * ".join(map(str, fs)) if len(fs) > 1 else "prime"
        new = all(f not in ps for f in fs)
        print(f"{k:2d}  {n:15d}   {shown:22}  {'yes' if new else 'NO'}")
    print()
    upto = 10_000
    g = running_check(lambda i: i, lambda n: n * (n - 1) // 2, upto)
    o = running_check(lambda i: 2 * i + 1, lambda n: n * n, upto)
    print(f"Gauss: 0+1+...+(n-1) = n(n-1)/2, n <= {upto}: "
          f"{'no failure' if g is None else g}")
    print(f"Odd numbers: 1+3+...+(2n-1) = n^2, n <= {upto}: "
          f"{'no failure' if o is None else o}")
    step = all(step_difference(n) == 2 * (n + 1) for n in range(upto + 1))
    base = first_failure(lambda n: (n * n + n + 1) % 2 == 0, upto)
    print("'n^2+n+1 is even': consecutive values differ by 2(n+1) for all")
    print(f"  n <= {upto}: {step}. So the inductive step works - yet the claim")
    print(f"  fails at n = {base}, the base case, and in fact at every n.")
    print()
    print("Epistemic status: exact arithmetic. The factorisations are complete")
    print("and show that Euclid's numbers need not be prime. The formula checks")
    print("cover n <= 10000 only - finite evidence. The induction proofs in the")
    print("lesson cover every n; the last line shows why a base case is needed.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Used in