Skip to content
The Lumenary
First-year graduateGraduate 130 min

Experimental mathematics: conjectures and counterexamples

Computation as a laboratory — finding patterns and closed forms, hunting counterexamples with stated bounds, detecting integer relations, and judging computer-assisted proofs, without ever mistaking evidence for proof.

Formally verified · 19 LeanComputationally tested · 2 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review
MotivationH

Mathematics as an experimental science

Around 1731 Euler computed 1+14+19+116+⋯1 + \tfrac14 + \tfrac19 + \tfrac1{16} + \cdots to many decimal places — no easy task, since the series converges painfully slowly — and obtained 1.644934…1.644934\ldots. He recognised the number as π2/6\pi^2/6, announced the result in 1735 with a daring argument treating sin⁡x/x\sin x / x as an infinite polynomial, and spent years making it rigorous. As a teenager in the 1790s Gauss counted primes in tables and conjectured that their density near xx is about 1/ln⁡x1/\ln x; the prime number theorem was proved a century later. Birch and Swinnerton-Dyer's famous conjecture came out of computations on Cambridge's EDSAC computer in the early 1960s.

Computation lets mathematicians see patterns, guess closed forms, and refute conjectures with a single counterexample. It also misleads: primes ≡3(mod4)\equiv 3 \pmod 4 lead primes ≡1(mod4)\equiv 1 \pmod 4 for every xx below 26,86126{,}861, and the inequality π(x)<li(x)\pi(x) \lt \mathrm{li}(x) holds for every xx ever checked — yet both patterns fail. This lesson is about using computation as a laboratory: generating conjectures, designing searches with honest bounds, detecting integer relations at high precision, and judging computer-assisted proofs.

IntuitionH

The experimental cycle

Experimental mathematics follows a cycle:

  1. Explore. Compute many cases, plot, tabulate; look sequences up in the On-Line Encyclopedia of Integer Sequences (OEIS).
  2. Conjecture. Formulate a precise statement that fits the data.
  3. Test. Try hard to break it: extend the range, look at extreme cases, compute to higher precision. A conjecture that survives honest attempts at refutation earns credibility — but not truth.
  4. Prove or refute. A counterexample settles the question at once; a proof settles it for ever. Often the experiment also suggests the proof, by revealing the structure behind the pattern.

Different statements interact with computation differently. A statement "for all nn, P(n)P(n)" with PP decidable — such as Goldbach's conjecture — can be refuted by a finite computation but never confirmed by one. A closed form such as "this constant equals π2/6\pi^2/6" can be tested to a thousand digits, but agreement to a thousand digits is still not a proof. And an existence statement can be settled by exhibiting an object, which the computer can then certify.

The lesson assumes high-precision and floating-point computation from numerical methods and search techniques such as meet-in-the-middle from algorithm design; for how to package and report such computations, see computational reproducibility.

DefinitionsH

Definitions

Definition— integer relation

An integer relation among real numbers x1,…,xnx_1, \dots, x_n is a non-zero vector (a1,…,an)∈Zn(a_1, \dots, a_n) \in \Z^n with a1x1+⋯+anxn=0a_1 x_1 + \cdots + a_n x_n = 0. For instance (1,−1,−1)(1, -1, -1) is an integer relation for (φ2,φ,1)(\varphi^2, \varphi, 1), where φ\varphi is the golden ratio. A number α\alpha is algebraic of degree at most dd exactly when (1,α,…,αd)(1, \alpha, \dots, \alpha^d) has an integer relation.

Definition— exhaustive search up to a bound

A counterexample search for a statement ∀n∈D P(n)\forall n \in D\ P(n) is exhaustive up to the bound NN if it checks every case n∈Dn \in D with n≤Nn \le N (or every case in an explicitly described finite set). Its report must state the bound, the exact set searched, and how completeness of the search was ensured.

Definition— computer-assisted proof

A computer-assisted proof is a proof in which some steps are carried out by computation — typically a reduction, proved by hand, of the theorem to finitely many cases, followed by a computer check of those cases. Its reliability depends on the reduction, the code, and the computing environment.

In this lesson a conjecture is a precise statement that has been proposed but neither proved nor refuted, and numerical evidence for an identity means agreement to a stated number of digits.

Worked examplesH

Patterns that failed, and one that did not

Example— Fermat numbers

Fermat (1640) observed that Fn=22n+1F_n = 2^{2^n} + 1 is prime for n=0,1,2,3,4n = 0, 1, 2, 3, 4 — namely 3,5,17,257,655373, 5, 17, 257, 65537 — and conjectured that all are prime. Euler (1732) found 641∣F5641 \mid F_5. No further Fermat prime is known: F5,…,F32F_5, \dots, F_{32} are all known to be composite. Five confirming cases did not make a theorem, and the opposite conjecture — that only finitely many FnF_n are prime — is also open.

Example— Euler's sum-of-powers conjecture

