Zulip Chat Archive
Stream: Is there code for X?
Topic: cons is to snoc as Fin.eq_zero_or_eq_succ is to
Bolton Bailey (Aug 17 2023 at 00:01):
Do we have
theorem Fin.eq_castSucc_or_eq_last {n : Nat} : ∀ i : Fin (n + 1),
(∃ j : Fin n, i = j.castSucc) ∨ i = n
anywhere?
Bolton Bailey (Aug 17 2023 at 00:16):
theorem Fin.eq_castSucc_or_eq_last {n : Nat} : ∀ i : Fin (n + 1),
(∃ j : Fin n, i = j.castSucc) ∨ i = n := by
intro ⟨i, hi⟩
by_cases h : i < n
· left
use ⟨i, by assumption⟩
simp only [castSucc_mk]
· right
apply Fin.eq_of_val_eq
simp only [coe_ofNat_eq_mod]
rw [Nat.mod_eq_of_lt (Nat.lt.base n), Nat.eq_of_lt_succ_of_not_lt hi h]
Eric Wieser (Aug 17 2023 at 00:44):
docs#Fin.snocInduction maybe?
Eric Wieser (Aug 17 2023 at 00:46):
docs#Fin.consCases is the lemma that I think we should actually have a snoc
version of
Bolton Bailey (Aug 17 2023 at 01:15):
I'm starting to think we should have a to_snoc
modifier like to_additive
for some of these, seems like a bunch of totally analogous lemmas.
cons <-> snoc
tail <-> init
succ <-> castSucc
zero <-> last
pred <-> ???
Bolton Bailey (Aug 17 2023 at 01:16):
Or more simply a reverse
function, some lemmas about it, and then use that to prove things about snoc type functions
Bolton Bailey (Aug 17 2023 at 03:54):
(In fact, docs#Fin.rev exists)
Bolton Bailey (Sep 30 2023 at 17:18):
Is there any hope of this? I can define
def reverse {α : Fin n → Type u} (q : ∀ i, α i) : ∀ i : Fin n, α (rev i) :=
fun i => q (rev i)
and
theorem init_eq_reverse_tail_reverse (q : ∀ i, α i) (k) : init q k = reverse (tail (reverse q)) k := by sorry
but then I get
type mismatch
reverse (tail (reverse q)) k
has type
α (rev (succ (rev k))) : Type u
but is expected to have type
α (castSucc k) : Type u
Is there some way of getting lean to know these types are the same?
Bolton Bailey (Sep 30 2023 at 17:19):
Is this a use case for heterogenous equality?
Eric Wieser (Sep 30 2023 at 17:22):
I would recommend composing with Fin.cast
on one side
Bolton Bailey (Sep 30 2023 at 17:24):
Sweet, that's exactly what I'm looking for, thanks.
Bolton Bailey (Sep 30 2023 at 17:41):
Hmm, maybe I spoke too soon. It seems docs#Fin.cast casts Fin n
to Fin m
when n = m
. But what I need is to cast alpha i
to alpha j
where i = j
are equal elements, both of Fin (n + 1)
Bolton Bailey (Sep 30 2023 at 17:50):
I think I want docs#cast
Timo Carlin-Burns (Sep 30 2023 at 18:09):
I'm not sure if there's a reason to prefer Eq.cast
or ▸
(\t), but here's a starting place using the latter
open Fin
def reverse {n : ℕ} {α : Fin n → Type u} (q : ∀ i, α i) : ∀ i : Fin n, α (rev i) :=
fun i => q (rev i)
theorem castSucc_eq_rev_succ_rev {n : ℕ} (k : Fin n) : castSucc k = rev (succ (rev k)) := by
sorry
theorem init_eq_reverse_tail_reverse {n : ℕ} {α : Fin (n + 1) → Type u} (q : ∀ i, α i) (k : Fin n) : init q k = castSucc_eq_rev_succ_rev k ▸ reverse (tail (reverse q)) k := by
sorry
Timo Carlin-Burns (Sep 30 2023 at 18:10):
You could also change your goal to HEq (init q k) (reverse (tail (reverse q)) k)
Bolton Bailey (Sep 30 2023 at 18:29):
It works!
theorem init_eq_reverse_tail_reverse (q : ∀ i, α i) (i) :
init q i = _root_.cast (by rw [castSucc_eq_rev_succ_rev]) (reverse (tail (reverse (q))) i) := by
rw [init, reverse, tail, eq_comm, cast_eq_iff_heq, castSucc_eq_rev_succ_rev]
exact congr_arg_heq q (Eq.refl (rev (succ (rev i))))
Bolton Bailey (Sep 30 2023 at 18:31):
snoc_eq_reverse_cons_reverse
being tricky though
Timo Carlin-Burns (Sep 30 2023 at 19:56):
@Bolton Bailey I'm a beginner and I'm curious, does your proof of castSucc_eq_rev_succ_rev
look much different from mine?
import Mathlib
namespace Fin
@[simp]
theorem succ_rev {n : ℕ} (k : Fin n) : succ (rev k) = rev (castSucc k) := by
ext
simp only [val_succ, val_rev, coe_castSucc, Nat.succ_sub_succ_eq_sub]
zify [show k + 1 ≤ n from k.is_lt, show k ≤ n from is_le']
ring
theorem rev_succ_rev {n : ℕ} (k : Fin n) : rev (succ (rev k)) = castSucc k := by
simp
end Fin
Bolton Bailey (Sep 30 2023 at 21:02):
I have been using this software for years now and I still do not know how to prove lemmas about tsub, I had just sorried it
Bolton Bailey (Sep 30 2023 at 21:14):
There should be a zify!
tactic which just assumes every tsub
it sees is nondegenerate and then throws off the proofs it needs to throw off.
Bolton Bailey (Sep 30 2023 at 21:22):
Can I steal this? (also I think the one with succ should be the one it simplifies to).
Timo Carlin-Burns (Sep 30 2023 at 21:56):
Sure!
Timo Carlin-Burns (Sep 30 2023 at 21:59):
I was thinking that the simp normal form should push rev
s to the outside like how there's a simp lemma for -(a + b) = -b - a
Bolton Bailey (Sep 30 2023 at 22:09):
Maybe. My sort of goal with all of this is to make all the things on the right hand side of the comment above simplify to their right hand counterparts so we can easily reduce to one bigger API.
Timo Carlin-Burns (Sep 30 2023 at 22:15):
I think I mixed myself up. You're right. We push negs to the inside, so we should do the same with rev
s.
Timo Carlin-Burns (Oct 01 2023 at 04:46):
Playing around with this, after I proved that _ ▸ (reverse (reverse q)) = q
, I realized I would really want to be able to float these casts in and out of expressions, so I tried to prove _ ▸ (reverse q) = reverse (_ ▸ q)
Unfortunately, I think it's impossible. It's similar to the following statement:
import Mathlib.Logic.Basic
universe u
theorem cast_behaves {ι : Type u} {α β : ι → Type u}
(h : ∀ i, α i = β i) (f : ∀ i, α i) (i : ι) :
cast (h i) (f i) = cast (pi_congr (congrFun (funext h))) f i :=
sorry -- unprovable, right? we can't prove anything about the result of applying casted functions.
Timo Carlin-Burns (Oct 01 2023 at 05:07):
I PRed some of the above lemmas: std4#277
Eric Wieser (Oct 01 2023 at 09:47):
I think you can prove that with revert h
, rw [<-funext_iff]
, rintro rfl
or similar
Eric Wieser (Oct 01 2023 at 09:48):
If rw
doesn't work then applying docs#forall_prop_congr or similar might
Alex J. Best (Oct 01 2023 at 14:15):
Bolton Bailey said:
There should be a
zify!
tactic which just assumes everytsub
it sees is nondegenerate and then throws off the proofs it needs to throw off.
Can you open an issue for this? It sounds like a nice idea and it would be great if it wasn't forgotten. There are definitely people out there (myself included) that look at the tactics issues when bored and want a small project to implement.
Bolton Bailey (Oct 01 2023 at 14:28):
Alex J. Best said:
Bolton Bailey said:
There should be a
zify!
tactic which just assumes everytsub
it sees is nondegenerate and then throws off the proofs it needs to throw off.Can you open an issue for this? It sounds like a nice idea and it would be great if it wasn't forgotten. There are definitely people out there (myself included) that look at the tactics issues when bored and want a small project to implement.
Done! #7450
Timo Carlin-Burns (Oct 01 2023 at 16:42):
Eric Wieser said:
I think you can prove that with
revert h
,rw [<-funext_iff]
,rintro rfl
or similar
That approach doesn't work
import Mathlib
universe u
theorem cast_behaves {ι : Type u} {α β : ι → Type u}
(h : ∀ i, α i = β i) (f : ∀ i, α i) (i : ι) :
cast (h i) (f i) = cast (pi_congr (congrFun (funext h))) f i := by
revert h
rw [← Function.funext_iff]
-- ⊢ (fun h ↦ cast _ (f i)) = fun h ↦ cast _ f i
rintro rfl -- error: our goal is not an implication
Eric Wieser (Oct 01 2023 at 19:56):
import Mathlib
universe u
theorem cast_behaves {ι : Type u} {α β : ι → Type u}
(h : ∀ i, α i = β i) (f : ∀ i, α i) (i : ι) :
cast (h i) (f i) = cast (pi_congr (congrFun (funext h))) f i := by
revert h
refine (forall_prop_congr (fun x => Iff.rfl) (Function.funext_iff).symm).mpr ?_
rintro (rfl : α = β)
rfl
Last updated: Dec 20 2023 at 11:08 UTC