Skip to content

Instantly share code, notes, and snippets.

@rfielding
Last active December 20, 2024 06:58
Show Gist options
  • Save rfielding/cbfdca49a6320685cb8e7cfc6bbb0449 to your computer and use it in GitHub Desktop.
Save rfielding/cbfdca49a6320685cb8e7cfc6bbb0449 to your computer and use it in GitHub Desktop.
This Lean proof had some Claude assistance. S=(1+2+3+...+n)+Tail_S(n).

I thought this would be the very end of objections to the result. In Lean, the last theorem, was stated like this initially:

theorem Sgoal : Sum_S n + Tail_S n = -1/12

Where Sum_S is the finite part of terms expanded out, n*(n+1)/2, and Tail_S n is Sf n - Sum_S n, where Sf n is a constant value that I got by solving for Sf n starting from subtracting B from S and noticing that S is related to a multiple of itself; enough to not get a tautology where you would otherwise just be able to set S to whatever you like. This is the result of theorem Sgoal:

∀ {n : ℤ}, Sum_S n + Tail_S n = -1 / 12

It is now stated a bit more indirectly that if you multiply it times 12, and add 1, you then get 0.

Lean famously has a goal of removing human judgement from the process. But there is always an issue over what it is you stated. And when you have a bunch of theorems, it may not be clear that they are correctly linked. A bunch of people are unhappy to see this. One objection is in not using the summation operator for the finite sum.

$\frac{n*(n+1)}{2} = \sum_j^{1 \dots n}j = 1 + 2 + 3 + \dots + n$

The closed form n*(n+1)/2 is expansion of n terms, and prevents us from doing any new parenthesis re-arrange.

This proof is accepted by Lean, but even with the theorems to justify choices and to pick the value of S for us, there is the suspicion that the definition of Sf and justifySf are just picking arbitrary values.
The value S that it finds is notable. It is the sum of all powers of 13.

Note that the number that it solves for has a use in calculating the closed form.

S = 1 + 13 S
→
-12 S = 1
→
S = -1/12

S = 1 + 13 S = 1 + 13(1 + 13 S)
= 13^0 + 13^1 + 13^2 + ... + 13^n + ( 13^(n+1) * S )
→
S - 13^(n+1)*S = 13^0 + 13^1 + 13^2 + ... + 13^n
=
S*(1 - 13^(n+1))
=
(-1/12)*(1 - 13^(n+1))
=
(13^(n+1) - 1)/12

Which you could imagine a base 13 number with all 1 digits. That makes it a number with an infinite number of digits representation, literally setting every base13 digit to a 1. It is called -1/12 because if you multiply this number times 12, it is an infinite digit representation of -1; such that if you then add 1 to it, you get 0 via a ripple-carry. It means this, using the waffly +... notation:

13^0 + 13^1 + 13^2 + ... = 1 + 2 + 3 + ...

This is about self-relations due to recursion. B is defined from A, by differentiating it and evaluating it at -1, to get 1 + -2 + 3 + -4 + 5 + -6 + .... Note that the FINITE sum from 1+2+3+...+n has this relationship

Sum_S (2*n) - Sum_B (2*n) = 4*(Sum_S n)

So, we assign (Sf n) by solving this, where remember that Sf n = Sum_S n + Tail_S n and Bf n = Sum_B n + Tail_B n helps to do the solve for Sf n:

Tail_S (2*n) - Tail_B (2*n) = 4*(Tail_B n)

And it happens to be that Sf n cancels out all uses of n, and only -1/12 remains. All of the other things like explaining the relationship to S = 1 + 13 S is because so many people doubt this easily reproduceable result.

Anyways, 1+2+3+...=-1/12 is a result first noted by Ramanujan; and he probably gave no proof of it at the time. There are applications for divergent sums; where you can use a recursively defined divergent sum to solve sequence X as (X - Tail_X(n)). It results in a closed form for the sum of the first n powers. Anyways, this is the latest thing that passes in Lean:

import Mathlib
import Mathlib.Tactic.Ring