Euler (1769) conjectured that a kk-th power is never the sum of fewer than kk positive kk-th powers (true for k=3k = 3, by Fermat's last theorem for cubes). In 1966 Lander and Parkin published, in a two-sentence paper, a counterexample found by a computer search:

275+845+1105+1335=1445.27^5 + 84^5 + 110^5 + 133^5 = 144^5 .

For fourth powers Elkies (1988) found 26824404+153656394+187967604=2061567342682440^4 + 15365639^4 + 18796760^4 = 20615673^4 using elliptic curves, and Frye then found the smallest example, 958004+2175194+4145604=422481495800^4 + 217519^4 + 414560^4 = 422481^4, by a search guided by Elkies's analysis. The first experiment below repeats Lander and Parkin's search exhaustively for e≤150e \le 150.

Example— A prime race

Let π(x;4,a)\pi(x; 4, a) be the number of primes p≤xp \le x with p≡a(mod4)p \equiv a \pmod 4. For every x<26861x \lt 26861 we have π(x;4,3)≥π(x;4,1)\pi(x; 4, 3) \ge \pi(x; 4, 1), and the lead of the "3" team looks permanent. At x=26861x = 26861 the "1" team goes ahead (Leech, 1957) — for two values of xx; it leads again from 616841616841. Littlewood (1914) proved that the lead changes infinitely often.

Example— π(x) and li(x)

The logarithmic integral li(x)=∫0xdtln⁡t\mathrm{li}(x) = \int_0^x \frac{dt}{\ln t} (a principal value) is an excellent approximation to the prime-counting function π(x)\pi(x), and π(x)<li(x)\pi(x) \lt \mathrm{li}(x) for every xx that has ever been checked — at least up to 101410^{14} (Kotnik, 2008). For a long time it was widely believed always to hold. Littlewood (1914) proved that π(x)−li(x)\pi(x) - \mathrm{li}(x) changes sign infinitely often; the first sign change is known to occur below about 1.4×103161.4 \times 10^{316} (Bays and Hudson, 2000, with later refinements), far beyond direct computation.

Example— Borwein integrals

For n=0,1,…,6n = 0, 1, \dots, 6,

∫0∞∏k=0nsin⁡(x/(2k+1))x/(2k+1) dx=π2,\int_0^\infty \prod_{k=0}^{n} \frac{\sin(x/(2k+1))}{x/(2k+1)}\, dx = \frac{\pi}{2},

and the pattern seems certain. For n=7n = 7 the integral is π2−2.31×10−11\frac{\pi}{2} - 2.31 \times 10^{-11} approximately — exactly 467807924713440738696537864469935615849440640907310521750000 π\frac{467807924713440738696537864469}{935615849440640907310521750000}\,\pi. The reason (D. and J. Borwein, 2001) is that the value is π/2\pi/2 precisely while 13+15+⋯+12n+1<1\frac13 + \frac15 + \cdots + \frac1{2n+1} \lt 1, and that sum first exceeds 11 at n=7n = 7. A numerical integrator working to eight digits would have "confirmed" the pattern.

Example— A closed form found by computer

In 1995 Simon Plouffe, using David Bailey's implementation of the PSLQ algorithm, searched for an integer relation among π\pi and the eight constants Sj=∑k≥016−k/(8k+j)S_j = \sum_{k \ge 0} 16^{-k}/(8k + j), j=1,…,8j = 1, \dots, 8, computed to high precision. The relation found,

π=∑k=0∞116k(48k+1−28k+4−18k+5−18k+6),\pi = \sum_{k=0}^{\infty} \frac{1}{16^k}\left(\frac{4}{8k+1} - \frac{2}{8k+4} - \frac{1}{8k+5} - \frac{1}{8k+6}\right),

is the Bailey–Borwein–Plouffe (BBP) formula (published 1997). It was then proved by elementary calculus (Theorem 2), and it has a striking consequence: hexadecimal digits of π\pi can be computed far after the point without computing the earlier ones (Theorem 3).

ProofH

Proofs behind the experiments

Theorem— Theorem 1 (Euler, 1732)

641641 divides F5=232+1F_5 = 2^{32} + 1.

Proof

Note 641=5⋅27+1=54+24641 = 5 \cdot 2^7 + 1 = 5^4 + 2^4. Modulo 641641, the first form gives 5⋅27≡−15 \cdot 2^7 \equiv -1, hence 54⋅228=(5⋅27)4≡15^4 \cdot 2^{28} = (5 \cdot 2^7)^4 \equiv 1; the second gives 54≡−245^4 \equiv -2^4. Therefore 232=24⋅228≡−54⋅228≡−12^{32} = 2^4 \cdot 2^{28} \equiv -5^4 \cdot 2^{28} \equiv -1, i.e. 641∣232+1641 \mid 2^{32} + 1. ■\blacksquare

∎

Euler did not stumble on 641641: he had shown that every prime factor of FnF_n has the form 2n+1k+12^{n+1}k + 1 (later sharpened to 2n+2k+12^{n+2}k + 1 by Lucas), so for F5F_5 only primes 64k+164k + 1 need testing — 193193, 257257, 449449, 577577, 641641 — a small search guided by theory.

Theorem— Theorem 2 (Bailey, Borwein and Plouffe, 1997)

π=∑k=0∞116k(48k+1−28k+4−18k+5−18k+6).\displaystyle \pi = \sum_{k=0}^{\infty} \frac{1}{16^k}\left(\frac{4}{8k+1} - \frac{2}{8k+4} - \frac{1}{8k+5} - \frac{1}{8k+6}\right).

Proof

For 1≤j≤81 \le j \le 8, expand 1/(1−x8)1/(1 - x^8) as a geometric series, which converges uniformly on [0,1/2][0, 1/\sqrt2] (there x8≤116x^8 \le \tfrac1{16}), and integrate term by term:

∫01/2xj−11−x8 dx=∑k≥0∫01/2x8k+j−1 dx=∑k≥02−(8k+j)/28k+j=2−j/2Sj.\int_0^{1/\sqrt2} \frac{x^{j-1}}{1 - x^8}\, dx = \sum_{k \ge 0} \int_0^{1/\sqrt2} x^{8k + j - 1}\, dx = \sum_{k \ge 0} \frac{2^{-(8k+j)/2}}{8k + j} = 2^{-j/2} S_j .

Hence

4S1−2S4−S5−S6=∫01/242−8x3−42 x4−8x51−x8 dx.4S_1 - 2S_4 - S_5 - S_6 = \int_0^{1/\sqrt2} \frac{4\sqrt2 - 8x^3 - 4\sqrt2\, x^4 - 8x^5}{1 - x^8}\, dx .

Substitute x=y/2x = y/\sqrt2. The integrand becomes 16(4−2y3−y4−y5)16−y8\dfrac{16(4 - 2y^3 - y^4 - y^5)}{16 - y^8}, and factoring 4−2y3−y4−y5=−(y−1)(y2+2)(y2+2y+2)4 - 2y^3 - y^4 - y^5 = -(y-1)(y^2+2)(y^2+2y+2) and 16−y8=−(y2−2)(y2+2)(y2−2y+2)(y2+2y+2)16 - y^8 = -(y^2-2)(y^2+2)(y^2-2y+2)(y^2+2y+2) gives

4S1−2S4−S5−S6=∫0116y−16y4−2y3+4y−4 dy=∫01(4yy2−2−4y−8y2−2y+2)dy4S_1 - 2S_4 - S_5 - S_6 = \int_0^1 \frac{16y - 16}{y^4 - 2y^3 + 4y - 4}\, dy = \int_0^1 \left(\frac{4y}{y^2 - 2} - \frac{4y - 8}{y^2 - 2y + 2}\right) dy

by partial fractions. On [0,1][0, 1] an antiderivative is F(y)=2ln⁡(2−y2)−2ln⁡(y2−2y+2)+4arctan⁡(y−1)F(y) = 2\ln(2 - y^2) - 2\ln(y^2 - 2y + 2) + 4\arctan(y - 1), because y2−2y+2=1+(y−1)2y^2 - 2y + 2 = 1 + (y - 1)^2. So the integral is F(1)−F(0)=0−(2ln⁡2−2ln⁡2+4arctan⁡(−1))=πF(1) - F(0) = 0 - (2\ln 2 - 2\ln 2 + 4\arctan(-1)) = \pi. ■\blacksquare

∎

Theorem— Theorem 3 (BBP digit extraction)

Let {t}\{t\} denote the fractional part of tt, and d≥0d \ge 0. Then

{16dπ}={4{16dS1}−2{16dS4}−{16dS5}−{16dS6}},{16dSj}={∑k=0d16d−k mod (8k+j)8k+j+∑k>d16d−k8k+j},\{16^d \pi\} = \big\{ 4\{16^d S_1\} - 2\{16^d S_4\} - \{16^d S_5\} - \{16^d S_6\} \big\}, \qquad \{16^d S_j\} = \Big\{ \sum_{k=0}^{d} \frac{16^{d-k} \bmod (8k+j)}{8k+j} + \sum_{k \gt d} \frac{16^{d-k}}{8k+j} \Big\},

so the hexadecimal digits of π\pi in positions d+1,d+2,…d + 1, d + 2, \dots can be computed with O(dlog⁡d)O(d \log d) operations on numbers of O(log⁡d)O(\log d) bits, without computing the first dd digits.

Proof

Multiply the BBP formula by 16d16^d; fractional parts are additive modulo integers, which gives the first identity. In 16dSj=∑k16d−k/(8k+j)16^d S_j = \sum_k 16^{d-k}/(8k+j), the terms with k≤dk \le d are 16d−k/(8k+j)16^{d-k}/(8k + j), whose integer part does not affect the fractional part, so 16d−k16^{d-k} may be reduced modulo 8k+j8k + j; the remaining terms form a rapidly convergent tail. Each modular power costs O(log⁡d)O(\log d) multiplications by binary exponentiation, and there are O(d)O(d) of them. ■\blacksquare

∎

In practice the sums are carried in floating point, so only the first several digits after position dd are reliable, and the computation below checks them against an independent exact calculation. No analogous formula is known for the decimal digits of π\pi.

How are such relations found? An integer relation algorithm takes approximations of x1,…,xnx_1, \dots, x_n and either returns a candidate relation or certifies that none exists with small coefficients.

Theorem— Theorem 4 (integer relation detection; Ferguson, Bailey and Arno 1999) — stated, not proved here

Let x∈Rnx \in \R^n. The PSLQ algorithm, run in exact real arithmetic, maintains a lower-trapezoidal matrix HH with the property that every integer relation mm for xx satisfies ∥m∥≥1/max⁡j∣Hjj∣\|m\| \ge 1/\max_j |H_{jj}|. If xx has an integer relation, PSLQ finds one after a number of iterations bounded by a polynomial in nn and log⁡∥mmin⁡∥\log \|m_{\min}\|, where mmin⁡m_{\min} is a shortest relation.

Integer relations can also be found with the LLL lattice-basis reduction algorithm (Lenstra, Lenstra and Lovász, 1982), as shown in polynomial time by Håstad, Just, Lagarias and Schnorr (1989). In real life the input is only known to finite precision, so two warnings apply. A "relation" with coefficients of size 10c10^{c} among nn numbers known to DD digits is meaningful only if DD comfortably exceeds ncnc: otherwise PSLQ finds spurious relations that disappear at higher precision. And the lower bound for relations is trustworthy only if the working precision was sufficient. A relation that persists when the precision is doubled is strong evidence — and the signal to look for a proof.

Theorem— Theorem 5 (Littlewood 1914) — stated, not proved here

Both π(x)−li(x)\pi(x) - \mathrm{li}(x) and π(x;4,1)−π(x;4,3)\pi(x; 4, 1) - \pi(x; 4, 3) change sign infinitely often as x→∞x \to \infty.

The proof uses the zeros of the Riemann zeta function and of the Dirichlet LL-function for the character modulo 44 (Ingham, 1932, chapter V). Rubinstein and Sarnak (1994) explained why the data mislead: assuming the generalised Riemann hypothesis and a linear-independence hypothesis on the zeros, the set of xx with π(x;4,3)>π(x;4,1)\pi(x;4,3) \gt \pi(x;4,1) has logarithmic density about 0.99590.9959 — the "3" team leads almost always, but not always. Note the three levels in that sentence: a theorem (Littlewood), a conditional theorem (Rubinstein–Sarnak), and numerical evidence (the race up to 10510^5 below).

ExplanationH

Assessing computer-assisted proofs

A computer-assisted proof is as good as three things: the mathematical reduction to finitely many cases, the correctness of the computation, and the environment it ran in. The great examples show the ways in which each has been secured.

  • The four colour theorem (Appel and Haken, 1976). A hand-proved reduction showed that it suffices to check that each configuration in an unavoidable set of 1,936 is reducible, which a computer did in about 1,200 hours. Doubts about the unrefereeable computation (and some errors in the hand part, later corrected) led Robertson, Sanders, Seymour and Thomas (1997) to a new proof with 633 configurations and new, independently written programs; Gonthier (2005) then checked a complete proof in the Coq proof assistant — reduction and computation together.
  • The Kepler conjecture (Hales, with Ferguson, 1998). The densest packing of equal balls in space has density π/18\pi/\sqrt{18}. The proof reduced the problem to several thousand configurations, described by planar graphs, and to many nonlinear inequalities, verified with interval arithmetic and linear programming. The referees reported that they were "99% certain" of its correctness but could not check every computation; the paper appeared in the Annals of Mathematics in 2005. Hales then led the Flyspeck project, which completed a formal proof in HOL Light and Isabelle in 2014.
  • Non-existence of a projective plane of order 10 (Lam, Thiel and Swiercz, 1989) used thousands of hours on a Cray supercomputer; it has since been re-verified independently, including with SAT solvers that produce checkable certificates.
  • SAT-solver proofs such as the Boolean Pythagorean triples theorem (Heule, Kullmann and Marek, 2016: {1,…,7824}\{1, \dots, 7824\} can be split into two classes with no Pythagorean triple inside a class, but {1,…,7825}\{1, \dots, 7825\} cannot) and Keller's conjecture in dimension 7 (Brakensiek, Heule, Mackey and Narváez, 2020) produce proof certificates — for unsatisfiability, a DRAT proof — that are checked by independent, sometimes formally verified, checkers.
  • Validated numerics turns floating-point computation into proof by computing with intervals and outward rounding: Tucker's 2002 proof that the Lorenz equations have a strange attractor, and the numerical parts of Helfgott's 2013 proof of the ternary Goldbach conjecture (every odd number greater than 55 is a sum of three primes), whose small cases were checked by a separate computation with Platt.

Questions to ask of any computer-assisted proof: Is the reduction to finitely many cases proved, and where? Is the code available, and has it been independently reimplemented? Does the computation emit certificates that a simpler program can check? Were floating-point computations made rigorous? Has any part been formally verified? Compare computational reproducibility and formalising published mathematics.

Formal mathematicsF

Experiments and their proofs in Lean

Fermat's evidence, Euler's refutation by his own argument (no 2322^{32} is computed), and the conclusion:

fermatLean 4Formally verified
/-- The Fermat numbers `Fₙ = 2^(2^n) + 1`: 3, 5, 17, 257, 65537, … -/
def fermat (n : ℕ) : ℕ := 2 ^ (2 ^ n) + 1
Axioms used: propextformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
fermat_prime_le_fourLean 4Proved here from basic factsFormally verified
/-- The evidence Fermat had: `F₀, …, F₄` are all prime (checked here by `norm_num`'s
certified primality test). -/
theorem fermat_prime_le_four (n : ℕ) (hn : n ≤ 4) : (fermat n).Prime := by
  interval_cases n <;> norm_num [fermat]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
euler_641Lean 4Proved here from basic factsFormally verified
/-- **Euler (1732): `641 ∣ 2³² + 1`**, by Euler's argument rather than by computing `2³²`.
Since `641 = 5·2⁷ + 1 = 5⁴ + 2⁴`, modulo 641 we have `5·2⁷ = -1` and `5⁴ = -2⁴`. Hence
`2³² = 2⁴·2²⁸ = -5⁴·2²⁸ = -(5·2⁷)⁴ = -1`. -/
theorem euler_641 : (2 : ZMod 641) ^ 32 + 1 = 0 := by
  have h1 : (5 : ZMod 641) * 2 ^ 7 = -1 := by decide
  have h2 : (5 : ZMod 641) ^ 4 = -(2 ^ 4) := by decide
  calc (2 : ZMod 641) ^ 32 + 1 = -(5 ^ 4) * 2 ^ 28 + 1 := by rw [h2]; ring
    _ = -((5 * 2 ^ 7) ^ 4) + 1 := by ring
    _ = 0 := by rw [h1]; ring
Axioms used: propext, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
fermat_conjecture_falseLean 4Proved here from basic factsFormally verified
/-- **Fermat's conjecture is false**: not every Fermat number is prime, because
`F₅ = 641 · 6700417`. Five cases of evidence did not make a theorem. -/
theorem fermat_conjecture_false : ¬ ∀ n, (fermat n).Prime := by
  intro h
  have h5 : fermat 5 = 641 * 6700417 := by norm_num [fermat]
  have := h 5
  rw [h5] at this
  exact Nat.not_prime_mul (by norm_num) (by norm_num) this
Axioms used: propextformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor

Euler's sum-of-powers conjecture is defined as a proposition, and refuted by the counterexample:

EulerConjectureFiveLean 4Formally verified
/-- Euler's sum-of-powers conjecture for fifth powers (1769): no fifth power is a sum of four
positive fifth powers. Defined as a proposition — stating it is not asserting it. -/
def EulerConjectureFive : Prop :=
  ∀ a b c d e : ℕ, 0 < a → 0 < b → 0 < c → 0 < d → a ^ 5 + b ^ 5 + c ^ 5 + d ^ 5 ≠ e ^ 5
Axioms used: propextformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
lander_parkinLean 4Proved here from basic factsFormally verified
/-- **Lander and Parkin (1966)**, found by a computer search on a CDC 6600:
`27⁵ + 84⁵ + 110⁵ + 133⁵ = 144⁵`. -/
theorem lander_parkin : 27 ^ 5 + 84 ^ 5 + 110 ^ 5 + 133 ^ 5 = 144 ^ 5 := by norm_num
Axioms used: propextformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
euler_conjecture_five_falseLean 4Proved here from basic factsFormally verified
/-- Hence Euler's conjecture for fifth powers is false. One counterexample suffices. -/
theorem euler_conjecture_five_false : ¬ EulerConjectureFive := fun h =>
  h 27 84 110 133 144 (by norm_num) (by norm_num) (by norm_num) (by norm_num) lander_parkin
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor

Integer relations: a relation that exists, and a proof that none exists for (2,1)(\sqrt2, 1) — the kind of statement no search can establish:

IsIntegerRelationLean 4Formally verified
/-- An **integer relation** for real numbers `x₀, …, xₙ₋₁` is a non-zero integer vector `a`
with `a₀x₀ + ⋯ + aₙ₋₁xₙ₋₁ = 0`. Algorithms such as PSLQ search for them numerically. -/
def IsIntegerRelation {n : ℕ} (x : Fin n → ℝ) (a : Fin n → ℤ) : Prop :=
  a ≠ 0 ∧ ∑ i, (a i : ℝ) * x i = 0
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
golden_relationLean 4Proved here from basic factsFormally verified
/-- `(1, -1, -1)` is an integer relation for `(φ², φ, 1)`: the golden ratio satisfies
`φ² - φ - 1 = 0` (Mathlib's `goldenRatio_sq`). -/
theorem golden_relation :
    IsIntegerRelation ![goldenRatio ^ 2, goldenRatio, 1] ![1, -1, -1] := by
  refine ⟨fun h => by simpa using congrFun h 0, ?_⟩
  simp [Fin.sum_univ_three, goldenRatio_sq]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
no_relation_sqrt_twoLean 4Proved here from basic factsFormally verified
/-- **No integer relation exists for `(√2, 1)`.** If `a₀√2 + a₁ = 0` with `a₀ ≠ 0` then `√2` would
be rational; if `a₀ = 0` then `a₁ = 0` too. Absence of relations is an irrationality statement:
a search can only rule out relations up to a size bound, while this needs a proof
(Mathlib's `irrational_sqrt_two`). -/
theorem no_relation_sqrt_two (a : Fin 2 → ℤ) : ¬ IsIntegerRelation ![√2, 1] a := by
  rintro ⟨hne, hsum⟩
  simp only [Fin.sum_univ_two, Matrix.cons_val_zero, Matrix.cons_val_one, mul_one] at hsum
  by_cases h0 : a 0 = 0
  · have h1 : a 1 = 0 := by
      rw [h0] at hsum
      simpa using hsum
    exact hne (funext fun i => by fin_cases i <;> simp [h0, h1])
  · have hq : √2 = ((-(a 1) / a 0 : ℚ) : ℝ) := by
      have ha0 : (a 0 : ℝ) ≠ 0 := by exact_mod_cast h0
      push_cast
      field_simp
      linarith
    exact irrational_sqrt_two ⟨_, hq.symm⟩
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor

The analytic heart of Theorem 2 — partial fractions and the integral equal to π\pi, proved with the fundamental theorem of calculus exactly as above:

bbpIntegrandLean 4Formally verified
/-- The integrand to which the BBP series reduces after writing `1/(8k+j)` as an integral,
summing the geometric series and substituting `y = √2 x`. -/
noncomputable def bbpIntegrand (y : ℝ) : ℝ := (16 * y - 16) / (y ^ 4 - 2 * y ^ 3 + 4 * y - 4)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
bbp_partial_fractionsLean 4Proved here from basic factsFormally verified
/-- Partial fractions: since `y⁴ - 2y³ + 4y - 4 = (y² - 2)(y² - 2y + 2)`,
`(16y - 16)/(y⁴ - 2y³ + 4y - 4) = 4y/(y² - 2) - (4y - 8)/(y² - 2y + 2)` whenever `y² ≠ 2`. -/
theorem bbp_partial_fractions (y : ℝ) (hy : y ^ 2 ≠ 2) :
    bbpIntegrand y = 4 * y / (y ^ 2 - 2) - (4 * y - 8) / (y ^ 2 - 2 * y + 2) := by
  have h1 : y ^ 2 - 2 ≠ 0 := sub_ne_zero.2 hy
  have h2 : y ^ 2 - 2 * y + 2 ≠ 0 := by nlinarith [sq_nonneg (y - 1)]
  have h3 : y ^ 4 - 2 * y ^ 3 + 4 * y - 4 = (y ^ 2 - 2) * (y ^ 2 - 2 * y + 2) := by ring
  rw [bbpIntegrand, h3, div_sub_div _ _ h1 h2]
  congr 1
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
bbp_integralLean 4Proved here from basic factsFormally verified
/-- **`∫₀¹ (16y - 16)/(y⁴ - 2y³ + 4y - 4) dy = π`.** An antiderivative on `[0, 1]` is
`F(y) = 2 log(2 - y²) - 2 log(y² - 2y + 2) + 4 arctan(y - 1)`; its derivative is the integrand
by `bbp_partial_fractions`, and `F(1) - F(0) = 0 - 4 arctan(-1) = π`. Together with the
(unformalised) conversion of the series into this integral, this proves the BBP formula
`π = Σₖ 16⁻ᵏ (4/(8k+1) - 2/(8k+4) - 1/(8k+5) - 1/(8k+6))`. -/
theorem bbp_integral : ∫ y in (0 : ℝ)..1, bbpIntegrand y = π := by
  set F : ℝ → ℝ := fun y => 2 * log (2 - y ^ 2) - 2 * log (y ^ 2 - 2 * y + 2)
    + 4 * arctan (y - 1) with hF
  have hderiv : ∀ y ∈ Set.uIcc (0 : ℝ) 1, HasDerivAt F (bbpIntegrand y) y := by
    intro y hy
    rw [Set.uIcc_of_le zero_le_one] at hy
    obtain ⟨hy0, hy1⟩ := hy
    have hA : 0 < 2 - y ^ 2 := by nlinarith
    have hB : 0 < y ^ 2 - 2 * y + 2 := by nlinarith [sq_nonneg (y - 1)]
    have dA : HasDerivAt (fun y : ℝ => 2 - y ^ 2) (-(2 * y)) y := by
      simpa using (hasDerivAt_pow 2 y).const_sub (2 : ℝ)
    have dB : HasDerivAt (fun y : ℝ => y ^ 2 - 2 * y + 2) (2 * y - 2) y := by
      have := ((hasDerivAt_pow 2 y).sub ((hasDerivAt_id y).const_mul 2)).add_const (2 : ℝ)
      simpa using this
    have dC : HasDerivAt (fun y : ℝ => arctan (y - 1)) (1 / (1 + (y - 1) ^ 2) * 1) y :=
      ((hasDerivAt_id y).sub_const 1).arctan
    have dF := (((dA.log hA.ne').const_mul 2).sub ((dB.log hB.ne').const_mul 2)).add
      (dC.const_mul 4)
    convert dF using 1
    rw [bbp_partial_fractions y (by nlinarith)]
    have hC : 1 + (y - 1) ^ 2 = y ^ 2 - 2 * y + 2 := by ring
    have hA' : 2 - y ^ 2 ≠ 0 := hA.ne'
    have hA'' : y ^ 2 - 2 ≠ 0 := by linarith
    have hB' : y ^ 2 - 2 * y + 2 ≠ 0 := hB.ne'
    rw [hC]
    field_simp
    ring
  have hcont : ContinuousOn bbpIntegrand (Set.uIcc (0 : ℝ) 1) := by
    apply ContinuousOn.div (by fun_prop) (by fun_prop)
    intro y hy
    rw [Set.uIcc_of_le zero_le_one] at hy
    obtain ⟨hy0, hy1⟩ := hy
    have h3 : y ^ 4 - 2 * y ^ 3 + 4 * y - 4 = (y ^ 2 - 2) * (y ^ 2 - 2 * y + 2) := by ring
    rw [h3]
    apply mul_ne_zero <;> nlinarith [sq_nonneg (y - 1)]
  rw [intervalIntegral.integral_eq_sub_of_hasDerivAt hderiv hcont.intervalIntegrable]
  simp only [hF]
  norm_num [arctan_neg, arctan_one]
  ring
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor

Euler's numerically discovered sum, from Mathlib:

baselLean 4Applies a library theoremFormally verified
/-- **The Basel problem (Euler, 1734/35):** `Σ_{n ≥ 1} 1/n² = π²/6`. Euler first computed the sum
to several decimals with acceleration techniques and recognised `π²/6`; this applies Mathlib's
`hasSum_zeta_two`. (The `n = 0` term is `1/0 = 0` in Lean's conventions.) -/
theorem basel : HasSum (fun n : ℕ => 1 / (n : ℝ) ^ 2) (π ^ 2 / 6) := hasSum_zeta_two
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor

Finally the difference between a bounded check and a conjecture, made precise. The Collatz conjecture is stated as a definition; a bounded search is proved sound; and the search, run by Lean's kernel, proves the conjecture for n≤500n \le 500 — and nothing more:

collatzStepLean 4Formally verified
/-- One step of the Collatz map: halve even numbers, send odd `n` to `3n + 1`. -/
def collatzStep (n : ℕ) : ℕ := if n % 2 = 0 then n / 2 else 3 * n + 1
Axioms used: No axiomsformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
CollatzConjectureLean 4Formally verified
/-- The **Collatz conjecture**: every positive integer reaches `1`. Stated, not asserted — it is
open. -/
def CollatzConjecture : Prop := ∀ n, 0 < n → ∃ k, collatzStep^[k] n = 1
Axioms used: No axiomsformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
reachesOneLean 4Formally verified
/-- A bounded search: does `n` reach `1` within `fuel` steps? -/
def reachesOne : ℕ → ℕ → Bool
  | 0, n => n == 1
  | fuel + 1, n => n == 1 || reachesOne fuel (collatzStep n)
Axioms used: No axiomsformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
reachesOne_soundLean 4Proved here from basic factsFormally verified
/-- The search is sound: if it says yes, `n` really reaches `1`. Induction on the fuel. -/
theorem reachesOne_sound (fuel n : ℕ) (h : reachesOne fuel n = true) :
    ∃ k, collatzStep^[k] n = 1 := by
  induction fuel generalizing n with
  | zero => exact ⟨0, by simpa [reachesOne] using h⟩
  | succ fuel ih =>
    simp only [reachesOne, Bool.or_eq_true, beq_iff_eq] at h
    rcases h with h | h
    · exact ⟨0, h⟩
    · obtain ⟨k, hk⟩ := ih _ h
      exact ⟨k + 1, by rw [Function.iterate_succ_apply]; exact hk⟩
Axioms used: propext, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor
collatz_up_to_500Lean 4Proved here from basic factsFormally verified
/-- **An exhaustive check with a stated bound:** every `n` with `1 ≤ n ≤ 500` reaches `1`.
The bounded search is run by the kernel (`decide +kernel`) and turned into a theorem by
`reachesOne_sound`. This says nothing about `n > 500`; `CollatzConjecture` stays open. -/
theorem collatz_up_to_500 (n : ℕ) (h0 : 0 < n) (h : n ≤ 500) :
    ∃ k, collatzStep^[k] n = 1 := by
  have hall : ∀ m < 500, reachesOne 150 (m + 1) = true := by decide +kernel
  obtain ⟨m, rfl⟩ : ∃ m, n = m + 1 := ⟨n - 1, by omega⟩
  exact reachesOne_sound 150 _ (hall m (by omega))
Axioms used: propext, Quot.soundformal/Lumenary/ExperimentalMathematics.leanTry it in the Lean web editor

Not formalised: the first step of Theorem 2 (exchanging the series and the integral, and the substitution), so the BBP formula itself is proved here only on paper; Theorems 3–5; and the PSLQ algorithm. Mathlib does not yet contain Littlewood's theorem.

ComputationC

Experiments

The first experiment rediscovers the BBP formula: it computes π\pi and S1,…,S8S_1, \dots, S_8 to 6060 digits with exact rational arithmetic, runs PSLQ, and rechecks the relation at 100100 digits. It then shows a spurious relation found at 88 digits, a PSLQ lower bound when no relation is found, and BBP digit extraction checked against an exact computation.

PSLQ rediscovers the BBP formula for piPythonNumerical approximationExact computationComputationally tested
"""Rediscovering the Bailey-Borwein-Plouffe formula, and using it.

The constants S_j = sum_k 16^-k / (8k + j), j = 1..8, and pi are computed to
60 digits with exact rational arithmetic (pi by Machin's formula). The PSLQ
integer-relation algorithm (Ferguson and Bailey), implemented here with
Python's decimal module, finds the relation pi = 4 S_1 - 2 S_4 - S_5 - S_6,
which is then re-checked at 100 digits. Two cautionary runs follow: with only
8 digits PSLQ "finds" a spurious relation for (pi, e, 1), and at 40 digits it
only bounds the size of any relation. Finally the formula is used to compute
hexadecimal digits of pi far after the point without the earlier ones, and
these are compared with an independent exact computation. A found relation is
numerical evidence; the lesson gives the proof.
"""

from decimal import Decimal, localcontext, ROUND_HALF_EVEN
from fractions import Fraction
import math

HEX = "0123456789ABCDEF"

def arctan_inv(x, scale):
    """floor-ish of arctan(1/x) * scale with integer arithmetic (error < terms)."""
    total = term = scale // x
    x2, k, sign = x * x, 1, -1
    while term:
        term //= x2
        total += sign * (term // (2 * k + 1))
        sign, k = -sign, k + 1
    return total

def pi_fraction(digits):
    """pi to about `digits` decimal digits (Machin: pi = 16 atan 1/5 - 4 atan 1/239)."""
    scale = 10 ** (digits + 10)
    return Fraction(4 * (4 * arctan_inv(5, scale) - arctan_inv(239, scale)), scale)

def e_fraction(digits):
    """e to well beyond `digits` digits, as an exact partial sum of 1/k!."""
    terms = 10
    while math.lgamma(terms + 1) / math.log(10) < digits + 5:
        terms += 5
    return sum(Fraction(1, math.factorial(k)) for k in range(terms))

def bbp_sum(j, digits):
    """S_j = sum_k 16^-k / (8k + j), truncated with error below 10^-digits."""
    terms = int(digits / 1.2) + 5
    return sum(Fraction(1, 16 ** k * (8 * k + j)) for k in range(terms))

def pslq(xs, digits, max_norm, max_iter=1000):
    """PSLQ on the reals xs (given as Fractions) at `digits` digits.

    Returns (relation or None, iterations, bound): if a relation is found it is
    an integer vector; otherwise every relation has norm at least `bound`.
    """
    n = len(xs)
    with localcontext() as ctx:
        ctx.prec = digits + 10
        x = [Decimal(f.numerator) / Decimal(f.denominator) for f in xs]
        eps = Decimal(10) ** (2 - digits)
        gamma = (Decimal(4) / 3).sqrt()
        A = [[int(i == j) for j in range(n)] for i in range(n)]
        B = [[int(i == j) for j in range(n)] for i in range(n)]
        s = [sum((v * v for v in x[k:]), Decimal(0)).sqrt() for k in range(n)]
        y = [v / s[0] for v in x]
        s = [v / s[0] for v in s]
        H = [[Decimal(0)] * (n - 1) for _ in range(n)]
        for i in range(n):
            if i < n - 1:
                H[i][i] = s[i + 1] / s[i]
            for j in range(min(i, n - 1)):
                H[i][j] = -y[i] * y[j] / (s[j] * s[j + 1])

        def reduce(i, j):
            t = int((H[i][j] / H[j][j]).to_integral_value(ROUND_HALF_EVEN))
            if t:
                y[j] += t * y[i]
                for k in range(j + 1):
                    H[i][k] -= t * H[j][k]
                for k in range(n):
                    A[i][k] -= t * A[j][k]
                    B[k][j] += t * B[k][i]

        for i in range(1, n):
            for j in range(i - 1, -1, -1):
                reduce(i, j)
        bound = Decimal(0)
        for it in range(1, max_iter + 1):
            m = max(range(n - 1), key=lambda i: gamma ** (i + 1) * abs(H[i][i]))
            y[m], y[m + 1] = y[m + 1], y[m]
            A[m], A[m + 1] = A[m + 1], A[m]
            H[m], H[m + 1] = H[m + 1], H[m]
            for row in B:
                row[m], row[m + 1] = row[m + 1], row[m]
            if m < n - 2:
                t0 = (H[m][m] ** 2 + H[m][m + 1] ** 2).sqrt()
                t1, t2 = H[m][m] / t0, H[m][m + 1] / t0
                for i in range(m, n):
                    t3, t4 = H[i][m], H[i][m + 1]
                    H[i][m] = t1 * t3 + t2 * t4
                    H[i][m + 1] = -t2 * t3 + t1 * t4
            for i in range(m + 1, n):
                for j in range(min(i - 1, m + 1), -1, -1):
                    reduce(i, j)
            jmin = min(range(n), key=lambda j: abs(y[j]))
            if abs(y[jmin]) < eps:
                rel = [B[k][jmin] for k in range(n)]
                sign = 1 if next(c for c in rel if c) > 0 else -1
                return [sign * c for c in rel], it, None
            bound = 1 / max(abs(H[i][i]) for i in range(n - 1))
            if bound > max_norm:
                break
        return None, it, float(bound)

def format_combination(rel):
    """Write -(rel_1 S_1 + ... + rel_8 S_8) as text, e.g. '4 S_1 - 2 S_4'."""
    text = ""
    for k, c in enumerate(rel):
        coeff = -c
        if k == 0 or coeff == 0:
            continue
        sign = "-" if coeff < 0 else "+"
        size = "" if abs(coeff) == 1 else f"{abs(coeff)} "
        text += f" {sign} {size}S_{k}"
    text = text.strip()
    return text[2:] if text.startswith("+ ") else text

def residual(rel, xs):
    """|sum rel_i * x_i| computed exactly from the Fractions xs."""
    return abs(sum(c * v for c, v in zip(rel, xs)))

def bbp_hex_digits(d, count):
    """Hex digits of pi at positions d+1, ..., d+count (BBP digit extraction)."""
    def frac_series(j):
        s = 0.0
        for k in range(d + 1):
            s = (s + pow(16, d - k, 8 * k + j) / (8 * k + j)) % 1.0
        k = d + 1
        while True:
            term = 16.0 ** (d - k) / (8 * k + j)
            if term < 1e-17:
                return s
            s, k = s + term, k + 1

    x = (4 * frac_series(1) - 2 * frac_series(4)
         - frac_series(5) - frac_series(6)) % 1.0
    out = ""
    for _ in range(count):
        x *= 16
        digit = int(x)
        out += HEX[digit]
        x -= digit
    return out

def exact_hex_digits(d, count):
    """The same digits from an exact integer computation (Machin, base 16)."""
    guard = 8
    scale = 16 ** (d + count + guard)
    pi_scaled = 4 * (4 * arctan_inv(5, scale) - arctan_inv(239, scale))
    block = (pi_scaled // 16 ** guard) % 16 ** count
    return format(block, "X").rjust(count, "0")

def main():
    digits = 60
    xs = [pi_fraction(digits)] + [bbp_sum(j, digits) for j in range(1, 9)]
    rel, its, _ = pslq(xs, digits, max_norm=10 ** 12)
    print("PSLQ on (pi, S_1, ..., S_8) at 60 digits, "
          "S_j = sum_k 16^-k/(8k+j):")
    print(f"  relation after {its} iterations: {tuple(rel)}")
    print(f"  i.e. pi = {format_combination(rel)}")
    xs100 = [pi_fraction(100)] + [bbp_sum(j, 100) for j in range(1, 9)]
    print("  residual with 100-digit values: "
          f"{float(residual(rel, xs100)):.1e}")
    print()
    low = [pi_fraction(8), e_fraction(8), Fraction(1)]
    fake, _, _ = pslq(low, 8, max_norm=10 ** 6)
    high = [pi_fraction(40), e_fraction(40), Fraction(1)]
    print(f"(pi, e, 1) at 8 digits: 'relation' {tuple(fake)}, but at 40 digits")
    print(f"  its residual is {float(residual(fake, high)):.1e}: spurious.")
    none, its, bound = pslq(high, 40, max_norm=10 ** 10)
    print(f"(pi, e, 1) at 40 digits: no relation; after {its} iterations every")
    print(f"  integer relation would need norm > {bound:.1e}.")
    print()
    d = 5000
    fast, exact = bbp_hex_digits(d, 8), exact_hex_digits(d, 8)
    print(f"Hex digits of pi after the point: {bbp_hex_digits(0, 8)} ...")
    print(f"Positions {d + 1}-{d + 8} by BBP digit extraction: {fast}")
    print(f"Same positions by exact integer arithmetic:      {exact}")
    print()
    print("Epistemic status: the relation is numerical evidence (60 digits, with")
    print("the residual rechecked at 100); its proof is in the lesson. The 'no")
    print("relation' bound is PSLQ's guarantee only if 40 digits were enough;")
    print("whether pi + e is irrational is an open problem. The hex digits agree")
    print("between two independent methods: an exact check of those 8 digits.")

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

The second experiment runs four searches with stated bounds: Euler's conjecture for fifth powers (exhaustive for e≤150e \le 150, by a meet-in-the-middle search over sums of two fifth powers), the prime race modulo 44, π(x)\pi(x) against li(x)\mathrm{li}(x), and the exact values of the Borwein integrals.

Counterexample searches with stated boundsPythonExhaustive finite checkCounterexampleNumerical approximationExact computationComputationally tested
"""Patterns that fail: four searches with stated bounds.

1. Euler's sum-of-powers conjecture for fifth powers: an exhaustive search
   over all a <= b <= c <= d < e <= 150 (meet in the middle: sums of two fifth
   powers, looked up with NumPy) finds Lander and Parkin's counterexample.
2. The prime race modulo 4: primes 3 mod 4 lead primes 1 mod 4 for every x
   below 26861, then fall behind (Leech, 1957).
3. pi(x) < li(x) for every real x in [2, 10^6] (and far beyond), although
   Littlewood proved that the inequality reverses infinitely often.
4. The Borwein integrals: an exact rational computation shows when the
   pattern "the integral equals pi/2" breaks, and by how little.
Searches 1-3 are exhaustive up to the stated bounds; li(x) is computed in
floating point with a convergent series.
"""

import math
from fractions import Fraction

import numpy as np

EULER_GAMMA = 0.5772156649015329

def euler_fifth_power_search(limit):
    """All (a, b, c, d, e) with a<=b<=c<=d<e<=limit and a^5+b^5+c^5+d^5 = e^5."""
    fifth = np.arange(limit + 1, dtype=np.int64) ** 5
    a, b = np.triu_indices(limit + 1, k=0)
    keep = (a >= 1)
    a, b = a[keep], b[keep]
    sums = fifth[a] + fifth[b]
    order = np.argsort(sums, kind="stable")
    sums, a, b = sums[order], a[order], b[order]
    found = set()
    for e in range(2, limit + 1):
        target = fifth[e] - sums                      # e^5 - (c^5 + d^5)
        ok = (target > 0)
        idx = np.searchsorted(sums, target[ok])
        idx = np.minimum(idx, len(sums) - 1)
        hits = np.nonzero(sums[idx] == target[ok])[0]
        cd = np.nonzero(ok)[0][hits]
        for i, j in zip(idx[hits], cd):
            quad = tuple(sorted((int(a[i]), int(b[i]), int(a[j]), int(b[j]))))
            if quad[3] < e:
                found.add(quad + (e,))
    return sorted(found)

def prime_sieve(limit):
    """Boolean array is_prime[0..limit]."""
    is_prime = np.ones(limit + 1, dtype=bool)
    is_prime[:2] = False
    for p in range(2, int(limit ** 0.5) + 1):
        if is_prime[p]:
            is_prime[p * p::p] = False
    return is_prime

def race_mod_4(limit):
    """First x where #primes = 1 mod 4 exceeds #primes = 3 mod 4, and the
    number of integers x <= limit at which it does."""
    is_prime = prime_sieve(limit)
    n = np.arange(limit + 1)
    ones = np.cumsum(is_prime & (n % 4 == 1))
    threes = np.cumsum(is_prime & (n % 4 == 3))
    ahead = np.nonzero(ones > threes)[0]
    return int(ahead[0]), int(len(ahead))

def li(x):
    """Logarithmic integral li(x) = gamma + ln ln x + sum (ln x)^k / (k k!)."""
    t = math.log(x)
    total, term, k = 0.0, 1.0, 1
    while True:
        term *= t / k
        add = term / k
        total += add
        if add < 1e-17 * total:
            break
        k += 1
    return EULER_GAMMA + math.log(t) + total

def li_array(xs):
    """li for a NumPy array of x > 1, by the same series (vectorised)."""
    t = np.log(np.asarray(xs, dtype=float))
    total, term = np.zeros_like(t), np.ones_like(t)
    for k in range(1, 200):
        term = term * t / k
        total += term / k
        if np.all(term / k < 1e-17 * total):
            break
    return EULER_GAMMA + np.log(t) + total

def li_exceeds_pi_up_to(limit):
    """Is li(x) > pi(x) for every real 2 <= x <= limit?  Since li increases and
    pi is constant between primes, it suffices to check x = each prime."""
    is_prime = prime_sieve(limit)
    primes = np.nonzero(is_prime)[0]
    margin = li_array(primes) - np.arange(1, len(primes) + 1)
    return bool(np.all(margin > 0)), float(margin.min())

def borwein_pattern(max_n):
    """For n = 1..max_n: (s_n, exact value of the n-th Borwein integral / pi).

    The n-th integral is that of prod_{k=0}^{n} sinc(x/(2k+1)) over (0, inf).
    It equals pi/2 while s_n = 1/3 + ... + 1/(2n+1) < 1; at the first n with
    s_n > 1 it equals (pi/2)(1 - (s_n - 1)^n / (2^(n-1) n! prod 1/(2k+1)))
    (D. and J. Borwein, 2001).
    """
    rows = []
    for n in range(1, max_n + 1):
        a = [Fraction(1, 2 * k + 1) for k in range(1, n + 1)]
        s = sum(a)
        if s < 1:
            rows.append((s, Fraction(1, 2)))
        else:
            prod = math.prod(a)
            deficit = (s - 1) ** n / (2 ** (n - 1) * math.factorial(n) * prod)
            rows.append((s, Fraction(1, 2) * (1 - deficit)))
            break
    return rows

def main():
    sols = euler_fifth_power_search(150)
    print("1. a^5 + b^5 + c^5 + d^5 = e^5, all 1 <= a<=b<=c<=d < e <= 150:")
    for a, b, c, d, e in sols:
        print(f"   {a}^5 + {b}^5 + {c}^5 + {d}^5 = {e}^5")
    print(f"   {len(sols)} solution(s): Euler's conjecture (1769) is false.")
    first, count = race_mod_4(10 ** 5)
    print("2. Prime race mod 4, x <= 100000: primes 1 mod 4 first lead at")
    print(f"   x = {first}; they lead at only {count} of the 100000 values of x.")
    is_prime = prime_sieve(10 ** 6)
    counts = np.cumsum(is_prime)
    print("3. pi(x) versus li(x):")
    for k in range(2, 7):
        x = 10 ** k
        print(f"   x = 10^{k}: pi(x) = {int(counts[x]):>6}, "
              f"li(x) = {li(x):>10.1f}, li(x) - pi(x) = {li(x) - counts[x]:6.1f}")
    holds, margin = li_exceeds_pi_up_to(10 ** 6)
    print(f"   li(x) > pi(x) for all real 2 <= x <= 10^6: {holds} "
          f"(smallest gap {margin:.3f})")
    print("4. Borwein integrals, exact values divided by pi:")
    for n, (s, value) in enumerate(borwein_pattern(10), start=1):
        tag = "= 1/2" if value == Fraction(1, 2) else \
            f"= 1/2 - {float(Fraction(1, 2) - value):.3e}"
        print(f"   n = {n}: 1/3 + ... + 1/{2 * n + 1} = {float(s):.4f}, "
              f"integral/pi {tag}")
    print()
    print("Epistemic status: searches 1 and 2 are exhaustive and exact up to their")
    print("stated bounds, and 4 is exact rational arithmetic on a proved formula.")
    print("Check 3 uses floating-point li(x) at every prime up to 10^6: numerical")
    print("evidence only - and Littlewood's theorem shows that this evidence,")
    print("however far it is extended, points the wrong way.")

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

Notice how each report is phrased: what was searched, how the search is known to be complete, and what kind of evidence the result is. That is the standard to apply to your own experiments, and to those you read.

Explore

Explore: Euler's experiment and the four colour theorem

Euler's problem: the partial sums of ∑1/n2\sum 1/n^2 creep towards π2/6\pi^2/6 with an error of about 1/N1/N after NN terms, so a thousand terms give only three correct digits. Euler needed acceleration (the Euler–Maclaurin formula) to get enough digits to recognise the limit. Increase NN and watch how slowly the gap closes.

Euler's experiment: 1 + 1/4 + 1/9 + ⋯

Add the terms one by one. Do the partial sums Sₙ settle down, or keep growing?

Examples
an =
  • partial sums Sₙ
  • terms aₙ
  • Known sum

S1000 = a1 + … + a1000 = 1.643935

Known sum: L = π²/6 ≈ 1.644934 · still missing: L − S1000 ≈ 0.001

Partial sums on a screen are evidence, never proof: a series can look settled and still diverge, as the harmonic series does.

The colouring widget computes chromatic numbers of small graphs by exhaustive search — a finite computation that settles a finite question. The four colour theorem is a statement about infinitely many planar graphs; its proof needed a theorem reducing it to finitely many configurations before any computer could help. Try the wheel and the Petersen graph, then K5K_5, which is not planar.

Graph explorer

Dots joined by lines: count degrees, walk along edges, colour vertices, grow spanning trees and count walks with a matrix.

ABCDEH
|V| = 6|E| = 10Click a vertex to change its colour (Delete removes it).

0

colours used

0

clashes

6

uncoloured

Give every vertex a colour so that the two ends of each edge differ.

This graph is planar: it can be drawn with no edges crossing. The Four Colour Theorem says every planar graph can be coloured with at most four colours. Kenneth Appel and Wolfgang Haken proved it in 1976 with essential help from a computer, which checked well over a thousand cases; in 2005 Georges Gonthier completed a fully computer-checked proof in the Coq proof assistant.

Exercises

Exercises

1. Experimental mathematics: conjectures and counterexamples

Warm-upHuman

The Fermat numbers are Fn=22n+1F_n = 2^{2^n} + 1. What is the smallest nn for which FnF_n is not prime?

2. Experimental mathematics: conjectures and counterexamples

Warm-upHuman

Let φ=(1+5)/2\varphi = (1 + \sqrt5)/2. Which vector is an integer relation for (φ2,φ,1)(\varphi^2, \varphi, 1)?

Choose one

3. Experimental mathematics: conjectures and counterexamples

CoreHuman

Which of these are honest, adequately specified reports of a counterexample search for Goldbach's conjecture? (Choose all that apply.)

Choose all that apply

4. Experimental mathematics: conjectures and counterexamples

CoreHuman

At 100 digits, PSLQ finds a relation with coefficients of size below 100100 among six constants, with residual 10−9510^{-95}; at 200 digits the same relation holds to 10−19510^{-195}. What may you claim?

Choose one

5. Experimental mathematics: conjectures and counterexamples

CoreComputational

Among the primes p≤50p \le 50, let TT be the number with p≡3(mod4)p \equiv 3 \pmod 4 and OO the number with p≡1(mod4)p \equiv 1 \pmod 4. Compute T−OT - O.

6. Experimental mathematics: conjectures and counterexamples

CoreHuman

In the proof of the BBP formula, which step needs an analytic justification rather than algebra alone?

Choose one

7. Experimental mathematics: conjectures and counterexamples

CoreFormal

With fermat n = 2 ^ (2 ^ n) + 1, which Lean statement says that Fermat's conjecture is false?

Choose one

8. Experimental mathematics: conjectures and counterexamples

CoreHuman

Which conjecture would be refuted by a finite counterexample that a computer can check, whatever form the counterexample takes?

Choose one
Common misconceptionsH

Common misconceptions

Misconception

"A pattern that holds in many cases is established." The prime race holds for 26,86026{,}860 consecutive values; π(x)<li(x)\pi(x) \lt \mathrm{li}(x) holds beyond 101410^{14}; the Borwein pattern holds for seven integrals; Fermat had five primes. All fail. Evidence makes a conjecture worth trying to prove; only a proof (or a counterexample) settles it.

Misconception

"We searched and found no counterexample" is a result. Not without its bounds. A report must say exactly what was searched (which nn, which parameters), how completeness was ensured (for example, why the meet-in-the-middle search misses no case), and that a negative result says nothing beyond the bound.

Misconception

"PSLQ proved the formula." An integer relation found numerically is a conjecture, however many digits support it — and at low precision it may be spurious. The BBP formula became a theorem when it was proved by calculus.

Misconception

"Computer-assisted proofs are less reliable than human proofs." Human proofs also contain errors, some found only decades later. What matters is whether each part can be checked: hand-proved reductions, open and independently reimplemented code, certificates, validated numerics and formal verification can make a computer-assisted proof among the most reliable in mathematics.

ViewpointsH

Many ways of seeing

Number theory— Relations, irrationality and transcendence

Finding an integer relation is easy to verify and hard to rule out. A proof that no relation exists is an irrationality or transcendence theorem: (1,α)(1, \alpha) has no relation iff α\alpha is irrational, and (1,α,…,αd)(1, \alpha, \dots, \alpha^d) has none for every dd iff α\alpha is transcendental. Lindemann (1882) proved π\pi transcendental, and Apéry (1978) proved ζ(3)\zeta(3) irrational — his proof itself began with mysterious, experimentally checked recurrences. But it is unknown whether π+e\pi + e, πe\pi e or Euler's constant γ\gamma is irrational. Integer-relation searches give bounds: PSLQ can certify that γ\gamma satisfies no polynomial of small degree with small coefficients — evidence, not proof. See algebraic number theory.

Geometry— Lattices and the geometry of numbers

An integer relation is a short vector in a lattice. Scale the numbers by a large CC and consider the lattice in Rn+1\R^{n+1} spanned by the vectors (ei,⌊Cxi⌉)(e_i, \lfloor C x_i \rceil); a relation aa gives the lattice vector (a,∑ai⌊Cxi⌉)(a, \sum a_i \lfloor Cx_i\rceil), whose last coordinate is unusually small. Minkowski's convex body theorem guarantees that short vectors exist; LLL finds a vector within a factor 2(n−1)/22^{(n-1)/2} of the shortest in polynomial time, by a reduction process that makes the basis nearly orthogonal. Geometry is also the subject of the Kepler conjecture, where the computer's task was to rule out every competing local arrangement of spheres.

Analysis— Why the numbers mislead

Riemann's explicit formula writes π(x)\pi(x) as li(x)\mathrm{li}(x) minus a correction from prime squares, about 12li(x)≈x/ln⁡x\tfrac12 \mathrm{li}(\sqrt x) \approx \sqrt x/\ln x, plus oscillating terms li(xρ)\mathrm{li}(x^\rho) from the zeros ρ=12+iγ\rho = \tfrac12 + i\gamma of ζ\zeta (assuming the Riemann hypothesis). The oscillations have size about x/ln⁡x\sqrt x/\ln x times ∑γsin⁡(γln⁡x)/γ\sum_\gamma \sin(\gamma \ln x)/\gamma, and they vary on the scale of ln⁡x\ln x, not xx: to overcome the bias the zeros must align, which happens first only for astronomically large xx. Prime races have the same anatomy, with Dirichlet LL-functions. The lesson for experiments: asymptotic behaviour that lives on a logarithmic scale cannot be seen in data on a linear one. See analytic number theory.

Probability— Heuristics from random models

Cramér's model treats each nn as "prime" independently with probability 1/ln⁡n1/\ln n. It predicts, for example, that the number of twin primes up to xx is about Cx/(ln⁡x)2C x/(\ln x)^2 — with the correct constant only after Hardy and Littlewood corrected for divisibility by small primes — and the numerical agreement is spectacular. Such random models are heuristics: they suggest conjectures and the right size of answers, but they are not proofs, and Maier (1985) showed that Cramér's model fails in short intervals. Experimental mathematics often tests such predictions; the honest report distinguishes the heuristic, the data and the theorem.

Logic— What a search can and cannot do

Goldbach's conjecture is a Π1\Pi_1 statement: "for all nn, a decidable property holds". If it is false, a finite computation exhibits the counterexample, and Peano arithmetic proves the refutation. So if Goldbach's conjecture is independent of PA it is true. The Collatz conjecture is Π2\Pi_2 ("for all nn there exists kk …"): a counterexample could be a diverging trajectory, which no finite computation can display. Conway (1972) proved that a natural generalisation of the Collatz problem is undecidable. Logic thus classifies what experiments can achieve: Π1\Pi_1 statements are refutable by search, Σ1\Sigma_1 statements confirmable by search, and anything more complex needs proof. See the incompleteness theorems.

History & global context

History and global context

  • Before computers. Euler's numerical work on the Basel problem (1730s) and his factor of F5F_5 (1732); Gauss's prime tables (1790s); Ramanujan's notebooks, written in India in the 1900s–1910s, full of formulas found by extraordinary calculation and insight, many proved only decades later by Berndt and others.
  • Machines. D. N. and D. H. Lehmer built mechanical and photoelectric sieves for number theory in the 1920s and 1930s. Turing computed zeros of the Riemann zeta function on the Manchester Mark 1 (published 1953). Birch and Swinnerton-Dyer's computations on EDSAC led to their conjecture (published 1963–65). Lander and Parkin refuted Euler's conjecture in 1966.
  • Counterexamples to famous conjectures. Haselgrove (1958) disproved Pólya's conjecture on the parity of prime factors; Tanaka (1980) found the smallest counterexample, 906,150,257906{,}150{,}257. Odlyzko and te Riele (1985) disproved the Mertens conjecture without exhibiting a counterexample.
  • Algorithms. Ferguson and Forcade gave an integer relation algorithm (1979); Lenstra, Lenstra and Lovász gave LLL (1982); Ferguson and Bailey gave PSLQ (1992); in 2000 the journal Computing in Science and Engineering listed integer relation detection among the top ten algorithms of the twentieth century. Wu Wenjun in China developed a mechanical method for proving geometry theorems (1977), a landmark of automated reasoning.
  • A discipline. Sloane began collecting integer sequences in 1964; the OEIS has been online since 1996. The journal Experimental Mathematics was founded in 1992. Computer-assisted proofs — the four colour theorem (1976), the Kepler conjecture (1998; formal proof 2014), and Helfgott's ternary Goldbach theorem (2013), by a mathematician from Peru working in France and Germany — changed what mathematicians accept as proof and how they check it.
Further reading

Further reading

  • Jonathan Borwein and David Bailey, Mathematics by Experiment: Plausible Reasoning in the 21st Century (2004; 2nd ed. 2008), with its companion David Bailey, Jonathan Borwein and Roland Girgensohn, Experimentation in Mathematics (2004).
  • Richard K. Guy, "The strong law of small numbers", American Mathematical Monthly (1988).
  • Andrew Granville and Greg Martin, "Prime number races", American Mathematical Monthly (2006).
  • David Bailey, Peter Borwein and Simon Plouffe, "On the rapid computation of various polylogarithmic constants", Mathematics of Computation (1997); Helaman Ferguson, David Bailey and Steve Arno, "Analysis of PSLQ, an integer relation finding algorithm", Mathematics of Computation (1999).
  • Georges Gonthier, "Formal proof — the four-color theorem", Notices of the AMS (2008); Thomas Hales et al., "A formal proof of the Kepler conjecture", Forum of Mathematics, Pi (2017).
  • A. E. Ingham, The Distribution of Prime Numbers (1932), for Littlewood's theorem.