Zulip Chat Archive

Stream: new members

Topic: Proving equations with divisions?


Fernando Chu (Nov 25 2025 at 20:58):

I was trying the following example:

import Mathlib

example (n : ) : ( k  Finset.range (n), k) = n*(n-1)/2 := by
  induction' n with n ih
  · simp
  · ring_nf
    rw [Finset.sum_range_add (fun x  x) 1 n, Finset.sum_add_distrib, ih]
    simp
    sorry

Is there a nice way to close the goal?

Aaron Liu (Nov 25 2025 at 21:04):

what's your reasoning for why this should be true

Aaron Liu (Nov 25 2025 at 21:05):

note that it's not completely trivial because (2 * n + 1) / 2 = n so division doesn't always distribute over addition

Fernando Chu (Nov 25 2025 at 21:11):

Interesting point, that made me think that I should continue on with

    have : n = 2 * n / 2 := by simp
    nth_rw 1 [this]

So that the goal is now

2 * n / 2 + n * (n - 1) / 2 = (n * n + n) / 2

I had hoped that maybe ring would solve this but seems not

Fernando Chu (Nov 25 2025 at 21:18):

Ah, I think the problem is n * (n - 1)? Maybe ring doesn't know about negation when working on a semiring?

Robin Arnez (Nov 25 2025 at 21:27):

- on Nat isn't working with negation, it's instead truncated subtraction (e.g. 3 - 4 = 0)

Kevin Buzzard (Nov 25 2025 at 21:28):

I would claim that you're trying to prove the wrong thing. n*(n-1)/2 doesn't mean what you think it means because neither natural subtraction nor natural division are what mathematicians expect them to mean.

Ruben Van de Velde (Nov 25 2025 at 21:32):

I was writing "as Kevin would say, this isn't what you want to prove...", but there we go :)

Ruben Van de Velde (Nov 25 2025 at 21:34):

It's possible to prove this form, but sort of only by accident and not with tools that assume well-behaved subtraction like ring. In fact, the ring_nf you started with only makes things harder for you

Proof

Kevin Buzzard (Nov 25 2025 at 21:42):

Note how much easier it is to prove the mathematically correct statement -- I coerce to the rationals and then subtraction and division have their correct meaning.

import Mathlib

example (n : ) : ( k  Finset.range (n), (k : )) = n*(n-1)/2 := by
  induction n with
  | zero => simp
  | succ n IH => rw [Finset.sum_range_succ, IH]; grind

Aaron Liu (Nov 25 2025 at 21:46):

Using grind is cheating

Kevin Buzzard (Nov 25 2025 at 21:49):

import Mathlib

example (n : ) : ( k  Finset.range n, (k : )) = n*(n-1)/2 := by
  induction n with
  | zero => simp
  | succ n IH => rw [Finset.sum_range_succ, IH]; push_cast; ring

Aaron Liu (Nov 25 2025 at 21:49):

Fine you win

Fernando Chu (Nov 26 2025 at 03:28):

Thanks for the answers!

Yannick Seurin (Nov 26 2025 at 09:52):

Note that MIL has a similar example in Section 5.2:

import Mathlib

theorem sum_id (n : ) :  i  Finset.range (n + 1), i = n * (n + 1) / 2 := by
  symm; apply Nat.div_eq_of_eq_mul_right (by norm_num : 0 < 2)
  induction' n with n ih
  · simp
  rw [Finset.sum_range_succ, mul_add 2,  ih]
  ring

Quoting:

The first step of the proof clears the denominator. This is generally useful when formalizing identities, because calculations with division generally have side conditions. (It is similarly useful to avoid using subtraction on the natural numbers when possible.)

Yannick Seurin (Nov 26 2025 at 10:17):

For the original statement, it can be adapted as follows:

import Mathlib

theorem sum_id (n : ) :  i  Finset.range n, i = n * (n - 1) / 2 := by
  symm; apply Nat.div_eq_of_eq_mul_right (by norm_num : 0 < 2)
  induction' n with n ih
  · simp
  rw [Finset.sum_range_succ, mul_add 2,  ih]
  cases n with
  | zero => simp
  | succ n => simp; ring

Last updated: Dec 20 2025 at 21:32 UTC