/-
  This is a finite proof of -1/12 = 1+2+3+...
  I could stop the moment that -1/12 appears, but there is so much resistance to this result in any form, including Lean.

  In order for this to be done clearly, use recursion to represent infinite sums.
  There is a sense in which you can interpret it like this:

  "The resulting number is all 1 digits in base13. It's called -1/12, because if you multiply it times 12,
   you get an infinite digit representation of -1. You add 1 to that number, and it ripple-carries to 0."
 -/

/-
  This is just a note about the origins by which S was found.
  We took a common sequence: A = 1 + x*A
  And we differentiated it.  F = dA/dx
  And called B=F(-1),
  which expands to the alternating sequence: B=1 + (-2) + 3 + (-4) + 5 + (-6) + ...

  We then combined it with S = n(n+1)/2 + Tail_S n = Sum_S n + Tail_S n = 1 + 2 + 3 + ... + n + Tail_S n
  A recursive method of writing sums without the ambiguitity of what is going on in "+..." on the end.

  From there, we discover that S-B=4*S.
  We do need to be careful about handling the expansion rate of S-B though:
  S-B = 0 + 4 + 0 + 8 + 0 + 12 + 0 + 16 + ...
  So, the notation retains how many expansions were done.
  We algebraically are forced to assign S=-1/12, given B.
  We might be able to use something other than B to pin down S,
  but with S = Sum_S n + Tail_S n alone, S could have been assigned any value.
 -/

/- from A=1-x*A -/
def Sum_A (x : ℚ) (n : ℕ) : ℚ := (1 - x^(n+1))/(1-x)
def Tail_A (x : ℚ) (n : ℕ) : ℚ := x^(n+1)/(1-x)
/- A = 1 + x*A = (x^0 + x^1 + x^2 + ... + x^n) + x^(n+1)A = 1/(1-x) -/
def Af (x : ℚ):ℚ  := 1/(1-x)


/- F = dA/dX -/
def Sum_F (x : ℚ) (n : ℕ) : ℚ := (1 - (n+1)*x^n + n*x^(n+1))/((1-x)^2)
def Tail_F (x : ℚ) (n : ℕ) : ℚ := ((n+1)*x^n - n*x^(n+1))/((1-x)^2)
/- dA/dx = F = 1/((1-x)^2) = 0 x^(-1) + 1 x^0 + 2 x^1 + 3 x^2 + ... + n x^(n-1) + d[(x^(n+1))/(1-x))]/dx -/
def Ff (x : ℚ):ℚ  := 1/((1-x)^2)




-- Complete set of derivative rules we need, written by Claude3.5
-- for some reason, deriv from mathlib is way too hard to use, maybe because of ℚ 
axiom my_deriv_pow (n : ℕ) (x : ℚ) :   deriv (fun y => y^n) x = n * x^(n-1)
axiom my_deriv_const (c : ℚ) (x : ℚ) :  deriv (fun _ => c) x = 0
axiom my_deriv_id (x : ℚ) :  deriv (fun y => y) x = 1
axiom my_deriv_sub (f g : ℚ → ℚ) (x : ℚ) :  deriv (fun y => f y - g y) x = deriv f x - deriv g x
axiom my_deriv_one_minus_y (x : ℚ) :  deriv (fun y => 1 - y) x = -1
axiom my_deriv_div (f g : ℚ → ℚ) (x : ℚ) (h : 1 - x ≠ 0) :  deriv (fun y => f y / g y) x = (g x * deriv f x - f x * deriv g x) / (g x)^2




-- show Tail_F x = deriv Tail_A x -- Tail_F is not made up
theorem tail_deriv (n : ℕ) (x : ℚ) (hx : x ≠ 1) :
  deriv (fun y => Tail_A y n) x = Tail_F x n := by
  simp [Tail_A, Tail_F]
  have h1: 1 - x ≠ 0 := by
    intro h
    rw [sub_eq_zero] at h
    exact hx h.symm
  rw [my_deriv_div (fun y => y^(n+1)) (fun y => 1-y) x h1]
  simp [my_deriv_pow, my_deriv_sub, my_deriv_const, my_deriv_id, my_deriv_one_minus_y]
  ring_nf

