Zulip Chat Archive
Stream: new members
Topic: dependent lift with quotient
Yakov Pechersky (Apr 14 2021 at 01:29):
What's the right way to have a dependent definition on a quotient? I have defined my own setoid on list which is whether two lists are rotations of one another:
def is_rotated (l l' : list α) : Prop := ∃ n, l.rotate n = l'
infixr ` ~r `:1000 := is_rotated
[...]
def is_rotated.setoid : setoid (list α) :=
{ r := is_rotated, iseqv := is_rotated.eqv }
so I can define a cycle
via a quotient:
def cycle (α : Type*) : Type* := quotient (@is_rotated.setoid α)
In fact, properties like nodup
can be lifted into the quotient
lemma is_rotated.nodup_iff {l l' : list α} (h : l ~r l') : nodup l ↔ nodup l' :=
h.perm.nodup_iff
def nodup (s : cycle α) : Prop :=
quot.lift_on s nodup (λ l₁ l₂ (e : l₁ ~r l₂), propext $ e.nodup_iff)
I've also defined a cyclical permutation from the list, and shown that it is invariant to rotation
def form_perm : equiv.perm α :=
(zip_with equiv.swap l (l.rotate 1)).tail.prod
lemma form_perm_eq_of_is_rotated {l l' : list α} (hd : nodup l) (h : l ~r l') :
form_perm l = form_perm l' :=
begin
obtain ⟨n, rfl⟩ := h.def,
exact (form_perm_rotate l hd n).symm
end
My question is, what's the right invocation to make this dependent definition:
def perm [decidable_eq α] : Π (s : cycle α) (h : nodup s), equiv.perm α :=
λ s, quot.lift_on s
_ -- list α → s.nodup → equiv.perm α
_ -- ∀ (a b : list α), setoid.r a b → ⁇ a = ⁇ b
Yakov Pechersky (Apr 14 2021 at 01:30):
Do I instead use quot.induction_on
?
Yury G. Kudryashov (Apr 14 2021 at 01:39):
What's wrong with quot.lift_on
?
Yakov Pechersky (Apr 14 2021 at 01:42):
I don't know how to unlift the provided cycle.nodup s
to provide me list.nodup
with the proof I supply for the last argument of lift_on
Yury G. Kudryashov (Apr 14 2021 at 01:46):
Could you please post an #mwe that others can copy+paste to make experiments?
Yury G. Kudryashov (Apr 14 2021 at 01:47):
It seems that docs#quot.lift_on is for non-dependent functions.
Yury G. Kudryashov (Apr 14 2021 at 01:48):
There is a docs#quotient.hrec_on'
Yakov Pechersky (Apr 14 2021 at 01:51):
import data.list.rotate
import data.list.erase_dup
import group_theory.perm.basic
variables {α : Type*}
namespace list
def is_rotated (l l' : list α) : Prop := ∃ n, l.rotate n = l'
infixr ` ~r `:1000 := is_rotated
def is_rotated.setoid : setoid (list α) :=
{ r := is_rotated, iseqv := sorry }
lemma is_rotated.perm {l l' : list α} (h : l ~r l') : l ~ l' :=
exists.elim h (λ _ hl, hl ▸ (rotate_perm _ _).symm)
lemma is_rotated.nodup_iff {l l' : list α} (h : l ~r l') : nodup l ↔ nodup l' :=
h.perm.nodup_iff
def form_perm [decidable_eq α] (l : list α) : equiv.perm α :=
(zip_with equiv.swap l (l.rotate 1)).tail.prod
lemma form_perm_eq_of_is_rotated [decidable_eq α] {l l' : list α} (hd : nodup l) (h : l ~r l') :
form_perm l = form_perm l' := sorry
end list
open list
def cycle (α : Type*) : Type* := quotient (@is_rotated.setoid α)
namespace cycle
instance : has_coe (list α) (cycle α) := ⟨quot.mk _⟩
def nodup (s : cycle α) : Prop :=
quot.lift_on s nodup (λ l₁ l₂ (e : l₁ ~r l₂), propext $ e.nodup_iff)
def perm [decidable_eq α] : Π (s : cycle α) (h : nodup s), equiv.perm α :=
λ s, quot.lift_on s
(λ l (h : nodup s), form_perm l)
(λ l₁ l₂ (e : l₁ ~ l₂), by { ext1 (hd : nodup s), simp only, sorry })
def perm' [decidable_eq α] : Π (s : cycle α) (h : nodup s), equiv.perm α :=
λ s, quot.rec_on s
(λ l (h : nodup _), form_perm l)
(λ l₁ l₂ h, by { ext1 hd, sorry })
end cycle
Yakov Pechersky (Apr 14 2021 at 02:01):
hrec
leads to a heq
I'm not sure how to discharge:
def perm' [decidable_eq α] : Π (s : cycle α) (h : nodup s), equiv.perm α :=
λ s, quot.hrec_on s (λ l h, form_perm l)
(λ l₁ l₂ h, by { })
Yakov Pechersky (Apr 14 2021 at 02:07):
Thank you Yury! Here's my solution:
def perm [decidable_eq α] : Π (s : cycle α) (h : nodup s), equiv.perm α :=
λ s, quot.hrec_on s (λ l h, form_perm l)
(λ l₁ l₂ (h : l₁ ~r l₂), by {
ext,
{ exact is_rotated.nodup_iff h },
{ intros h1 h2 he,
refine heq_of_eq _,
rw form_perm_eq_of_is_rotated _ h,
exact h1 } })
Yakov Pechersky (May 07 2021 at 01:15):
Another quotient problem: what about defining a dependent product on a multiset if I know that the multiplication is commutative within the multiset?
import data.finset.fold
variables {α : Type*} [monoid α]
namespace multiset
@[to_additive]
def noncomm_prod' : Π (s : multiset α) (comm : ∀ ⦃x⦄ (hx : x ∈ s) ⦃y⦄ (hy : y ∈ s), commute x y),
α :=
λ s, quotient.hrec_on s (λ l h, l.prod) -- how do I build the output to encode `h` as well?
(λ l l' (h : l ~ l'),
begin
ext,
{ refine forall_congr (λ x, _),
refine imp_congr h.mem_iff _,
refine forall_congr (λ y, _),
exact imp_congr h.mem_iff iff.rfl },
{ rintros - - -,
rw heq_iff_eq,
refine h.prod_eq' _,
sorry -- no access to `h` here
},
end)
end multiset
Yakov Pechersky (May 07 2021 at 01:16):
Do I have to use
pprod (∀ ⦃x⦄ (hx : x ∈ s) ⦃y⦄ (hy : y ∈ s), commute x y) α :=
Yakov Pechersky (May 07 2021 at 01:17):
And then define another function to extract it?
Yakov Pechersky (May 07 2021 at 01:18):
(no pprod.ext
=C )
Yakov Pechersky (May 07 2021 at 01:25):
Oh I guess I threw away the info, didn't need the pprod
Last updated: Dec 20 2023 at 11:08 UTC