Zulip Chat Archive
Stream: maths
Topic: Is there an idiom for applying a subproof in two directions?
Dan Abramov (Feb 19 2025 at 15:57):
Here's a little example:
import Mathlib
open Set
open Function
variable {α β : Type*} [Nonempty β]
variable (f : α → β) (g : β → α
example (x : Set α) (hx: x = univ ∨ x = ∅) : (Injective f) := by
intro a1 a2 heq
have direct_iif : a1 ∈ x ↔ a2 ∈ x := by
constructor
· intro aex
rcases hx with (h1 | h2)
· rw [h1]
trivial
· rw [h2] at aex
trivial
· intro aex
rcases hx with (h1 | h2)
· rw [h1]
trivial
· rw [h2] at aex
trivial
sorry
Note I'm interested in having a statement like direct_iif : a1 ∈ x ↔ a2 ∈ x
so I can use it later. However, I'm not excited about proving it in both directions because a1
and a2
are equivalent and the exact same proof can be reused. In the above example, it's this part:
· intro aex
rcases hx with (h1 | h2)
· rw [h1]
trivial
· rw [h2] at aex
trivial
You can see it being repeated twice because we need to cover both directions.
Is there an idiomatic way to treat a1
and a2
as interchangeable in a certain context, saying "we proved this for a1
and a2
but we didn't rely on anything differentiating them during that proof, therefore the proof holds for a2
and a1
too".
I assume the wlog
tactic might have something to do with it but I can't figure out how to use it. (It would help if the documentation for each tactic contained at least a single actual example of actually using them to prove something — even a toy one. :)
Riccardo Brasca (Feb 19 2025 at 16:01):
Yeah, wlog
is a pain. The problem is that when we say informally "wlog a ≤ b
" we often say "since clearly the same proof works, interchanging a
and b
, let's suppose a ≤ b
. But Lean of course does not understand this "clearly" andwlog
asks to show that the case a ≤ b
implies the case b ≤ a
, that if often not our way of thinking.
Riccardo Brasca (Feb 19 2025 at 16:02):
Having said that, usually you can extract a sublemma. Here it would be that s = univ
implies x ∈ s
, for all x
.
Riccardo Brasca (Feb 19 2025 at 16:02):
No sorry, I misread your code.
Ruben Van de Velde (Feb 19 2025 at 16:04):
For your particular example, obtain rfl|rfl := hx <;> simp
works, but that might be simplified too much :)
Dan Abramov (Feb 19 2025 at 16:07):
Haha yeah the code is a bit simplified, the main thing is really this pattern:
- I have some
a1
anda2
of the same type - I want to prove something about their interrelation
- This thing I want to prove is symmetric and I'd rather not prove it twice
- I'd also rather not extract a whole lemma out of it or further abstract it with more variables
Riccardo Brasca (Feb 19 2025 at 16:11):
Something like
import Mathlib
open Set
open Function
variable {α β : Type*} [Nonempty β]
variable (f : α → β) (g : β → α)
lemma foo {x : Set α} (hx : x = univ ∨ x = ∅) {a1 a2 : α} (ha1 : a1 ∈ x) : a2 ∈ x := by
rcases hx with (h1 | h2)
· rw [h1]
trivial
· rw [h2] at ha1
trivial
example (x : Set α) (hx: x = univ ∨ x = ∅) : (Injective f) := by
intro a1 a2 heq
have direct_iif : a1 ∈ x ↔ a2 ∈ x := by
constructor
· exact foo hx
· exact foo hx
sorry
Riccardo Brasca (Feb 19 2025 at 16:13):
You can even do have direct_iif : a1 ∈ x ↔ a2 ∈ x := ⟨foo hx, foo hx⟩
Dan Abramov (Feb 19 2025 at 16:14):
Fair enough, guess that's where I'm going. No change wlog
would simplify this?
Riccardo Brasca (Feb 19 2025 at 16:14):
But maybe you are looking for
have direct_iif : a1 ∈ x ↔ a2 ∈ x := by
constructor
all_goals {
intro aex
rcases hx with (h1 | h2)
· rw [h1]
trivial
· rw [h2] at aex
trivial }
Dan Abramov (Feb 19 2025 at 16:20):
Heh, this is not bad.
Riccardo Brasca (Feb 19 2025 at 16:21):
There is also the similar any_goals
(not relevant here, but if learn about one it is worth to know that the other exists)
Riccardo Brasca (Feb 19 2025 at 16:24):
Note also that using by assumption
(or ‹_›
to look fancy) you can sometimes improves the behavior of all_goals tac
, since it works also if the only difference in the goals is a name of an hypothesis.
Yakov Pechersky (Feb 19 2025 at 16:34):
We also have swap_var
to do a rough renaming of hypotheses/variables that is a poor man's wlog
Dan Velleman (Feb 19 2025 at 17:58):
By the way, I don't see how your original example can be right. Did you perhaps mean:
example (h : ∀ (x : Set α), x = univ ∨ x = ∅) : Injective f
Dan Abramov (Feb 19 2025 at 18:06):
Please ignore the statement itself, I just wrote something minimal that typechecks to create something that can be copy pasted into the editor.
The actual problem I'm working on was this one, see heq_imp_same_directness
and how it's applied for what I was trying to achieve (I'd still like to see if it's possible to inline it without making the proof bloated).
Chris Wong (Feb 21 2025 at 03:38):
I think the reason why wlog
doesn't work here is because it doesn't actually understand symmetry, it just tries to negate the assumption, which works for linear orders (docs#le_of_not_le) but doesn't work for implication.
Chris Wong (Feb 21 2025 at 03:43):
I wonder if there's demand for a wlog_swap
that works for iffs.
Mario Carneiro (Feb 23 2025 at 18:03):
Note that wlog
used to be a lot smarter and it got downscoped because it had too many bells and whistles and/or was too slow. Maybe @Johan Commelin remembers the story better
Johan Commelin (Feb 24 2025 at 09:03):
It was so slow in Lean 3 that it wasn't really practical.
I agree that the current version is so downscoped that it isn't really practical either.
It would be great to have the Goldilocks version of wlog
. :bear: :bowl: :woman_blond_hair:
Last updated: May 02 2025 at 03:31 UTC