Zulip Chat Archive
Stream: general
Topic: wlog tactic : documentation/howto?
Antoine Chambert-Loir (Oct 27 2021 at 08:00):
I am wondering whether there is a documentation or howto for the wlog tactic.
In one of the theorems I'm proving, I have m n : nat
plus some properties such as a: s m
b : s n
and I wish to sort according m ≤ n
or n ≤ m
, while exchanging the roles of a
, b
if needed.
I have seen a few examples but they don't seem to happen in my case.
Johan Commelin (Oct 27 2021 at 08:01):
@Antoine Chambert-Loir unfortunately, the wlog tactic is not so easy to use.
Antoine Chambert-Loir (Oct 27 2021 at 08:02):
That's unfortunate !
Johan Commelin (Oct 27 2021 at 08:02):
Mario recently wrote a variant. It would be interesting to see if you find it better.
Johan Commelin (Oct 27 2021 at 08:02):
namespace tactic
meta def take_pi_args : nat → expr → list name
| (n+1) (expr.pi h _ _ e) := h :: take_pi_args n e
| _ _ := []
namespace interactive
setup_tactic_parser
meta def doneif (h : parse ident?) (t : parse (tk ":" *> texpr))
(revert : parse (
(tk "generalizing" *> ((none <$ tk "*") <|> some <$> ident*)) <|> pure (some []))) :
tactic unit := do
let h := h.get_or_else `this,
t ← i_to_expr ``(%%t : Sort*),
(num_generalized, goal) ← retrieve (do
assert_core h t, swap,
num_generalized ← match revert with
| none := revert_all
| some revert := revert.mmap tactic.get_local >>= revert_lst
end,
goal ← target,
return (num_generalized, goal)),
tactic.assert h goal,
goal ← target,
(take_pi_args num_generalized goal).reverse.mmap' $ λ h,
try (tactic.get_local h >>= tactic.clear),
intron (num_generalized + 1)
meta def wlog' (h : parse ident?) (t : parse (tk ":" *> texpr)) : tactic unit :=
doneif h t none >> swap
end interactive
end tactic
Johan Commelin (Oct 27 2021 at 08:03):
Could you please paste that somewhere near the top of your file, and then write wlog' hmn : m ≤ n
in your proof?
Johan Commelin (Oct 27 2021 at 08:04):
This wlog does not (yet) try to close any trivial goals for you. But it does create goals that you would otherwise have to setup manually.
Gabriel Ebner (Oct 27 2021 at 08:05):
This wlog does not (yet) try to close any trivial goals for you. But it does create goals that you would otherwise have to setup manually.
This is so much better than the current wlog!
Sebastien Gouezel (Oct 27 2021 at 08:06):
Honestly, the current wlog
is not so bad. Does
wlog hmn : m ≤ n := le_total m n using [m n, n m] tactic.skip,
work for you?
Johan Commelin (Oct 27 2021 at 08:07):
I would love to see the pushout of both wlog variants.
Kevin Buzzard (Oct 27 2021 at 08:07):
I think we have pushouts in category theory
Antoine Chambert-Loir (Oct 27 2021 at 08:49):
@Sebastien Gouezel No, not quite because I needed to introduce a lot of stuff before:
m
and n
come from other objects a
and b
, and I need to exchange them as well,
as well as sets u
and v
such that hau: a ∈ u
and hbv: b ∈ v
…
When I try to add hau
and hbv
in the permutation, Lean complains that hau
depends on u
.
IDK, maybe that'll better wait for the moment when I have to PL this material.
Antoine Chambert-Loir (Oct 27 2021 at 08:54):
@Johan Commelin Neither. Strangely, the object hmn
has more or less the same type as the theorem I need to prove, and not the type m ≤ n
which is expected…
Johan Commelin (Oct 27 2021 at 08:58):
@Antoine Chambert-Loir The hmn
should indeed have almost the same type as what you want to prove. But with an additional assumption m ≤ n
somewhere in the middle. With this "bare bones" wlog'
you have to do the case split on m ≤ n ∨ n ≤ m
manually. And you also have to do all the permutation stuff manually.
Johan Commelin (Oct 27 2021 at 08:59):
What wlog'
does is: you claim that it suffices to treat the case with m ≤ n
, now you have to do two thing: (1) prove that it is sufficient to do that (2) prove the goal under this added assumption.
Johan Commelin (Oct 27 2021 at 08:59):
But it doesn't give you any help with (1). It only sets up the goal state for you.
Sebastien Gouezel (Oct 27 2021 at 09:02):
If you have a #mwe, we can have a more detailed look.
Antoine Chambert-Loir (Oct 27 2021 at 09:15):
Sebastien Gouezel said:
If you have a #mwe, we can have a more detailed look.
The following example is a working example, minimal in the sense that deleting any line makes it break ;-) , but not that small.
But Idk how to make it smaller (the complexity comes from the is_preconnected
function).
import topology.connected
open set classical topological_space
open_locale classical topological_space
universes u
variables {α : Type u} [topological_space α] {s t : set α}
/--
The union Union s of an increasing mapping s of preconnected sets
is preconnected
-/
variable ι : Type _
variables [ linear_order ι ]
theorem is_preconnected.Union_of_directed { s : ι → set α }
(H : ∀ n: ι, is_preconnected (s n))
(K : ∀ m n: ι, m ≤ n → s m ⊆ s n) :
is_preconnected ( Union s ) :=
begin
rw is_preconnected,
intros u v hu hv Huv Ku Kv ,
obtain ⟨ a, Kua ⟩ : ∃ a, a ∈ Union s ∩ u, from Ku,
obtain ⟨ b, Kvb ⟩ : ∃ b, b ∈ Union s ∩ v, from Kv,
obtain ⟨ m, Kam ⟩ : ∃ m, a ∈ s m , from mem_Union.1 Kua.left,
obtain ⟨ n, Kbn ⟩ : ∃ n, b ∈ s n , from mem_Union.1 Kvb.left,
cases le_total m n with hmn hnm,
/- Le cas où m ≤ n -/
have Kan : a ∈ s n := mem_of_mem_of_subset Kam ((K m n) hmn),
have Hnuv : ((s n) ∩ (u ∩ v)).nonempty :=
begin
apply (H n), apply hu, apply hv,
apply has_subset.subset.trans (subset_Union s n) Huv,
apply nonempty_of_mem (mem_inter Kan Kua.right),
apply nonempty_of_mem (mem_inter Kbn Kvb.right),
end,
have Knuv : ((s n) ∩ (u ∩ v)) ⊆ Union s ∩ (u ∩ v) :=
begin
apply inter_subset_inter,
apply subset_Union,
apply eq.subset, refl,
end,
exact nonempty.mono Knuv Hnuv,
/- Le cas où n ≤ m -/
have Kbm : b ∈ s m := mem_of_mem_of_subset Kbn ((K n m) hnm),
have Hnuv : ((s m) ∩ (u ∩ v)).nonempty :=
begin
apply (H m), apply hu, apply hv,
apply has_subset.subset.trans (subset_Union s m) Huv,
apply nonempty_of_mem (mem_inter Kam Kua.right),
apply nonempty_of_mem (mem_inter Kbm Kvb.right),
end,
have Kmuv : ((s m) ∩ (u ∩ v)) ⊆ Union s ∩ (u ∩ v) :=
begin
apply inter_subset_inter,
apply subset_Union,
apply eq.subset, refl,
end,
exact nonempty.mono Kmuv Hnuv,
end
Sebastien Gouezel (Oct 27 2021 at 09:35):
You can try with
revert a b u v,
wlog hmn : m ≤ n := le_total m n using [m n, n m] tactic.skip,
Does it help?
Antoine Chambert-Loir (Oct 27 2021 at 10:11):
Sebastien Gouezel said:
You can try with
revert a b u v, wlog hmn : m ≤ n := le_total m n using [m n, n m] tactic.skip,
Does it help?
Yes!
I could then just prove the second case using
intros a b u v hu hv Huv Ku Kv Kau Kbv Kam Kbn,
rw union_comm at Huv,
rw inter_comm u v,
exact this b a v u hv hu Huv Kv Ku Kbv Kau Kbn Kam
(and, by the way, I understood a bit more how this wlog
tactic works, thanks!).
Thanks a lot!
Johan Commelin (Oct 27 2021 at 10:16):
This works with wlog'
wlog' H : m ≤ n,
{ cases le_total m n with hmn hnm,
{ apply H, assumption' },
{ rw set.inter_comm u v, apply H, assumption', rwa set.union_comm, } },
rename H_1 hmn,
Johan Commelin (Oct 27 2021 at 10:17):
That rename
is a "bug" in wlog'
. It should allow the user to specify the name of the hypothesis.
Alex J. Best (Oct 28 2021 at 20:26):
@Johan Commelin and @Mario Carneiro where did this variant of wlog come from, I ended up writing my own version of this wlog' today (at https://github.com/leanprover-community/flt-regular/blob/may-assume/src/tactic/may_assume.lean called may assume) without realising it basically already existed till after I was done! It would be great to have one or the other in mathlib
Mario Carneiro (Oct 28 2021 at 20:36):
It was requested by @Tom Barnet-Lamb in another stream a few weeks ago
Last updated: Dec 20 2023 at 11:08 UTC