Zulip Chat Archive
Stream: mathlib4
Topic: sqrt 4 = 2
Li Xuanji (Feb 11 2024 at 16:33):
I was trying to prove that and . Are these the shortest proofs? I feel like they should both be one-liners
example : Real.sqrt 4 = 2 := by {
rw [Real.sqrt_eq_iff_sq_eq]
repeat norm_num
}
example : Real.sqrt 18 = 3*Real.sqrt 2 := by {
rw [Real.sqrt_eq_iff_sq_eq]
ring_nf
field_simp
norm_num
norm_num
simp
exact Real.sqrt_nonneg 2
}
Kyle Miller (Feb 11 2024 at 17:05):
This turns out to be a little simpler:
example : Real.sqrt 4 = 2 := by {
rw [Real.sqrt_eq_cases]
norm_num
}
example : Real.sqrt 18 = 3*Real.sqrt 2 := by {
rw [Real.sqrt_eq_cases]
ring_nf
norm_num
}
Kyle Miller (Feb 11 2024 at 17:06):
(@Mario Carneiro Is normalizing square roots of rationals in the purview of norm_num
? I think I remember you mentioning it at some point as a future feature, or future non-feature, I can't remember which.)
Kyle Miller (Feb 11 2024 at 17:16):
I tried making an argument where it suffices to square both sides, but then that pushes some difficulty to needing to say that square roots are non-negative.
theorem Real.eq_of_sq_eq {x y : ℝ} (hx : 0 ≤ x) (hy : 0 ≤ y) (h : x^2 = y^2) : x = y := by
rw [← sqrt_sq hx, ← sqrt_sq hy, h]
example : Real.sqrt 4 = 2 := by {
apply Real.eq_of_sq_eq <;> norm_num
apply Real.sqrt_nonneg
}
example : Real.sqrt 18 = 3*Real.sqrt 2 := by {
apply Real.eq_of_sq_eq <;> ring_nf <;> norm_num
apply Real.sqrt_nonneg
}
Kyle Miller (Feb 11 2024 at 17:16):
Those can be compressed to the one-liner general proof apply Real.eq_of_sq_eq <;> ring_nf <;> norm_num [Real.sqrt_nonneg]
(you can pass Real.sqrt_nonneg
to norm_num
since it is a fine simp lemma)
Damiano Testa (Feb 11 2024 at 17:56):
The first equality can also be proved by splitting the equality in two steps, before seeking help from automation:
example : Real.sqrt 4 = 2 := Eq.trans (by norm_num) (Real.sqrt_sq zero_le_two)
Li Xuanji (Feb 11 2024 at 20:06):
Thanks! With Kyle's proof being more uniform I wrote a small tactic to dispatch these
-- sqrt_eq_cases for y = √ x
theorem eq_sqrt_cases (x y : ℝ) : y = Real.sqrt x ↔ y * y = x ∧ 0 ≤ y ∨ x < 0 ∧ y = 0 := by
have r : y = Real.sqrt x ↔ Real.sqrt x = y := by exact eq_comm
rw [r]
exact Real.sqrt_eq_cases
macro "norm_sqrt_eq" : tactic => `(tactic| rw [Real.sqrt_eq_cases] <;> ring_nf <;> repeat norm_num )
macro "norm_eq_sqrt" : tactic => `(tactic| rw [eq_sqrt_cases] <;> ring_nf <;> repeat norm_num )
-- Normalize square roots of rational literals
macro "norm_sqrt" : tactic => `(tactic| first | norm_sqrt_eq | norm_eq_sqrt)
example : Real.sqrt 25 = 5 := by norm_sqrt
example : Real.sqrt 4 = 2 := by norm_sqrt
example : Real.sqrt 18 = 3*Real.sqrt 2 := by norm_sqrt
example : 2 = Real.sqrt 4:= by norm_sqrt
example : Real.sqrt (1/4) = 1/2 := by norm_sqrt
example : Real.sqrt (1/2) = Real.sqrt 2 / 2 := by norm_sqrt
Emilie (Shad Amethyst) (Feb 11 2024 at 20:08):
Isn't norm_eq_sqrt
just rw [eq_comm]; norm_sqrt_eq
?
Damiano Testa (Feb 11 2024 at 20:12):
Also, if you use macro_rules
and finishing with done
you can probably get away with a single tactic that tries either approach and only uses the first that works. (Untested, as I'm on mobile)
Emilie (Shad Amethyst) (Feb 11 2024 at 20:13):
I feel like ideally such a macro would replace Real.sqrt x
in the current proof with y
, and in the examples the proofs could then be closed with rfl
Emilie (Shad Amethyst) (Feb 11 2024 at 20:25):
But this is kind of what norm_num
should be for to begin with...
I really need to learn how to write more advanced tactics
Mario Carneiro (Feb 11 2024 at 20:29):
Kyle Miller said:
(Mario Carneiro Is normalizing square roots of rationals in the purview of
norm_num
? I think I remember you mentioning it at some point as a future feature, or future non-feature, I can't remember which.)
I think this should be a separate tactic, it has much more in common with ring
than norm_num
because I don't think there are canonical forms in full generality (it will start to look like the algebraic numbers stuff from the CAD discussion)
Li Xuanji (Feb 12 2024 at 02:28):
I feel like ideally such a macro would replace Real.sqrt x in the current proof with y, and in the examples the proofs could then be closed with rfl
Yes, but idk how to write a tactic which will do that computation. (Happy to learn if someone wants to give it a try though)
Emilie (Shad Amethyst) (Feb 12 2024 at 10:51):
Unfortunately this is something that I only know how to do in Coq, not in Lean. I really would like to learn how to do that, though
Eric Wieser (Feb 12 2024 at 10:54):
Mario, would you be opposed to norm_num being taught how to find the square root of squares?
Mario Carneiro (Feb 12 2024 at 11:33):
no, that would be fine
Mario Carneiro (Feb 12 2024 at 11:34):
the trouble is only when you have to expand the set of normal forms
Mario Carneiro (Feb 12 2024 at 11:34):
since then every other norm_num extension has to interact with it
Eric Wieser (Feb 12 2024 at 12:25):
You mean like I tried to do in #9915?
Mario Carneiro (Feb 12 2024 at 12:26):
yes
Kyle Miller (Feb 12 2024 at 16:37):
Could this be a globally enabled simproc
?
Li Xuanji (Feb 12 2024 at 16:42):
I didn't know about simproc
! Gonna play with it. The reduceFoo
example looks useful to learn from too.
Last updated: May 02 2025 at 03:31 UTC