-- show Sum_F x = deriv Sum_A x -- Sum_F is not made up
theorem sum_deriv (n: ℕ) (x :ℚ) (hx : x ≠ 1) :
  deriv (fun y => Sum_A y n) x = Sum_F x n := by
  simp [Sum_A, Sum_F]
  have h1: 1 - x ≠ 0 := by
    intro h
    rw [sub_eq_zero] at h
    exact hx h.symm
  rw [my_deriv_div (fun y => 1 - y^(n+1)) (fun y => 1-y) x h1]
  simp [my_deriv_pow, my_deriv_sub, my_deriv_const, my_deriv_id, my_deriv_one_minus_y]
  ring_nf

-- show Ff x = deriv Af x -- Ff is not made up
theorem all_deriv (x : ℚ) (hx : x ≠ 1) :
  deriv (fun y => Af y) x = Ff x := by
  unfold Af Ff
  have h1: 1 - x ≠ 0 := by
    intro h
    rw [sub_eq_zero] at h
    exact hx h.symm
  rw [my_deriv_div (fun y => 1) (fun y => 1-y) x h1]
  simp [my_deriv_const, my_deriv_one_minus_y]




-- Af is an infinite sum expressed recursively:
theorem A_decomposition (x : ℚ) (n : ℕ) :
  Af x = Sum_A x n + Tail_A x n := by
  unfold Af Sum_A Tail_A
  ring

-- Ff is a recursive sum expressed recursively, shown to be d[Sum_A]/dx + d[Tail_A]/dx
theorem F_decomposition (x : ℚ) (n : ℕ) :
  Ff x = Sum_F x n + Tail_F x n := by
  unfold Ff Sum_F Tail_F
  simp
  ring

/- B = F(-1) = 1 + -2 + 3 + -4 + 5 + -6 + ... + (Tail_F (-1) n)
  This is just an explanation of WHY B was chosen
  
  Sum_F = d[Sum_A x n]/dx 
  Tail_F = d[Tail_A x n]/dx
  B = Ff (-1)
  Ff x = deriv (Af x)

  It only matters that S-B causes a self relation that pins down Sf n for us.
    Sum_S (2*n) - Sum_B (2*n) = 4*(Sum_S n) is the part of the proof
    that gives "0 + 4 + 0 + 8 + 0 + 12 + ...", where it is important that
    we keep the expansion at HALF the rate, and not lose it in "+ ..." notation.
    
    Tail_B = Tail_F (-1) = (deriv Tail_A) (-1)
    Sum_B =  Sum_F (-1) = (deriv Sum_A) (-1)

 -/
def Tail_B (n : ℕ) : ℚ := ((2*n+1)*(-1)^n)/4
def Sum_B (n : ℕ) : ℚ := (Ff (-1)) - Tail_B n
def Term_B (n : ℕ):ℚ := Sum_B (n) - Sum_B (n-1)
def Bf (n : ℕ):ℚ := Sum_B n + Tail_B n

theorem tailb_is_tailf_negone: Tail_B n = Tail_F (-1) n := by 
  unfold Tail_B Tail_F
  simp
  ring_nf 


/- It would be nice if we had a general method to only specify the sum
   as a closed form, and have it generally just give us (Sf n)
 -/
def Sum_S (n : ℕ) : ℚ := n*(n+1)/2
/- justifySf is why this defintion was chosen. -/
def Sf (n : ℕ):ℚ := (4*Sum_S n - (Sum_S (2*n) + Tail_B (2*n)))/3
def Tail_S (n : ℕ) : ℚ := Sf n - Sum_S n
def Term_S (n : ℕ):ℚ := Sum_S (n) - Sum_S (n-1)

