Zulip Chat Archive

Stream: new members

Topic: Can some tactic take care of this easy algebra?


Adam Dingle (Feb 11 2024 at 11:26):

In a proof I've gotten to a point that looks like this (where a, b : Nat):

ih1: b * ((a - b) / b) + (a - b) % b = a - b
 b * ((a - b) / b + 1) + (a - b) % b = a

Now, this looks super easy: all I have to do is add b to both sides of ih1, then factor it into the expression on the left. I could look up the names of several lemmas to perform rewrite steps that will get me there. But that seems like a bother. Is there some tactic that can just finish off the job for me?

Yagub Aliyev (Feb 11 2024 at 14:10):

I am new here. I could complete the proof with an extra assumption b ≤ a. Also not sure what to import first.

import Mathlib.Tactic

theorem addb' (a b: Nat) (ih1: b * ((a - b) / b) + (a - b) / b = a - b) (ineq': b  a) : b * ((a - b) / b + 1) + (a - b) / b = a := by

let c := b * ((a - b) / b) + (a - b) / b
ring_nf
have h : c =b * ((a - b) / b) + (a - b) / b
tauto
rw[ h] at ih1
rw[Nat.add_assoc]
rw[ h]
have ih : a-b=c
tauto
apply Nat.eq_add_of_sub_eq at ih
rw[Nat.add_comm]
tauto
exact ineq'

Timo Carlin-Burns (Feb 11 2024 at 18:24):

@Yagub Aliyev you're right that the proof needs b ≤ a, but it looks like you proved a slightly different goal which replaces (a - b) % b with (a - b) / b.

Timo Carlin-Burns (Feb 11 2024 at 18:25):

Here is a proof of the original goal assuming b ≤ a. In fact, ih1 is not needed.

import Mathlib.Tactic

@[simp]
theorem Int.sub_emod_self {a b : } : (a - b) % b = a % b := by
  simp [Int.sub_emod]

theorem Int.sub_ediv_self (a : ) {b : } (hb : b  0) : (a - b) / b = a / b - 1 := by
  simp [Int.sub_ediv_of_dvd a (Int.dvd_refl b), hb]

example (a b : Nat) (hba : b  a) :
    b * ((a - b) / b + 1) + (a - b) % b = a := by
  zify [hba]
  by_cases hb : (b : ) = 0
  . simp [hb]
  simp [Int.sub_ediv_self _ hb, Int.ediv_add_emod]

Kevin Buzzard (Feb 11 2024 at 18:28):

Note that slim_check finds counterexamples to the original claim (e.g. a = 0, b = 1).

Timo Carlin-Burns (Feb 11 2024 at 18:54):

To answer your question about tactics for easy algebra, ring, linarith, and polyrith often help, but they don't work well with natural subtraction or integer division, since those are not very algebraically well-behaved operations. If you have evidence that those operations are well-behaved in your instance (for natural subtraction b ≤ a and for integer division b ∣ a), then you can use zify or qify to convert the goal into one about integer subtraction or rational division instead. And lastly there's omega, which is like linarith for natural numbers. It doesn't solve this goal because it doesn't understand %.

Yagub Aliyev (Feb 12 2024 at 05:49):

Timo Carlin-Burns said:

Yagub Aliyev you're right that the proof needs b ≤ a, but it looks like you proved a slightly different goal which replaces (a - b) % b with (a - b) / b.

Yes, Thank you. I misread the question.

Adam Dingle (Feb 14 2024 at 10:34):

Thanks to everyone for the super helpful responses.

You're all right that b ≤ a is necessary to prove my claim. I didn't mention it because I failed to take into account that subtraction is not well-behaved over Nat, i.e. it's not always true that a - b + b = a. For that reason the condition b ≤ a is necessary.

The situation I originally described arose when I was trying to prove "b * (a / b) + a % b = a" as an exercise. (I know that it's a library theorem anyway.) I used induction over a. In the inductive case it's indeed true that b ≤ a, so that condition is available.

Thanks for mentioning slim_check, qify, polyrith and omega. I wasn't aware of any of them since I think they're not mentioned in the Lean tutorials such as "Theorem Proving in Lean" and "Mathematics in Lean". I'll add them to my tactic vocabulary. For working with ℕ or ℤ, omega seems very powerful and useful.

Given h1 : b ≤ a, I've now realized that it's easy to get from ih1 to my goal:

 zify [h1] at ih1
 zify [h1]
 linarith

Timo Carlin-Burns (Feb 14 2024 at 17:45):

Nice! Here's a way to save one more line ( means the goal)

 zify [h1] at ih1 
 linarith

Adam Dingle (Feb 14 2024 at 19:03):

Aha - I wasn't aware of that syntax. Great, thanks!


Last updated: May 02 2025 at 03:31 UTC