Zulip Chat Archive

Stream: Is there code for X?

Topic: a * b^2 = c^2 implies IsSquare a


David Renshaw (Dec 06 2023 at 01:30):

import Mathlib.Tactic

lemma foo {a b c : } (hb : b  0) (h : a * b^2 = c^2) : IsSquare a  := by
  sorry

I'm stuck on this. It seems like it ought to be easy. Am I missing something?

Eric Wieser (Dec 06 2023 at 02:39):

import Mathlib

lemma foo {a b c : } (hb : b  0) (h : a * b^2 = c^2) : IsSquare a  := by
  have : b^2  c^2 := by dsimp only [Int.instDvdInt]; exact a, h.symm.trans <| mul_comm _ _
  rw [Int.pow_dvd_pow_iff two_pos] at this
  obtain k, rfl := this
  rw [mul_pow, mul_comm, mul_right_inj' (pow_ne_zero _ hb)] at h
  rw [h]
  exact k, sq k

David Renshaw (Dec 06 2023 at 02:41):

Nice!

David Renshaw (Dec 06 2023 at 02:41):

Surely that first line should be

  have : b^2  c^2 := Dvd.intro_left a h

Eric Wieser (Dec 06 2023 at 02:41):

I was struggling to find the lemma, thanks

David Renshaw (Dec 06 2023 at 02:41):

does exact? not find it for you?

Eric Wieser (Dec 06 2023 at 02:41):

I didn't try

David Renshaw (Dec 06 2023 at 02:43):

Int.pow_dvd_pow_iff two_pos is the big thing I was missing here. I suppose that exact? didn't find it for me because it needed the two_pos.

Eric Wieser (Dec 06 2023 at 02:50):

Maybe a more general form:

lemma IsSquare.of_int_mul {a b : } (ha : IsSquare a) (ha0 : a  0) (hb : IsSquare (a * b)) : IsSquare b := by
  obtain a, rfl := ha
  obtain z, hb := hb
  rw [mul_comm] at hb
  have := Dvd.intro_left _ hb
  rw [ sq,  sq, Int.pow_dvd_pow_iff two_pos] at this
  obtain k, rfl := this
  rw [mul_mul_mul_comm, mul_comm, mul_right_inj' ha0] at hb
  rw [hb]
  exact k, rfl

Eric Wieser (Dec 06 2023 at 02:50):

Not golfed at all

Heather Macbeth (Dec 06 2023 at 03:09):

I can give you a proof with an "explicit" witness:

import Mathlib.Tactic.Polyrith
import Mathlib.RingTheory.Int.Basic

open Int hiding gcd gcd_dvd_left gcd_dvd_right

lemma foo {a b c : } (hb : b  0) (h : a * b^2 = c^2) : IsSquare a  := by
  obtain k, hk :  k, b = gcd b c * k := gcd_dvd_left b c
  obtain l, hl :  l, c = gcd b c * l  := gcd_dvd_right b c
  use a * k * gcdB b c + l * gcdA b c
  have hd : gcd b c  0 := fun hd => hb (by simpa [hd] using hk)
  apply mul_right_cancel₀ (pow_ne_zero 2 hd)
  have H : gcd b c = b * gcdA b c + c * gcdB b c := Int.gcd_eq_gcd_ab b c
  polyrith

Ruben Van de Velde (Dec 06 2023 at 08:17):

My mind went to docs#exists_associated_pow_of_mul_eq_pow, but it doesn't apply here

David Renshaw (Dec 06 2023 at 11:37):

Some previous cases of folks getting stuck on basically the same thing:

https://leanprover.zulipchat.com/#narrow/stream/113489-new-members/topic/.E2.9C.94.20.60a.5E2.20.E2.88.A3.20b.5E2.20.E2.86.92.20a.20.E2.88.A3.20b.60.20.3F/near/275563324

https://leanprover.zulipchat.com/#narrow/stream/217875-Is-there-code-for-X.3F/topic/.60a.20*.20a.20.E2.88.A3.20b.20*.20b.20.E2.86.92.20a.20.E2.88.A3.20b.60.20on.20the.20integers/near/221755947

David Renshaw (Dec 06 2023 at 11:40):

Neither exact?nor rw? are helpful here. Nor is moogle.ai (at least with the queries I tried).

Yury G. Kudryashov (Dec 06 2023 at 13:48):

Should we add Int.div_pow with some divisibility assumption?

Yury G. Kudryashov (Dec 06 2023 at 13:48):

(and Nat.div_pow)

Yaël Dillies (Dec 06 2023 at 13:49):

docs#Nat.pow_div is something to look out for

Yury G. Kudryashov (Dec 06 2023 at 14:25):

It's about x ^ m / x ^ n, we need (x / y) ^ n.

Yaël Dillies (Dec 06 2023 at 14:26):

Yes, so you should make clear in the lemma names how your new lemma is different from the old.

Yury G. Kudryashov (Dec 06 2023 at 14:27):

IMHO, Nat.pow_div should be renamed to Nat.pow_sub with swapped LHS and RHS.

Yury G. Kudryashov (Dec 06 2023 at 14:28):

Compare with docs#pow_sub

Yury G. Kudryashov (Dec 06 2023 at 14:31):

BTW, should we have a typeclass for b ≠ 0 → (a * b) / b = a? It's true for GroupWithZeros but also for Nat and Int.

Yaël Dillies (Dec 06 2023 at 14:32):

Semi-related: #8839


Last updated: Dec 20 2023 at 11:08 UTC