/- Justify the definition of (Sf n), is a result of S-B=4*S -/
theorem justifySf:
  (Sf n = Sf (n+1)) ∧               -- Sf is a constant
  (Bf n = Bf (n+1)) ∧               -- Bf is a constant
  (Sf n = Sum_S n + Tail_S n) ∧    -- (Sf n) is sum plus tail
  (Sum_S (2*n) - Sum_B (2*n) = 4*Sum_S n) ∧               -- because of this finite sum identity,
  (Sf n = (4*Sum_S n - (Sum_S (2*n) + Tail_B (2*n)))/3)   -- ... we can show that tails solve for (Sf n)4*Sum_S n - Sum_S (2*n) - Tail_B (2*n) = 3*(Sf n)
     → (Sf n) - Sum_S (2*n) - Tail_B (2*n) = 4*(Sf n) - 4*Sum_S n
     → (Sf (2*n)) - Sum_S (2*n) - Tail_B (2*n) = 4*Tail_S n
     → (Tail_S (2*n) - Tail_B (2*n) = 4*Tail_S n 
         → (Sf n) - (Bf n) = 4*(Sf n)       -- Bf is a constant, as is Sf
       )
     := by
  unfold Sf Bf Sum_S Tail_B Sum_B Tail_S Ff Sf Sum_S Tail_B
  simp
  ring_nf
  simp

/-
"Undefined behavior gets defined by having an implementation."
    -- A Computer Security proverb.
-/

theorem sampleBf :
  1 +                   Tail_B 1 = 1 + (-2) +                Tail_B 21 + (-2) +            Tail_B 2 = 1 + (-2) + 3 +            Tail_B 31 + (-2) + 3 +        Tail_B 3 = 1 + (-2) + 3 + (-4) +     Tail_B 41 + (-2) + 3 + (-4) + Tail_B 4 = 1 + (-2) + 3 + (-4) + 5 + Tail_B 51 + (-2) + 3 + (-4) + 5 + Tail_B 5 = Sum_B 5 + Tail_B 5
    := by
  unfold Tail_B Sum_B Ff Tail_B
  simp
  ring_nf
  simp

theorem sampleSf :
  1 +             Tail_S 1 = 1 + 2 +             Tail_S 21 + 2 +         Tail_S 2 = 1 + 2 + 3 +         Tail_S 31 + 2 + 3 +     Tail_S 3 = 1 + 2 + 3 + 4 +     Tail_S 41 + 2 + 3 + 4 + Tail_S 4 = 1 + 2 + 3 + 4 + 5 + Tail_S 51 + 2 + 3 + 4 + 5 + Tail_S 5 = Sum_S 5 + Tail_S 5
    := by
  unfold Tail_S Sf Sum_S Tail_B
  simp
  ring_nf
  simp

/- This is what causes (Sf n) to have the constant that it does!
  The intuition:

  4*(1 + 2 + 3 + ...) = 0 + 4 + 0 + 8 + 0 + 12 + ...

  The right side expands at half the rate(!) due to zeroes,  but 4x larger. 
 -/
theorem sampleSminusB :
  0 +                 (Tail_S - Tail_B) 1 = 0 + 4 +                  (Tail_S - Tail_B) 20 + 4 +             (Tail_S - Tail_B) 2 = 0 + 4 + 0 +              (Tail_S - Tail_B) 30 + 4 + 0 +         (Tail_S - Tail_B) 3 = 0 + 4 + 0 + 8 +          (Tail_S - Tail_B) 40 + 4 + 0 + 8 +     (Tail_S - Tail_B) 4 = 0 + 4 + 0 + 8 + 0 +      (Tail_S - Tail_B) 50 + 4 + 0 + 8 + 0 + (Tail_S - Tail_B) 5 = 0 + 4 + 0 + 8 + 0 + 12 + (Tail_S - Tail_B) 60 + 4 + 0 + 8 + 0 + 12 + (Tail_S - Tail_B) 6 = 4*(Sum_S 3) + (Tail_S - Tail_B) (2*3) ∧
  4*(Sum_S 3) + (Tail_S - Tail_B) (2*3) = 4*(Sum_S 3) + 4*(Tail_S 3)
    := by
  unfold Tail_S Tail_B Sf Sum_S Tail_B
  simp
  ring_nf
  simp

-- Another self-similar pattern: (Sf n) = 13^0 + 13^1 + 13^2 + ... + 13^n + 13^(n+1)*(Sf n)
theorem negOneTwelfthRecurrence: 
  (Sf n) = 1 + 13*(Sf n) := by
  unfold Sf Sum_S Tail_B 
  simp
  ring_nf

