Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit be22d07

Browse files
feat(data/sym/basic): some basic lemmas in preparation for stars and bars (#12479)
Some lemmas extracted from @huynhtrankhanh's #11162, moved here to a separate PR Co-authored-by: Huỳnh Trần Khanh <qcdz9r6wpcbh59@gmail.com>
1 parent 609eb59 commit be22d07

File tree

1 file changed

+84
-18
lines changed

1 file changed

+84
-18
lines changed

src/data/sym/basic.lean

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ symmetric powers
2828
2929
-/
3030

31-
universes u
31+
open function
3232

3333
/--
3434
The nth symmetric power is n-tuples up to permutation. We define it
3535
as a subtype of `multiset` since these are well developed in the
3636
library. We also give a definition `sym.sym'` in terms of vectors, and we
3737
show these are equivalent in `sym.sym_equiv_sym'`.
3838
-/
39-
def sym (α : Type u) (n : ℕ) := {s : multiset α // s.card = n}
39+
def sym (α : Type*) (n : ℕ) := {s : multiset α // s.card = n}
4040

4141
instance sym.has_coe (α : Type*) (n : ℕ) : has_coe (sym α n) (multiset α) := coe_subtype
4242

@@ -46,14 +46,25 @@ This is the `list.perm` setoid lifted to `vector`.
4646
See note [reducible non-instances].
4747
-/
4848
@[reducible]
49-
def vector.perm.is_setoid (α : Type u) (n : ℕ) : setoid (vector α n) :=
49+
def vector.perm.is_setoid (α : Type*) (n : ℕ) : setoid (vector α n) :=
5050
(list.is_setoid α).comap subtype.val
5151

5252
local attribute [instance] vector.perm.is_setoid
5353

5454
namespace sym
5555

56-
variables {α : Type u} {n : ℕ} {s : sym α n} {a b : α}
56+
variables {α β : Type*} {n : ℕ} {s : sym α n} {a b : α}
57+
58+
lemma coe_injective : injective (coe : sym α n → multiset α) := subtype.coe_injective
59+
60+
@[simp, norm_cast] lemma coe_inj {s₁ s₂ : sym α n} : (s₁ : multiset α) = s₂ ↔ s₁ = s₂ :=
61+
coe_injective.eq_iff
62+
63+
/--
64+
Construct an element of the `n`th symmetric power from a multiset of cardinality `n`.
65+
-/
66+
@[simps, pattern]
67+
abbreviation mk (m : multiset α) (h : m.card = n) : sym α n := ⟨m, h⟩
5768

5869
/--
5970
The unique element in `sym α 0`.
@@ -63,7 +74,7 @@ The unique element in `sym α 0`.
6374
/--
6475
Inserts an element into the term of `sym α n`, increasing the length by one.
6576
-/
66-
@[pattern] def cons (a : α) (s : sym α n) : sym α (nat.succ n) :=
77+
@[pattern] def cons (a : α) (s : sym α n) : sym α n.succ :=
6778
⟨a ::ₘ s.1, by rw [multiset.card_cons, s.2]⟩
6879

6980
notation a :: b := cons a b
@@ -79,6 +90,8 @@ subtype.ext_iff.trans $ multiset.cons_inj_left _
7990
lemma cons_swap (a b : α) (s : sym α n) : a :: b :: s = b :: a :: s :=
8091
subtype.ext $ multiset.cons_swap a b s.1
8192

93+
lemma coe_cons (s : sym α n) (a : α) : (a :: s : multiset α) = a ::ₘ s := rfl
94+
8295
/--
8396
This is the quotient map that takes a list of n elements as an n-tuple and produces an nth
8497
symmetric power.
@@ -99,6 +112,9 @@ instance : has_mem α (sym α n) := ⟨λ a s, a ∈ s.1⟩
99112
instance decidable_mem [decidable_eq α] (a : α) (s : sym α n) : decidable (a ∈ s) :=
100113
s.1.decidable_mem _
101114

115+
@[simp]
116+
lemma mem_mk (a : α) (s : multiset α) (h : s.card = n) : a ∈ mk s h ↔ a ∈ s := iff.rfl
117+
102118
@[simp] lemma mem_cons {a b : α} {s : sym α n} : a ∈ b :: s ↔ a = b ∨ a ∈ s :=
103119
multiset.mem_cons
104120

@@ -119,29 +135,40 @@ subtype.ext $ quotient.sound h
119135
def erase [decidable_eq α] (s : sym α (n + 1)) (a : α) (h : a ∈ s) : sym α n :=
120136
⟨s.val.erase a, (multiset.card_erase_of_mem h).trans $ s.property.symm ▸ n.pred_succ⟩
121137

122-
@[simp] lemma cons_erase [decidable_eq α] (s : sym α (n + 1)) (a : α) (h : a ∈ s) :
123-
a :: s.erase a h = s := subtype.ext $ multiset.cons_erase h
138+
@[simp] lemma erase_mk [decidable_eq α] (m : multiset α) (hc : m.card = n + 1) (a : α) (h : a ∈ m) :
139+
(mk m hc).erase a h = mk (m.erase a) (by { rw [multiset.card_erase_of_mem h, hc], refl }) := rfl
140+
141+
@[simp] lemma coe_erase [decidable_eq α] {s : sym α n.succ} {a : α} (h : a ∈ s) :
142+
(s.erase a h : multiset α) = multiset.erase s a := rfl
143+
144+
@[simp] lemma cons_erase [decidable_eq α] {s : sym α n.succ} {a : α} (h : a ∈ s) :
145+
a :: s.erase a h = s :=
146+
coe_injective $ multiset.cons_erase h
147+
148+
@[simp] lemma erase_cons_head [decidable_eq α] (s : sym α n) (a : α)
149+
(h : a ∈ a :: s := mem_cons_self a s) : (a :: s).erase a h = s :=
150+
coe_injective $ multiset.erase_cons_head a s.1
124151

125152
/--
126153
Another definition of the nth symmetric power, using vectors modulo permutations. (See `sym`.)
127154
-/
128-
def sym' (α : Type u) (n : ℕ) := quotient (vector.perm.is_setoid α n)
155+
def sym' (α : Type*) (n : ℕ) := quotient (vector.perm.is_setoid α n)
129156

130157
/--
131158
This is `cons` but for the alternative `sym'` definition.
132159
-/
133-
def cons' {α : Type u} {n : ℕ} : α → sym' α n → sym' α (nat.succ n) :=
160+
def cons' {α : Type*} {n : ℕ} : α → sym' α n → sym' α (nat.succ n) :=
134161
λ a, quotient.map (vector.cons a) (λ ⟨l₁, h₁⟩ ⟨l₂, h₂⟩ h, list.perm.cons _ h)
135162

136163
notation a :: b := cons' a b
137164

138165
/--
139166
Multisets of cardinality n are equivalent to length-n vectors up to permutations.
140167
-/
141-
def sym_equiv_sym' {α : Type u} {n : ℕ} : sym α n ≃ sym' α n :=
168+
def sym_equiv_sym' {α : Type*} {n : ℕ} : sym α n ≃ sym' α n :=
142169
equiv.subtype_quotient_equiv_quotient_subtype _ _ (λ _, by refl) (λ _ _, by refl)
143170

144-
lemma cons_equiv_eq_equiv_cons (α : Type u) (n : ℕ) (a : α) (s : sym α n) :
171+
lemma cons_equiv_eq_equiv_cons (α : Type*) (n : ℕ) (a : α) (s : sym α n) :
145172
a :: sym_equiv_sym' s = sym_equiv_sym' (a :: s) :=
146173
by { rcases s with ⟨⟨l⟩, _⟩, refl, }
147174

@@ -177,7 +204,7 @@ lemma exists_eq_cons_of_succ (s : sym α n.succ) : ∃ (a : α) (s' : sym α n),
177204
begin
178205
obtain ⟨a, ha⟩ := exists_mem s,
179206
classical,
180-
exact ⟨a, s.erase a ha, (s.cons_erase _ _).symm⟩,
207+
exact ⟨a, s.erase a ha, (cons_erase ha).symm⟩,
181208
end
182209

183210
lemma eq_repeat {a : α} {n : ℕ} {s : sym α n} : s = repeat a n ↔ ∀ b ∈ s, b = a :=
@@ -217,33 +244,72 @@ instance (n : ℕ) [nontrivial α] : nontrivial (sym α (n + 1)) :=
217244

218245
/-- A function `α → β` induces a function `sym α n → sym β n` by applying it to every element of
219246
the underlying `n`-tuple. -/
220-
def map {α β : Type*} {n : ℕ} (f : α → β) (x : sym α n) : sym β n :=
247+
def map {n : ℕ} (f : α → β) (x : sym α n) : sym β n :=
221248
⟨x.val.map f, by simpa [multiset.card_map] using x.property⟩
222249

223-
@[simp] lemma mem_map {α β : Type*} {n : ℕ} {f : α → β} {b : β} {l : sym α n} :
250+
@[simp] lemma mem_map {n : ℕ} {f : α → β} {b : β} {l : sym α n} :
224251
b ∈ sym.map f l ↔ ∃ a, a ∈ l ∧ f a = b := multiset.mem_map
225252

226-
@[simp] lemma map_id {α : Type*} {n : ℕ} (s : sym α n) : sym.map id s = s :=
253+
/-- Note: `sym.map_id` is not simp-normal, as simp ends up unfolding `id` with `sym.map_congr` -/
254+
@[simp] lemma map_id' {α : Type*} {n : ℕ} (s : sym α n) : sym.map (λ (x : α), x) s = s :=
255+
by simp [sym.map]
256+
257+
lemma map_id {α : Type*} {n : ℕ} (s : sym α n) : sym.map id s = s :=
227258
by simp [sym.map]
228259

229260
@[simp] lemma map_map {α β γ : Type*} {n : ℕ} (g : β → γ) (f : α → β) (s : sym α n) :
230261
sym.map g (sym.map f s) = sym.map (g ∘ f) s :=
231262
by simp [sym.map]
232263

233-
@[simp] lemma map_zero {α β : Type*} (f : α → β) :
264+
@[simp] lemma map_zero (f : α → β) :
234265
sym.map f (0 : sym α 0) = (0 : sym β 0) := rfl
235266

236-
@[simp] lemma map_cons {α β : Type*} {n : ℕ} (f : α → β) (a : α) (s : sym α n) :
267+
@[simp] lemma map_cons {n : ℕ} (f : α → β) (a : α) (s : sym α n) :
237268
(a :: s).map f = (f a) :: s.map f :=
238269
by simp [map, cons]
239270

271+
@[congr] lemma map_congr {f g : α → β} {s : sym α n} (h : ∀ x ∈ s, f x = g x) :
272+
map f s = map g s := subtype.ext $ multiset.map_congr rfl h
273+
274+
@[simp] lemma map_mk {f : α → β} {m : multiset α} {hc : m.card = n} :
275+
map f (mk m hc) = mk (m.map f) (by simp [hc]) := rfl
276+
277+
@[simp] lemma coe_map (s : sym α n) (f : α → β) : ↑(s.map f) = multiset.map f s := rfl
278+
279+
lemma map_injective {f : α → β} (hf : injective f) (n : ℕ) :
280+
injective (map f : sym α n → sym β n) :=
281+
λ s t h, coe_injective $ multiset.map_injective hf $ coe_inj.2 h
282+
240283
/-- Mapping an equivalence `α ≃ β` using `sym.map` gives an equivalence between `sym α n` and
241284
`sym β n`. -/
242285
@[simps]
243-
def equiv_congr {β : Type u} (e : α ≃ β) : sym α n ≃ sym β n :=
286+
def equiv_congr (e : α ≃ β) : sym α n ≃ sym β n :=
244287
{ to_fun := map e,
245288
inv_fun := map e.symm,
246289
left_inv := λ x, by rw [map_map, equiv.symm_comp_self, map_id],
247290
right_inv := λ x, by rw [map_map, equiv.self_comp_symm, map_id] }
248291

292+
/-- "Attach" a proof that `a ∈ s` to each element `a` in `s` to produce
293+
an element of the symmetric power on `{x // x ∈ s}`. -/
294+
def attach (s : sym α n) : sym {x // x ∈ s} n := ⟨s.val.attach, by rw [multiset.card_attach, s.2]⟩
295+
296+
@[simp] lemma attach_mk {m : multiset α} {hc : m.card = n} :
297+
attach (mk m hc) = mk m.attach (multiset.card_attach.trans hc) := rfl
298+
299+
@[simp] lemma coe_attach (s : sym α n) : (s.attach : multiset {a // a ∈ s}) = multiset.attach s :=
300+
rfl
301+
302+
lemma attach_map_coe (s : sym α n) : s.attach.map coe = s :=
303+
coe_injective $ multiset.attach_map_val _
304+
305+
@[simp] lemma mem_attach (s : sym α n) (x : {x // x ∈ s}) : x ∈ s.attach :=
306+
multiset.mem_attach _ _
307+
308+
@[simp] lemma attach_nil : (nil : sym α 0).attach = nil := rfl
309+
310+
@[simp] lemma attach_cons (x : α) (s : sym α n) :
311+
(cons x s).attach = cons ⟨x, mem_cons_self _ _⟩ (s.attach.map (λ x, ⟨x, mem_cons_of_mem x.prop⟩))
312+
:=
313+
coe_injective $ multiset.attach_cons _ _
314+
249315
end sym

0 commit comments

Comments
 (0)