Zulip Chat Archive

Stream: mathlib4

Topic: feature request: field_simp in Nat


Asei Inoue (Mar 06 2024 at 13:47):

import Mathlib.Tactic

example (n m : Nat) : n * m = ((n + m) ^ 2 - n ^ 2 - m ^ 2 ) / 2 := by
  -- `field_simp` fails.
  -- Why doesn't `field_simp` use `Nat.div_eq_of_eq_mul_right` here?
  try field_simp

  symm
  apply Nat.div_eq_of_eq_mul_right
  . norm_num
  rw [show (n + m) ^ 2 = n ^ 2 + 2 * n * m + m ^ 2 from by ring]
  calc n ^ 2 + 2 * n * m + m ^ 2 - n ^ 2 - m ^ 2
    _ = (n ^ 2 - n ^ 2) + 2 * n * m + (m ^ 2 - m ^ 2) := by simp [add_assoc]
    _ = 0 + 2 * n * m + 0 := by congr 2 <;> simp_arith
    _ = 2 * (n * m) := by simp [mul_assoc]

example (n m : Rat) : n * m = ((n + m) ^ 2 - n ^ 2 - m ^ 2 ) / 2 := by
  -- `field_simp` works! :)
  field_simp
  ring

Johan Commelin (Mar 06 2024 at 13:48):

Because Rat is a field and Nat is not.

Asei Inoue (Mar 06 2024 at 13:49):

My point is that it would be useful if field_simp could also can be used in Nat.

Johan Commelin (Mar 06 2024 at 13:50):

It is out of scope. Division on Nat is pretty pathological

Eric Wieser (Mar 06 2024 at 13:51):

As is subtraction

Ruben Van de Velde (Mar 06 2024 at 13:52):

You can rify or qify first, but you'll need to show that you're not in a pathological case for that to work

Asei Inoue (Mar 06 2024 at 13:54):

I know it's not field_simp's job to do this.

Just having a tactic to try Nat.div_eq_of_eq_mul_right and Nat.div_eq_of_eq_mul_left would be useful for me.

It would be nice to have a tactic that hits the commonly performed operation of 'erasing the denominator'.

Asei Inoue (Mar 06 2024 at 13:56):

@Ruben Van de Velde

You can rify or qify first, but you'll need to show that you're not in a pathological case for that to work

Thank you ... But I didn't know how to do it. I would like to see an example code.

Bolton Bailey (Mar 06 2024 at 14:33):

Well, I think the issue with trying to use qify here is that you will run into the non-obviousness of the fact that ((n + m) ^ 2 - n ^ 2 - m ^ 2 ) is evenly divisible by 2.

Kim Morrison (Mar 07 2024 at 00:52):

omega is not very good at dealing with polynomials, but

import Mathlib.Tactic

example (n m : Nat) : n * m = ((n + m) ^ 2 - n ^ 2 - m ^ 2 ) / 2 := by
  ring_nf
  generalize n * m = nm
  omega

does work.

Kim Morrison (Mar 07 2024 at 00:54):

Actually, the need for generalize there seems to be a straight up omega bug. I'll investigate.

Kim Morrison (Mar 07 2024 at 01:00):

Ah, I see, omega has no way of knowing:

import Mathlib.Tactic

example (n m : Nat) : n * m = ((n + m) ^ 2 - n ^ 2 - m ^ 2) / 2 := by
  ring_nf
  have : 0  (n : Int) * (m : Int) := sorry
  omega -- works

Kim Morrison (Mar 07 2024 at 01:01):

(This is essentially the difference between linarith and nlinarith.)

Kim Morrison (Mar 07 2024 at 01:03):

I think this is far enough afield that I am not going to pursue it now. We had talked about adding an extensible mechanism for telling omega new facts about atoms, but have decided not to implement that immediately.

If someone is keen to push on this I'm happy to explain what would be required.

Kevin Buzzard (Mar 07 2024 at 07:16):

Asei Inoue said:

It would be nice to have a tactic that hits the commonly performed operation of 'erasing the denominator'.

I would say that natural division is not at all common and was arguably a code smell. a = b / c is sometimes what you want but far more common is the strictly stronger statement a * c = b which is what people would usually use rather than division.


Last updated: May 02 2025 at 03:31 UTC