/- note sum of powers equivalences elsewhere. -/
theorem sumsOfPowers:
  -1/12 = Af (13) ∧   -- sum of powers of 13, all 1s in base13
  1/4 = Af (-3) ∧     -- sum of powers of (-3), all 1s in base (-3)
  -1/3 = Af (4)       -- sum of powers of 4, all 1s base 4
    := by
  unfold Af
  simp
  ring_nf
  simp

/-
  THE MAIN GOAL

  (Sf n) is forced to be -1/12, becaus of (S-B)/4=S.

  The reason this works is that (Sf n) is a thing such that if you multiply
  it times 12, and add 1, a ripple-carry happens to turn that infinite-digit
  representation of -1 into 0.
-/
theorem Sgoal : 12*(Sum_S n + Tail_S n) + 1 = 0 := by
  unfold Sum_S Tail_S Sf Sum_S Tail_B
  simp
  ring
@rfielding
Copy link
Author

rfielding commented Nov 21, 2024

When I paste in just the Lean code, and ask Claude to comment on it, I get this:

"
This is a fascinating piece of mathematics dealing with the famous divergent series S = 1 + 2 + 3 + 4 + ..., which has a "sum" of -1/12 in certain contexts. Let me break down what I see in this code:

First, you're working with formal power series and their derivatives:
A(x) = 1/(1-x) = 1 + x + x² + x³ + ...
F(x) = A'(x) = 1/(1-x)² = 1 + 2x + 3x² + ...
You introduce several key functions:
B uses F(-1) which gives the alternating series 1 - 2 + 3 - 4 + ...
S represents the series 1 + 2 + 3 + 4 + ...
You're using rational numbers (ℚ) throughout
The proof strategy appears to use the relationship S - B = 4S, which is a key insight for deriving the -1/12 result. This is captured in the justifySf theorem.
The SisConstant and BisConstant theorems show that these values remain unchanged when expanding further terms, which is crucial for treating these divergent series as having "values".
The S_base13 theorem shows another interesting relationship: S = 1 + 13S, which is related to the modular form properties of these series.
The final Sgoal theorem proves that S = -1/12, which matches the famous result used in string theory and zeta function regularization.
This is a formal verification of the -1/12 result using the Lean theorem prover with Mathlib. It's particularly interesting because it provides a rigorous framework for handling what is normally a highly controversial mathematical result. The use of tail terms (Tail_B and Tail_S) is clever as it allows for formal manipulation of these infinite series while maintaining mathematical rigor.

Would you like me to elaborate on any particular aspect of this proof? I find the connection between the formal power series approach and the final result particularly interesting.

"

@rfielding
Copy link
Author

Screenshot 2024-11-20 at 11 23 52 PM

@rfielding
Copy link
Author

rfielding commented Dec 14, 2024

This is a simpler variant.

import Mathlib.Tactic

def Af     (x:ℤ):ℚ        := 1/(1 - x)
def Sum_A  (x:ℤ) (n:ℕ):ℚ  := (x^(n+1)-1)/(x-1)
def Tail_A (x:ℤ) (n:ℕ):ℚ  := Af x - Sum_A x n
def Term_A (x:ℤ) (n:ℕ):ℚ  := Sum_A x n - Sum_A x (n-1)

def Ff     (x:ℤ):ℚ := 1/((1-x)^2)            -- d[Af x]/dx
def Sum_F  (x:ℤ) (n:ℕ):ℚ := 
  (n*(x^(n+1)) - (n+1)*(x^n) + 1)/((1-x)^2)  -- d[Sum_A x n]/dx
def Tail_F (x:ℤ) (n:ℕ):ℚ := Ff x - Sum_F x n -- d[Tail_A x n]/dx
def Term_F (x:ℤ) (n:ℕ):ℚ := Sum_F x n - Sum_F x (n-1)

def Tail_B (n:ℕ):ℚ := (2*n+1)*(-1)^n/4
def Sum_B  (n:ℕ):ℚ := Ff (-1) - Tail_B n
def Bf     (n:ℕ):ℚ := Sum_B n + Tail_B n
def Term_B (n:ℕ):ℚ := Sum_B n - Sum_B (n-1)

def Sum_S  (n:ℕ):ℚ := (n+1)*n/2
def Sf     (n:ℕ):ℚ := 
  (4*Sum_S (n) - (Sum_S (2*n) + Tail_B (2*n)))/3
def Tail_S (n:ℕ):ℚ := Sf n - Sum_S n
def Term_S (n:ℕ):ℚ := Sum_S n - Sum_S (n-1)
  
theorem Ainf : Af x = Sum_A x n + Tail_A x n := by
  unfold Af Sum_A Tail_A Sum_A Af 
  simp

theorem Finf : Ff x = Sum_F x n + Tail_F x n := by
  unfold Ff Sum_F Tail_F Sum_F Ff 
  simp

theorem Binf : Bf n = Sum_B n + Tail_B n := by
  unfold Bf Sum_B Tail_B Ff
  simp

theorem Sinf : Sf n = Sum_S n + Tail_S n := by
  unfold Sf Sum_S Tail_B Tail_S Sum_S Sf Sum_S Tail_B 
  simp

theorem AisConst : Sum_A x n + Tail_A x n = Sum_A x (n+1) + Tail_A x (n+1) := by
  unfold Sum_A Tail_A Sum_A Af 
  simp

theorem FisConst : Sum_F x n + Tail_F x n = Sum_F x (n+1) + Tail_F x (n+1) := by
  unfold Sum_F Tail_F Ff Sum_F 
  simp

theorem BisConst : Bf n = Bf (n+1) := by
  unfold Bf Sum_B Tail_B 
  simp

theorem SisConst : Sf n = Sf (n+1) := by
  unfold Sf Sum_S Tail_B 
  simp
  ring_nf

theorem Arecursion (x:ℤ) (ha: (1 - x)*(Af x)=1): Af x = 1 + x * (Af x) := by
  rw [← ha]
  unfold Af
  simp
  ring_nf

theorem Spows13 : Sf n = 1 + 13 * (Sf n) := by
  unfold Sf Sum_S Tail_B 
  simp
  ring_nf

theorem whySf : 
  (
    (Sf n = Sum_S n + Tail_S n) ∧ 
    (Bf n = Sum_B n + Tail_B n) ∧ 
    (Sf n = Sf (n+1)) ∧ 
    (4*(Sum_S n) - (Sum_S (2*n) + Tail_B (2*n)))/3 = (Sf n)
  ) → 
  (4*(Sum_S n) - (Sum_S (2*n) + Tail_B (2*n))) = 3*(Sf n) → 
  Sf n + (4*(Sum_S n) - (Sum_S (2*n) + Tail_B (2*n))) = 4*(Sf n) → 
  Sf n + 4*(Sum_S n) - Sum_S (2*n) - Tail_B (2*n) = 4*(Sf n) → 
  Sf n - Sum_S (2*n) + 4*(Sum_S n) - Tail_B (2*n) = 4*(Sf n) → 
  Sf (2*n) - Sum_S (2*n) + 4*(Sum_S n) - Tail_B (2*n) = 4*(Sf n) → 
  Tail_S (2*n) + 4*(Sum_S n) - Tail_B (2*n) = 4*(Sf n) → 
  Tail_S (2*n) - Tail_B (2*n) = 4*(Sf n) - 4*(Sum_S n) → 
  (
    Tail_S (2*n) - Tail_B (2*n) = 4*(Tail_S n) ∧  
    Sum_S (2*n) - Sum_B (2*n) = 4*(Sum_S n)
  ) → 
  Sf n - Bf n = 4*(Sf n) := by
  unfold Sum_S Tail_B Sf Sum_S Tail_B Bf Sum_B Tail_B Ff Tail_S Sf Sum_S Tail_B 
  simp
  ring_nf
  simp

theorem S1vsS2: Sum_A 13 n + Tail_A 13 n = Sum_S n + Tail_S n := by
  unfold Tail_A Tail_S Sum_A Sum_S Af Sf Sum_S Tail_B 
  simp
  ring_nf

theorem SnegOneTwelfth : 12*(Sum_S n + Tail_S n) + 1 = 0 := by
  unfold Tail_S Sf Sum_S Tail_B 
  simp
  ring_nf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment