data.list.perm
⟷
Mathlib.Data.List.Perm
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(last sync)
attach
and filter
lemmas (#18087)
Left commutativity and cardinality of list.filter
/multiset.filter
/finset.filter
. Interaction of count
/countp
and attach
.
@@ -396,7 +396,7 @@ theorem subperm.countp_le (p : α → Prop) [decidable_pred p]
| ⟨l, p', s⟩ := p'.countp_eq p ▸ s.countp_le p
theorem perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [decidable_pred p] [decidable_pred p']
- (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
+ (hp : ∀ x ∈ l₁, p x ↔ p' x) : l₁.countp p = l₂.countp p' :=
begin
rw ← s.countp_eq p',
clear s,
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
list.replicate
with Mathlib 4 (#18181)
Sync arguments order and golfs with leanprover-community/mathlib4#1579
@@ -150,21 +150,21 @@ theorem perm_cons_append_cons {l l₁ l₂ : list α} (a : α) (p : l ~ l₁++l
a::l ~ l₁++(a::l₂) :=
(p.cons a).trans perm_middle.symm
-@[simp] theorem perm_replicate {a : α} {n : ℕ} {l : list α} :
+@[simp] theorem perm_replicate {n : ℕ} {a : α} {l : list α} :
l ~ replicate n a ↔ l = replicate n a :=
⟨λ p, eq_replicate.2
⟨p.length_eq.trans $ length_replicate _ _, λ b m, eq_of_mem_replicate $ p.subset m⟩,
λ h, h ▸ perm.refl _⟩
-@[simp] theorem replicate_perm {a : α} {n : ℕ} {l : list α} :
+@[simp] theorem replicate_perm {n : ℕ} {a : α} {l : list α} :
replicate n a ~ l ↔ replicate n a = l :=
(perm_comm.trans perm_replicate).trans eq_comm
@[simp] theorem perm_singleton {a : α} {l : list α} : l ~ [a] ↔ l = [a] :=
-@perm_replicate α a 1 l
+@perm_replicate α 1 a l
@[simp] theorem singleton_perm {a : α} {l : list α} : [a] ~ l ↔ [a] = l :=
-@replicate_perm α a 1 l
+@replicate_perm α 1 a l
alias perm_singleton ↔ perm.eq_singleton _
alias singleton_perm ↔ perm.singleton_eq _
(no changes)
(no changes)
list.replicate
and migrate to it (#18127)
This definition differs from list.repeat
by the order of arguments. The new order is in sync with the Lean 4 version.
@@ -150,26 +150,24 @@ theorem perm_cons_append_cons {l l₁ l₂ : list α} (a : α) (p : l ~ l₁++l
a::l ~ l₁++(a::l₂) :=
(p.cons a).trans perm_middle.symm
-@[simp] theorem perm_repeat {a : α} {n : ℕ} {l : list α} : l ~ repeat a n ↔ l = repeat a n :=
-⟨λ p, (eq_repeat.2
- ⟨p.length_eq.trans $ length_repeat _ _,
- λ b m, eq_of_mem_repeat $ p.subset m⟩),
- λ h, h ▸ perm.refl _⟩
+@[simp] theorem perm_replicate {a : α} {n : ℕ} {l : list α} :
+ l ~ replicate n a ↔ l = replicate n a :=
+⟨λ p, eq_replicate.2
+ ⟨p.length_eq.trans $ length_replicate _ _, λ b m, eq_of_mem_replicate $ p.subset m⟩,
+ λ h, h ▸ perm.refl _⟩
-@[simp] theorem repeat_perm {a : α} {n : ℕ} {l : list α} : repeat a n ~ l ↔ repeat a n = l :=
-(perm_comm.trans perm_repeat).trans eq_comm
+@[simp] theorem replicate_perm {a : α} {n : ℕ} {l : list α} :
+ replicate n a ~ l ↔ replicate n a = l :=
+(perm_comm.trans perm_replicate).trans eq_comm
@[simp] theorem perm_singleton {a : α} {l : list α} : l ~ [a] ↔ l = [a] :=
-@perm_repeat α a 1 l
+@perm_replicate α a 1 l
@[simp] theorem singleton_perm {a : α} {l : list α} : [a] ~ l ↔ [a] = l :=
-@repeat_perm α a 1 l
+@replicate_perm α a 1 l
-theorem perm.eq_singleton {a : α} {l : list α} (p : l ~ [a]) : l = [a] :=
-perm_singleton.1 p
-
-theorem perm.singleton_eq {a : α} {l : list α} (p : [a] ~ l) : [a] = l :=
-p.symm.eq_singleton.symm
+alias perm_singleton ↔ perm.eq_singleton _
+alias singleton_perm ↔ perm.singleton_eq _
theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b :=
by simp
@@ -736,12 +734,12 @@ theorem perm_iff_count {l₁ l₂ : list α} : l₁ ~ l₂ ↔ ∀ a, count a l
by_cases b = a; simp [h] at H ⊢; assumption }
end⟩
-theorem perm_repeat_append_repeat {l : list α} {a b : α} {m n : ℕ} (h : a ≠ b) :
- l ~ repeat a m ++ repeat b n ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] :=
+theorem perm_replicate_append_replicate {l : list α} {a b : α} {m n : ℕ} (h : a ≠ b) :
+ l ~ replicate m a ++ replicate n b ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] :=
begin
rw [perm_iff_count, ← decidable.and_forall_ne a, ← decidable.and_forall_ne b],
suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l,
- { simp [count_repeat, h, h.symm, this] { contextual := tt } },
+ { simp [count_replicate, h, h.symm, this] { contextual := tt } },
simp_rw [ne.def, ← and_imp, ← not_or_distrib, decidable.not_imp_not, subset_def, mem_cons_iff,
not_mem_nil, or_false, or_comm],
end
(no changes)
(no changes)
(no changes)
(no changes)
Also add some supporting lemmas.
@@ -79,6 +79,12 @@ theorem perm.subset {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ :=
theorem perm.mem_iff {a : α} {l₁ l₂ : list α} (h : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
iff.intro (λ m, h.subset m) (λ m, h.symm.subset m)
+lemma perm.subset_congr_left {l₁ l₂ l₃ : list α} (h : l₁ ~ l₂) : l₁ ⊆ l₃ ↔ l₂ ⊆ l₃ :=
+⟨h.symm.subset.trans, h.subset.trans⟩
+
+lemma perm.subset_congr_right {l₁ l₂ l₃ : list α} (h : l₁ ~ l₂) : l₃ ⊆ l₁ ↔ l₃ ⊆ l₂ :=
+⟨λ h', h'.trans h.subset, λ h', h'.trans h.symm.subset⟩
+
theorem perm.append_right {l₁ l₂ : list α} (t₁ : list α) (p : l₁ ~ l₂) : l₁++t₁ ~ l₂++t₁ :=
perm.rec_on p
(perm.refl ([] ++ t₁))
@@ -730,6 +736,16 @@ theorem perm_iff_count {l₁ l₂ : list α} : l₁ ~ l₂ ↔ ∀ a, count a l
by_cases b = a; simp [h] at H ⊢; assumption }
end⟩
+theorem perm_repeat_append_repeat {l : list α} {a b : α} {m n : ℕ} (h : a ≠ b) :
+ l ~ repeat a m ++ repeat b n ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] :=
+begin
+ rw [perm_iff_count, ← decidable.and_forall_ne a, ← decidable.and_forall_ne b],
+ suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l,
+ { simp [count_repeat, h, h.symm, this] { contextual := tt } },
+ simp_rw [ne.def, ← and_imp, ← not_or_distrib, decidable.not_imp_not, subset_def, mem_cons_iff,
+ not_mem_nil, or_false, or_comm],
+end
+
lemma subperm.cons_right {α : Type*} {l l' : list α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
h.trans (sublist_cons x l').subperm
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(first ported)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -1055,7 +1055,7 @@ theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h
suffices l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l by
simp (config := { contextual := true }) [count_replicate, h, h.symm, this]
simp_rw [Ne.def, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons_iff,
- not_mem_nil, or_false_iff, or_comm']
+ not_mem_nil, or_false_iff, or_comm]
#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -343,7 +343,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
#align list.filter_append_perm List.filter_append_perm
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (l₁' list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
@@ -458,7 +458,7 @@ end Rel
section Subperm
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (l list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (l list.perm l₁) -/
#print List.Subperm /-
/-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
@@ -1519,7 +1519,7 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
#align list.length_permutations List.length_permutations
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
#print List.mem_permutations_of_perm_lemma /-
theorem mem_permutations_of_perm_lemma {is l : List α}
(H : l ~ [] ++ is → (∃ (ts' : _) (_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
@@ -1527,7 +1527,7 @@ theorem mem_permutations_of_perm_lemma {is l : List α}
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (is' list.perm is) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:642:2: warning: expanding binder collection (is' list.perm is) -/
#print List.mem_permutationsAux_of_perm /-
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -440,7 +440,7 @@ theorem rel_perm_imp (hr : RightUnique r) : (Forall₂ r ⇒ Forall₂ r ⇒ Imp
fun a b h₁ c d h₂ h =>
have : (flip (Forall₂ r) ∘r Perm ∘r Forall₂ r) b d := ⟨a, h₁, c, h, h₂⟩
have : ((flip (Forall₂ r) ∘r Forall₂ r) ∘r Perm) b d := by
- rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← Relation.comp_assoc] at this
+ rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← Relation.comp_assoc] at this
let ⟨b', ⟨c', hbc, hcb⟩, hbd⟩ := this
have : b' = b := right_unique_forall₂' hr hcb hbc
this ▸ hbd
@@ -587,7 +587,7 @@ theorem Perm.countP_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred
clear s
induction' l₁ with y s hs
· rfl
- · simp only [mem_cons_iff, forall_eq_or_imp] at hp
+ · simp only [mem_cons_iff, forall_eq_or_imp] at hp
simp only [countp_cons, hs hp.2, hp.1]
#align list.perm.countp_congr List.Perm.countP_congr
-/
@@ -721,13 +721,13 @@ theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} :
fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => _ <;>
intro l₁ l₂ r₁ r₂ e₁ e₂
· apply (not_mem_nil a).elim; rw [← e₁]; simp
- · cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
+ · cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
· substs t₁ t₂; exact p
· substs z t₁ t₂; exact p.trans perm_middle
· substs y t₁ t₂; exact perm_middle.symm.trans p
· substs z t₁ t₂; exact (IH rfl rfl).cons y
· rcases l₁ with (_ | ⟨y, _ | ⟨z, l₁⟩⟩) <;> rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩) <;>
- dsimp at e₁ e₂ <;> injections <;> substs x y
+ dsimp at e₁ e₂ <;> injections <;> substs x y
· substs r₁ r₂; exact p.cons a
· substs r₁ r₂; exact p.cons u
· substs r₁ v t₂; exact (p.trans perm_middle).cons u
@@ -805,7 +805,7 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
induction s generalizing l₁
case slnil => cases h₂
case cons r₁ r₂ b s' ih =>
- simp at h₂
+ simp at h₂
cases' h₂ with e m
· subst b; exact ⟨a :: r₁, p.cons a, s'.cons2 _ _ _⟩
· rcases ih m d₁ h₁ p with ⟨t, p', s'⟩; exact ⟨t, p', s'.cons _ _ _⟩
@@ -862,7 +862,7 @@ protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~
induction' d with a l₁' h d IH
· exact ⟨nil, perm.nil, nil_sublist _⟩
· cases' forall_mem_cons.1 H with H₁ H₂
- simp at h
+ simp at h
exact cons_subperm_of_mem d h H₁ (IH H₂)
#align list.nodup.subperm List.Nodup.subperm
-/
@@ -881,12 +881,12 @@ theorem Nodup.perm_iff_eq_of_sublist {l₁ l₂ l : List α} (d : Nodup l) (s₁
⟨fun h => by
induction' s₂ with l₂ l a s₂ IH l₂ l a s₂ IH generalizing l₁
· exact h.eq_nil
- · simp at d
+ · simp at d
cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
· exact IH d.2 s₁ h
· apply d.1.elim
exact subperm.subset ⟨_, h.symm, s₂⟩ (mem_cons_self _ _)
- · simp at d
+ · simp at d
cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
· apply d.1.elim
exact subperm.subset ⟨_, h, s₁⟩ (mem_cons_self _ _)
@@ -1038,11 +1038,11 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
⟨Perm.count_eq, fun H => by
induction' l₁ with a l₁ IH generalizing l₂
· cases' l₂ with b l₂; · rfl
- specialize H b; simp at H ; contradiction
+ specialize H b; simp at H; contradiction
· have : a ∈ l₂ := count_pos.1 (by rw [← H] <;> simp <;> apply Nat.succ_pos)
refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
specialize H b
- rw [(perm_cons_erase this).count_eq] at H
+ rw [(perm_cons_erase this).count_eq] at H
by_cases b = a <;> simp [h] at H ⊢ <;> assumption⟩
#align list.perm_iff_count List.perm_iff_count
-/
@@ -1080,7 +1080,7 @@ theorem subperm_append_diff_self_of_count_le {l₁ l₂ : List α}
rw [cons_append, diff_cons, perm_cons]
refine' IH fun x hx => _
specialize h x (mem_cons_of_mem _ hx)
- rw [perm_iff_count.mp this] at h
+ rw [perm_iff_count.mp this] at h
by_cases hx : x = hd
· subst hd
simpa [Nat.succ_le_succ_iff] using h
@@ -1110,7 +1110,7 @@ instance decidableSubperm : DecidableRel ((· <+~ ·) : List α → List α →
#print List.singleton_subperm_iff /-
@[simp]
theorem singleton_subperm_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈ l :=
- ⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h , fun h =>
+ ⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h, fun h =>
⟨[a], Perm.refl _, singleton_sublist.mpr h⟩⟩
#align list.subperm_singleton_iff List.singleton_subperm_iff
-/
@@ -1357,7 +1357,7 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
lookmap f l₁ ~ lookmap f l₂ :=
by
let F a b := ∀ c ∈ f a, ∀ d ∈ f b, a = b ∧ c = d
- change Pairwise F l₁ at H
+ change Pairwise F l₁ at H
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂; · simp
· cases h : f a
· simp [h]; exact IH (pairwise_cons.1 H).2
@@ -1379,7 +1379,7 @@ theorem Perm.eraseP (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
(H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ :=
by
let F a b := f a → f b → False
- change Pairwise F l₁ at H
+ change Pairwise F l₁ at H
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂; · simp
· by_cases h : f a
· simp [h, p]
@@ -1479,12 +1479,12 @@ theorem perm_of_mem_permutationsAux :
by
refine' permutations_aux.rec (by simp) _
introv IH1 IH2 m
- rw [permutations_aux_cons, permutations, mem_foldr_permutations_aux2] at m
+ rw [permutations_aux_cons, permutations, mem_foldr_permutations_aux2] at m
rcases m with (m | ⟨l₁, l₂, m, _, e⟩)
· exact (IH1 m).trans perm_middle
· subst e
have p : l₁ ++ l₂ ~ is := by
- simp [permutations] at m
+ simp [permutations] at m
cases' m with e m; · simp [e]
exact is.append_nil ▸ IH2 m
exact ((perm_middle.trans (p.cons _)).append_right _).trans (perm_append_comm.cons _)
@@ -1505,7 +1505,7 @@ theorem length_permutationsAux :
refine' permutations_aux.rec (by simp) _
intro t ts is IH1 IH2
have IH2 : length (permutations_aux is nil) + 1 = is.length ! := by simpa using IH2
- simp [-add_comm, Nat.factorial, Nat.add_succ, mul_comm] at IH1
+ simp [-add_comm, Nat.factorial, Nat.add_succ, mul_comm] at IH1
rw [permutations_aux_cons,
length_foldr_permutations_aux2' _ _ _ _ _ fun l m => (perm_of_mem_permutations m).length_eq,
permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, mul_comm (Nat.succ _), ←
@@ -1598,7 +1598,7 @@ theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.pe
obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
induction' n with n IH generalizing ts; · cases h
refine' List.reverseRecOn ts (fun h => _) (fun ts t _ h => _) h; · simp [permutations]
- rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
+ rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
simp only [permutations_append, foldr_permutations_aux2, permutations_aux_nil,
permutations_aux_cons, append_nil]
@@ -1647,7 +1647,7 @@ theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
(permutations'Aux x s).nthLe n hn = s.insertNth n x :=
by
induction' s with y s IH generalizing n
- · simp only [length, permutations'_aux, Nat.lt_one_iff] at hn
+ · simp only [length, permutations'_aux, Nat.lt_one_iff] at hn
simp [hn]
· cases n
· simp
@@ -1711,7 +1711,7 @@ theorem nodup_permutations'Aux_of_not_mem (s : List α) (x : α) (hx : x ∉ s)
Nodup (permutations'Aux x s) := by
induction' s with y s IH
· simp
- · simp only [not_or, mem_cons_iff] at hx
+ · simp only [not_or, mem_cons_iff] at hx
simp only [not_and, exists_eq_right_right, mem_map, permutations'_aux, nodup_cons]
refine' ⟨fun _ => Ne.symm hx.left, _⟩
rw [nodup_map_iff]
@@ -1726,7 +1726,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
refine' ⟨fun h => _, nodup_permutations'_aux_of_not_mem _ _⟩
intro H
obtain ⟨k, hk, hk'⟩ := nth_le_of_mem H
- rw [nodup_iff_nth_le_inj] at h
+ rw [nodup_iff_nth_le_inj] at h
suffices k = k + 1 by simpa using this
refine' h k (k + 1) _ _ _
· simpa [Nat.lt_succ_iff] using hk.le
@@ -1748,7 +1748,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
convert nth_le_insert_nth_add_succ _ _ _ 0 _
simpa using hk
· obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt H'
- rw [length_insert_nth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn
+ rw [length_insert_nth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn
rw [nth_le_insert_nth_add_succ]
convert nth_le_insert_nth_add_succ s x k m.succ _ using 2
· simp [Nat.add_succ, Nat.succ_add]
@@ -1768,7 +1768,7 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :
rw [nodup_bind]
constructor
· intro ys hy
- rw [mem_permutations'] at hy
+ rw [mem_permutations'] at hy
rw [nodup_permutations'_aux_iff, hy.mem_iff]
exact fun H => h x H rfl
· refine' IH.pairwise_of_forall_ne fun as ha bs hb H => _
@@ -1776,10 +1776,10 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :
rintro a ha' b hb' rfl
obtain ⟨n, hn, hn'⟩ := nth_le_of_mem ha'
obtain ⟨m, hm, hm'⟩ := nth_le_of_mem hb'
- rw [mem_permutations'] at ha hb
+ rw [mem_permutations'] at ha hb
have hl : as.length = bs.length := (ha.trans hb.symm).length_eq
- simp only [Nat.lt_succ_iff, length_permutations'_aux] at hn hm
- rw [nth_le_permutations'_aux] at hn' hm'
+ simp only [Nat.lt_succ_iff, length_permutations'_aux] at hn hm
+ rw [nth_le_permutations'_aux] at hn' hm'
have hx :
nth_le (insert_nth n x as) m (by rwa [length_insert_nth _ _ hn, Nat.lt_succ_iff, hl]) = x :=
by simp [hn', ← hm', hm]
@@ -1791,8 +1791,8 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :
· suffices x ∈ bs by exact h x (hb.subset this) rfl
rw [← hx', nth_le_insert_nth_of_lt _ _ _ _ ht (ht.trans_le hm)]
exact nth_le_mem _ _ _
- · simp only [ht] at hm' hn'
- rw [← hm'] at hn'
+ · simp only [ht] at hm' hn'
+ rw [← hm'] at hn'
exact H (insert_nth_injective _ _ hn')
· suffices x ∈ as by exact h x (ha.subset this) rfl
rw [← hx, nth_le_insert_nth_of_lt _ _ _ _ ht (ht.trans_le hn)]
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -659,7 +659,7 @@ theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l
section
-variable {op : α → α → α} [IsAssociative α op] [IsCommutative α op]
+variable {op : α → α → α} [Std.Associative α op] [Std.Commutative α op]
local notation a " * " b => op a b
@@ -667,7 +667,7 @@ local notation l " <*> " a => foldl op a l
#print List.Perm.fold_op_eq /-
theorem Perm.fold_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : (l₁ <*> a) = l₂ <*> a :=
- h.foldl_eq (right_comm _ IsCommutative.comm IsAssociative.assoc) _
+ h.foldl_eq (right_comm _ Std.Commutative.comm Std.Associative.assoc) _
#align list.perm.fold_op_eq List.Perm.fold_op_eq
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -1664,7 +1664,7 @@ theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
· rw [permutations'_aux, count_cons_self]
by_cases hx : x = y
· subst hx
- simpa [take_while, Nat.succ_inj'] using IH _
+ simpa [take_while, Nat.succ_inj] using IH _
· rw [take_while]
rw [if_neg hx]
cases' permutations'_aux x l with a as
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -278,14 +278,16 @@ theorem perm_cons_erase [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) :
#align list.perm_cons_erase List.perm_cons_erase
-/
+#print List.Perm.recOnSwap' /-
@[elab_as_elim]
-theorem perm_induction_on {P : List α → List α → Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂) (h₁ : P [] [])
- (h₂ : ∀ x l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (x :: l₁) (x :: l₂))
+theorem List.Perm.recOnSwap' {P : List α → List α → Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂)
+ (h₁ : P [] []) (h₂ : ∀ x l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (x :: l₁) (x :: l₂))
(h₃ : ∀ x y l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (y :: x :: l₁) (x :: y :: l₂))
(h₄ : ∀ l₁ l₂ l₃, l₁ ~ l₂ → l₂ ~ l₃ → P l₁ l₂ → P l₂ l₃ → P l₁ l₃) : P l₁ l₂ :=
have P_refl : ∀ l, P l l := fun l => List.recOn l h₁ fun x xs ih => h₂ x xs xs (Perm.refl xs) ih
Perm.rec_on p h₁ h₂ (fun x y l => h₃ x y l l (Perm.refl l) (P_refl l)) h₄
-#align list.perm_induction_on List.perm_induction_onₓ
+#align list.perm_induction_on List.Perm.recOnSwap'
+-/
#print List.Perm.filterMap /-
@[congr]
@@ -614,7 +616,7 @@ theorem Subperm.count_le [DecidableEq α] {l₁ l₂ : List α} (s : l₁ <+~ l
#print List.Perm.foldl_eq' /-
theorem Perm.foldl_eq' {f : β → α → β} {l₁ l₂ : List α} (p : l₁ ~ l₂) :
(∀ x ∈ l₁, ∀ y ∈ l₁, ∀ (z), f (f z x) y = f (f z y) x) → ∀ b, foldl f b l₁ = foldl f b l₂ :=
- perm_induction_on p (fun H b => rfl)
+ List.Perm.recOnSwap' p (fun H b => rfl)
(fun x t₁ t₂ p r H b => r (fun x hx y hy => H _ (Or.inr hx) _ (Or.inr hy)) _)
(fun x y t₁ t₂ p r H b => by
simp only [foldl]
@@ -635,7 +637,7 @@ theorem Perm.foldl_eq {f : β → α → β} {l₁ l₂ : List α} (rcomm : Righ
#print List.Perm.foldr_eq /-
theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : LeftCommutative f) (p : l₁ ~ l₂) :
∀ b, foldr f b l₁ = foldr f b l₂ :=
- perm_induction_on p (fun b => rfl) (fun x t₁ t₂ p r b => by simp <;> rw [r b])
+ List.Perm.recOnSwap' p (fun b => rfl) (fun x t₁ t₂ p r b => by simp <;> rw [r b])
(fun x y t₁ t₂ p r b => by simp <;> rw [lcomm, r b]) fun t₁ t₂ t₃ p₁ p₂ r₁ r₂ a =>
Eq.trans (r₁ a) (r₂ a)
#align list.perm.foldr_eq List.Perm.foldr_eq
@@ -865,17 +867,17 @@ protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~
#align list.nodup.subperm List.Nodup.subperm
-/
-#print List.perm_ext /-
-theorem perm_ext {l₁ l₂ : List α} (d₁ : Nodup l₁) (d₂ : Nodup l₂) :
+#print List.perm_ext_iff_of_nodup /-
+theorem perm_ext_iff_of_nodup {l₁ l₂ : List α} (d₁ : Nodup l₁) (d₂ : Nodup l₂) :
l₁ ~ l₂ ↔ ∀ a, a ∈ l₁ ↔ a ∈ l₂ :=
⟨fun p a => p.mem_iff, fun H =>
(d₁.Subperm fun a => (H a).1).antisymm <| d₂.Subperm fun a => (H a).2⟩
-#align list.perm_ext List.perm_ext
+#align list.perm_ext List.perm_ext_iff_of_nodup
-/
-#print List.Nodup.sublist_ext /-
-theorem Nodup.sublist_ext {l₁ l₂ l : List α} (d : Nodup l) (s₁ : l₁ <+ l) (s₂ : l₂ <+ l) :
- l₁ ~ l₂ ↔ l₁ = l₂ :=
+#print List.Nodup.perm_iff_eq_of_sublist /-
+theorem Nodup.perm_iff_eq_of_sublist {l₁ l₂ l : List α} (d : Nodup l) (s₁ : l₁ <+ l)
+ (s₂ : l₂ <+ l) : l₁ ~ l₂ ↔ l₁ = l₂ :=
⟨fun h => by
induction' s₂ with l₂ l a s₂ IH l₂ l a s₂ IH generalizing l₁
· exact h.eq_nil
@@ -889,7 +891,7 @@ theorem Nodup.sublist_ext {l₁ l₂ l : List α} (d : Nodup l) (s₁ : l₁ <+
· apply d.1.elim
exact subperm.subset ⟨_, h, s₁⟩ (mem_cons_self _ _)
· rw [IH d.2 s₁ h.cons_inv], fun h => by rw [h]⟩
-#align list.nodup.sublist_ext List.Nodup.sublist_ext
+#align list.nodup.sublist_ext List.Nodup.perm_iff_eq_of_sublist
-/
section
@@ -1372,8 +1374,8 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
#align list.perm_lookmap List.perm_lookmap
-/
-#print List.Perm.erasep /-
-theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
+#print List.Perm.eraseP /-
+theorem Perm.eraseP (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
(H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ :=
by
let F a b := f a → f b → False
@@ -1387,7 +1389,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
· apply swap
· refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
exact fun a b h h₁ h₂ => h h₂ h₁
-#align list.perm.erasep List.Perm.erasep
+#align list.perm.erasep List.Perm.eraseP
-/
#print List.Perm.take_inter /-
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -1105,12 +1105,12 @@ instance decidableSubperm : DecidableRel ((· <+~ ·) : List α → List α →
#align list.decidable_subperm List.decidableSubperm
-/
-#print List.subperm_singleton_iff /-
+#print List.singleton_subperm_iff /-
@[simp]
-theorem subperm_singleton_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈ l :=
+theorem singleton_subperm_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈ l :=
⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h , fun h =>
⟨[a], Perm.refl _, singleton_sublist.mpr h⟩⟩
-#align list.subperm_singleton_iff List.subperm_singleton_iff
+#align list.subperm_singleton_iff List.singleton_subperm_iff
-/
#print List.Subperm.cons_left /-
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -8,7 +8,7 @@ import Data.List.Permutation
import Data.List.Range
import Data.Nat.Factorial.Basic
-#align_import data.list.perm from "leanprover-community/mathlib"@"f2f413b9d4be3a02840d0663dace76e8fe3da053"
+#align_import data.list.perm from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83"
/-!
# List Permutations
@@ -579,7 +579,7 @@ theorem Subperm.countP_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List
#print List.Perm.countP_congr /-
theorem Perm.countP_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
- (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countP p = l₂.countP p' :=
+ (hp : ∀ x ∈ l₁, p x ↔ p' x) : l₁.countP p = l₂.countP p' :=
by
rw [← s.countp_eq p']
clear s
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,10 +3,10 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-/
-import Mathbin.Data.List.Dedup
-import Mathbin.Data.List.Permutation
-import Mathbin.Data.List.Range
-import Mathbin.Data.Nat.Factorial.Basic
+import Data.List.Dedup
+import Data.List.Permutation
+import Data.List.Range
+import Data.Nat.Factorial.Basic
#align_import data.list.perm from "leanprover-community/mathlib"@"f2f413b9d4be3a02840d0663dace76e8fe3da053"
@@ -341,7 +341,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
#align list.filter_append_perm List.filter_append_perm
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l₁' list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
@@ -456,7 +456,7 @@ end Rel
section Subperm
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (l list.perm l₁) -/
#print List.Subperm /-
/-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
@@ -1517,7 +1517,7 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
#align list.length_permutations List.length_permutations
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
#print List.mem_permutations_of_perm_lemma /-
theorem mem_permutations_of_perm_lemma {is l : List α}
(H : l ~ [] ++ is → (∃ (ts' : _) (_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
@@ -1525,7 +1525,7 @@ theorem mem_permutations_of_perm_lemma {is l : List α}
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (is' list.perm is) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:641:2: warning: expanding binder collection (is' list.perm is) -/
#print List.mem_permutationsAux_of_perm /-
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -260,10 +260,10 @@ theorem singleton_perm {a : α} {l : List α} : [a] ~ l ↔ [a] = l :=
#align list.singleton_perm List.singleton_perm
-/
-alias perm_singleton ↔ perm.eq_singleton _
+alias ⟨perm.eq_singleton, _⟩ := perm_singleton
#align list.perm.eq_singleton List.Perm.eq_singleton
-alias singleton_perm ↔ perm.singleton_eq _
+alias ⟨perm.singleton_eq, _⟩ := singleton_perm
#align list.perm.singleton_eq List.Perm.singleton_eq
#print List.singleton_perm_singleton /-
@@ -563,23 +563,23 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
-/
-#print List.Perm.countp_eq /-
-theorem Perm.countp_eq (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
- countp p l₁ = countp p l₂ := by
+#print List.Perm.countP_eq /-
+theorem Perm.countP_eq (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
+ countP p l₁ = countP p l₂ := by
rw [countp_eq_length_filter, countp_eq_length_filter] <;> exact (s.filter _).length_eq
-#align list.perm.countp_eq List.Perm.countp_eq
+#align list.perm.countp_eq List.Perm.countP_eq
-/
-#print List.Subperm.countp_le /-
-theorem Subperm.countp_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} :
- l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
- | ⟨l, p', s⟩ => p'.countp_eq p ▸ s.countp_le p
-#align list.subperm.countp_le List.Subperm.countp_le
+#print List.Subperm.countP_le /-
+theorem Subperm.countP_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} :
+ l₁ <+~ l₂ → countP p l₁ ≤ countP p l₂
+ | ⟨l, p', s⟩ => p'.countP_eq p ▸ s.countP_le p
+#align list.subperm.countp_le List.Subperm.countP_le
-/
-#print List.Perm.countp_congr /-
-theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
- (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
+#print List.Perm.countP_congr /-
+theorem Perm.countP_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
+ (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countP p = l₂.countP p' :=
by
rw [← s.countp_eq p']
clear s
@@ -587,27 +587,27 @@ theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred
· rfl
· simp only [mem_cons_iff, forall_eq_or_imp] at hp
simp only [countp_cons, hs hp.2, hp.1]
-#align list.perm.countp_congr List.Perm.countp_congr
+#align list.perm.countp_congr List.Perm.countP_congr
-/
-#print List.countp_eq_countp_filter_add /-
-theorem countp_eq_countp_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
- [DecidablePred q] : l.countp p = (l.filterₓ q).countp p + (l.filterₓ fun a => ¬q a).countp p :=
+#print List.countP_eq_countP_filter_add /-
+theorem countP_eq_countP_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
+ [DecidablePred q] : l.countP p = (l.filterₓ q).countP p + (l.filterₓ fun a => ¬q a).countP p :=
by rw [← countp_append]; exact perm.countp_eq _ (filter_append_perm _ _).symm
-#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_add
+#align list.countp_eq_countp_filter_add List.countP_eq_countP_filter_add
-/
#print List.Perm.count_eq /-
theorem Perm.count_eq [DecidableEq α] {l₁ l₂ : List α} (p : l₁ ~ l₂) (a) :
count a l₁ = count a l₂ :=
- p.countp_eq _
+ p.countP_eq _
#align list.perm.count_eq List.Perm.count_eq
-/
#print List.Subperm.count_le /-
theorem Subperm.count_le [DecidableEq α] {l₁ l₂ : List α} (s : l₁ <+~ l₂) (a) :
count a l₁ ≤ count a l₂ :=
- s.countp_le _
+ s.countP_le _
#align list.subperm.count_le List.Subperm.count_le
-/
@@ -789,7 +789,7 @@ theorem subperm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ <+~ a :: l₂
#align list.subperm_cons List.subperm_cons
-/
-alias subperm_cons ↔ subperm.of_cons subperm.cons
+alias ⟨subperm.of_cons, subperm.cons⟩ := subperm_cons
#align list.subperm.of_cons List.subperm.of_cons
#align list.subperm.cons List.subperm.cons
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,17 +2,14 @@
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-
-! This file was ported from Lean 3 source module data.list.perm
-! leanprover-community/mathlib commit f2f413b9d4be3a02840d0663dace76e8fe3da053
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Data.List.Dedup
import Mathbin.Data.List.Permutation
import Mathbin.Data.List.Range
import Mathbin.Data.Nat.Factorial.Basic
+#align_import data.list.perm from "leanprover-community/mathlib"@"f2f413b9d4be3a02840d0663dace76e8fe3da053"
+
/-!
# List Permutations
@@ -344,7 +341,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
#align list.filter_append_perm List.filter_append_perm
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (l₁' list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
@@ -459,7 +456,7 @@ end Rel
section Subperm
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (l list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l list.perm l₁) -/
#print List.Subperm /-
/-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
@@ -1520,7 +1517,7 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
#align list.length_permutations List.length_permutations
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
#print List.mem_permutations_of_perm_lemma /-
theorem mem_permutations_of_perm_lemma {is l : List α}
(H : l ~ [] ++ is → (∃ (ts' : _) (_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
@@ -1528,7 +1525,7 @@ theorem mem_permutations_of_perm_lemma {is l : List α}
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (is' list.perm is) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (is' list.perm is) -/
#print List.mem_permutationsAux_of_perm /-
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -49,7 +49,6 @@ inductive Perm : List α → List α → Prop
open Perm (symm)
--- mathport name: list.perm
infixl:50 " ~ " => Perm
#print List.Perm.refl /-
@@ -275,10 +274,12 @@ theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b := by simp
#align list.singleton_perm_singleton List.singleton_perm_singleton
-/
+#print List.perm_cons_erase /-
theorem perm_cons_erase [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : l ~ a :: l.eraseₓ a :=
let ⟨l₁, l₂, _, e₁, e₂⟩ := exists_erase_eq h
e₂.symm ▸ e₁.symm ▸ perm_middle
#align list.perm_cons_erase List.perm_cons_erase
+-/
@[elab_as_elim]
theorem perm_induction_on {P : List α → List α → Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂) (h₁ : P [] [])
@@ -322,10 +323,13 @@ theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α
#align list.perm.pmap List.Perm.pmap
-/
+#print List.Perm.filter /-
theorem Perm.filter (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
filter p l₁ ~ filter p l₂ := by rw [← filter_map_eq_filter] <;> apply s.filter_map _
#align list.perm.filter List.Perm.filter
+-/
+#print List.filter_append_perm /-
theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
filter p l ++ filter (fun x => ¬p x) l ~ l :=
by
@@ -338,6 +342,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
refine' perm.trans _ (ih.cons x)
exact perm_append_comm.trans (perm_append_comm.cons _)
#align list.filter_append_perm List.filter_append_perm
+-/
/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
@@ -368,6 +373,7 @@ theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p :
#align list.exists_perm_sublist List.exists_perm_sublist
-/
+#print List.Perm.sizeOf_eq_sizeOf /-
theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂) : l₁.sizeOf = l₂.sizeOf :=
by
induction' h with hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
@@ -376,6 +382,7 @@ theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂
· simp only [List.sizeof, add_left_comm]
· simp only [h_sz₁₂, h_sz₂₃]
#align list.perm.sizeof_eq_sizeof List.Perm.sizeOf_eq_sizeOf
+-/
section Rel
@@ -383,7 +390,6 @@ open Relator
variable {γ : Type _} {δ : Type _} {r : α → β → Prop} {p : γ → δ → Prop}
--- mathport name: «expr ∘r »
local infixr:80 " ∘r " => Relation.Comp
#print List.perm_comp_perm /-
@@ -463,7 +469,6 @@ def Subperm (l₁ l₂ : List α) : Prop :=
#align list.subperm List.Subperm
-/
--- mathport name: «expr <+~ »
infixl:50 " <+~ " => Subperm
#print List.nil_subperm /-
@@ -539,11 +544,13 @@ theorem Subperm.subset {l₁ l₂ : List α} : l₁ <+~ l₂ → l₁ ⊆ l₂
#align list.subperm.subset List.Subperm.subset
-/
+#print List.Subperm.filter /-
theorem Subperm.filter (p : α → Prop) [DecidablePred p] ⦃l l' : List α⦄ (h : l <+~ l') :
filter p l <+~ filter p l' := by
obtain ⟨xs, hp, h⟩ := h
exact ⟨_, hp.filter p, h.filter p⟩
#align list.subperm.filter List.Subperm.filter
+-/
end Subperm
@@ -559,16 +566,21 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
-/
+#print List.Perm.countp_eq /-
theorem Perm.countp_eq (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
countp p l₁ = countp p l₂ := by
rw [countp_eq_length_filter, countp_eq_length_filter] <;> exact (s.filter _).length_eq
#align list.perm.countp_eq List.Perm.countp_eq
+-/
+#print List.Subperm.countp_le /-
theorem Subperm.countp_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} :
l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
| ⟨l, p', s⟩ => p'.countp_eq p ▸ s.countp_le p
#align list.subperm.countp_le List.Subperm.countp_le
+-/
+#print List.Perm.countp_congr /-
theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
(hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
by
@@ -579,11 +591,14 @@ theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred
· simp only [mem_cons_iff, forall_eq_or_imp] at hp
simp only [countp_cons, hs hp.2, hp.1]
#align list.perm.countp_congr List.Perm.countp_congr
+-/
+#print List.countp_eq_countp_filter_add /-
theorem countp_eq_countp_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
[DecidablePred q] : l.countp p = (l.filterₓ q).countp p + (l.filterₓ fun a => ¬q a).countp p :=
by rw [← countp_append]; exact perm.countp_eq _ (filter_append_perm _ _).symm
#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_add
+-/
#print List.Perm.count_eq /-
theorem Perm.count_eq [DecidableEq α] {l₁ l₂ : List α} (p : l₁ ~ l₂) (a) :
@@ -629,6 +644,7 @@ theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : Left
#align list.perm.foldr_eq List.Perm.foldr_eq
-/
+#print List.Perm.rec_heq /-
theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
(hl : Perm l l') (f_congr : ∀ {a l l' b b'}, Perm l l' → HEq b b' → HEq (f a l b) (f a l' b'))
(f_swap : ∀ {a a' l b}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))) :
@@ -640,15 +656,14 @@ theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l
case swap a a' l => exact f_swap
case trans l₁ l₂ l₃ h₁ h₂ ih₁ ih₂ => exact HEq.trans ih₁ ih₂
#align list.perm.rec_heq List.Perm.rec_heq
+-/
section
variable {op : α → α → α} [IsAssociative α op] [IsCommutative α op]
--- mathport name: op
local notation a " * " b => op a b
--- mathport name: foldl
local notation l " <*> " a => foldl op a l
#print List.Perm.fold_op_eq /-
@@ -661,6 +676,7 @@ end
section CommMonoid
+#print List.Perm.prod_eq' /-
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
@@ -673,20 +689,25 @@ theorem Perm.prod_eq' [Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc :
_
#align list.perm.prod_eq' List.Perm.prod_eq'
#align list.perm.sum_eq' List.Perm.sum_eq'
+-/
variable [CommMonoid α]
+#print List.Perm.prod_eq /-
@[to_additive]
theorem Perm.prod_eq {l₁ l₂ : List α} (h : Perm l₁ l₂) : prod l₁ = prod l₂ :=
h.fold_op_eq
#align list.perm.prod_eq List.Perm.prod_eq
#align list.perm.sum_eq List.Perm.sum_eq
+-/
+#print List.prod_reverse /-
@[to_additive]
theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
(reverse_perm l).prod_eq
#align list.prod_reverse List.prod_reverse
#align list.sum_reverse List.sum_reverse
+-/
end CommMonoid
@@ -878,6 +899,7 @@ section
variable [DecidableEq α]
+#print List.Perm.erase /-
-- attribute [congr]
theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.eraseₓ a ~ l₂.eraseₓ a :=
if h₁ : a ∈ l₁ then
@@ -887,7 +909,9 @@ theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase
have h₂ : a ∉ l₂ := mt p.mem_iff.2 h₁
rw [erase_of_not_mem h₁, erase_of_not_mem h₂] <;> exact p
#align list.perm.erase List.Perm.erase
+-/
+#print List.subperm_cons_erase /-
theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.eraseₓ a :=
by
by_cases h : a ∈ l
@@ -895,36 +919,50 @@ theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.eraseₓ a :=
· rw [erase_of_not_mem h]
exact (sublist_cons _ _).Subperm
#align list.subperm_cons_erase List.subperm_cons_erase
+-/
+#print List.erase_subperm /-
theorem erase_subperm (a : α) (l : List α) : l.eraseₓ a <+~ l :=
(erase_sublist _ _).Subperm
#align list.erase_subperm List.erase_subperm
+-/
+#print List.Subperm.erase /-
theorem Subperm.erase {l₁ l₂ : List α} (a : α) (h : l₁ <+~ l₂) : l₁.eraseₓ a <+~ l₂.eraseₓ a :=
let ⟨l, hp, hs⟩ := h
⟨l.eraseₓ a, hp.eraseₓ _, hs.eraseₓ _⟩
#align list.subperm.erase List.Subperm.erase
+-/
+#print List.Perm.diff_right /-
theorem Perm.diff_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) : l₁.diffₓ t ~ l₂.diffₓ t := by
induction t generalizing l₁ l₂ h <;> simp [*, perm.erase]
#align list.perm.diff_right List.Perm.diff_right
+-/
+#print List.Perm.diff_left /-
theorem Perm.diff_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.diffₓ t₁ = l.diffₓ t₂ := by
induction h generalizing l <;>
first
| simp [*, perm.erase, erase_comm]
| exact (ih_1 _).trans (ih_2 _)
#align list.perm.diff_left List.Perm.diff_left
+-/
+#print List.Perm.diff /-
theorem Perm.diff {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
l₁.diffₓ t₁ ~ l₂.diffₓ t₂ :=
ht.diff_left l₂ ▸ hl.diff_right _
#align list.perm.diff List.Perm.diff
+-/
+#print List.Subperm.diff_right /-
theorem Subperm.diff_right {l₁ l₂ : List α} (h : l₁ <+~ l₂) (t : List α) :
l₁.diffₓ t <+~ l₂.diffₓ t := by induction t generalizing l₁ l₂ h <;> simp [*, subperm.erase]
#align list.subperm.diff_right List.Subperm.diff_right
+-/
+#print List.erase_cons_subperm_cons_erase /-
theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
(a :: l).eraseₓ b <+~ a :: l.eraseₓ b :=
by
@@ -934,7 +972,9 @@ theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
apply subperm_cons_erase
· rw [erase_cons_tail _ h]
#align list.erase_cons_subperm_cons_erase List.erase_cons_subperm_cons_erase
+-/
+#print List.subperm_cons_diff /-
theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : List α}, (a :: l₁).diffₓ l₂ <+~ a :: l₁.diffₓ l₂
| l₁, [] => ⟨a :: l₁, by simp⟩
| l₁, b :: l₂ => by
@@ -942,11 +982,15 @@ theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : List α}, (a :: l₁).diff
refine' ((erase_cons_subperm_cons_erase a b l₁).diff_right l₂).trans _
apply subperm_cons_diff
#align list.subperm_cons_diff List.subperm_cons_diff
+-/
+#print List.subset_cons_diff /-
theorem subset_cons_diff {a : α} {l₁ l₂ : List α} : (a :: l₁).diffₓ l₂ ⊆ a :: l₁.diffₓ l₂ :=
subperm_cons_diff.Subset
#align list.subset_cons_diff List.subset_cons_diff
+-/
+#print List.Perm.bagInter_right /-
theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
l₁.bagInterₓ t ~ l₂.bagInterₓ t :=
by
@@ -960,7 +1004,9 @@ theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂
· simp [xt, yt]
· exact (ih_1 _).trans (ih_2 _)
#align list.perm.bag_inter_right List.Perm.bagInter_right
+-/
+#print List.Perm.bagInter_left /-
theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
l.bagInterₓ t₁ = l.bagInterₓ t₂ :=
by
@@ -969,12 +1015,16 @@ theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂)
· simp [h, p.subset h, IH (p.erase _)]
· simp [h, mt p.mem_iff.2 h, IH p]
#align list.perm.bag_inter_left List.Perm.bagInter_left
+-/
+#print List.Perm.bagInter /-
theorem Perm.bagInter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
l₁.bagInterₓ t₁ ~ l₂.bagInterₓ t₂ :=
ht.bagInter_left l₂ ▸ hl.bagInter_right _
#align list.perm.bag_inter List.Perm.bagInter
+-/
+#print List.cons_perm_iff_perm_erase /-
theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
a :: l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.eraseₓ a :=
⟨fun h =>
@@ -982,6 +1032,7 @@ theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
⟨this, (h.trans <| perm_cons_erase this).cons_inv⟩,
fun ⟨m, h⟩ => (h.cons a).trans (perm_cons_erase m).symm⟩
#align list.cons_perm_iff_perm_erase List.cons_perm_iff_perm_erase
+-/
#print List.perm_iff_count /-
theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ :=
@@ -1324,6 +1375,7 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
#align list.perm_lookmap List.perm_lookmap
-/
+#print List.Perm.erasep /-
theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
(H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ :=
by
@@ -1339,6 +1391,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
· refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
exact fun a b h h₁ h₂ => h h₂ h₁
#align list.perm.erasep List.Perm.erasep
+-/
#print List.Perm.take_inter /-
theorem Perm.take_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys) (h' : ys.Nodup) :
mathlib commit https://github.com/leanprover-community/mathlib/commit/31c24aa72e7b3e5ed97a8412470e904f82b81004
@@ -339,7 +339,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
exact perm_append_comm.trans (perm_append_comm.cons _)
#align list.filter_append_perm List.filter_append_perm
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l₁' list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
@@ -453,7 +453,7 @@ end Rel
section Subperm
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (l list.perm l₁) -/
#print List.Subperm /-
/-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
@@ -1467,7 +1467,7 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
#align list.length_permutations List.length_permutations
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
#print List.mem_permutations_of_perm_lemma /-
theorem mem_permutations_of_perm_lemma {is l : List α}
(H : l ~ [] ++ is → (∃ (ts' : _) (_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
@@ -1475,7 +1475,7 @@ theorem mem_permutations_of_perm_lemma {is l : List α}
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (is' list.perm is) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:638:2: warning: expanding binder collection (is' list.perm is) -/
#print List.mem_permutationsAux_of_perm /-
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
mathlib commit https://github.com/leanprover-community/mathlib/commit/5f25c089cb34db4db112556f23c50d12da81b297
@@ -1047,7 +1047,7 @@ theorem subperm_ext_iff {l₁ l₂ : List α} : l₁ <+~ l₂ ↔ ∀ x ∈ l₁
by
refine' this.trans (perm.subperm _)
exact perm_append_comm.trans (subperm_append_diff_self_of_count_le h)
- convert(subperm_append_right _).mpr nil_subperm using 1
+ convert (subperm_append_right _).mpr nil_subperm using 1
#align list.subperm_ext_iff List.subperm_ext_iff
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -342,7 +342,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
- ∃ (l₁' : _)(_ : l₁' ~ l₁), l₁' <+ l₂' :=
+ ∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
by
induction' p with x l₂ l₂' p IH x y l₂ l₂ m₂ r₂ p₁ p₂ IH₁ IH₂ generalizing l₁ s
· exact ⟨[], eq_nil_of_sublist_nil s ▸ perm.refl _, nil_sublist _⟩
@@ -409,8 +409,8 @@ theorem perm_comp_forall₂ {l u v} (hlu : Perm l u) (huv : Forall₂ r u v) :
cases' h₂₃ with _ b₁ _ l₂ h₁ hr_₂₃
cases' hr_₂₃ with _ b₂ _ l₂ h₂ h₁₂
exact ⟨b₂ :: b₁ :: l₂, forall₂.cons h₂ (forall₂.cons h₁ h₁₂), perm.swap _ _ _⟩
- case
- trans la₁ la₂ la₃ _ _ ih₁ ih₂ =>
+ case trans la₁ la₂ la₃ _ _ ih₁
+ ih₂ =>
rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩
rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩
exact ⟨lb₁, hab₁, perm.trans h₁₂ h₂₃⟩
@@ -435,7 +435,7 @@ theorem rel_perm_imp (hr : RightUnique r) : (Forall₂ r ⇒ Forall₂ r ⇒ Imp
fun a b h₁ c d h₂ h =>
have : (flip (Forall₂ r) ∘r Perm ∘r Forall₂ r) b d := ⟨a, h₁, c, h, h₂⟩
have : ((flip (Forall₂ r) ∘r Forall₂ r) ∘r Perm) b d := by
- rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← Relation.comp_assoc] at this
+ rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← Relation.comp_assoc] at this
let ⟨b', ⟨c', hbc, hcb⟩, hbd⟩ := this
have : b' = b := right_unique_forall₂' hr hcb hbc
this ▸ hbd
@@ -459,7 +459,7 @@ section Subperm
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
multiplicities of elements, and is used for the `≤` relation on multisets. -/
def Subperm (l₁ l₂ : List α) : Prop :=
- ∃ (l : _)(_ : l ~ l₁), l <+ l₂
+ ∃ (l : _) (_ : l ~ l₁), l <+ l₂
#align list.subperm List.Subperm
-/
@@ -576,7 +576,7 @@ theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred
clear s
induction' l₁ with y s hs
· rfl
- · simp only [mem_cons_iff, forall_eq_or_imp] at hp
+ · simp only [mem_cons_iff, forall_eq_or_imp] at hp
simp only [countp_cons, hs hp.2, hp.1]
#align list.perm.countp_congr List.Perm.countp_congr
@@ -701,13 +701,13 @@ theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} :
fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => _ <;>
intro l₁ l₂ r₁ r₂ e₁ e₂
· apply (not_mem_nil a).elim; rw [← e₁]; simp
- · cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
+ · cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
· substs t₁ t₂; exact p
· substs z t₁ t₂; exact p.trans perm_middle
· substs y t₁ t₂; exact perm_middle.symm.trans p
· substs z t₁ t₂; exact (IH rfl rfl).cons y
· rcases l₁ with (_ | ⟨y, _ | ⟨z, l₁⟩⟩) <;> rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩) <;>
- dsimp at e₁ e₂ <;> injections <;> substs x y
+ dsimp at e₁ e₂ <;> injections <;> substs x y
· substs r₁ r₂; exact p.cons a
· substs r₁ r₂; exact p.cons u
· substs r₁ v t₂; exact (p.trans perm_middle).cons u
@@ -785,12 +785,12 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
induction s generalizing l₁
case slnil => cases h₂
case cons r₁ r₂ b s' ih =>
- simp at h₂
+ simp at h₂
cases' h₂ with e m
· subst b; exact ⟨a :: r₁, p.cons a, s'.cons2 _ _ _⟩
· rcases ih m d₁ h₁ p with ⟨t, p', s'⟩; exact ⟨t, p', s'.cons _ _ _⟩
- case
- cons2 r₁ r₂ b s' ih =>
+ case cons2 r₁ r₂ b s'
+ ih =>
have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
have am : a ∈ r₂ := h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
rcases mem_split bm with ⟨t₁, t₂, rfl⟩
@@ -842,7 +842,7 @@ protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~
induction' d with a l₁' h d IH
· exact ⟨nil, perm.nil, nil_sublist _⟩
· cases' forall_mem_cons.1 H with H₁ H₂
- simp at h
+ simp at h
exact cons_subperm_of_mem d h H₁ (IH H₂)
#align list.nodup.subperm List.Nodup.subperm
-/
@@ -861,12 +861,12 @@ theorem Nodup.sublist_ext {l₁ l₂ l : List α} (d : Nodup l) (s₁ : l₁ <+
⟨fun h => by
induction' s₂ with l₂ l a s₂ IH l₂ l a s₂ IH generalizing l₁
· exact h.eq_nil
- · simp at d
+ · simp at d
cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
· exact IH d.2 s₁ h
· apply d.1.elim
exact subperm.subset ⟨_, h.symm, s₂⟩ (mem_cons_self _ _)
- · simp at d
+ · simp at d
cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
· apply d.1.elim
exact subperm.subset ⟨_, h, s₁⟩ (mem_cons_self _ _)
@@ -911,7 +911,9 @@ theorem Perm.diff_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
theorem Perm.diff_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.diffₓ t₁ = l.diffₓ t₂ := by
induction h generalizing l <;>
- first |simp [*, perm.erase, erase_comm]|exact (ih_1 _).trans (ih_2 _)
+ first
+ | simp [*, perm.erase, erase_comm]
+ | exact (ih_1 _).trans (ih_2 _)
#align list.perm.diff_left List.Perm.diff_left
theorem Perm.diff {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
@@ -986,12 +988,12 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
⟨Perm.count_eq, fun H => by
induction' l₁ with a l₁ IH generalizing l₂
· cases' l₂ with b l₂; · rfl
- specialize H b; simp at H; contradiction
+ specialize H b; simp at H ; contradiction
· have : a ∈ l₂ := count_pos.1 (by rw [← H] <;> simp <;> apply Nat.succ_pos)
refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
specialize H b
- rw [(perm_cons_erase this).count_eq] at H
- by_cases b = a <;> simp [h] at H⊢ <;> assumption⟩
+ rw [(perm_cons_erase this).count_eq] at H
+ by_cases b = a <;> simp [h] at H ⊢ <;> assumption⟩
#align list.perm_iff_count List.perm_iff_count
-/
@@ -1028,7 +1030,7 @@ theorem subperm_append_diff_self_of_count_le {l₁ l₂ : List α}
rw [cons_append, diff_cons, perm_cons]
refine' IH fun x hx => _
specialize h x (mem_cons_of_mem _ hx)
- rw [perm_iff_count.mp this] at h
+ rw [perm_iff_count.mp this] at h
by_cases hx : x = hd
· subst hd
simpa [Nat.succ_le_succ_iff] using h
@@ -1058,7 +1060,7 @@ instance decidableSubperm : DecidableRel ((· <+~ ·) : List α → List α →
#print List.subperm_singleton_iff /-
@[simp]
theorem subperm_singleton_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈ l :=
- ⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h, fun h =>
+ ⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h , fun h =>
⟨[a], Perm.refl _, singleton_sublist.mpr h⟩⟩
#align list.subperm_singleton_iff List.subperm_singleton_iff
-/
@@ -1066,7 +1068,7 @@ theorem subperm_singleton_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈
#print List.Subperm.cons_left /-
theorem Subperm.cons_left {l₁ l₂ : List α} (h : l₁ <+~ l₂) (x : α) (hx : count x l₁ < count x l₂) :
x :: l₁ <+~ l₂ := by
- rw [subperm_ext_iff] at h⊢
+ rw [subperm_ext_iff] at h ⊢
intro y hy
by_cases hy' : y = x
· subst x
@@ -1305,7 +1307,7 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
lookmap f l₁ ~ lookmap f l₂ :=
by
let F a b := ∀ c ∈ f a, ∀ d ∈ f b, a = b ∧ c = d
- change Pairwise F l₁ at H
+ change Pairwise F l₁ at H
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂; · simp
· cases h : f a
· simp [h]; exact IH (pairwise_cons.1 H).2
@@ -1326,7 +1328,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
(H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ :=
by
let F a b := f a → f b → False
- change Pairwise F l₁ at H
+ change Pairwise F l₁ at H
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂; · simp
· by_cases h : f a
· simp [h, p]
@@ -1345,8 +1347,8 @@ theorem Perm.take_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : x
simp only [List.inter] at *
induction h generalizing n
case nil n => simp only [not_mem_nil, filter_false, take_nil]
- case
- cons h_x h_l₁ h_l₂ h_a h_ih n =>
+ case cons h_x h_l₁ h_l₂ h_a h_ih
+ n =>
cases n <;>
simp only [mem_cons_iff, true_or_iff, eq_self_iff_true, filter_cons_of_pos, perm_cons, take,
not_mem_nil, filter_false]
@@ -1362,7 +1364,7 @@ theorem Perm.take_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : x
cases n <;>
simp only [mem_cons_iff, false_or_iff, true_or_iff, Filter, *, Nat.zero_eq, if_true,
not_mem_nil, eq_self_iff_true, or_false_iff, if_false, perm_cons, take]
- · rw [filter_eq_nil.2]; intros ; solve_by_elim [Ne.symm]
+ · rw [filter_eq_nil.2]; intros; solve_by_elim [Ne.symm]
· convert perm.swap _ _ _; rw [@filter_congr' _ _ (· ∈ take n h_l)]
· clear h₁; induction n generalizing h_l; · simp
cases h_l <;>
@@ -1425,12 +1427,12 @@ theorem perm_of_mem_permutationsAux :
by
refine' permutations_aux.rec (by simp) _
introv IH1 IH2 m
- rw [permutations_aux_cons, permutations, mem_foldr_permutations_aux2] at m
+ rw [permutations_aux_cons, permutations, mem_foldr_permutations_aux2] at m
rcases m with (m | ⟨l₁, l₂, m, _, e⟩)
· exact (IH1 m).trans perm_middle
· subst e
have p : l₁ ++ l₂ ~ is := by
- simp [permutations] at m
+ simp [permutations] at m
cases' m with e m; · simp [e]
exact is.append_nil ▸ IH2 m
exact ((perm_middle.trans (p.cons _)).append_right _).trans (perm_append_comm.cons _)
@@ -1451,7 +1453,7 @@ theorem length_permutationsAux :
refine' permutations_aux.rec (by simp) _
intro t ts is IH1 IH2
have IH2 : length (permutations_aux is nil) + 1 = is.length ! := by simpa using IH2
- simp [-add_comm, Nat.factorial, Nat.add_succ, mul_comm] at IH1
+ simp [-add_comm, Nat.factorial, Nat.add_succ, mul_comm] at IH1
rw [permutations_aux_cons,
length_foldr_permutations_aux2' _ _ _ _ _ fun l m => (perm_of_mem_permutations m).length_eq,
permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, mul_comm (Nat.succ _), ←
@@ -1468,7 +1470,7 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
#print List.mem_permutations_of_perm_lemma /-
theorem mem_permutations_of_perm_lemma {is l : List α}
- (H : l ~ [] ++ is → (∃ (ts' : _)(_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
+ (H : l ~ [] ++ is → (∃ (ts' : _) (_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
l ~ is → l ∈ permutations is := by simpa [permutations, perm_nil] using H
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
-/
@@ -1477,7 +1479,7 @@ theorem mem_permutations_of_perm_lemma {is l : List α}
#print List.mem_permutationsAux_of_perm /-
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
- l ~ is ++ ts → (∃ (is' : _)(_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is :=
+ l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is :=
by
refine' permutations_aux.rec (by simp) _
intro t ts is IH1 IH2 l p
@@ -1544,7 +1546,7 @@ theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.pe
obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
induction' n with n IH generalizing ts; · cases h
refine' List.reverseRecOn ts (fun h => _) (fun ts t _ h => _) h; · simp [permutations]
- rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
+ rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
simp only [permutations_append, foldr_permutations_aux2, permutations_aux_nil,
permutations_aux_cons, append_nil]
@@ -1593,7 +1595,7 @@ theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
(permutations'Aux x s).nthLe n hn = s.insertNth n x :=
by
induction' s with y s IH generalizing n
- · simp only [length, permutations'_aux, Nat.lt_one_iff] at hn
+ · simp only [length, permutations'_aux, Nat.lt_one_iff] at hn
simp [hn]
· cases n
· simp
@@ -1657,7 +1659,7 @@ theorem nodup_permutations'Aux_of_not_mem (s : List α) (x : α) (hx : x ∉ s)
Nodup (permutations'Aux x s) := by
induction' s with y s IH
· simp
- · simp only [not_or, mem_cons_iff] at hx
+ · simp only [not_or, mem_cons_iff] at hx
simp only [not_and, exists_eq_right_right, mem_map, permutations'_aux, nodup_cons]
refine' ⟨fun _ => Ne.symm hx.left, _⟩
rw [nodup_map_iff]
@@ -1672,7 +1674,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
refine' ⟨fun h => _, nodup_permutations'_aux_of_not_mem _ _⟩
intro H
obtain ⟨k, hk, hk'⟩ := nth_le_of_mem H
- rw [nodup_iff_nth_le_inj] at h
+ rw [nodup_iff_nth_le_inj] at h
suffices k = k + 1 by simpa using this
refine' h k (k + 1) _ _ _
· simpa [Nat.lt_succ_iff] using hk.le
@@ -1694,7 +1696,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
convert nth_le_insert_nth_add_succ _ _ _ 0 _
simpa using hk
· obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt H'
- rw [length_insert_nth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn
+ rw [length_insert_nth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn
rw [nth_le_insert_nth_add_succ]
convert nth_le_insert_nth_add_succ s x k m.succ _ using 2
· simp [Nat.add_succ, Nat.succ_add]
@@ -1714,7 +1716,7 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :
rw [nodup_bind]
constructor
· intro ys hy
- rw [mem_permutations'] at hy
+ rw [mem_permutations'] at hy
rw [nodup_permutations'_aux_iff, hy.mem_iff]
exact fun H => h x H rfl
· refine' IH.pairwise_of_forall_ne fun as ha bs hb H => _
@@ -1722,10 +1724,10 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :
rintro a ha' b hb' rfl
obtain ⟨n, hn, hn'⟩ := nth_le_of_mem ha'
obtain ⟨m, hm, hm'⟩ := nth_le_of_mem hb'
- rw [mem_permutations'] at ha hb
+ rw [mem_permutations'] at ha hb
have hl : as.length = bs.length := (ha.trans hb.symm).length_eq
- simp only [Nat.lt_succ_iff, length_permutations'_aux] at hn hm
- rw [nth_le_permutations'_aux] at hn' hm'
+ simp only [Nat.lt_succ_iff, length_permutations'_aux] at hn hm
+ rw [nth_le_permutations'_aux] at hn' hm'
have hx :
nth_le (insert_nth n x as) m (by rwa [length_insert_nth _ _ hn, Nat.lt_succ_iff, hl]) = x :=
by simp [hn', ← hm', hm]
@@ -1737,8 +1739,8 @@ theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :
· suffices x ∈ bs by exact h x (hb.subset this) rfl
rw [← hx', nth_le_insert_nth_of_lt _ _ _ _ ht (ht.trans_le hm)]
exact nth_le_mem _ _ _
- · simp only [ht] at hm' hn'
- rw [← hm'] at hn'
+ · simp only [ht] at hm' hn'
+ rw [← hm'] at hn'
exact H (insert_nth_injective _ _ hn')
· suffices x ∈ as by exact h x (ha.subset this) rfl
rw [← hx, nth_le_insert_nth_of_lt _ _ _ _ ht (ht.trans_le hn)]
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -28,7 +28,7 @@ The notation `~` is used for permutation equivalence.
-/
-open Nat
+open scoped Nat
universe uu vv
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -275,12 +275,6 @@ theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b := by simp
#align list.singleton_perm_singleton List.singleton_perm_singleton
-/
-/- warning: list.perm_cons_erase -> List.perm_cons_erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l : List.{u1} α}, (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l) -> (List.Perm.{u1} α l (List.cons.{u1} α a (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l a)))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l : List.{u1} α}, (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l) -> (List.Perm.{u1} α l (List.cons.{u1} α a (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l a)))
-Case conversion may be inaccurate. Consider using '#align list.perm_cons_erase List.perm_cons_eraseₓ'. -/
theorem perm_cons_erase [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : l ~ a :: l.eraseₓ a :=
let ⟨l₁, l₂, _, e₁, e₂⟩ := exists_erase_eq h
e₂.symm ▸ e₁.symm ▸ perm_middle
@@ -328,22 +322,10 @@ theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α
#align list.perm.pmap List.Perm.pmap
-/
-/- warning: list.perm.filter -> List.Perm.filter is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (p : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.filterₓ.{u1} α p (fun (a : α) => _inst_1 a) l₁) (List.filterₓ.{u1} α p (fun (a : α) => _inst_1 a) l₂))
-but is expected to have type
- forall {α : Type.{u1}} (p : α -> Bool) {_inst_1 : List.{u1} α} {l₁ : List.{u1} α}, (List.Perm.{u1} α _inst_1 l₁) -> (List.Perm.{u1} α (List.filter.{u1} α p _inst_1) (List.filter.{u1} α p l₁))
-Case conversion may be inaccurate. Consider using '#align list.perm.filter List.Perm.filterₓ'. -/
theorem Perm.filter (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
filter p l₁ ~ filter p l₂ := by rw [← filter_map_eq_filter] <;> apply s.filter_map _
#align list.perm.filter List.Perm.filter
-/- warning: list.filter_append_perm -> List.filter_append_perm is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (p : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] (l : List.{u1} α), List.Perm.{u1} α (Append.append.{u1} (List.{u1} α) (List.hasAppend.{u1} α) (List.filterₓ.{u1} α p (fun (a : α) => _inst_1 a) l) (List.filterₓ.{u1} α (fun (x : α) => Not (p x)) (fun (a : α) => Not.decidable (p a) (_inst_1 a)) l)) l
-but is expected to have type
- forall {α : Type.{u1}} (p : α -> Bool) (_inst_1 : List.{u1} α), List.Perm.{u1} α (HAppend.hAppend.{u1, u1, u1} (List.{u1} α) (List.{u1} α) (List.{u1} α) (instHAppend.{u1} (List.{u1} α) (List.instAppendList.{u1} α)) (List.filter.{u1} α p _inst_1) (List.filter.{u1} α (fun (x : α) => Decidable.decide (Not (Eq.{1} Bool (p x) Bool.true)) (instDecidableNot (Eq.{1} Bool (p x) Bool.true) (instDecidableEqBool (p x) Bool.true))) _inst_1)) _inst_1
-Case conversion may be inaccurate. Consider using '#align list.filter_append_perm List.filter_append_permₓ'. -/
theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
filter p l ++ filter (fun x => ¬p x) l ~ l :=
by
@@ -386,12 +368,6 @@ theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p :
#align list.exists_perm_sublist List.exists_perm_sublist
-/
-/- warning: list.perm.sizeof_eq_sizeof -> List.Perm.sizeOf_eq_sizeOf is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : SizeOf.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (Eq.{1} Nat (List.sizeof.{u1} α _inst_1 l₁) (List.sizeof.{u1} α _inst_1 l₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : SizeOf.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (Eq.{1} Nat (SizeOf.sizeOf.{succ u1} (List.{u1} α) (List._sizeOf_inst.{u1} α _inst_1) l₁) (SizeOf.sizeOf.{succ u1} (List.{u1} α) (List._sizeOf_inst.{u1} α _inst_1) l₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.sizeof_eq_sizeof List.Perm.sizeOf_eq_sizeOfₓ'. -/
theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂) : l₁.sizeOf = l₂.sizeOf :=
by
induction' h with hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
@@ -563,12 +539,6 @@ theorem Subperm.subset {l₁ l₂ : List α} : l₁ <+~ l₂ → l₁ ⊆ l₂
#align list.subperm.subset List.Subperm.subset
-/
-/- warning: list.subperm.filter -> List.Subperm.filter is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (p : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] {{l : List.{u1} α}} {{l' : List.{u1} α}}, (List.Subperm.{u1} α l l') -> (List.Subperm.{u1} α (List.filterₓ.{u1} α p (fun (a : α) => _inst_1 a) l) (List.filterₓ.{u1} α p (fun (a : α) => _inst_1 a) l'))
-but is expected to have type
- forall {α : Type.{u1}} (p : α -> Bool) {{_inst_1 : List.{u1} α}} {{l : List.{u1} α}}, (List.Subperm.{u1} α _inst_1 l) -> (List.Subperm.{u1} α (List.filter.{u1} α p _inst_1) (List.filter.{u1} α p l))
-Case conversion may be inaccurate. Consider using '#align list.subperm.filter List.Subperm.filterₓ'. -/
theorem Subperm.filter (p : α → Prop) [DecidablePred p] ⦃l l' : List α⦄ (h : l <+~ l') :
filter p l <+~ filter p l' := by
obtain ⟨xs, hp, h⟩ := h
@@ -589,34 +559,16 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
-/
-/- warning: list.perm.countp_eq -> List.Perm.countp_eq is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (p : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (Eq.{1} Nat (List.countp.{u1} α p (fun (a : α) => _inst_1 a) l₁) (List.countp.{u1} α p (fun (a : α) => _inst_1 a) l₂))
-but is expected to have type
- forall {α : Type.{u1}} (p : α -> Bool) {_inst_1 : List.{u1} α} {l₁ : List.{u1} α}, (List.Perm.{u1} α _inst_1 l₁) -> (Eq.{1} Nat (List.countp.{u1} α p _inst_1) (List.countp.{u1} α p l₁))
-Case conversion may be inaccurate. Consider using '#align list.perm.countp_eq List.Perm.countp_eqₓ'. -/
theorem Perm.countp_eq (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
countp p l₁ = countp p l₂ := by
rw [countp_eq_length_filter, countp_eq_length_filter] <;> exact (s.filter _).length_eq
#align list.perm.countp_eq List.Perm.countp_eq
-/- warning: list.subperm.countp_le -> List.Subperm.countp_le is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (p : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Subperm.{u1} α l₁ l₂) -> (LE.le.{0} Nat Nat.hasLe (List.countp.{u1} α p (fun (a : α) => _inst_1 a) l₁) (List.countp.{u1} α p (fun (a : α) => _inst_1 a) l₂))
-but is expected to have type
- forall {α : Type.{u1}} (p : α -> Bool) {_inst_1 : List.{u1} α} {l₁ : List.{u1} α}, (List.Subperm.{u1} α _inst_1 l₁) -> (LE.le.{0} Nat instLENat (List.countp.{u1} α p _inst_1) (List.countp.{u1} α p l₁))
-Case conversion may be inaccurate. Consider using '#align list.subperm.countp_le List.Subperm.countp_leₓ'. -/
theorem Subperm.countp_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} :
l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
| ⟨l, p', s⟩ => p'.countp_eq p ▸ s.countp_le p
#align list.subperm.countp_le List.Subperm.countp_le
-/- warning: list.perm.countp_congr -> List.Perm.countp_congr is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (forall {p : α -> Prop} {p' : α -> Prop} [_inst_1 : DecidablePred.{succ u1} α p] [_inst_2 : DecidablePred.{succ u1} α p'], (forall (x : α), (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) x l₁) -> (Eq.{1} Prop (p x) (p' x))) -> (Eq.{1} Nat (List.countp.{u1} α p (fun (a : α) => _inst_1 a) l₁) (List.countp.{u1} α p' (fun (a : α) => _inst_2 a) l₂)))
-but is expected to have type
- forall {α : Type.{u1}} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (forall {p : α -> Bool} {p' : α -> Bool}, (forall (x : α), (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) x l₁) -> (Eq.{1} Bool (p x) (p' x))) -> (Eq.{1} Nat (List.countp.{u1} α p l₁) (List.countp.{u1} α p' l₂)))
-Case conversion may be inaccurate. Consider using '#align list.perm.countp_congr List.Perm.countp_congrₓ'. -/
theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
(hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
by
@@ -628,12 +580,6 @@ theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred
simp only [countp_cons, hs hp.2, hp.1]
#align list.perm.countp_congr List.Perm.countp_congr
-/- warning: list.countp_eq_countp_filter_add -> List.countp_eq_countp_filter_add is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (l : List.{u1} α) (p : α -> Prop) (q : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α p] [_inst_2 : DecidablePred.{succ u1} α q], Eq.{1} Nat (List.countp.{u1} α p (fun (a : α) => _inst_1 a) l) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat Nat.hasAdd) (List.countp.{u1} α p (fun (a : α) => _inst_1 a) (List.filterₓ.{u1} α q (fun (a : α) => _inst_2 a) l)) (List.countp.{u1} α p (fun (a : α) => _inst_1 a) (List.filterₓ.{u1} α (fun (a : α) => Not (q a)) (fun (a : α) => Not.decidable (q a) (_inst_2 a)) l)))
-but is expected to have type
- forall {α : Type.{u1}} (l : List.{u1} α) (p : α -> Bool) (q : α -> Bool), Eq.{1} Nat (List.countp.{u1} α p l) (HAdd.hAdd.{0, 0, 0} Nat Nat Nat (instHAdd.{0} Nat instAddNat) (List.countp.{u1} α p (List.filter.{u1} α q l)) (List.countp.{u1} α p (List.filter.{u1} α (fun (a : α) => Decidable.decide (Not (Eq.{1} Bool (q a) Bool.true)) (instDecidableNot (Eq.{1} Bool (q a) Bool.true) (instDecidableEqBool (q a) Bool.true))) l)))
-Case conversion may be inaccurate. Consider using '#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_addₓ'. -/
theorem countp_eq_countp_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
[DecidablePred q] : l.countp p = (l.filterₓ q).countp p + (l.filterₓ fun a => ¬q a).countp p :=
by rw [← countp_append]; exact perm.countp_eq _ (filter_append_perm _ _).symm
@@ -683,12 +629,6 @@ theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : Left
#align list.perm.foldr_eq List.Perm.foldr_eq
-/
-/- warning: list.perm.rec_heq -> List.Perm.rec_heq is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} {β : (List.{u1} α) -> Sort.{u2}} {f : forall (a : α) (l : List.{u1} α), (β l) -> (β (List.cons.{u1} α a l))} {b : β (List.nil.{u1} α)} {l : List.{u1} α} {l' : List.{u1} α}, (List.Perm.{u1} α l l') -> (forall {a : α} {l : List.{u1} α} {l' : List.{u1} α} {b : β l} {b' : β l'}, (List.Perm.{u1} α l l') -> (HEq.{u2} (β l) b (β l') b') -> (HEq.{u2} (β (List.cons.{u1} α a l)) (f a l b) (β (List.cons.{u1} α a l')) (f a l' b'))) -> (forall {a : α} {a' : α} {l : List.{u1} α} {b : β l}, HEq.{u2} (β (List.cons.{u1} α a (List.cons.{u1} α a' l))) (f a (List.cons.{u1} α a' l) (f a' l b)) (β (List.cons.{u1} α a' (List.cons.{u1} α a l))) (f a' (List.cons.{u1} α a l) (f a l b))) -> (HEq.{u2} (β l) (List.rec.{u2, u1} α β b f l) (β l') (List.rec.{u2, u1} α β b f l'))
-but is expected to have type
- forall {α : Type.{u2}} {β : (List.{u2} α) -> Sort.{u1}} {f : forall (a : α) (l : List.{u2} α), (β l) -> (β (List.cons.{u2} α a l))} {b : β (List.nil.{u2} α)} {l : List.{u2} α} {l' : List.{u2} α}, (List.Perm.{u2} α l l') -> (forall {a : α} {l : List.{u2} α} {l' : List.{u2} α} {b : β l} {b' : β l'}, (List.Perm.{u2} α l l') -> (HEq.{u1} (β l) b (β l') b') -> (HEq.{u1} (β (List.cons.{u2} α a l)) (f a l b) (β (List.cons.{u2} α a l')) (f a l' b'))) -> (forall {a : α} {a' : α} {l : List.{u2} α} {b : β l}, HEq.{u1} (β (List.cons.{u2} α a (List.cons.{u2} α a' l))) (f a (List.cons.{u2} α a' l) (f a' l b)) (β (List.cons.{u2} α a' (List.cons.{u2} α a l))) (f a' (List.cons.{u2} α a l) (f a l b))) -> (HEq.{u1} (β l) (List.rec.{u1, u2} α β b f l) (β l') (List.rec.{u1, u2} α β b f l'))
-Case conversion may be inaccurate. Consider using '#align list.perm.rec_heq List.Perm.rec_heqₓ'. -/
theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
(hl : Perm l l') (f_congr : ∀ {a l l' b b'}, Perm l l' → HEq b b' → HEq (f a l b) (f a l' b'))
(f_swap : ∀ {a a' l b}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))) :
@@ -721,12 +661,6 @@ end
section CommMonoid
-/- warning: list.perm.prod_eq' -> List.Perm.prod_eq' is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : Monoid.{u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Pairwise.{u1} α (Commute.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1))) l₁) -> (Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) l₁) (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) l₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : Monoid.{u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Pairwise.{u1} α (Commute.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1))) l₁) -> (Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (Monoid.toOne.{u1} α _inst_1) l₁) (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α _inst_1)) (Monoid.toOne.{u1} α _inst_1) l₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.prod_eq' List.Perm.prod_eq'ₓ'. -/
/-- If elements of a list commute with each other, then their product does not
depend on the order of elements. -/
@[to_additive
@@ -742,24 +676,12 @@ theorem Perm.prod_eq' [Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc :
variable [CommMonoid α]
-/- warning: list.perm.prod_eq -> List.Perm.prod_eq is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : CommMonoid.{u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) l₁) (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) l₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : CommMonoid.{u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (Monoid.toOne.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1)) l₁) (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (Monoid.toOne.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1)) l₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.prod_eq List.Perm.prod_eqₓ'. -/
@[to_additive]
theorem Perm.prod_eq {l₁ l₂ : List α} (h : Perm l₁ l₂) : prod l₁ = prod l₂ :=
h.fold_op_eq
#align list.perm.prod_eq List.Perm.prod_eq
#align list.perm.sum_eq List.Perm.sum_eq
-/- warning: list.prod_reverse -> List.prod_reverse is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : CommMonoid.{u1} α] (l : List.{u1} α), Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (List.reverse.{u1} α l)) (List.prod.{u1} α (MulOneClass.toHasMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (MulOneClass.toHasOne.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) l)
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : CommMonoid.{u1} α] (l : List.{u1} α), Eq.{succ u1} α (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (Monoid.toOne.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1)) (List.reverse.{u1} α l)) (List.prod.{u1} α (MulOneClass.toMul.{u1} α (Monoid.toMulOneClass.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1))) (Monoid.toOne.{u1} α (CommMonoid.toMonoid.{u1} α _inst_1)) l)
-Case conversion may be inaccurate. Consider using '#align list.prod_reverse List.prod_reverseₓ'. -/
@[to_additive]
theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
(reverse_perm l).prod_eq
@@ -956,12 +878,6 @@ section
variable [DecidableEq α]
-/- warning: list.perm.erase -> List.Perm.erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ a) (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ a))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ a) (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ a))
-Case conversion may be inaccurate. Consider using '#align list.perm.erase List.Perm.eraseₓ'. -/
-- attribute [congr]
theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.eraseₓ a ~ l₂.eraseₓ a :=
if h₁ : a ∈ l₁ then
@@ -972,12 +888,6 @@ theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase
rw [erase_of_not_mem h₁, erase_of_not_mem h₂] <;> exact p
#align list.perm.erase List.Perm.erase
-/- warning: list.subperm_cons_erase -> List.subperm_cons_erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) (l : List.{u1} α), List.Subperm.{u1} α l (List.cons.{u1} α a (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l a))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) (l : List.{u1} α), List.Subperm.{u1} α l (List.cons.{u1} α a (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l a))
-Case conversion may be inaccurate. Consider using '#align list.subperm_cons_erase List.subperm_cons_eraseₓ'. -/
theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.eraseₓ a :=
by
by_cases h : a ∈ l
@@ -986,75 +896,33 @@ theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.eraseₓ a :=
exact (sublist_cons _ _).Subperm
#align list.subperm_cons_erase List.subperm_cons_erase
-/- warning: list.erase_subperm -> List.erase_subperm is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) (l : List.{u1} α), List.Subperm.{u1} α (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l a) l
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) (l : List.{u1} α), List.Subperm.{u1} α (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l a) l
-Case conversion may be inaccurate. Consider using '#align list.erase_subperm List.erase_subpermₓ'. -/
theorem erase_subperm (a : α) (l : List α) : l.eraseₓ a <+~ l :=
(erase_sublist _ _).Subperm
#align list.erase_subperm List.erase_subperm
-/- warning: list.subperm.erase -> List.Subperm.erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} (a : α), (List.Subperm.{u1} α l₁ l₂) -> (List.Subperm.{u1} α (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ a) (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ a))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} (a : α), (List.Subperm.{u1} α l₁ l₂) -> (List.Subperm.{u1} α (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ a) (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ a))
-Case conversion may be inaccurate. Consider using '#align list.subperm.erase List.Subperm.eraseₓ'. -/
theorem Subperm.erase {l₁ l₂ : List α} (a : α) (h : l₁ <+~ l₂) : l₁.eraseₓ a <+~ l₂.eraseₓ a :=
let ⟨l, hp, hs⟩ := h
⟨l.eraseₓ a, hp.eraseₓ _, hs.eraseₓ _⟩
#align list.subperm.erase List.Subperm.erase
-/- warning: list.perm.diff_right -> List.Perm.diff_right is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} (t : List.{u1} α), (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ t) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ t))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} (t : List.{u1} α), (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ t) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ t))
-Case conversion may be inaccurate. Consider using '#align list.perm.diff_right List.Perm.diff_rightₓ'. -/
theorem Perm.diff_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) : l₁.diffₓ t ~ l₂.diffₓ t := by
induction t generalizing l₁ l₂ h <;> simp [*, perm.erase]
#align list.perm.diff_right List.Perm.diff_right
-/- warning: list.perm.diff_left -> List.Perm.diff_left is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α) {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α t₁ t₂) -> (Eq.{succ u1} (List.{u1} α) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l t₁) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l t₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α) {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α t₁ t₂) -> (Eq.{succ u1} (List.{u1} α) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l t₁) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l t₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.diff_left List.Perm.diff_leftₓ'. -/
theorem Perm.diff_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.diffₓ t₁ = l.diffₓ t₂ := by
induction h generalizing l <;>
first |simp [*, perm.erase, erase_comm]|exact (ih_1 _).trans (ih_2 _)
#align list.perm.diff_left List.Perm.diff_left
-/- warning: list.perm.diff -> List.Perm.diff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α t₁ t₂) -> (List.Perm.{u1} α (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ t₁) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ t₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α t₁ t₂) -> (List.Perm.{u1} α (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ t₁) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ t₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.diff List.Perm.diffₓ'. -/
theorem Perm.diff {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
l₁.diffₓ t₁ ~ l₂.diffₓ t₂ :=
ht.diff_left l₂ ▸ hl.diff_right _
#align list.perm.diff List.Perm.diff
-/- warning: list.subperm.diff_right -> List.Subperm.diff_right is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Subperm.{u1} α l₁ l₂) -> (forall (t : List.{u1} α), List.Subperm.{u1} α (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ t) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ t))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Subperm.{u1} α l₁ l₂) -> (forall (t : List.{u1} α), List.Subperm.{u1} α (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ t) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ t))
-Case conversion may be inaccurate. Consider using '#align list.subperm.diff_right List.Subperm.diff_rightₓ'. -/
theorem Subperm.diff_right {l₁ l₂ : List α} (h : l₁ <+~ l₂) (t : List α) :
l₁.diffₓ t <+~ l₂.diffₓ t := by induction t generalizing l₁ l₂ h <;> simp [*, subperm.erase]
#align list.subperm.diff_right List.Subperm.diff_right
-/- warning: list.erase_cons_subperm_cons_erase -> List.erase_cons_subperm_cons_erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) (b : α) (l : List.{u1} α), List.Subperm.{u1} α (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) (List.cons.{u1} α a l) b) (List.cons.{u1} α a (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l b))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (a : α) (b : α) (l : List.{u1} α), List.Subperm.{u1} α (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) (List.cons.{u1} α a l) b) (List.cons.{u1} α a (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l b))
-Case conversion may be inaccurate. Consider using '#align list.erase_cons_subperm_cons_erase List.erase_cons_subperm_cons_eraseₓ'. -/
theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
(a :: l).eraseₓ b <+~ a :: l.eraseₓ b :=
by
@@ -1065,12 +933,6 @@ theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
· rw [erase_cons_tail _ h]
#align list.erase_cons_subperm_cons_erase List.erase_cons_subperm_cons_erase
-/- warning: list.subperm_cons_diff -> List.subperm_cons_diff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, List.Subperm.{u1} α (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) (List.cons.{u1} α a l₁) l₂) (List.cons.{u1} α a (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, List.Subperm.{u1} α (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) (List.cons.{u1} α a l₁) l₂) (List.cons.{u1} α a (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂))
-Case conversion may be inaccurate. Consider using '#align list.subperm_cons_diff List.subperm_cons_diffₓ'. -/
theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : List α}, (a :: l₁).diffₓ l₂ <+~ a :: l₁.diffₓ l₂
| l₁, [] => ⟨a :: l₁, by simp⟩
| l₁, b :: l₂ => by
@@ -1079,22 +941,10 @@ theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : List α}, (a :: l₁).diff
apply subperm_cons_diff
#align list.subperm_cons_diff List.subperm_cons_diff
-/- warning: list.subset_cons_diff -> List.subset_cons_diff is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, HasSubset.Subset.{u1} (List.{u1} α) (List.hasSubset.{u1} α) (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) (List.cons.{u1} α a l₁) l₂) (List.cons.{u1} α a (List.diffₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ l₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, HasSubset.Subset.{u1} (List.{u1} α) (List.instHasSubsetList.{u1} α) (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) (List.cons.{u1} α a l₁) l₂) (List.cons.{u1} α a (List.diff.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ l₂))
-Case conversion may be inaccurate. Consider using '#align list.subset_cons_diff List.subset_cons_diffₓ'. -/
theorem subset_cons_diff {a : α} {l₁ l₂ : List α} : (a :: l₁).diffₓ l₂ ⊆ a :: l₁.diffₓ l₂ :=
subperm_cons_diff.Subset
#align list.subset_cons_diff List.subset_cons_diff
-/- warning: list.perm.bag_inter_right -> List.Perm.bagInter_right is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} (t : List.{u1} α), (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ t) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ t))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} (t : List.{u1} α), (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ t) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ t))
-Case conversion may be inaccurate. Consider using '#align list.perm.bag_inter_right List.Perm.bagInter_rightₓ'. -/
theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
l₁.bagInterₓ t ~ l₂.bagInterₓ t :=
by
@@ -1109,12 +959,6 @@ theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂
· exact (ih_1 _).trans (ih_2 _)
#align list.perm.bag_inter_right List.Perm.bagInter_right
-/- warning: list.perm.bag_inter_left -> List.Perm.bagInter_left is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α) {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α t₁ t₂) -> (Eq.{succ u1} (List.{u1} α) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l t₁) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l t₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] (l : List.{u1} α) {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α t₁ t₂) -> (Eq.{succ u1} (List.{u1} α) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l t₁) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l t₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.bag_inter_left List.Perm.bagInter_leftₓ'. -/
theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
l.bagInterₓ t₁ = l.bagInterₓ t₂ :=
by
@@ -1124,23 +968,11 @@ theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂)
· simp [h, mt p.mem_iff.2 h, IH p]
#align list.perm.bag_inter_left List.Perm.bagInter_left
-/- warning: list.perm.bag_inter -> List.Perm.bagInter is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α t₁ t₂) -> (List.Perm.{u1} α (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₁ t₁) (List.bagInterₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ t₂))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {l₁ : List.{u1} α} {l₂ : List.{u1} α} {t₁ : List.{u1} α} {t₂ : List.{u1} α}, (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α t₁ t₂) -> (List.Perm.{u1} α (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₁ t₁) (List.bagInter.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ t₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.bag_inter List.Perm.bagInterₓ'. -/
theorem Perm.bagInter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
l₁.bagInterₓ t₁ ~ l₂.bagInterₓ t₂ :=
ht.bagInter_left l₂ ▸ hl.bagInter_right _
#align list.perm.bag_inter List.Perm.bagInter
-/- warning: list.cons_perm_iff_perm_erase -> List.cons_perm_iff_perm_erase is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, Iff (List.Perm.{u1} α (List.cons.{u1} α a l₁) l₂) (And (Membership.Mem.{u1, u1} α (List.{u1} α) (List.hasMem.{u1} α) a l₂) (List.Perm.{u1} α l₁ (List.eraseₓ.{u1} α (fun (a : α) (b : α) => _inst_1 a b) l₂ a)))
-but is expected to have type
- forall {α : Type.{u1}} [_inst_1 : DecidableEq.{succ u1} α] {a : α} {l₁ : List.{u1} α} {l₂ : List.{u1} α}, Iff (List.Perm.{u1} α (List.cons.{u1} α a l₁) l₂) (And (Membership.mem.{u1, u1} α (List.{u1} α) (List.instMembershipList.{u1} α) a l₂) (List.Perm.{u1} α l₁ (List.erase.{u1} α (instBEq.{u1} α (fun (a : α) (b : α) => _inst_1 a b)) l₂ a)))
-Case conversion may be inaccurate. Consider using '#align list.cons_perm_iff_perm_erase List.cons_perm_iff_perm_eraseₓ'. -/
theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
a :: l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.eraseₓ a :=
⟨fun h =>
@@ -1490,12 +1322,6 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
#align list.perm_lookmap List.perm_lookmap
-/
-/- warning: list.perm.erasep -> List.Perm.erasep is a dubious translation:
-lean 3 declaration is
- forall {α : Type.{u1}} (f : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α f] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Pairwise.{u1} α (fun (a : α) (b : α) => (f a) -> (f b) -> False) l₁) -> (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.erasePₓ.{u1} α f (fun (a : α) => _inst_1 a) l₁) (List.erasePₓ.{u1} α f (fun (a : α) => _inst_1 a) l₂))
-but is expected to have type
- forall {α : Type.{u1}} (f : α -> Prop) [_inst_1 : DecidablePred.{succ u1} α f] {l₁ : List.{u1} α} {l₂ : List.{u1} α}, (List.Pairwise.{u1} α (fun (a : α) (b : α) => (f a) -> (f b) -> False) l₁) -> (List.Perm.{u1} α l₁ l₂) -> (List.Perm.{u1} α (List.eraseP.{u1} α (fun (a : α) => Decidable.decide (f a) ((fun (a : α) => _inst_1 a) a)) l₁) (List.eraseP.{u1} α (fun (a : α) => Decidable.decide (f a) ((fun (a : α) => _inst_1 a) a)) l₂))
-Case conversion may be inaccurate. Consider using '#align list.perm.erasep List.Perm.erasepₓ'. -/
theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
(H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ :=
by
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -302,10 +302,8 @@ theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~
by
induction' p with x l₂ l₂' p IH x y l₂ l₂ m₂ r₂ p₁ p₂ IH₁ IH₂
· simp
- · simp only [filter_map]
- cases' f x with a <;> simp [filter_map, IH, perm.cons]
- · simp only [filter_map]
- cases' f x with a <;> cases' f y with b <;> simp [filter_map, swap]
+ · simp only [filter_map]; cases' f x with a <;> simp [filter_map, IH, perm.cons]
+ · simp only [filter_map]; cases' f x with a <;> cases' f y with b <;> simp [filter_map, swap]
· exact IH₁.trans IH₂
#align list.perm.filter_map List.Perm.filterMap
-/
@@ -448,8 +446,7 @@ theorem forall₂_comp_perm_eq_perm_comp_forall₂ : Forall₂ r ∘r Perm = Per
by
funext l₁ l₃; apply propext
constructor
- · intro h
- rcases h with ⟨l₂, h₁₂, h₂₃⟩
+ · intro h; rcases h with ⟨l₂, h₁₂, h₂₃⟩
have : forall₂ (flip r) l₂ l₁ := h₁₂.flip
rcases perm_comp_forall₂ h₂₃.symm this with ⟨l', h₁, h₂⟩
exact ⟨l', h₂.symm, h₁.flip⟩
@@ -639,9 +636,7 @@ but is expected to have type
Case conversion may be inaccurate. Consider using '#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_addₓ'. -/
theorem countp_eq_countp_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
[DecidablePred q] : l.countp p = (l.filterₓ q).countp p + (l.filterₓ fun a => ¬q a).countp p :=
- by
- rw [← countp_append]
- exact perm.countp_eq _ (filter_append_perm _ _).symm
+ by rw [← countp_append]; exact perm.countp_eq _ (filter_append_perm _ _).symm
#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_add
#print List.Perm.count_eq /-
@@ -783,43 +778,27 @@ theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} :
perm_induction_on p _ (fun x t₁ t₂ p IH => _) (fun x y t₁ t₂ p IH => _)
fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => _ <;>
intro l₁ l₂ r₁ r₂ e₁ e₂
- · apply (not_mem_nil a).elim
- rw [← e₁]
- simp
+ · apply (not_mem_nil a).elim; rw [← e₁]; simp
· cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
- · substs t₁ t₂
- exact p
- · substs z t₁ t₂
- exact p.trans perm_middle
- · substs y t₁ t₂
- exact perm_middle.symm.trans p
- · substs z t₁ t₂
- exact (IH rfl rfl).cons y
+ · substs t₁ t₂; exact p
+ · substs z t₁ t₂; exact p.trans perm_middle
+ · substs y t₁ t₂; exact perm_middle.symm.trans p
+ · substs z t₁ t₂; exact (IH rfl rfl).cons y
· rcases l₁ with (_ | ⟨y, _ | ⟨z, l₁⟩⟩) <;> rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩) <;>
dsimp at e₁ e₂ <;> injections <;> substs x y
- · substs r₁ r₂
- exact p.cons a
- · substs r₁ r₂
- exact p.cons u
- · substs r₁ v t₂
- exact (p.trans perm_middle).cons u
- · substs r₁ r₂
- exact p.cons y
- · substs r₁ r₂ y u
- exact p.cons a
- · substs r₁ u v t₂
- exact ((p.trans perm_middle).cons y).trans (swap _ _ _)
- · substs r₂ z t₁
- exact (perm_middle.symm.trans p).cons y
- · substs r₂ y z t₁
- exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
- · substs u v t₁ t₂
- exact (IH rfl rfl).swap' _ _
+ · substs r₁ r₂; exact p.cons a
+ · substs r₁ r₂; exact p.cons u
+ · substs r₁ v t₂; exact (p.trans perm_middle).cons u
+ · substs r₁ r₂; exact p.cons y
+ · substs r₁ r₂ y u; exact p.cons a
+ · substs r₁ u v t₂; exact ((p.trans perm_middle).cons y).trans (swap _ _ _)
+ · substs r₂ z t₁; exact (perm_middle.symm.trans p).cons y
+ · substs r₂ y z t₁; exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
+ · substs u v t₁ t₂; exact (IH rfl rfl).swap' _ _
· substs t₁ t₃
have : a ∈ t₂ := p₁.subset (by simp)
rcases mem_split this with ⟨l₂, r₂, e₂⟩
- subst t₂
- exact (IH₁ rfl rfl).trans (IH₂ rfl rfl)
+ subst t₂; exact (IH₁ rfl rfl).trans (IH₂ rfl rfl)
#align list.perm_inv_core List.perm_inv_core
-/
@@ -886,10 +865,8 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
case cons r₁ r₂ b s' ih =>
simp at h₂
cases' h₂ with e m
- · subst b
- exact ⟨a :: r₁, p.cons a, s'.cons2 _ _ _⟩
- · rcases ih m d₁ h₁ p with ⟨t, p', s'⟩
- exact ⟨t, p', s'.cons _ _ _⟩
+ · subst b; exact ⟨a :: r₁, p.cons a, s'.cons2 _ _ _⟩
+ · rcases ih m d₁ h₁ p with ⟨t, p', s'⟩; exact ⟨t, p', s'.cons _ _ _⟩
case
cons2 r₁ r₂ b s' ih =>
have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
@@ -1123,8 +1100,7 @@ theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂
by
induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t; · simp
· by_cases x ∈ t <;> simp [*, perm.cons]
- · by_cases x = y
- · simp [h]
+ · by_cases x = y; · simp [h]
by_cases xt : x ∈ t <;> by_cases yt : y ∈ t
· simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (Ne.symm h), erase_comm, swap]
· simp [xt, yt, mt mem_of_mem_erase, perm.cons]
@@ -1177,11 +1153,8 @@ theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ :=
⟨Perm.count_eq, fun H => by
induction' l₁ with a l₁ IH generalizing l₂
- · cases' l₂ with b l₂
- · rfl
- specialize H b
- simp at H
- contradiction
+ · cases' l₂ with b l₂; · rfl
+ specialize H b; simp at H; contradiction
· have : a ∈ l₂ := count_pos.1 (by rw [← H] <;> simp <;> apply Nat.succ_pos)
refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
specialize H b
@@ -1312,15 +1285,12 @@ theorem perm_insert_swap (x y : α) (l : List α) : insert x (insert y l) ~ inse
theorem perm_insertNth {α} (x : α) (l : List α) {n} (h : n ≤ l.length) : insertNth n x l ~ x :: l :=
by
induction l generalizing n
- · cases n
- rfl
- cases h
+ · cases n; rfl; cases h
cases n
· simp [insert_nth]
· simp only [insert_nth, modify_nth_tail]
trans
- · apply perm.cons
- apply l_ih
+ · apply perm.cons; apply l_ih
apply Nat.le_of_succ_le_succ h
· apply perm.swap
#align list.perm_insert_nth List.perm_insertNth
@@ -1398,8 +1368,7 @@ theorem Perm.pairwise_iff {R : α → α → Prop} (S : Symmetric R) :
⟨this p, this p.symm⟩
fun l₁ l₂ p d => by
induction' d with a l₁ h d IH generalizing l₂
- · rw [← p.nil_eq]
- constructor
+ · rw [← p.nil_eq]; constructor
· have : a ∈ l₂ := p.subset (mem_cons_self _ _)
rcases mem_split this with ⟨s₂, t₂, rfl⟩
have p' := (p.trans perm_middle).cons_inv
@@ -1507,16 +1476,12 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
change Pairwise F l₁ at H
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂; · simp
· cases h : f a
- · simp [h]
- exact IH (pairwise_cons.1 H).2
+ · simp [h]; exact IH (pairwise_cons.1 H).2
· simp [lookmap_cons_some _ _ h, p]
· cases' h₁ : f a with c <;> cases' h₂ : f b with d
- · simp [h₁, h₂]
- apply swap
- · simp [h₁, lookmap_cons_some _ _ h₂]
- apply swap
- · simp [lookmap_cons_some _ _ h₁, h₂]
- apply swap
+ · simp [h₁, h₂]; apply swap
+ · simp [h₁, lookmap_cons_some _ _ h₂]; apply swap
+ · simp [lookmap_cons_some _ _ h₁, h₂]; apply swap
· simp [lookmap_cons_some _ _ h₁, lookmap_cons_some _ _ h₂]
rcases(pairwise_cons.1 H).1 _ (Or.inl rfl) _ h₂ _ h₁ with ⟨rfl, rfl⟩
rfl
@@ -1539,8 +1504,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ p₂ IH₁ IH₂; · simp
· by_cases h : f a
· simp [h, p]
- · simp [h]
- exact IH (pairwise_cons.1 H).2
+ · simp [h]; exact IH (pairwise_cons.1 H).2
· by_cases h₁ : f a <;> by_cases h₂ : f b <;> simp [h₁, h₂]
· cases (pairwise_cons.1 H).1 _ (Or.inl rfl) h₂ h₁
· apply swap
@@ -1572,29 +1536,20 @@ theorem Perm.take_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : x
cases n <;>
simp only [mem_cons_iff, false_or_iff, true_or_iff, Filter, *, Nat.zero_eq, if_true,
not_mem_nil, eq_self_iff_true, or_false_iff, if_false, perm_cons, take]
- · rw [filter_eq_nil.2]
- intros
- solve_by_elim [Ne.symm]
- · convert perm.swap _ _ _
- rw [@filter_congr' _ _ (· ∈ take n h_l)]
- · clear h₁
- induction n generalizing h_l
- · simp
+ · rw [filter_eq_nil.2]; intros ; solve_by_elim [Ne.symm]
+ · convert perm.swap _ _ _; rw [@filter_congr' _ _ (· ∈ take n h_l)]
+ · clear h₁; induction n generalizing h_l; · simp
cases h_l <;>
simp only [mem_cons_iff, true_or_iff, eq_self_iff_true, filter_cons_of_pos, true_and_iff,
take, not_mem_nil, filter_false, take_nil]
cases' h₃ with _ _ h₃ h₄
rwa [@filter_congr' _ _ (· ∈ take n_n h_l_tl), n_ih]
- · introv h
- apply h₂ _ (Or.inr h)
- · introv h
- simp only [(h₃ x h).symm, false_or_iff]
- · introv h
- simp only [(h₂ x h).symm, (h₁ x (Or.inr h)).symm, false_or_iff]
+ · introv h; apply h₂ _ (Or.inr h)
+ · introv h; simp only [(h₃ x h).symm, false_or_iff]
+ · introv h; simp only [(h₂ x h).symm, (h₁ x (Or.inr h)).symm, false_or_iff]
case trans h_l₁ h_l₂ h_l₃ h₀ h₁ h_ih₀ h_ih₁ n =>
trans
- · apply h_ih₀
- rwa [h₁.nodup_iff]
+ · apply h_ih₀; rwa [h₁.nodup_iff]
· apply perm.filter _ h₁
#align list.perm.take_inter List.Perm.take_inter
-/
@@ -1605,9 +1560,7 @@ theorem Perm.drop_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : x
by
by_cases h'' : n ≤ xs.length
· let n' := xs.length - n
- have h₀ : n = xs.length - n' := by
- dsimp [n']
- rwa [tsub_tsub_cancel_of_le]
+ have h₀ : n = xs.length - n' := by dsimp [n']; rwa [tsub_tsub_cancel_of_le]
have h₁ : n' ≤ xs.length := by apply tsub_le_self
have h₂ : xs.drop n = (xs.reverse.take n').reverse := by
rw [reverse_take _ h₁, h₀, reverse_reverse]
@@ -1652,8 +1605,7 @@ theorem perm_of_mem_permutationsAux :
· subst e
have p : l₁ ++ l₂ ~ is := by
simp [permutations] at m
- cases' m with e m
- · simp [e]
+ cases' m with e m; · simp [e]
exact is.append_nil ▸ IH2 m
exact ((perm_middle.trans (p.cons _)).append_right _).trans (perm_append_comm.cons _)
#align list.perm_of_mem_permutations_aux List.perm_of_mem_permutationsAux
@@ -1705,8 +1657,7 @@ theorem mem_permutationsAux_of_perm :
intro t ts is IH1 IH2 l p
rw [permutations_aux_cons, mem_foldr_permutations_aux2]
rcases IH1 (p.trans perm_middle) with (⟨is', p', e⟩ | m)
- · clear p
- subst e
+ · clear p; subst e
rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
subst is'
have p := (perm_middle.symm.trans p').cons_inv
@@ -1729,10 +1680,8 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
(permutations'Aux a l).bind (permutations'Aux b) ~
(permutations'Aux b l).bind (permutations'Aux a) :=
by
- induction' l with c l ih
- · simp [swap]
- simp [permutations'_aux]
- apply perm.swap'
+ induction' l with c l ih; · simp [swap]
+ simp [permutations'_aux]; apply perm.swap'
have :
∀ a b,
(map (cons c) (permutations'_aux a l)).bind (permutations'_aux b) ~
@@ -1753,8 +1702,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t :=
by
induction' p with a s t p IH a b l s t u p₁ p₂ IH₁ IH₂; · simp
- · simp only [permutations']
- exact IH.bind_right _
+ · simp only [permutations']; exact IH.bind_right _
· simp only [permutations']
rw [bind_assoc, bind_assoc]
apply perm.bind_left
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce7e9d53d4bbc38065db3b595cd5bd73c323bc1d
@@ -1240,7 +1240,7 @@ theorem subperm_ext_iff {l₁ l₂ : List α} : l₁ <+~ l₂ ↔ ∀ x ∈ l₁
by
refine' this.trans (perm.subperm _)
exact perm_append_comm.trans (subperm_append_diff_self_of_count_le h)
- convert (subperm_append_right _).mpr nil_subperm using 1
+ convert(subperm_append_right _).mpr nil_subperm using 1
#align list.subperm_ext_iff List.subperm_ext_iff
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/4c586d291f189eecb9d00581aeb3dd998ac34442
@@ -359,7 +359,7 @@ theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
exact perm_append_comm.trans (perm_append_comm.cons _)
#align list.filter_append_perm List.filter_append_perm
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (l₁' list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l₁' list.perm l₁) -/
#print List.exists_perm_sublist /-
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
∃ (l₁' : _)(_ : l₁' ~ l₁), l₁' <+ l₂' :=
@@ -480,7 +480,7 @@ end Rel
section Subperm
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (l list.perm l₁) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (l list.perm l₁) -/
#print List.Subperm /-
/-- `subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
@@ -1687,7 +1687,7 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
#align list.length_permutations List.length_permutations
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (ts' list.perm «expr[ ,]»([])) -/
#print List.mem_permutations_of_perm_lemma /-
theorem mem_permutations_of_perm_lemma {is l : List α}
(H : l ~ [] ++ is → (∃ (ts' : _)(_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
@@ -1695,7 +1695,7 @@ theorem mem_permutations_of_perm_lemma {is l : List α}
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
-/
-/- ./././Mathport/Syntax/Translate/Basic.lean:628:2: warning: expanding binder collection (is' list.perm is) -/
+/- ./././Mathport/Syntax/Translate/Basic.lean:635:2: warning: expanding binder collection (is' list.perm is) -/
#print List.mem_permutationsAux_of_perm /-
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
@@ -853,9 +853,9 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
· obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt H'
erw [length_insertNth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn
rw [nthLe_insertNth_add_succ]
- convert nthLe_insertNth_add_succ s x k m.succ (by simpa using hn) using 2
- · simp [Nat.add_succ, Nat.succ_add]
- · simp [Nat.add_left_comm, Nat.add_comm]
+ · convert nthLe_insertNth_add_succ s x k m.succ (by simpa using hn) using 2
+ · simp [Nat.add_succ, Nat.succ_add]
+ · simp [Nat.add_left_comm, Nat.add_comm]
· simpa [Nat.succ_add] using hn
#align list.nodup_permutations'_aux_iff List.nodup_permutations'Aux_iff
This is a bit longer, partially duplicating the argument from UniqueFactorizationMonoid.multiplicity_eq_count_normalizedFactors, but it means we no longer need to depend on RingTheory.Int.Basic
at this point.
The other added lemmas seem useful regardless.
@@ -241,6 +241,19 @@ lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
· rintro (rfl | rfl)
exacts [nil_subperm, Subperm.refl _]
+attribute [simp] nil_subperm
+
+@[simp]
+theorem subperm_nil : List.Subperm l [] ↔ l = [] :=
+ match l with
+ | [] => by simp
+ | head :: tail => by
+ simp only [iff_false]
+ intro h
+ have := h.length_le
+ simp only [List.length_cons, List.length_nil, Nat.succ_ne_zero, ← Nat.not_lt, Nat.zero_lt_succ,
+ not_true_eq_false] at this
+
#align list.perm.countp_eq List.Perm.countP_eq
#align list.subperm.countp_le List.Subperm.countP_le
@@ -559,11 +559,6 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
apply h d hd c hc
#align list.perm_lookmap List.perm_lookmap
-@[deprecated Perm.eraseP]
-theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
- (H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) :
- List.eraseP f l₁ ~ List.eraseP f l₂ :=
- p.eraseP f (by simp [H])
#align list.perm.erasep List.Perm.eraseP
theorem Perm.take_inter {α : Type*} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
These are changes from #11997, the latest adaptation PR for nightly-2024-04-07, which can be made directly on master.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com>
@@ -422,7 +422,7 @@ theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h
rw [perm_iff_count, ← Decidable.and_forall_ne a, ← Decidable.and_forall_ne b]
suffices l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l by
simp (config := { contextual := true }) [count_replicate, h, h.symm, this, count_eq_zero]
- simp_rw [Ne.def, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons,
+ simp_rw [Ne, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons,
not_mem_nil, or_false, or_comm]
#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
Remove dependencies on algebra in the Data.List
folder except for:
Data.List.EditDistance
: Actually relies on algebra. Maybe should be moved?Data.List.Card
: Completely unused and redundant.Data.List.Cycle
: Relies on Fintype
, which shouldn't rely on algebra but it's hard to fix right now. Maybe should be moved?Data.List.Func
: Completely unused and redundant.Data.List.Lex
: That's order theory. Could be moved.Data.List.Prime
. That's algebra. Should definitely be moved.Data.List.Sym
: Relies on Multiset
, which shouldn't rely on algebra but it's hard to fix right now. Maybe should be moved?Data.List.ToFinsupp
: That's algebra. Should definitely be moved.As a consequence, move the big operators lemmas that were in there to Algebra.BigOperators.List.Basic
. For the lemmas that were Nat
-specific and not about auxiliary definitions, keep a version of them in the original file but stated using Nat.sum
.
Before
After
@@ -5,12 +5,10 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-/
import Mathlib.Data.List.Count
import Mathlib.Data.List.Dedup
-import Mathlib.Data.List.Permutation
-import Mathlib.Data.List.Pairwise
import Mathlib.Data.List.InsertNth
import Mathlib.Data.List.Lattice
+import Mathlib.Data.List.Permutation
import Mathlib.Data.Nat.Factorial.Basic
-import Mathlib.Data.List.Count
#align_import data.list.perm from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83"
@@ -25,6 +23,8 @@ another.
The notation `~` is used for permutation equivalence.
-/
+-- Make sure we don't import algebra
+assert_not_exists Monoid
open Nat
@@ -292,42 +292,6 @@ theorem Perm.fold_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : (l₁
end
-section CommMonoid
-
-/-- If elements of a list commute with each other, then their product does not
-depend on the order of elements. -/
-@[to_additive
- "If elements of a list additively commute with each other, then their sum does not
- depend on the order of elements."]
-theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
- l₁.prod = l₂.prod := by
- refine h.foldl_eq' ?_ _
- apply Pairwise.forall_of_forall
- · intro x y h z
- exact (h z).symm
- · intros; rfl
- · apply hc.imp
- intro a b h z
- rw [mul_assoc z, mul_assoc z, h]
-#align list.perm.prod_eq' List.Perm.prod_eq'
-#align list.perm.sum_eq' List.Perm.sum_eq'
-
-variable [CommMonoid α]
-
-@[to_additive]
-theorem Perm.prod_eq {l₁ l₂ : List α} (h : Perm l₁ l₂) : prod l₁ = prod l₂ :=
- h.fold_op_eq
-#align list.perm.prod_eq List.Perm.prod_eq
-#align list.perm.sum_eq List.Perm.sum_eq
-
-@[to_additive]
-theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
- (reverse_perm l).prod_eq
-#align list.prod_reverse List.prod_reverse
-#align list.sum_reverse List.sum_reverse
-
-end CommMonoid
-
#align list.perm_inv_core List.perm_inv_core
#align list.perm.cons_inv List.Perm.cons_inv
@@ -669,12 +633,12 @@ theorem length_permutationsAux :
refine' permutationsAux.rec (by simp) _
intro t ts is IH1 IH2
have IH2 : length (permutationsAux is nil) + 1 = is.length ! := by simpa using IH2
- simp? [Nat.factorial, Nat.add_succ, mul_comm] at IH1 says
- simp only [factorial, add_eq, add_zero, mul_comm] at IH1
+ simp? [Nat.factorial, Nat.add_succ, Nat.mul_comm] at IH1 says
+ simp only [factorial, add_eq, Nat.add_zero, Nat.mul_comm] at IH1
rw [permutationsAux_cons,
length_foldr_permutationsAux2' _ _ _ _ _ fun l m => (perm_of_mem_permutations m).length_eq,
- permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, mul_comm (_ + 1),
- ← Nat.succ_eq_add_one, ← IH1, add_comm (_ * _), add_assoc, Nat.mul_succ, mul_comm]
+ permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, Nat.mul_comm (_ + 1),
+ ← Nat.succ_eq_add_one, ← IH1, Nat.add_comm (_ * _), Nat.add_assoc, Nat.mul_succ, Nat.mul_comm]
#align list.length_permutations_aux List.length_permutationsAux
theorem length_permutations (l : List α) : length (permutations l) = (length l)! :=
@@ -800,7 +764,7 @@ theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
(hn : n < length (permutations'Aux x s)) :
(permutations'Aux x s).nthLe n hn = s.insertNth n x := by
induction' s with y s IH generalizing n
- · simp only [length, zero_add, Nat.lt_one_iff] at hn
+ · simp only [length, Nat.zero_add, Nat.lt_one_iff] at hn
simp [hn]
· cases n
· simp [nthLe]
@@ -817,7 +781,7 @@ theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
simpa [takeWhile, Nat.succ_inj', DecEq_eq] using IH _
· rw [takeWhile]
simp only [mem_map, cons.injEq, Ne.symm hx, false_and, and_false, exists_false,
- not_false_iff, count_eq_zero_of_not_mem, zero_add, hx, decide_False, length_nil]
+ not_false_iff, count_eq_zero_of_not_mem, Nat.zero_add, hx, decide_False, length_nil]
#align list.count_permutations'_aux_self List.count_permutations'Aux_self
@[simp]
@@ -883,7 +847,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
rw [nthLe_insertNth_add_succ]
convert nthLe_insertNth_add_succ s x k m.succ (by simpa using hn) using 2
· simp [Nat.add_succ, Nat.succ_add]
- · simp [add_left_comm, add_comm]
+ · simp [Nat.add_left_comm, Nat.add_comm]
· simpa [Nat.succ_add] using hn
#align list.nodup_permutations'_aux_iff List.nodup_permutations'Aux_iff
@@ -137,7 +137,6 @@ open Relator
variable {γ : Type*} {δ : Type*} {r : α → β → Prop} {p : γ → δ → Prop}
--- mathport name: «expr ∘r »
local infixr:80 " ∘r " => Relation.Comp
theorem perm_comp_perm : (Perm ∘r Perm : List α → List α → Prop) = Perm := by
@@ -283,10 +282,8 @@ section
variable {op : α → α → α} [IA : Std.Associative op] [IC : Std.Commutative op]
--- mathport name: op
local notation a " * " b => op a b
--- mathport name: foldl
local notation l " <*> " a => foldl op a l
theorem Perm.fold_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : (l₁ <*> a) = l₂ <*> a :=
Algebra.BigOperators.List.Basic
, Data.List.Chain
not depend on Data.Nat.Order.Basic
by using Nat
-specific Std lemmas rather than general mathlib ones. I leave the Data.Nat.Basic
import since Algebra.BigOperators.List.Basic
is algebra territory.Algebra.BigOperators.List.Basic
not depend on Algebra.Divisibility.Basic
. I'm not too sure about that one since they already are algebra. My motivation is that they involve ring-like objects while big operators are about group-like objects, but this is in some sense a second order refactor.MonoidWithZero
lemmas from Algebra.BigOperators.List.Basic
to Algebra.BigOperators.List.Lemmas
.Algebra.BigOperators.List.Defs
to Algebra.BigOperators.List.Basic
since no file imported the former without the latter and their imports are becoming very close after this PR.Data.List.Count
, Data.List.Dedup
, Data.List.ProdSigma
, Data.List.Zip
not depend on Algebra.BigOperators.List.Basic
.Algebra.BigOperators.List.Basic
. For the lemmas that were Nat
-specific, keep a version of them stated using Nat.sum
.Nat.sum_eq_listSum (l : List Nat) : Nat.sum l = l.sum
.@@ -3,6 +3,7 @@ Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-/
+import Mathlib.Data.List.Count
import Mathlib.Data.List.Dedup
import Mathlib.Data.List.Permutation
import Mathlib.Data.List.Pairwise
@@ -607,7 +607,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
theorem Perm.take_inter {α : Type*} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
(h' : ys.Nodup) : xs.take n ~ ys.inter (xs.take n) := by
simp only [List.inter]
- exact Perm.trans (show xs.take n ~ xs.filter (· ∈ xs.take n) by
+ exact Perm.trans (show xs.take n ~ xs.filter (xs.take n).elem by
conv_lhs => rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')])
(Perm.filter _ h)
#align list.perm.take_inter List.Perm.take_inter
Data.List.Count
, Data.List.Dedup
, Data.List.ProdSigma
, Data.List.Range
, Data.List.Rotate
, Data.List.Zip
not depend on Data.List.BigOperators.Basic
.Data.List.BigOperators.Basic
. For the lemmas that were Nat
-specific, keep a version of them in the original file but stated using Nat.sum
.Nat.sum_eq_listSum (l : List Nat) : Nat.sum l = l.sum
.@@ -9,6 +9,7 @@ import Mathlib.Data.List.Pairwise
import Mathlib.Data.List.InsertNth
import Mathlib.Data.List.Lattice
import Mathlib.Data.Nat.Factorial.Basic
+import Mathlib.Data.List.Count
#align_import data.list.perm from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83"
Move basic Nat
lemmas from Data.Nat.Order.Basic
and Data.Nat.Pow
to Data.Nat.Defs
. Most proofs need adapting, but that's easily solved by replacing the general mathlib lemmas by the new Std Nat
-specific lemmas and using omega
.
Data.Nat.Pow
to Algebra.GroupPower.Order
Data.Nat.Pow
to Algebra.GroupPower.Order
bit
/bit0
/bit1
lemmas from Data.Nat.Order.Basic
to Data.Nat.Bits
Data.Nat.Order.Basic
anymoreNat
-specific lemmas to help fix the fallout (look for nolint simpNF
)Nat.mul_self_le_mul_self_iff
and Nat.mul_self_lt_mul_self_iff
around (they were misnamed)Nat.one_lt_pow
implicit@@ -615,9 +615,8 @@ theorem Perm.drop_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : x
xs.drop n ~ ys.inter (xs.drop n) := by
by_cases h'' : n ≤ xs.length
· let n' := xs.length - n
- have h₀ : n = xs.length - n' := by
- rwa [tsub_tsub_cancel_of_le]
- have h₁ : n' ≤ xs.length := by apply tsub_le_self
+ have h₀ : n = xs.length - n' := by rwa [Nat.sub_sub_self]
+ have h₁ : n' ≤ xs.length := Nat.sub_le ..
have h₂ : xs.drop n = (xs.reverse.take n').reverse := by
rw [reverse_take _ h₁, h₀, reverse_reverse]
rw [h₂]
@@ -627,7 +626,7 @@ theorem Perm.drop_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : x
apply (reverse_perm _).trans; assumption
· have : drop n xs = [] := by
apply eq_nil_of_length_eq_zero
- rw [length_drop, tsub_eq_zero_iff_le]
+ rw [length_drop, Nat.sub_eq_zero_iff_le]
apply le_of_not_ge h''
simp [this, List.inter]
#align list.perm.drop_inter List.Perm.drop_inter
@@ -802,7 +801,7 @@ theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
(hn : n < length (permutations'Aux x s)) :
(permutations'Aux x s).nthLe n hn = s.insertNth n x := by
induction' s with y s IH generalizing n
- · simp only [length, zero_add, lt_one_iff] at hn
+ · simp only [length, zero_add, Nat.lt_one_iff] at hn
simp [hn]
· cases n
· simp [nthLe]
@@ -864,8 +863,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
intro H
obtain ⟨k, hk, hk'⟩ := nthLe_of_mem H
rw [nodup_iff_nthLe_inj] at h
- suffices k = k + 1 by simp at this
- refine' h k (k + 1) _ _ _
+ refine k.succ_ne_self.symm $ h k (k + 1) ?_ ?_ ?_
· simpa [Nat.lt_succ_iff] using hk.le
· simpa using hk
rw [nthLe_permutations'Aux, nthLe_permutations'Aux]
List.mem_split
duplicates List.append_of_mem
from Std
:
https://github.com/leanprover/std4/blob/a756b7d643ae5dcd7bf314e99f8e493e5d81b9ed/Std/Data/List/Lemmas.lean#L94-L96
This PR makes it an alias.
Co-authored-by: Yaël Dillies <yael.dillies@gmail.com>
@@ -373,7 +373,7 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
have am : a ∈ r₂ := by
simp only [find?, mem_cons] at h₂
exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
- rcases mem_split bm with ⟨t₁, t₂, rfl⟩
+ rcases append_of_mem bm with ⟨t₁, t₂, rfl⟩
have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp
rcases ih (d₁.sublist st) (mt (fun x => st.subset x) h₁) am
(Perm.cons_inv <| p.trans perm_middle) with
@@ -699,7 +699,7 @@ theorem mem_permutationsAux_of_perm :
rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
· clear p
subst e
- rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
+ rcases append_of_mem (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
subst is'
have p := (perm_middle.symm.trans p').cons_inv
cases' l₂ with a l₂'
Removes the insertNth
section of this long file to its own new file. This section seems to be completely independent of the rest of the file, so this is a fairly easy split to make.
@@ -6,6 +6,7 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
import Mathlib.Data.List.Dedup
import Mathlib.Data.List.Permutation
import Mathlib.Data.List.Pairwise
+import Mathlib.Data.List.InsertNth
import Mathlib.Data.List.Lattice
import Mathlib.Data.Nat.Factorial.Basic
@@ -653,7 +653,7 @@ theorem perm_of_mem_permutationsAux :
rcases m with (m | ⟨l₁, l₂, m, _, rfl⟩)
· exact (IH1 _ m).trans perm_middle
· have p : l₁ ++ l₂ ~ is := by
- simp [permutations] at m
+ simp only [mem_cons] at m
cases' m with e m
· simp [e]
exact is.append_nil ▸ IH2 _ m
Homogenises porting notes via capitalisation and addition of whitespace.
It makes the following changes:
@@ -352,7 +352,7 @@ alias ⟨subperm.of_cons, subperm.cons⟩ := subperm_cons
#align list.subperm.of_cons List.subperm.of_cons
#align list.subperm.cons List.subperm.cons
---Porting note: commented out
+-- Porting note: commented out
--attribute [protected] subperm.cons
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
@@ -712,7 +712,7 @@ theorem mem_permutations {s t : List α} : s ∈ permutations t ↔ s ~ t :=
⟨perm_of_mem_permutations, mem_permutations_of_perm_lemma mem_permutationsAux_of_perm⟩
#align list.mem_permutations List.mem_permutations
---Porting note: temporary theorem to solve diamond issue
+-- Porting note: temporary theorem to solve diamond issue
private theorem DecEq_eq {α : Type*} [DecidableEq α] :
instBEqList = @instBEq (List α) instDecidableEqList :=
congr_arg BEq.mk <| by
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
@@ -278,7 +278,7 @@ theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : Left
section
-variable {op : α → α → α} [IA : IsAssociative α op] [IC : IsCommutative α op]
+variable {op : α → α → α} [IA : Std.Associative op] [IC : Std.Commutative op]
-- mathport name: op
local notation a " * " b => op a b
@@ -5,7 +5,8 @@ Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-/
import Mathlib.Data.List.Dedup
import Mathlib.Data.List.Permutation
-import Mathlib.Data.List.Range
+import Mathlib.Data.List.Pairwise
+import Mathlib.Data.List.Lattice
import Mathlib.Data.Nat.Factorial.Basic
#align_import data.list.perm from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83"
This is needed to work with leanprover/lean4#3087
@@ -746,7 +746,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
· exact IH.bind_right _
- · dsimp [permutations']
+ · dsimp
rw [bind_assoc, bind_assoc]
apply Perm.bind_left
intro l' _
cases x with | ...
instead of cases x; case => ...
(#9321)
This converts usages of the pattern
cases h
case inl h' => ...
case inr h' => ...
which derive from mathported code, to the "structured cases
" syntax:
cases h with
| inl h' => ...
| inr h' => ...
The case where the subgoals are handled with ·
instead of case
is more contentious (and much more numerous) so I left those alone. This pattern also appears with cases'
, induction
, induction'
, and rcases
. Furthermore, there is a similar transformation for by_cases
:
by_cases h : cond
case pos => ...
case neg => ...
is replaced by:
if h : cond then
...
else
...
Co-authored-by: Mario Carneiro <di.gama@gmail.com>
@@ -145,18 +145,17 @@ theorem perm_comp_perm : (Perm ∘r Perm : List α → List α → Prop) = Perm
theorem perm_comp_forall₂ {l u v} (hlu : Perm l u) (huv : Forall₂ r u v) :
(Forall₂ r ∘r Perm) l v := by
- induction hlu generalizing v
- case nil => cases huv; exact ⟨[], Forall₂.nil, Perm.nil⟩
- case cons a l u _hlu ih =>
+ induction hlu generalizing v with
+ | nil => cases huv; exact ⟨[], Forall₂.nil, Perm.nil⟩
+ | cons u _hlu ih =>
cases' huv with _ b _ v hab huv'
rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩
exact ⟨b :: l₂, Forall₂.cons hab h₁₂, h₂₃.cons _⟩
- case swap a₁ a₂ h₂₃ =>
+ | swap a₁ a₂ h₂₃ =>
cases' huv with _ b₁ _ l₂ h₁ hr₂₃
cases' hr₂₃ with _ b₂ _ l₂ h₂ h₁₂
exact ⟨b₂ :: b₁ :: l₂, Forall₂.cons h₂ (Forall₂.cons h₁ h₁₂), Perm.swap _ _ _⟩
- case
- trans la₁ la₂ la₃ _ _ ih₁ ih₂ =>
+ | trans _ _ ih₁ ih₂ =>
rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩
rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩
exact ⟨lb₁, hab₁, Perm.trans h₁₂ h₂₃⟩
@@ -267,11 +266,11 @@ theorem Perm.foldl_eq {f : β → α → β} {l₁ l₂ : List α} (rcomm : Righ
theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : LeftCommutative f) (p : l₁ ~ l₂) :
∀ b, foldr f b l₁ = foldr f b l₂ := by
intro b
- induction p using Perm.recOnSwap' generalizing b
- case nil => rfl
- case cons r => simp; rw [r b]
- case swap' r => simp; rw [lcomm, r b]
- case trans r₁ r₂ => exact Eq.trans (r₁ b) (r₂ b)
+ induction p using Perm.recOnSwap' generalizing b with
+ | nil => rfl
+ | cons _ _ r => simp; rw [r b]
+ | swap' _ _ _ r => simp; rw [lcomm, r b]
+ | trans _ _ r₁ r₂ => exact Eq.trans (r₁ b) (r₂ b)
#align list.perm.foldr_eq List.Perm.foldr_eq
#align list.perm.rec_heq List.Perm.rec_heq
@@ -358,16 +357,16 @@ alias ⟨subperm.of_cons, subperm.cons⟩ := subperm_cons
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
(s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
rcases s with ⟨l, p, s⟩
- induction s generalizing l₁
- case slnil => cases h₂
- case cons r₁ r₂ b s' ih =>
+ induction s generalizing l₁ with
+ | slnil => cases h₂
+ | @cons r₁ r₂ b s' ih =>
simp? at h₂ says simp only [mem_cons] at h₂
cases' h₂ with e m
· subst b
exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
· rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
exact ⟨t, p', s'.cons _⟩
- case cons₂ r₁ r₂ b _ ih =>
+ | @cons₂ r₁ r₂ b _ ih =>
have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
have am : a ∈ r₂ := by
simp only [find?, mem_cons] at h₂
@@ -503,9 +502,9 @@ theorem Perm.dedup {l₁ l₂ : List α} (p : l₁ ~ l₂) : dedup l₁ ~ dedup
theorem Perm.inter_append {l t₁ t₂ : List α} (h : Disjoint t₁ t₂) :
l ∩ (t₁ ++ t₂) ~ l ∩ t₁ ++ l ∩ t₂ := by
- induction l
- case nil => simp
- case cons x xs l_ih =>
+ induction l with
+ | nil => simp
+ | cons x xs l_ih =>
by_cases h₁ : x ∈ t₁
· have h₂ : x ∉ t₂ := h h₁
simp [*]
bump/v4.5.0
branch. (#9188)
This PR:
v4.5.0-rc1
v4.5.0-rc1
bump/v4.5.0
branch
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@@ -361,7 +361,7 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
induction s generalizing l₁
case slnil => cases h₂
case cons r₁ r₂ b s' ih =>
- simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
+ simp? at h₂ says simp only [mem_cons] at h₂
cases' h₂ with e m
· subst b
exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
@@ -361,7 +361,7 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
induction s generalizing l₁
case slnil => cases h₂
case cons r₁ r₂ b s' ih =>
- simp at h₂
+ simp? at h₂ says simp only [Bool.not_eq_true, mem_cons] at h₂
cases' h₂ with e m
· subst b
exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
@@ -670,7 +670,8 @@ theorem length_permutationsAux :
refine' permutationsAux.rec (by simp) _
intro t ts is IH1 IH2
have IH2 : length (permutationsAux is nil) + 1 = is.length ! := by simpa using IH2
- simp [Nat.factorial, Nat.add_succ, mul_comm] at IH1
+ simp? [Nat.factorial, Nat.add_succ, mul_comm] at IH1 says
+ simp only [factorial, add_eq, add_zero, mul_comm] at IH1
rw [permutationsAux_cons,
length_foldr_permutationsAux2' _ _ _ _ _ fun l m => (perm_of_mem_permutations m).length_eq,
permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, mul_comm (_ + 1),
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -229,14 +229,9 @@ lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
obtain ⟨l', h₂⟩ := h₂.exists_perm_append
exact ⟨l₁ ++ l', (h₂.trans (h₁.append_right _)).symm, (prefix_append _ _).sublist⟩
--- This is now in `Std`, but apparently misnamed as `List.subperm_singleton_iff`.
-lemma singleton_subperm_iff : [a] <+~ l ↔ a ∈ l :=
- ⟨fun ⟨s, hla, h⟩ ↦ by rwa [perm_singleton.1 hla, singleton_sublist] at h,
- fun h ↦ ⟨[a], perm_rfl, singleton_sublist.2 h⟩⟩
#align list.subperm_singleton_iff List.singleton_subperm_iff
--- The prime could be removed if `List.subperm_singleton_iff` is renamed in Std.
-@[simp] lemma subperm_singleton_iff' : l <+~ [a] ↔ l = [] ∨ l = [a] := by
+@[simp] lemma subperm_singleton_iff : l <+~ [a] ↔ l = [] ∨ l = [a] := by
constructor
· rw [subperm_iff]
rintro ⟨s, hla, h⟩
Co-authored-by: James <jamesgallicchio@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mario Carneiro <di.gama@gmail.com> Co-authored-by: Siddharth Bhat <siddu.druid@gmail.com>
@@ -229,7 +229,6 @@ lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
obtain ⟨l', h₂⟩ := h₂.exists_perm_append
exact ⟨l₁ ++ l', (h₂.trans (h₁.append_right _)).symm, (prefix_append _ _).sublist⟩
-
-- This is now in `Std`, but apparently misnamed as `List.subperm_singleton_iff`.
lemma singleton_subperm_iff : [a] <+~ l ↔ a ∈ l :=
⟨fun ⟨s, hla, h⟩ ↦ by rwa [perm_singleton.1 hla, singleton_sublist] at h,
@@ -27,13 +27,6 @@ open Nat
namespace List
variable {α β : Type*} {l l₁ l₂ : List α} {a : α}
-/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
- of each other. This is defined by induction using pairwise swaps. -/
-inductive Perm : List α → List α → Prop
- | nil : Perm [] []
- | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
- | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
- | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
#align list.perm List.Perm
instance {α : Type*} : Trans (@List.Perm α) (@List.Perm α) List.Perm where
@@ -41,61 +34,27 @@ instance {α : Type*} : Trans (@List.Perm α) (@List.Perm α) List.Perm where
open Perm (swap)
-/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
- of each other. This is defined by induction using pairwise swaps. -/
-infixl:50 " ~ " => Perm
-
-@[simp, refl]
-protected theorem Perm.refl : ∀ l : List α, l ~ l
- | [] => Perm.nil
- | x :: xs => (Perm.refl xs).cons x
+attribute [refl] Perm.refl
#align list.perm.refl List.Perm.refl
lemma perm_rfl : l ~ l := Perm.refl _
-- Porting note: used rec_on in mathlib3; lean4 eqn compiler still doesn't like it
-@[symm]
-protected theorem Perm.symm {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₂ ~ l₁ :=
- p.rec
- .nil
- (fun x _ _ _ r₁ => .cons x r₁)
- (fun x y l => .swap y x l)
- (fun _ _ r₁ r₂ => .trans r₂ r₁)
+attribute [symm] Perm.symm
#align list.perm.symm List.Perm.symm
-theorem perm_comm {l₁ l₂ : List α} : l₁ ~ l₂ ↔ l₂ ~ l₁ :=
- ⟨Perm.symm, Perm.symm⟩
#align list.perm_comm List.perm_comm
-theorem Perm.swap' (x y : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : y :: x :: l₁ ~ x :: y :: l₂ :=
- (swap _ _ _).trans ((p.cons _).cons _)
#align list.perm.swap' List.Perm.swap'
attribute [trans] Perm.trans
-theorem Perm.eqv (α) : Equivalence (@Perm α) :=
- ⟨Perm.refl, Perm.symm, Perm.trans⟩
#align list.perm.eqv List.Perm.eqv
---Porting note: new theorem
-theorem Perm.of_eq (h : l₁ = l₂) : l₁ ~ l₂ :=
- h ▸ Perm.refl l₁
-
-instance isSetoid (α) : Setoid (List α) :=
- Setoid.mk (@Perm α) (Perm.eqv α)
#align list.is_setoid List.isSetoid
--- Porting note: used rec_on in mathlib3; lean4 eqn compiler still doesn't like it
-theorem Perm.mem_iff {a : α} {l₁ l₂ : List α} (p : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
- p.rec
- Iff.rfl
- (fun _ _ _ _ hs => by simp only [mem_cons, hs])
- (fun _ _ _ => by simp only [mem_cons, or_left_comm])
- (fun _ _ => Iff.trans)
#align list.perm.mem_iff List.Perm.mem_iff
-theorem Perm.subset {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ :=
- fun _ => p.mem_iff.mp
#align list.perm.subset List.Perm.subset
theorem Perm.subset_congr_left {l₁ l₂ l₃ : List α} (h : l₁ ~ l₂) : l₁ ⊆ l₃ ↔ l₂ ⊆ l₃ :=
@@ -106,219 +65,66 @@ theorem Perm.subset_congr_right {l₁ l₂ l₃ : List α} (h : l₁ ~ l₂) : l
⟨fun h' => h'.trans h.subset, fun h' => h'.trans h.symm.subset⟩
#align list.perm.subset_congr_right List.Perm.subset_congr_right
-theorem Perm.append_right {l₁ l₂ : List α} (t₁ : List α) (p : l₁ ~ l₂) : l₁ ++ t₁ ~ l₂ ++ t₁ :=
- p.rec
- (Perm.refl ([] ++ t₁))
- (fun x _ _ _ r₁ => r₁.cons x)
- (fun x y _ => swap x y _)
- (fun _ _ r₁ r₂ => r₁.trans r₂)
#align list.perm.append_right List.Perm.append_right
-theorem Perm.append_left {t₁ t₂ : List α} : ∀ l : List α, t₁ ~ t₂ → l ++ t₁ ~ l ++ t₂
- | [], p => p
- | x :: xs, p => (p.append_left xs).cons x
#align list.perm.append_left List.Perm.append_left
-theorem Perm.append {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ++ t₁ ~ l₂ ++ t₂ :=
- (p₁.append_right t₁).trans (p₂.append_left l₂)
#align list.perm.append List.Perm.append
-theorem Perm.append_cons (a : α) {h₁ h₂ t₁ t₂ : List α} (p₁ : h₁ ~ h₂) (p₂ : t₁ ~ t₂) :
- h₁ ++ a :: t₁ ~ h₂ ++ a :: t₂ :=
- p₁.append (p₂.cons a)
#align list.perm.append_cons List.Perm.append_cons
-@[simp]
-theorem perm_middle {a : α} : ∀ {l₁ l₂ : List α}, l₁ ++ a :: l₂ ~ a :: (l₁ ++ l₂)
- | [], _ => Perm.refl _
- | b :: l₁, l₂ => ((@perm_middle a l₁ l₂).cons _).trans (swap a b _)
#align list.perm_middle List.perm_middle
-@[simp]
-theorem perm_append_singleton (a : α) (l : List α) : l ++ [a] ~ a :: l :=
- perm_middle.trans <| by rw [append_nil]
#align list.perm_append_singleton List.perm_append_singleton
-theorem perm_append_comm : ∀ {l₁ l₂ : List α}, l₁ ++ l₂ ~ l₂ ++ l₁
- | [], l₂ => by simp
- | a :: t, l₂ => (perm_append_comm.cons _).trans perm_middle.symm
#align list.perm_append_comm List.perm_append_comm
-theorem concat_perm (l : List α) (a : α) : concat l a ~ a :: l := by simp
#align list.concat_perm List.concat_perm
-theorem Perm.length_eq {l₁ l₂ : List α} (p : l₁ ~ l₂) : length l₁ = length l₂ :=
- p.rec
- rfl
- (fun _x l₁ l₂ _p r => by simp [r])
- (fun _x _y l => by simp)
- (fun _p₁ _p₂ r₁ r₂ => Eq.trans r₁ r₂)
#align list.perm.length_eq List.Perm.length_eq
-theorem Perm.eq_nil {l : List α} (p : l ~ []) : l = [] :=
- eq_nil_of_length_eq_zero p.length_eq
#align list.perm.eq_nil List.Perm.eq_nil
-theorem Perm.nil_eq {l : List α} (p : [] ~ l) : [] = l :=
- p.symm.eq_nil.symm
#align list.perm.nil_eq List.Perm.nil_eq
-@[simp]
-theorem perm_nil {l₁ : List α} : l₁ ~ [] ↔ l₁ = [] :=
- ⟨fun p => p.eq_nil, fun e => e ▸ Perm.refl _⟩
#align list.perm_nil List.perm_nil
-@[simp]
-theorem nil_perm {l₁ : List α} : [] ~ l₁ ↔ l₁ = [] :=
- perm_comm.trans perm_nil
#align list.nil_perm List.nil_perm
-theorem not_perm_nil_cons (x : α) (l : List α) : ¬[] ~ x :: l
- | p => by injection p.symm.eq_nil
#align list.not_perm_nil_cons List.not_perm_nil_cons
-@[simp]
-theorem reverse_perm : ∀ l : List α, reverse l ~ l
- | [] => Perm.nil
- | a :: l => by
- rw [reverse_cons]
- exact (perm_append_singleton _ _).trans ((reverse_perm l).cons a)
#align list.reverse_perm List.reverse_perm
-theorem perm_cons_append_cons {l l₁ l₂ : List α} (a : α) (p : l ~ l₁ ++ l₂) :
- a :: l ~ l₁ ++ a :: l₂ :=
- (p.cons a).trans perm_middle.symm
#align list.perm_cons_append_cons List.perm_cons_append_cons
-@[simp]
-theorem perm_replicate {n : ℕ} {a : α} {l : List α} :
- l ~ replicate n a ↔ l = replicate n a :=
- ⟨fun p => eq_replicate.2
- ⟨p.length_eq.trans <| length_replicate _ _, fun _b m => eq_of_mem_replicate <| p.subset m⟩,
- fun h => h ▸ Perm.refl _⟩
#align list.perm_replicate List.perm_replicate
-@[simp]
-theorem replicate_perm {n : ℕ} {a : α} {l : List α} :
- replicate n a ~ l ↔ replicate n a = l :=
- (perm_comm.trans perm_replicate).trans eq_comm
#align list.replicate_perm List.replicate_perm
-@[simp]
-theorem perm_singleton {a : α} {l : List α} : l ~ [a] ↔ l = [a] :=
- @perm_replicate α 1 a l
#align list.perm_singleton List.perm_singleton
-@[simp]
-theorem singleton_perm {a : α} {l : List α} : [a] ~ l ↔ [a] = l :=
- @replicate_perm α 1 a l
#align list.singleton_perm List.singleton_perm
-alias ⟨Perm.eq_singleton, _⟩ := perm_singleton
-alias ⟨Perm.singleton_eq, _⟩ := singleton_perm
-
-theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b := by simp
#align list.singleton_perm_singleton List.singleton_perm_singleton
-theorem perm_cons_erase [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : l ~ a :: l.erase a :=
- let ⟨_l₁, _l₂, _, e₁, e₂⟩ := exists_erase_eq h
- e₂.symm ▸ e₁.symm ▸ perm_middle
#align list.perm_cons_erase List.perm_cons_erase
-@[elab_as_elim]
-theorem perm_induction_on {P : List α → List α → Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂) (h₁ : P [] [])
- (h₂ : ∀ x l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (x :: l₁) (x :: l₂))
- (h₃ : ∀ x y l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (y :: x :: l₁) (x :: y :: l₂))
- (h₄ : ∀ l₁ l₂ l₃, l₁ ~ l₂ → l₂ ~ l₃ → P l₁ l₂ → P l₂ l₃ → P l₁ l₃) : P l₁ l₂ :=
- have P_refl : ∀ l, P l l := fun l => List.recOn l h₁ fun x xs ih => h₂ x xs xs (Perm.refl xs) ih
- p.rec h₁ h₂ (fun x y l => h₃ x y l l (Perm.refl l) (P_refl l)) @h₄
-#align list.perm_induction_on List.perm_induction_onₓ
+#align list.perm_induction_on List.Perm.recOnSwap'
--- Porting note: TODO figure out why invalid congr
--- @[congr]
-theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~ l₂) :
- filterMap f l₁ ~ filterMap f l₂ := by
- induction p with
- | nil => simp
- | cons x _p IH =>
- cases h : f x
- <;> simp [h, filterMap, IH, Perm.cons]
- | swap x y l₂ =>
- cases hx : f x
- <;> cases hy : f y
- <;> simp [hx, hy, filterMap, swap]
- | trans _p₁ _p₂ IH₁ IH₂ =>
- exact IH₁.trans IH₂
+-- Porting note: used to be @[congr]
#align list.perm.filter_map List.Perm.filterMap
--- Porting note: TODO figure out why invalid congr
--- @[congr]
-theorem Perm.map (f : α → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) : map f l₁ ~ map f l₂ :=
- filterMap_eq_map f ▸ p.filterMap _
+-- Porting note: used to be @[congr]
#align list.perm.map List.Perm.map
-theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) {H₁ H₂} :
- pmap f l₁ H₁ ~ pmap f l₂ H₂ := by
- induction p with
- | nil => simp
- | cons x _p IH => simp [IH, Perm.cons]
- | swap x y => simp [swap]
- | trans _p₁ p₂ IH₁ IH₂ =>
- refine' IH₁.trans IH₂
- exact fun a m => H₂ a (p₂.subset m)
#align list.perm.pmap List.Perm.pmap
-theorem Perm.filter (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
- filter p l₁ ~ filter p l₂ := by rw [← filterMap_eq_filter]; apply s.filterMap _
#align list.perm.filter List.Perm.filter
-theorem filter_append_perm (p : α → Bool) (l : List α) :
- filter p l ++ filter (fun x => ¬p x) l ~ l := by
- induction' l with x l ih
- · rfl
- · by_cases h : p x
- · simp only [h, filter_cons_of_pos, filter_cons_of_neg, not_true, not_false_iff, cons_append,
- decide_False]
- exact ih.cons x
- · simp only [h, filter_cons_of_neg, not_false_iff, filter_cons_of_pos, cons_append,
- not_false_eq_true, decide_True]
- refine' Perm.trans _ (ih.cons x)
- exact perm_append_comm.trans (perm_append_comm.cons _)
#align list.filter_append_perm List.filter_append_perm
-theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
- ∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' := by
- induction p generalizing l₁ with
- | nil =>
- exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
- | cons x _ IH =>
- cases' s with _ _ _ s l₁ _ _ s
- · exact
- let ⟨l₁', p', s'⟩ := IH s
- ⟨l₁', p', s'.cons _⟩
- · exact
- let ⟨l₁', p', s'⟩ := IH s
- ⟨x :: l₁', p'.cons x, s'.cons₂ _⟩
- | swap x y _ =>
- cases' s with _ _ _ s l₁ _ _ s <;> cases' s with _ _ _ s l₁ _ _ s
- · exact ⟨l₁, Perm.refl _, (s.cons _).cons _⟩
- · exact ⟨x :: l₁, Perm.refl _, (s.cons _).cons₂ _⟩
- · exact ⟨y :: l₁, Perm.refl _, (s.cons₂ _).cons _⟩
- · exact ⟨x :: y :: l₁, Perm.swap _ _ _, (s.cons₂ _).cons₂ _⟩
- | trans _ _ IH₁ IH₂ =>
- exact
- let ⟨m₁, pm, sm⟩ := IH₁ s
- let ⟨r₁, pr, sr⟩ := IH₂ sm
- ⟨r₁, pr.trans pm, sr⟩
#align list.exists_perm_sublist List.exists_perm_sublist
-theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂) :
- sizeOf l₁ = sizeOf l₂ := by
- induction h with -- hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
- | nil => rfl
- | cons _ _ h_sz₁₂ => simp [h_sz₁₂]
- | swap => simp [add_left_comm]
- | trans _ _ h_sz₁₂ h_sz₂₃ => simp [h_sz₁₂, h_sz₂₃]
#align list.perm.sizeof_eq_sizeof List.Perm.sizeOf_eq_sizeOf
section Rel
@@ -387,85 +193,34 @@ end Rel
section Subperm
-/-- `Subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
- a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
- multiplicities of elements, and is used for the `≤` relation on multisets. -/
-def Subperm (l₁ l₂ : List α) : Prop :=
- ∃ (l : _) (_ : l ~ l₁), l <+ l₂
-#align list.subperm List.Subperm
-
-/-- `Subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
- a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
- multiplicities of elements, and is used for the `≤` relation on multisets. -/
-infixl:50 " <+~ " => Subperm
-
-theorem nil_subperm {l : List α} : [] <+~ l :=
- ⟨[], Perm.nil, by simp⟩
#align list.nil_subperm List.nil_subperm
-theorem Perm.subperm_left {l l₁ l₂ : List α} (p : l₁ ~ l₂) : l <+~ l₁ ↔ l <+~ l₂ :=
- suffices ∀ {l₁ l₂ : List α}, l₁ ~ l₂ → l <+~ l₁ → l <+~ l₂ from ⟨this p, this p.symm⟩
- fun p ⟨_u, pu, su⟩ =>
- let ⟨v, pv, sv⟩ := exists_perm_sublist su p
- ⟨v, pv.trans pu, sv⟩
#align list.perm.subperm_left List.Perm.subperm_left
-theorem Perm.subperm_right {l₁ l₂ l : List α} (p : l₁ ~ l₂) : l₁ <+~ l ↔ l₂ <+~ l :=
- ⟨fun ⟨u, pu, su⟩ => ⟨u, pu.trans p, su⟩, fun ⟨u, pu, su⟩ => ⟨u, pu.trans p.symm, su⟩⟩
#align list.perm.subperm_right List.Perm.subperm_right
-theorem Sublist.subperm {l₁ l₂ : List α} (s : l₁ <+ l₂) : l₁ <+~ l₂ :=
- ⟨l₁, Perm.refl _, s⟩
#align list.sublist.subperm List.Sublist.subperm
-theorem Perm.subperm {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ <+~ l₂ :=
- ⟨l₂, p.symm, Sublist.refl _⟩
#align list.perm.subperm List.Perm.subperm
-@[refl]
-theorem Subperm.refl (l : List α) : l <+~ l :=
- (Perm.refl _).subperm
+attribute [refl] Subperm.refl
#align list.subperm.refl List.Subperm.refl
-@[trans]
-theorem Subperm.trans {l₁ l₂ l₃ : List α} : l₁ <+~ l₂ → l₂ <+~ l₃ → l₁ <+~ l₃
- | s, ⟨_l₂', p₂, s₂⟩ =>
- let ⟨l₁', p₁, s₁⟩ := p₂.subperm_left.2 s
- ⟨l₁', p₁, s₁.trans s₂⟩
+attribute [trans] Subperm.trans
#align list.subperm.trans List.Subperm.trans
-theorem Subperm.length_le {l₁ l₂ : List α} : l₁ <+~ l₂ → length l₁ ≤ length l₂
- | ⟨_l, p, s⟩ => p.length_eq ▸ s.length_le
#align list.subperm.length_le List.Subperm.length_le
-theorem Subperm.perm_of_length_le {l₁ l₂ : List α} : l₁ <+~ l₂ → length l₂ ≤ length l₁ → l₁ ~ l₂
- | ⟨_l, p, s⟩, h => (s.eq_of_length_le <| p.symm.length_eq ▸ h) ▸ p.symm
#align list.subperm.perm_of_length_le List.Subperm.perm_of_length_le
-theorem Subperm.antisymm {l₁ l₂ : List α} (h₁ : l₁ <+~ l₂) (h₂ : l₂ <+~ l₁) : l₁ ~ l₂ :=
- h₁.perm_of_length_le h₂.length_le
#align list.subperm.antisymm List.Subperm.antisymm
-theorem Subperm.subset {l₁ l₂ : List α} : l₁ <+~ l₂ → l₁ ⊆ l₂
- | ⟨_l, p, s⟩ => Subset.trans p.symm.subset s.subset
#align list.subperm.subset List.Subperm.subset
-theorem Subperm.filter (p : α → Bool) ⦃l l' : List α⦄ (h : l <+~ l') :
- filter p l <+~ filter p l' := by
- obtain ⟨xs, hp, h⟩ := h
- exact ⟨_, hp.filter p, h.filter p⟩
#align list.subperm.filter List.Subperm.filter
end Subperm
-theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → ∃ l, l₂ ~ l₁ ++ l
- | _, _, Sublist.slnil => ⟨nil, Perm.refl _⟩
- | _, _, Sublist.cons a s =>
- let ⟨l, p⟩ := Sublist.exists_perm_append s
- ⟨a :: l, (p.cons a).trans perm_middle.symm⟩
- | _, _, Sublist.cons₂ a s =>
- let ⟨l, p⟩ := Sublist.exists_perm_append s
- ⟨l, p.cons a⟩
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
@@ -474,12 +229,15 @@ lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
obtain ⟨l', h₂⟩ := h₂.exists_perm_append
exact ⟨l₁ ++ l', (h₂.trans (h₁.append_right _)).symm, (prefix_append _ _).sublist⟩
-@[simp] lemma singleton_subperm_iff : [a] <+~ l ↔ a ∈ l :=
+
+-- This is now in `Std`, but apparently misnamed as `List.subperm_singleton_iff`.
+lemma singleton_subperm_iff : [a] <+~ l ↔ a ∈ l :=
⟨fun ⟨s, hla, h⟩ ↦ by rwa [perm_singleton.1 hla, singleton_sublist] at h,
fun h ↦ ⟨[a], perm_rfl, singleton_sublist.2 h⟩⟩
#align list.subperm_singleton_iff List.singleton_subperm_iff
-@[simp] lemma subperm_singleton_iff : l <+~ [a] ↔ l = [] ∨ l = [a] := by
+-- The prime could be removed if `List.subperm_singleton_iff` is renamed in Std.
+@[simp] lemma subperm_singleton_iff' : l <+~ [a] ↔ l = [] ∨ l = [a] := by
constructor
· rw [subperm_iff]
rintro ⟨s, hla, h⟩
@@ -487,58 +245,24 @@ lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
· rintro (rfl | rfl)
exacts [nil_subperm, Subperm.refl _]
-theorem Perm.countP_eq (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
- countP p l₁ = countP p l₂ := by
- rw [countP_eq_length_filter, countP_eq_length_filter]; exact (s.filter _).length_eq
#align list.perm.countp_eq List.Perm.countP_eq
-theorem Subperm.countP_le (p : α → Bool) {l₁ l₂ : List α} :
- l₁ <+~ l₂ → countP p l₁ ≤ countP p l₂
- | ⟨_l, p', s⟩ => p'.countP_eq p ▸ s.countP_le p
#align list.subperm.countp_le List.Subperm.countP_le
-theorem Perm.countP_congr (s : l₁ ~ l₂) {p p' : α → Bool}
- (hp : ∀ x ∈ l₁, p x ↔ p' x) : l₁.countP p = l₂.countP p' := by
- rw [← s.countP_eq p']
- clear s
- induction' l₁ with y s hs
- · rfl
- · simp only [mem_cons, forall_eq_or_imp] at hp
- simp only [countP_cons, hs hp.2, hp.1]
#align list.perm.countp_congr List.Perm.countP_congr
-theorem countP_eq_countP_filter_add (l : List α) (p q : α → Bool) :
- l.countP p = (l.filter q).countP p + (l.filter fun a => ¬q a).countP p := by
- rw [← countP_append]
- exact Perm.countP_eq _ (filter_append_perm _ _).symm
#align list.countp_eq_countp_filter_add List.countP_eq_countP_filter_add
lemma count_eq_count_filter_add [DecidableEq α] (P : α → Prop) [DecidablePred P]
(l : List α) (a : α) :
count a l = count a (l.filter P) + count a (l.filter (¬ P ·)) := by
convert countP_eq_countP_filter_add l _ P
- simp only [decide_eq_true_eq]
+ simp only [decide_not]
-theorem Perm.count_eq [DecidableEq α] {l₁ l₂ : List α} (p : l₁ ~ l₂) (a) :
- count a l₁ = count a l₂ :=
- p.countP_eq _
#align list.perm.count_eq List.Perm.count_eq
-theorem Subperm.count_le [DecidableEq α] {l₁ l₂ : List α} (s : l₁ <+~ l₂) (a) :
- count a l₁ ≤ count a l₂ :=
- s.countP_le _
#align list.subperm.count_le List.Subperm.count_le
-theorem Perm.foldl_eq' {f : β → α → β} {l₁ l₂ : List α} (p : l₁ ~ l₂) :
- (∀ x ∈ l₁, ∀ y ∈ l₁, ∀ (z), f (f z x) y = f (f z y) x) → ∀ b, foldl f b l₁ = foldl f b l₂ :=
- perm_induction_on p (fun _H b => rfl)
- (fun x t₁ t₂ _p r H b => r (fun x hx y hy => H _ (.tail _ hx) _ (.tail _ hy)) _)
- (fun x y t₁ t₂ _p r H b => by
- simp only [foldl]
- rw [H x (.tail _ <| .head _) y (.head _)]
- exact r (fun x hx y hy => H _ (.tail _ <| .tail _ hx) _ (.tail _ <| .tail _ hy)) _)
- fun t₁ t₂ t₃ p₁ _p₂ r₁ r₂ H b =>
- Eq.trans (r₁ H b) (r₂ (fun x hx y hy => H _ (p₁.symm.subset hx) _ (p₁.symm.subset hy)) b)
#align list.perm.foldl_eq' List.Perm.foldl_eq'
theorem Perm.foldl_eq {f : β → α → β} {l₁ l₂ : List α} (rcomm : RightCommutative f) (p : l₁ ~ l₂) :
@@ -547,21 +271,15 @@ theorem Perm.foldl_eq {f : β → α → β} {l₁ l₂ : List α} (rcomm : Righ
#align list.perm.foldl_eq List.Perm.foldl_eq
theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : LeftCommutative f) (p : l₁ ~ l₂) :
- ∀ b, foldr f b l₁ = foldr f b l₂ :=
- perm_induction_on p (fun b => rfl) (fun x t₁ t₂ _p r b => by simp; rw [r b])
- (fun x y t₁ t₂ _p r b => by simp; rw [lcomm, r b]) fun t₁ t₂ t₃ _p₁ _p₂ r₁ r₂ a =>
- Eq.trans (r₁ a) (r₂ a)
+ ∀ b, foldr f b l₁ = foldr f b l₂ := by
+ intro b
+ induction p using Perm.recOnSwap' generalizing b
+ case nil => rfl
+ case cons r => simp; rw [r b]
+ case swap' r => simp; rw [lcomm, r b]
+ case trans r₁ r₂ => exact Eq.trans (r₁ b) (r₂ b)
#align list.perm.foldr_eq List.Perm.foldr_eq
-theorem Perm.rec_heq {β : List α → Sort*} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
- (hl : Perm l l') (f_congr : ∀ {a l l' b b'}, Perm l l' → HEq b b' → HEq (f a l b) (f a l' b'))
- (f_swap : ∀ {a a' l b}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))) :
- HEq (@List.rec α β b f l) (@List.rec α β b f l') := by
- induction hl
- case nil => rfl
- case cons a l l' h ih => exact f_congr h ih
- case swap a a' l => exact f_swap
- case trans l₁ l₂ l₃ _h₁ _h₂ ih₁ ih₂ => exact HEq.trans ih₁ ih₂
#align list.perm.rec_heq List.Perm.rec_heq
section
@@ -616,71 +334,14 @@ theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
end CommMonoid
-theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} :
- l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂ := by
- generalize e₁ : l₁ ++ a :: r₁ = s₁; generalize e₂ : l₂ ++ a :: r₂ = s₂
- intro p; revert l₁ l₂ r₁ r₂ e₁ e₂; clear l₁ l₂ β
- show ∀ _ _ _ _, _
- refine
- perm_induction_on p ?_ (fun x t₁ t₂ p IH => ?_) (fun x y t₁ t₂ p IH => ?_)
- fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => ?_
- <;> intro l₁ l₂ r₁ r₂ e₁ e₂
- · apply (not_mem_nil a).elim
- rw [← e₁]
- simp
- · cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
- · substs t₁ t₂
- exact p
- · substs z t₁ t₂
- exact p.trans perm_middle
- · substs y t₁ t₂
- exact perm_middle.symm.trans p
- · substs z t₁ t₂
- exact (IH _ _ _ _ rfl rfl).cons y
- · rcases l₁ with (_ | ⟨y, _ | ⟨z, l₁⟩⟩) <;> rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩) <;>
- dsimp at e₁ e₂ <;> injections <;> substs x y
- · substs r₁ r₂
- exact p.cons a
- · substs r₁ r₂
- exact p.cons u
- · substs r₁ v t₂
- exact (p.trans perm_middle).cons u
- · substs r₁ r₂
- exact p.cons y
- · substs r₁ r₂ y u
- exact p.cons a
- · substs r₁ u v t₂
- exact ((p.trans perm_middle).cons y).trans (swap _ _ _)
- · substs r₂ z t₁
- exact (perm_middle.symm.trans p).cons y
- · substs r₂ y z t₁
- exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
- · substs u v t₁ t₂
- exact (IH _ _ _ _ rfl rfl).swap' _ _
- · substs t₁ t₃
- have : a ∈ t₂ := p₁.subset (by simp)
- rcases mem_split this with ⟨l₂, r₂, e₂⟩
- subst t₂
- exact (IH₁ _ _ _ _ rfl rfl).trans (IH₂ _ _ _ _ rfl rfl)
#align list.perm_inv_core List.perm_inv_core
-theorem Perm.cons_inv {a : α} {l₁ l₂ : List α} : a :: l₁ ~ a :: l₂ → l₁ ~ l₂ :=
- @perm_inv_core _ _ [] [] _ _
#align list.perm.cons_inv List.Perm.cons_inv
-@[simp]
-theorem perm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ ~ a :: l₂ ↔ l₁ ~ l₂ :=
- ⟨Perm.cons_inv, Perm.cons a⟩
#align list.perm_cons List.perm_cons
-theorem perm_append_left_iff {l₁ l₂ : List α} : ∀ l, l ++ l₁ ~ l ++ l₂ ↔ l₁ ~ l₂
- | [] => Iff.rfl
- | a :: l => (perm_cons a).trans (perm_append_left_iff l)
#align list.perm_append_left_iff List.perm_append_left_iff
-theorem perm_append_right_iff {l₁ l₂ : List α} (l) : l₁ ++ l ~ l₂ ++ l ↔ l₁ ~ l₂ :=
- ⟨fun p => (perm_append_left_iff _).1 <| perm_append_comm.trans <| p.trans perm_append_comm,
- Perm.append_right _⟩
#align list.perm_append_right_iff List.perm_append_right_iff
theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
@@ -691,11 +352,6 @@ theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList
· exact Option.mem_toList.1 (p.symm.subset <| by simp)
#align list.perm_option_to_list List.perm_option_to_list
-theorem subperm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ <+~ a :: l₂ ↔ l₁ <+~ l₂ :=
- ⟨fun ⟨l, p, s⟩ => by
- cases' s with _ _ _ s' u _ _ s'
- · exact (p.subperm_left.2 <| (sublist_cons _ _).subperm).trans s'.subperm
- · exact ⟨u, p.cons_inv, s'⟩, fun ⟨l, p, s⟩ => ⟨a :: l, p.cons a, s.cons₂ _⟩⟩
#align list.subperm_cons List.subperm_cons
alias ⟨subperm.of_cons, subperm.cons⟩ := subperm_cons
@@ -731,127 +387,45 @@ theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (
⟨b :: t, (p'.cons b).trans <| (swap _ _ _).trans (perm_middle.symm.cons a), s'.cons₂ _⟩
#align list.cons_subperm_of_mem List.cons_subperm_of_mem
-theorem subperm_append_left {l₁ l₂ : List α} : ∀ l, l ++ l₁ <+~ l ++ l₂ ↔ l₁ <+~ l₂
- | [] => Iff.rfl
- | a :: l => (subperm_cons a).trans (subperm_append_left l)
#align list.subperm_append_left List.subperm_append_left
-theorem subperm_append_right {l₁ l₂ : List α} (l) : l₁ ++ l <+~ l₂ ++ l ↔ l₁ <+~ l₂ :=
- (perm_append_comm.subperm_left.trans perm_append_comm.subperm_right).trans (subperm_append_left l)
#align list.subperm_append_right List.subperm_append_right
-theorem Subperm.exists_of_length_lt {l₁ l₂ : List α} :
- l₁ <+~ l₂ → length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
- | ⟨l, p, s⟩, h => by
- suffices length l < length l₂ → ∃ a : α, a :: l <+~ l₂ from
- (this <| p.symm.length_eq ▸ h).imp fun a => (p.cons a).subperm_right.1
- clear h p l₁
- induction' s with l₁ l₂ a s IH _ _ b _ IH <;> intro h
- · cases h
- · cases' lt_or_eq_of_le (Nat.le_of_lt_succ h : length l₁ ≤ length l₂) with h h
- · exact (IH h).imp fun a s => s.trans (sublist_cons _ _).subperm
- · exact ⟨a, s.eq_of_length h ▸ Subperm.refl _⟩
- · exact (IH <| Nat.lt_of_succ_lt_succ h).imp fun a s =>
- (swap _ _ _).subperm_right.1 <| (subperm_cons _).2 s
#align list.subperm.exists_of_length_lt List.Subperm.exists_of_length_lt
-protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ := by
- induction' d with a l₁' h d IH
- · exact ⟨nil, Perm.nil, nil_sublist _⟩
- · cases' forall_mem_cons.1 H with H₁ H₂
- simp at h
- exact cons_subperm_of_mem d h H₁ (IH H₂)
+protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ :=
+ subperm_of_subset d H
#align list.nodup.subperm List.Nodup.subperm
-theorem perm_ext {l₁ l₂ : List α} (d₁ : Nodup l₁) (d₂ : Nodup l₂) :
- l₁ ~ l₂ ↔ ∀ a, a ∈ l₁ ↔ a ∈ l₂ :=
- ⟨fun p _ => p.mem_iff, fun H =>
- (d₁.subperm fun a => (H a).1).antisymm <| d₂.subperm fun a => (H a).2⟩
-#align list.perm_ext List.perm_ext
-
-theorem Nodup.sublist_ext {l₁ l₂ l : List α} (d : Nodup l) (s₁ : l₁ <+ l) (s₂ : l₂ <+ l) :
- l₁ ~ l₂ ↔ l₁ = l₂ :=
- ⟨fun h => by
- induction' s₂ with l₂ l a s₂ IH l₂ l a _ IH generalizing l₁
- · exact h.eq_nil
- · simp at d
- cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
- · exact IH d.2 s₁ h
- · apply d.1.elim
- exact Subperm.subset ⟨_, h.symm, s₂⟩ (mem_cons_self _ _)
- · simp at d
- cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
- · apply d.1.elim
- exact Subperm.subset ⟨_, h, s₁⟩ (mem_cons_self _ _)
- · rw [IH d.2 s₁ h.cons_inv], fun h => by rw [h]⟩
-#align list.nodup.sublist_ext List.Nodup.sublist_ext
+#align list.perm_ext List.perm_ext_iff_of_nodup
+
+#align list.nodup.sublist_ext List.Nodup.perm_iff_eq_of_sublist
section
variable [DecidableEq α]
-- attribute [congr]
-theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase a ~ l₂.erase a :=
- if h₁ : a ∈ l₁ then
- have h₂ : a ∈ l₂ := p.subset h₁
- Perm.cons_inv <| (perm_cons_erase h₁).symm.trans <| p.trans (perm_cons_erase h₂)
- else by
- have h₂ : a ∉ l₂ := mt p.mem_iff.2 h₁
- rw [erase_of_not_mem h₁, erase_of_not_mem h₂]; exact p
#align list.perm.erase List.Perm.erase
-theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.erase a := by
- by_cases h : a ∈ l
- · exact (perm_cons_erase h).subperm
- · rw [erase_of_not_mem h]
- exact (sublist_cons _ _).subperm
#align list.subperm_cons_erase List.subperm_cons_erase
-theorem erase_subperm (a : α) (l : List α) : l.erase a <+~ l :=
- (erase_sublist _ _).subperm
#align list.erase_subperm List.erase_subperm
-theorem Subperm.erase {l₁ l₂ : List α} (a : α) (h : l₁ <+~ l₂) : l₁.erase a <+~ l₂.erase a :=
- let ⟨l, hp, hs⟩ := h
- ⟨l.erase a, hp.erase _, hs.erase _⟩
#align list.subperm.erase List.Subperm.erase
-theorem Perm.diff_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) : l₁.diff t ~ l₂.diff t := by
- induction t generalizing l₁ l₂ h <;> simp [*, Perm.erase]
#align list.perm.diff_right List.Perm.diff_right
-theorem Perm.diff_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.diff t₁ = l.diff t₂ := by
- induction h generalizing l <;>
- first |simp [*, Perm.erase, erase_comm]
#align list.perm.diff_left List.Perm.diff_left
-theorem Perm.diff {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) : l₁.diff t₁ ~ l₂.diff t₂ :=
- ht.diff_left l₂ ▸ hl.diff_right _
#align list.perm.diff List.Perm.diff
-theorem Subperm.diff_right {l₁ l₂ : List α} (h : l₁ <+~ l₂) (t : List α) :
- l₁.diff t <+~ l₂.diff t := by induction t generalizing l₁ l₂ h <;> simp [*, Subperm.erase]
#align list.subperm.diff_right List.Subperm.diff_right
-theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
- (a :: l).erase b <+~ a :: l.erase b := by
- by_cases h : a = b
- · subst b
- rw [erase_cons_head]
- apply subperm_cons_erase
- · rw [erase_cons_tail _ h]
#align list.erase_cons_subperm_cons_erase List.erase_cons_subperm_cons_erase
-theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : List α}, (a :: l₁).diff l₂ <+~ a :: l₁.diff l₂
- | l₁, [] => ⟨a :: l₁, by simp⟩
- | l₁, b :: l₂ => by
- simp only [diff_cons]
- refine' ((erase_cons_subperm_cons_erase a b l₁).diff_right l₂).trans _
- apply subperm_cons_diff
#align list.subperm_cons_diff List.subperm_cons_diff
-theorem subset_cons_diff {a : α} {l₁ l₂ : List α} : (a :: l₁).diff l₂ ⊆ a :: l₁.diff l₂ :=
- subperm_cons_diff.subset
#align list.subset_cons_diff List.subset_cons_diff
theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
@@ -881,27 +455,8 @@ theorem Perm.bagInter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t
ht.bagInter_left l₂ ▸ hl.bagInter_right _
#align list.perm.bag_inter List.Perm.bagInter
-theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
- a :: l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.erase a :=
- ⟨fun h =>
- have : a ∈ l₂ := h.subset (mem_cons_self a l₁)
- ⟨this, (h.trans <| perm_cons_erase this).cons_inv⟩,
- fun ⟨m, h⟩ => (h.cons a).trans (perm_cons_erase m).symm⟩
#align list.cons_perm_iff_perm_erase List.cons_perm_iff_perm_erase
-theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ :=
- ⟨Perm.count_eq, fun H => by
- induction' l₁ with a l₁ IH generalizing l₂
- · cases' l₂ with b l₂
- · rfl
- specialize H b
- simp at H
- contradiction
- · have : a ∈ l₂ := count_pos_iff_mem.1 (by rw [← H, count_pos_iff_mem]; simp)
- refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
- specialize H b
- rw [(perm_cons_erase this).count_eq] at H
- by_cases h : b = a <;> simpa [h] using H⟩
#align list.perm_iff_count List.perm_iff_count
theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h : a ≠ b) :
@@ -913,61 +468,16 @@ theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h
not_mem_nil, or_false, or_comm]
#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
-theorem Subperm.cons_right {α : Type*} {l l' : List α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
- h.trans (sublist_cons x l').subperm
#align list.subperm.cons_right List.Subperm.cons_right
-/-- The list version of `add_tsub_cancel_of_le` for multisets. -/
-theorem subperm_append_diff_self_of_count_le {l₁ l₂ : List α}
- (h : ∀ x ∈ l₁, count x l₁ ≤ count x l₂) : l₁ ++ l₂.diff l₁ ~ l₂ := by
- induction' l₁ with hd tl IH generalizing l₂
- · simp
- · have : hd ∈ l₂ := by
- rw [← count_pos_iff_mem]
- exact lt_of_lt_of_le (count_pos_iff_mem.mpr (mem_cons_self _ _)) (h hd (mem_cons_self _ _))
- replace := perm_cons_erase this
- refine' Perm.trans _ this.symm
- rw [cons_append, diff_cons, perm_cons]
- refine' IH fun x hx => _
- specialize h x (mem_cons_of_mem _ hx)
- rw [perm_iff_count.mp this] at h
- by_cases hx : x = hd
- · subst hd
- simpa [Nat.succ_le_succ_iff] using h
- · simpa [hx] using h
#align list.subperm_append_diff_self_of_count_le List.subperm_append_diff_self_of_count_le
-/-- The list version of `Multiset.le_iff_count`. -/
-theorem subperm_ext_iff {l₁ l₂ : List α} : l₁ <+~ l₂ ↔ ∀ x ∈ l₁, count x l₁ ≤ count x l₂ := by
- refine' ⟨fun h x _ => Subperm.count_le h x, fun h => _⟩
- suffices l₁ <+~ l₂.diff l₁ ++ l₁ by
- refine' this.trans (Perm.subperm _)
- exact perm_append_comm.trans (subperm_append_diff_self_of_count_le h)
- exact (subperm_append_right l₁).mpr nil_subperm
#align list.subperm_ext_iff List.subperm_ext_iff
-instance decidableSubperm : DecidableRel ((· <+~ ·) : List α → List α → Prop) := fun _ _ =>
- decidable_of_iff _ List.subperm_ext_iff.symm
#align list.decidable_subperm List.decidableSubperm
-theorem Subperm.cons_left {l₁ l₂ : List α} (h : l₁ <+~ l₂) (x : α) (hx : count x l₁ < count x l₂) :
- x :: l₁ <+~ l₂ := by
- rw [subperm_ext_iff] at h ⊢
- intro y hy
- by_cases hy' : y = x
- · subst x
- simpa using Nat.succ_le_of_lt hx
- · rw [count_cons_of_ne hy']
- refine' h y _
- simpa [hy'] using hy
#align list.subperm.cons_left List.Subperm.cons_left
-instance decidablePerm : ∀ l₁ l₂ : List α, Decidable (l₁ ~ l₂)
- | [], [] => isTrue <| Perm.refl _
- | [], b :: l₂ => isFalse fun h => by have := h.nil_eq; contradiction
- | a :: l₁, l₂ =>
- haveI := decidablePerm l₁ (l₂.erase a)
- decidable_of_iff' _ cons_perm_iff_perm_erase
#align list.decidable_perm List.decidablePerm
-- @[congr]
@@ -977,62 +487,24 @@ theorem Perm.dedup {l₁ l₂ : List α} (p : l₁ ~ l₂) : dedup l₁ ~ dedup
#align list.perm.dedup List.Perm.dedup
-- attribute [congr]
-protected theorem Perm.insert (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.insert a ~ l₂.insert a :=
- if h : a ∈ l₁ then by simpa [h, p.subset h] using p
- else by simpa [h, mt p.mem_iff.2 h] using p.cons a
#align list.perm.insert List.Perm.insert
-theorem perm_insert_swap (x y : α) (l : List α) :
- List.insert x (List.insert y l) ~ List.insert y (List.insert x l) := by
- by_cases xl : x ∈ l <;> by_cases yl : y ∈ l <;> simp [xl, yl]
- by_cases xy : x = y; · simp [xy]
- simp only [List.insert, Bool.not_eq_true, mem_cons, xy, xl, or_self, ite_false, Ne.symm xy, yl]
- constructor
#align list.perm_insert_swap List.perm_insert_swap
-theorem perm_insertNth {α} (x : α) (l : List α) {n} (h : n ≤ l.length) :
- insertNth n x l ~ x :: l := by
- induction' l with _ _ l_ih generalizing n
- · cases n
- rfl
- cases h
- cases n
- · simp [insertNth]
- · simp only [insertNth, modifyNthTail]
- refine' Perm.trans (Perm.cons _ (l_ih _)) _
- · apply Nat.le_of_succ_le_succ h
- · apply Perm.swap
#align list.perm_insert_nth List.perm_insertNth
-theorem Perm.union_right {l₁ l₂ : List α} (t₁ : List α) (h : l₁ ~ l₂) :
- l₁ ∪ t₁ ~ l₂ ∪ t₁ := by
- induction' h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2 <;> try simp
- · exact ih.insert a
- · apply perm_insert_swap
- · exact ih_1.trans ih_2
#align list.perm.union_right List.Perm.union_right
-theorem Perm.union_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l ∪ t₁ ~ l ∪ t₂ := by
- induction l <;> simp [*, Perm.insert]
#align list.perm.union_left List.Perm.union_left
-- @[congr]
-theorem Perm.union {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) :
- l₁ ∪ t₁ ~ l₂ ∪ t₂ :=
- (p₁.union_right t₁).trans (p₂.union_left l₂)
#align list.perm.union List.Perm.union
-theorem Perm.inter_right {l₁ l₂ : List α} (t₁ : List α) : l₁ ~ l₂ → l₁ ∩ t₁ ~ l₂ ∩ t₁ :=
- Perm.filter _
#align list.perm.inter_right List.Perm.inter_right
-theorem Perm.inter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) : l ∩ t₁ = l ∩ t₂ :=
- filter_congr' fun a _ => by simpa using p.mem_iff
#align list.perm.inter_left List.Perm.inter_left
-- @[congr]
-theorem Perm.inter {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ∩ t₁ ~ l₂ ∩ t₂ :=
- p₂.inter_left l₂ ▸ p₁.inter_right t₁
#align list.perm.inter List.Perm.inter
theorem Perm.inter_append {l t₁ t₂ : List α} (h : Disjoint t₁ t₂) :
@@ -1055,50 +527,19 @@ theorem Perm.inter_append {l t₁ t₂ : List α} (h : Disjoint t₁ t₂) :
end
-theorem Perm.pairwise_iff {R : α → α → Prop} (S : Symmetric R) :
- ∀ {l₁ l₂ : List α} (_p : l₁ ~ l₂), Pairwise R l₁ ↔ Pairwise R l₂ :=
- suffices ∀ {l₁ l₂}, l₁ ~ l₂ → Pairwise R l₁ → Pairwise R l₂
- from fun p => ⟨this p, this p.symm⟩
- @fun l₁ l₂ p d => by
- induction' d with a l₁ h _ IH generalizing l₂
- · rw [← p.nil_eq]
- constructor
- · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
- rcases mem_split this with ⟨s₂, t₂, rfl⟩
- have p' := (p.trans perm_middle).cons_inv
- refine' (pairwise_middle @S).2 (pairwise_cons.2 ⟨fun b m => _, IH _ p'⟩)
- exact h _ (p'.symm.subset m)
#align list.perm.pairwise_iff List.Perm.pairwise_iff
-theorem Pairwise.perm {R : α → α → Prop} {l l' : List α} (hR : l.Pairwise R) (hl : l ~ l')
- (hsymm : Symmetric R) : l'.Pairwise R :=
- (hl.pairwise_iff hsymm).mp hR
#align list.pairwise.perm List.Pairwise.perm
-theorem Perm.pairwise {R : α → α → Prop} {l l' : List α} (hl : l ~ l') (hR : l.Pairwise R)
- (hsymm : Symmetric R) : l'.Pairwise R :=
- hR.perm hl hsymm
#align list.perm.pairwise List.Perm.pairwise
-theorem Perm.nodup_iff {l₁ l₂ : List α} : l₁ ~ l₂ → (Nodup l₁ ↔ Nodup l₂) :=
- Perm.pairwise_iff <| @Ne.symm α
#align list.perm.nodup_iff List.Perm.nodup_iff
-theorem Perm.join {l₁ l₂ : List (List α)} (h : l₁ ~ l₂) : l₁.join ~ l₂.join :=
- Perm.recOn h (Perm.refl _) (fun x xs₁ xs₂ _ ih => ih.append_left x)
- (fun x₁ x₂ xs => by simpa only [join, append_assoc] using perm_append_comm.append_right _)
- @fun xs₁ xs₂ xs₃ _ _ => Perm.trans
#align list.perm.join List.Perm.join
-theorem Perm.bind_right {l₁ l₂ : List α} (f : α → List β) (p : l₁ ~ l₂) : l₁.bind f ~ l₂.bind f :=
- (p.map _).join
#align list.perm.bind_right List.Perm.bind_right
-theorem Perm.join_congr :
- ∀ {l₁ l₂ : List (List α)} (_ : List.Forall₂ (· ~ ·) l₁ l₂), l₁.join ~ l₂.join
- | _, _, Forall₂.nil => Perm.refl _
- | _ :: _, _ :: _, Forall₂.cons h₁ h₂ => h₁.append (Perm.join_congr h₂)
#align list.perm.join_congr List.Perm.join_congr
theorem Perm.bind_left (l : List α) {f g : α → List β} (h : ∀ a ∈ l, f a ~ g a) :
@@ -1155,22 +596,17 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
rcases (pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) _ h₂ _ h₁ with ⟨rfl, rfl⟩
exact Perm.refl _
· refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
- exact fun a b h c h₁ d h₂ => (h d h₂ c h₁).imp Eq.symm Eq.symm
+ intro x y h c hc d hd
+ rw [@eq_comm _ y, @eq_comm _ c]
+ apply h d hd c hc
#align list.perm_lookmap List.perm_lookmap
+@[deprecated Perm.eraseP]
theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
- (H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ := by
- induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ _ IH₁ IH₂; · simp
- · by_cases h : f a
- · simp [h, p]
- · simp [h]
- exact IH (pairwise_cons.1 H).2
- · by_cases h₁ : f a <;> by_cases h₂ : f b <;> simp [h₁, h₂]
- · cases (pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) h₂ h₁
- · apply swap
- · refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
- exact fun a b h h₁ h₂ => h h₂ h₁
-#align list.perm.erasep List.Perm.erasep
+ (H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) :
+ List.eraseP f l₁ ~ List.eraseP f l₂ :=
+ p.eraseP f (by simp [H])
+#align list.perm.erasep List.Perm.eraseP
theorem Perm.take_inter {α : Type*} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
(h' : ys.Nodup) : xs.take n ~ ys.inter (xs.take n) := by
Characterise IsAtom
, IsCoatom
, Covby
in Set α
, Multiset α
, Finset α
and deduce that Multiset α
, Finset α
are graded orders.
Note I am moving some existing characterisations to here because it makes sense thematically, but I could be convinced otherwise.
@@ -24,11 +24,8 @@ The notation `~` is used for permutation equivalence.
open Nat
-universe uu vv
-
namespace List
-
-variable {α : Type uu} {β : Type vv} {l₁ l₂ : List α}
+variable {α β : Type*} {l l₁ l₂ : List α} {a : α}
/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps. -/
@@ -54,6 +51,8 @@ protected theorem Perm.refl : ∀ l : List α, l ~ l
| x :: xs => (Perm.refl xs).cons x
#align list.perm.refl List.Perm.refl
+lemma perm_rfl : l ~ l := Perm.refl _
+
-- Porting note: used rec_on in mathlib3; lean4 eqn compiler still doesn't like it
@[symm]
protected theorem Perm.symm {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₂ ~ l₁ :=
@@ -469,6 +468,25 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
⟨l, p.cons a⟩
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
+lemma subperm_iff : l₁ <+~ l₂ ↔ ∃ l, l ~ l₂ ∧ l₁ <+ l := by
+ refine ⟨?_, fun ⟨l, h₁, h₂⟩ ↦ h₂.subperm.trans h₁.subperm⟩
+ rintro ⟨l, h₁, h₂⟩
+ obtain ⟨l', h₂⟩ := h₂.exists_perm_append
+ exact ⟨l₁ ++ l', (h₂.trans (h₁.append_right _)).symm, (prefix_append _ _).sublist⟩
+
+@[simp] lemma singleton_subperm_iff : [a] <+~ l ↔ a ∈ l :=
+ ⟨fun ⟨s, hla, h⟩ ↦ by rwa [perm_singleton.1 hla, singleton_sublist] at h,
+ fun h ↦ ⟨[a], perm_rfl, singleton_sublist.2 h⟩⟩
+#align list.subperm_singleton_iff List.singleton_subperm_iff
+
+@[simp] lemma subperm_singleton_iff : l <+~ [a] ↔ l = [] ∨ l = [a] := by
+ constructor
+ · rw [subperm_iff]
+ rintro ⟨s, hla, h⟩
+ rwa [perm_singleton.mp hla, sublist_singleton] at h
+ · rintro (rfl | rfl)
+ exacts [nil_subperm, Subperm.refl _]
+
theorem Perm.countP_eq (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
countP p l₁ = countP p l₂ := by
rw [countP_eq_length_filter, countP_eq_length_filter]; exact (s.filter _).length_eq
@@ -932,12 +950,6 @@ instance decidableSubperm : DecidableRel ((· <+~ ·) : List α → List α →
decidable_of_iff _ List.subperm_ext_iff.symm
#align list.decidable_subperm List.decidableSubperm
-@[simp]
-theorem subperm_singleton_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈ l :=
- ⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h, fun h =>
- ⟨[a], Perm.refl _, singleton_sublist.mpr h⟩⟩
-#align list.subperm_singleton_iff List.subperm_singleton_iff
-
theorem Subperm.cons_left {l₁ l₂ : List α} (h : l₁ <+~ l₂) (x : α) (hx : count x l₁ < count x l₂) :
x :: l₁ <+~ l₂ := by
rw [subperm_ext_iff] at h ⊢
(· op ·) a
by (a op ·)
(#8843)
I used the regex \(\(· (.) ·\) (.)\)
, replacing with ($2 $1 ·)
.
@@ -1366,7 +1366,7 @@ theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
#align list.nth_le_permutations'_aux List.nthLe_permutations'Aux
theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
- count (x :: l) (permutations'Aux x l) = length (takeWhile ((· = ·) x) l) + 1 := by
+ count (x :: l) (permutations'Aux x l) = length (takeWhile (x = ·) l) + 1 := by
induction' l with y l IH generalizing x
· simp [takeWhile, count]
· rw [permutations'Aux, DecEq_eq, count_cons_self]
This is the supremum of
along with some minor fixes from failures on nightly-testing as Mathlib master
is merged into it.
Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.
I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0
branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.
In particular this includes adjustments for the Lean PRs
We can get rid of all the
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)
macros across Mathlib (and in any projects that want to write natural number powers of reals).
Changes the default behaviour of simp
to (config := {decide := false})
. This makes simp
(and consequentially norm_num
) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp
or norm_num
to decide
or rfl
, or adding (config := {decide := true})
.
This changed the behaviour of simp
so that simp [f]
will only unfold "fully applied" occurrences of f
. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true })
. We may in future add a syntax for this, e.g. simp [!f]
; please provide feedback! In the meantime, we have made the following changes:
(config := { unfoldPartialApp := true })
in some places, to recover the old behaviour@[eqns]
to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp
and Function.flip
.This change in Lean may require further changes down the line (e.g. adding the !f
syntax, and/or upstreaming the special treatment for Function.comp
and Function.flip
, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!
Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>
@@ -278,9 +278,11 @@ theorem filter_append_perm (p : α → Bool) (l : List α) :
induction' l with x l ih
· rfl
· by_cases h : p x
- · simp only [h, filter_cons_of_pos, filter_cons_of_neg, not_true, not_false_iff, cons_append]
+ · simp only [h, filter_cons_of_pos, filter_cons_of_neg, not_true, not_false_iff, cons_append,
+ decide_False]
exact ih.cons x
- · simp only [h, filter_cons_of_neg, not_false_iff, filter_cons_of_pos]
+ · simp only [h, filter_cons_of_neg, not_false_iff, filter_cons_of_pos, cons_append,
+ not_false_eq_true, decide_True]
refine' Perm.trans _ (ih.cons x)
exact perm_append_comm.trans (perm_append_comm.cons _)
#align list.filter_append_perm List.filter_append_perm
Trans
instance for List.Perm and a lemma on List
s (#8189)
This PR adds
List.count_filter_add_count_filter
in Data.List.Count
Trans ([@List](https://github.com/List).Perm α) ([@List](https://github.com/List).Perm α) ([@List](https://github.com/List).Perm α)
to allow using permutation equivalence of Lists
in a calc
block in Data.List.Perm
See here on Zulip.
Co-authored-by: Michael Stoll <99838730+MichaelStollBayreuth@users.noreply.github.com>
@@ -39,6 +39,9 @@ inductive Perm : List α → List α → Prop
| trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
#align list.perm List.Perm
+instance {α : Type*} : Trans (@List.Perm α) (@List.Perm α) List.Perm where
+ trans := @List.Perm.trans α
+
open Perm (swap)
/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
@@ -490,6 +493,12 @@ theorem countP_eq_countP_filter_add (l : List α) (p q : α → Bool) :
exact Perm.countP_eq _ (filter_append_perm _ _).symm
#align list.countp_eq_countp_filter_add List.countP_eq_countP_filter_add
+lemma count_eq_count_filter_add [DecidableEq α] (P : α → Prop) [DecidablePred P]
+ (l : List α) (a : α) :
+ count a l = count a (l.filter P) + count a (l.filter (¬ P ·)) := by
+ convert countP_eq_countP_filter_add l _ P
+ simp only [decide_eq_true_eq]
+
theorem Perm.count_eq [DecidableEq α] {l₁ l₂ : List α} (p : l₁ ~ l₂) (a) :
count a l₁ = count a l₂ :=
p.countP_eq _
attach
and filter
lemmas (#1470)
Match https://github.com/leanprover-community/mathlib/pull/18087
@@ -8,7 +8,7 @@ import Mathlib.Data.List.Permutation
import Mathlib.Data.List.Range
import Mathlib.Data.Nat.Factorial.Basic
-#align_import data.list.perm from "leanprover-community/mathlib"@"47adfab39a11a072db552f47594bf8ed2cf8a722"
+#align_import data.list.perm from "leanprover-community/mathlib"@"65a1391a0106c9204fe45bc73a039f056558cb83"
/-!
# List Permutations
@@ -475,7 +475,7 @@ theorem Subperm.countP_le (p : α → Bool) {l₁ l₂ : List α} :
#align list.subperm.countp_le List.Subperm.countP_le
theorem Perm.countP_congr (s : l₁ ~ l₂) {p p' : α → Bool}
- (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countP p = l₂.countP p' := by
+ (hp : ∀ x ∈ l₁, p x ↔ p' x) : l₁.countP p = l₂.countP p' := by
rw [← s.countP_eq p']
clear s
induction' l₁ with y s hs
@@ -1197,10 +1197,9 @@ theorem perm_of_mem_permutationsAux :
refine' permutationsAux.rec (by simp) _
introv IH1 IH2 m
rw [permutationsAux_cons, permutations, mem_foldr_permutationsAux2] at m
- rcases m with (m | ⟨l₁, l₂, m, _, e⟩)
+ rcases m with (m | ⟨l₁, l₂, m, _, rfl⟩)
· exact (IH1 _ m).trans perm_middle
- · subst e
- have p : l₁ ++ l₂ ~ is := by
+ · have p : l₁ ++ l₂ ~ is := by
simp [permutations] at m
cases' m with e m
· simp [e]
Removes nonterminal simps on lines looking like simp [...]
@@ -963,7 +963,7 @@ theorem perm_insert_swap (x y : α) (l : List α) :
List.insert x (List.insert y l) ~ List.insert y (List.insert x l) := by
by_cases xl : x ∈ l <;> by_cases yl : y ∈ l <;> simp [xl, yl]
by_cases xy : x = y; · simp [xy]
- simp [List.insert, xl, yl, xy, Ne.symm xy]
+ simp only [List.insert, Bool.not_eq_true, mem_cons, xy, xl, or_self, ite_false, Ne.symm xy, yl]
constructor
#align list.perm_insert_swap List.perm_insert_swap
@@ -1272,7 +1272,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
(permutations'Aux b l).bind (permutations'Aux a) := by
induction' l with c l ih
· simp [swap]
- simp [permutations'Aux]
+ simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
apply Perm.swap'
have :
∀ a b,
rcases
, convert
and congrm
(#7725)
Replace rcases(
with rcases (
. Same thing for convert(
and congrm(
. No other change.
@@ -1129,7 +1129,7 @@ theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
· simp [lookmap_cons_some _ _ h₁, h₂]
apply swap
· simp [lookmap_cons_some _ _ h₁, lookmap_cons_some _ _ h₂]
- rcases(pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) _ h₂ _ h₁ with ⟨rfl, rfl⟩
+ rcases (pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) _ h₂ _ h₁ with ⟨rfl, rfl⟩
exact Perm.refl _
· refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
exact fun a b h c h₁ d h₂ => (h d h₂ c h₁).imp Eq.symm Eq.symm
@@ -1423,7 +1423,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
nthLe_insertNth_of_lt _ _ _ _ (H.trans (Nat.lt_succ_self _))]
· rw [nthLe_insertNth_self _ _ _ hk.le, nthLe_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk,
hk']
- · rcases(Nat.succ_le_of_lt H).eq_or_lt with (rfl | H')
+ · rcases (Nat.succ_le_of_lt H).eq_or_lt with (rfl | H')
· rw [nthLe_insertNth_self _ _ _ (Nat.succ_le_of_lt hk)]
convert hk' using 1
exact nthLe_insertNth_add_succ _ _ _ 0 _
Std bump patch for https://github.com/leanprover/std4/pull/100
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -1043,7 +1043,7 @@ theorem Perm.pairwise_iff {R : α → α → Prop} (S : Symmetric R) :
· have : a ∈ l₂ := p.subset (mem_cons_self _ _)
rcases mem_split this with ⟨s₂, t₂, rfl⟩
have p' := (p.trans perm_middle).cons_inv
- refine' (pairwise_middle S).2 (pairwise_cons.2 ⟨fun b m => _, IH _ p'⟩)
+ refine' (pairwise_middle @S).2 (pairwise_cons.2 ⟨fun b m => _, IH _ p'⟩)
exact h _ (p'.symm.subset m)
#align list.perm.pairwise_iff List.Perm.pairwise_iff
Many proofs use the "stream of consciousness" style from Lean 3, rather than have ... :=
or suffices ... from/by
.
This PR updates a fraction of these to the preferred Lean 4 style.
I think a good goal would be to delete the "deferred" versions of have
, suffices
, and let
at the bottom of Mathlib.Tactic.Have
(Anyone who would like to contribute more cleanup is welcome to push directly to this branch.)
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -878,8 +878,8 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h : a ≠ b) :
l ~ replicate m a ++ replicate n b ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] := by
rw [perm_iff_count, ← Decidable.and_forall_ne a, ← Decidable.and_forall_ne b]
- suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l
- { simp (config := { contextual := true }) [count_replicate, h, h.symm, this, count_eq_zero] }
+ suffices l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l by
+ simp (config := { contextual := true }) [count_replicate, h, h.symm, this, count_eq_zero]
simp_rw [Ne.def, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons,
not_mem_nil, or_false, or_comm]
#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
@@ -212,8 +212,8 @@ theorem singleton_perm {a : α} {l : List α} : [a] ~ l ↔ [a] = l :=
@replicate_perm α 1 a l
#align list.singleton_perm List.singleton_perm
-alias perm_singleton ↔ Perm.eq_singleton _
-alias singleton_perm ↔ Perm.singleton_eq _
+alias ⟨Perm.eq_singleton, _⟩ := perm_singleton
+alias ⟨Perm.singleton_eq, _⟩ := singleton_perm
theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b := by simp
#align list.singleton_perm_singleton List.singleton_perm_singleton
@@ -669,7 +669,7 @@ theorem subperm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ <+~ a :: l₂
· exact ⟨u, p.cons_inv, s'⟩, fun ⟨l, p, s⟩ => ⟨a :: l, p.cons a, s.cons₂ _⟩⟩
#align list.subperm_cons List.subperm_cons
-alias subperm_cons ↔ subperm.of_cons subperm.cons
+alias ⟨subperm.of_cons, subperm.cons⟩ := subperm_cons
#align list.subperm.of_cons List.subperm.of_cons
#align list.subperm.cons List.subperm.cons
This incorporates changes from https://github.com/leanprover-community/mathlib4/pull/6575
I have also renamed Multiset.countp
to Multiset.countP
for consistency.
Co-authored-by: James Gallichio <jamesgallicchio@gmail.com>
Co-authored-by: James <jamesgallicchio@gmail.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -464,40 +464,40 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
⟨l, p.cons a⟩
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
-theorem Perm.countp_eq (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
- countp p l₁ = countp p l₂ := by
- rw [countp_eq_length_filter, countp_eq_length_filter]; exact (s.filter _).length_eq
-#align list.perm.countp_eq List.Perm.countp_eq
-
-theorem Subperm.countp_le (p : α → Bool) {l₁ l₂ : List α} :
- l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
- | ⟨_l, p', s⟩ => p'.countp_eq p ▸ s.countp_le p
-#align list.subperm.countp_le List.Subperm.countp_le
-
-theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Bool}
- (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' := by
- rw [← s.countp_eq p']
+theorem Perm.countP_eq (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
+ countP p l₁ = countP p l₂ := by
+ rw [countP_eq_length_filter, countP_eq_length_filter]; exact (s.filter _).length_eq
+#align list.perm.countp_eq List.Perm.countP_eq
+
+theorem Subperm.countP_le (p : α → Bool) {l₁ l₂ : List α} :
+ l₁ <+~ l₂ → countP p l₁ ≤ countP p l₂
+ | ⟨_l, p', s⟩ => p'.countP_eq p ▸ s.countP_le p
+#align list.subperm.countp_le List.Subperm.countP_le
+
+theorem Perm.countP_congr (s : l₁ ~ l₂) {p p' : α → Bool}
+ (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countP p = l₂.countP p' := by
+ rw [← s.countP_eq p']
clear s
induction' l₁ with y s hs
· rfl
· simp only [mem_cons, forall_eq_or_imp] at hp
- simp only [countp_cons, hs hp.2, hp.1]
-#align list.perm.countp_congr List.Perm.countp_congr
+ simp only [countP_cons, hs hp.2, hp.1]
+#align list.perm.countp_congr List.Perm.countP_congr
-theorem countp_eq_countp_filter_add (l : List α) (p q : α → Bool) :
- l.countp p = (l.filter q).countp p + (l.filter fun a => ¬q a).countp p := by
- rw [← countp_append]
- exact Perm.countp_eq _ (filter_append_perm _ _).symm
-#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_add
+theorem countP_eq_countP_filter_add (l : List α) (p q : α → Bool) :
+ l.countP p = (l.filter q).countP p + (l.filter fun a => ¬q a).countP p := by
+ rw [← countP_append]
+ exact Perm.countP_eq _ (filter_append_perm _ _).symm
+#align list.countp_eq_countp_filter_add List.countP_eq_countP_filter_add
theorem Perm.count_eq [DecidableEq α] {l₁ l₂ : List α} (p : l₁ ~ l₂) (a) :
count a l₁ = count a l₂ :=
- p.countp_eq _
+ p.countP_eq _
#align list.perm.count_eq List.Perm.count_eq
theorem Subperm.count_le [DecidableEq α] {l₁ l₂ : List α} (s : l₁ <+~ l₂) (a) :
count a l₁ ≤ count a l₂ :=
- s.countp_le _
+ s.countP_le _
#align list.subperm.count_le List.Subperm.count_le
theorem Perm.foldl_eq' {f : β → α → β} {l₁ l₂ : List α} (p : l₁ ~ l₂) :
@@ -868,7 +868,7 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
specialize H b
simp at H
contradiction
- · have : a ∈ l₂ := count_pos.1 (by rw [← H]; simp)
+ · have : a ∈ l₂ := count_pos_iff_mem.1 (by rw [← H, count_pos_iff_mem]; simp)
refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
specialize H b
rw [(perm_cons_erase this).count_eq] at H
@@ -879,7 +879,7 @@ theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h
l ~ replicate m a ++ replicate n b ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] := by
rw [perm_iff_count, ← Decidable.and_forall_ne a, ← Decidable.and_forall_ne b]
suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l
- { simp (config := { contextual := true }) [count_replicate, h, h.symm, this] }
+ { simp (config := { contextual := true }) [count_replicate, h, h.symm, this, count_eq_zero] }
simp_rw [Ne.def, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons,
not_mem_nil, or_false, or_comm]
#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
@@ -894,8 +894,8 @@ theorem subperm_append_diff_self_of_count_le {l₁ l₂ : List α}
induction' l₁ with hd tl IH generalizing l₂
· simp
· have : hd ∈ l₂ := by
- rw [← count_pos]
- exact lt_of_lt_of_le (count_pos.mpr (mem_cons_self _ _)) (h hd (mem_cons_self _ _))
+ rw [← count_pos_iff_mem]
+ exact lt_of_lt_of_le (count_pos_iff_mem.mpr (mem_cons_self _ _)) (h hd (mem_cons_self _ _))
replace := perm_cons_erase this
refine' Perm.trans _ this.symm
rw [cons_append, diff_cons, perm_cons]
@@ -239,11 +239,9 @@ theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~
induction p with
| nil => simp
| cons x _p IH =>
- simp only [filterMap]
cases h : f x
<;> simp [h, filterMap, IH, Perm.cons]
| swap x y l₂ =>
- simp only [filterMap]
cases hx : f x
<;> cases hy : f y
<;> simp [hx, hy, filterMap, swap]
@@ -1295,8 +1293,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
- · simp only [permutations']
- exact IH.bind_right _
+ · exact IH.bind_right _
· dsimp [permutations']
rw [bind_assoc, bind_assoc]
apply Perm.bind_left
Type _
and Sort _
(#6499)
We remove all possible occurences of Type _
and Sort _
in favor of Type*
and Sort*
.
This has nice performance benefits.
@@ -323,7 +323,7 @@ section Rel
open Relator
-variable {γ : Type _} {δ : Type _} {r : α → β → Prop} {p : γ → δ → Prop}
+variable {γ : Type*} {δ : Type*} {r : α → β → Prop} {p : γ → δ → Prop}
-- mathport name: «expr ∘r »
local infixr:80 " ∘r " => Relation.Comp
@@ -526,7 +526,7 @@ theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : Left
Eq.trans (r₁ a) (r₂ a)
#align list.perm.foldr_eq List.Perm.foldr_eq
-theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
+theorem Perm.rec_heq {β : List α → Sort*} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
(hl : Perm l l') (f_congr : ∀ {a l l' b b'}, Perm l l' → HEq b b' → HEq (f a l b) (f a l' b'))
(f_swap : ∀ {a a' l b}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))) :
HEq (@List.rec α β b f l) (@List.rec α β b f l') := by
@@ -886,7 +886,7 @@ theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h
not_mem_nil, or_false, or_comm]
#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
-theorem Subperm.cons_right {α : Type _} {l l' : List α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
+theorem Subperm.cons_right {α : Type*} {l l' : List α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
h.trans (sublist_cons x l').subperm
#align list.subperm.cons_right List.Subperm.cons_right
@@ -1151,7 +1151,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
exact fun a b h h₁ h₂ => h h₂ h₁
#align list.perm.erasep List.Perm.erasep
-theorem Perm.take_inter {α : Type _} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
+theorem Perm.take_inter {α : Type*} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
(h' : ys.Nodup) : xs.take n ~ ys.inter (xs.take n) := by
simp only [List.inter]
exact Perm.trans (show xs.take n ~ xs.filter (· ∈ xs.take n) by
@@ -1262,7 +1262,7 @@ theorem mem_permutations {s t : List α} : s ∈ permutations t ↔ s ~ t :=
#align list.mem_permutations List.mem_permutations
--Porting note: temporary theorem to solve diamond issue
-private theorem DecEq_eq {α : Type _} [DecidableEq α] :
+private theorem DecEq_eq {α : Type*} [DecidableEq α] :
instBEqList = @instBEq (List α) instDecidableEqList :=
congr_arg BEq.mk <| by
funext l₁ l₂
Notably there is now a l1 ∪ l2
notation for List.union
.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Bulhwi Cha <chabulhwi@semmalgil.com>
@@ -984,20 +984,20 @@ theorem perm_insertNth {α} (x : α) (l : List α) {n} (h : n ≤ l.length) :
#align list.perm_insert_nth List.perm_insertNth
theorem Perm.union_right {l₁ l₂ : List α} (t₁ : List α) (h : l₁ ~ l₂) :
- l₁.union t₁ ~ l₂.union t₁ := by
+ l₁ ∪ t₁ ~ l₂ ∪ t₁ := by
induction' h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2 <;> try simp
· exact ih.insert a
· apply perm_insert_swap
· exact ih_1.trans ih_2
#align list.perm.union_right List.Perm.union_right
-theorem Perm.union_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.union t₁ ~ l.union t₂ := by
+theorem Perm.union_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l ∪ t₁ ~ l ∪ t₂ := by
induction l <;> simp [*, Perm.insert]
#align list.perm.union_left List.Perm.union_left
-- @[congr]
theorem Perm.union {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) :
- l₁.union t₁ ~ l₂.union t₂ :=
+ l₁ ∪ t₁ ~ l₂ ∪ t₂ :=
(p₁.union_right t₁).trans (p₂.union_left l₂)
#align list.perm.union List.Perm.union
@@ -572,7 +572,6 @@ theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (h
rw [mul_assoc z, mul_assoc z, h]
#align list.perm.prod_eq' List.Perm.prod_eq'
#align list.perm.sum_eq' List.Perm.sum_eq'
--- Porting note: TODO do I need to do anything to handle the to_additive instance?
variable [CommMonoid α]
protected
to *.insert
theorems (#6142)
Otherwise code like
theorem ContMDiffWithinAt.mythm (h : x ∈ insert y s) : _ = _
interprets insert
as ContMDiffWithinAt.insert
, not Insert.insert
.
@@ -957,7 +957,7 @@ theorem Perm.dedup {l₁ l₂ : List α} (p : l₁ ~ l₂) : dedup l₁ ~ dedup
#align list.perm.dedup List.Perm.dedup
-- attribute [congr]
-theorem Perm.insert (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.insert a ~ l₂.insert a :=
+protected theorem Perm.insert (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.insert a ~ l₂.insert a :=
if h : a ∈ l₁ then by simpa [h, p.subset h] using p
else by simpa [h, mt p.mem_iff.2 h] using p.cons a
#align list.perm.insert List.Perm.insert
@@ -1155,7 +1155,7 @@ theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
theorem Perm.take_inter {α : Type _} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
(h' : ys.Nodup) : xs.take n ~ ys.inter (xs.take n) := by
simp only [List.inter]
- exact Perm.trans (show xs.take n ~ xs.filter (. ∈ xs.take n) by
+ exact Perm.trans (show xs.take n ~ xs.filter (· ∈ xs.take n) by
conv_lhs => rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')])
(Perm.filter _ h)
#align list.perm.take_inter List.Perm.take_inter
@@ -2,17 +2,14 @@
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
-
-! This file was ported from Lean 3 source module data.list.perm
-! leanprover-community/mathlib commit 47adfab39a11a072db552f47594bf8ed2cf8a722
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathlib.Data.List.Dedup
import Mathlib.Data.List.Permutation
import Mathlib.Data.List.Range
import Mathlib.Data.Nat.Factorial.Basic
+#align_import data.list.perm from "leanprover-community/mathlib"@"47adfab39a11a072db552f47594bf8ed2cf8a722"
+
/-!
# List Permutations
This is the second half of the changes originally in #5699, removing all occurrences of ;
after a space and implementing a linter rule to enforce it.
In most cases this 2-character substring has a space after it, so the following command was run first:
find . -type f -name "*.lean" -exec sed -i -E 's/ ; /; /g' {} \;
The remaining cases were few enough in number that they were done manually.
@@ -272,7 +272,7 @@ theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α
#align list.perm.pmap List.Perm.pmap
theorem Perm.filter (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
- filter p l₁ ~ filter p l₂ := by rw [← filterMap_eq_filter] ; apply s.filterMap _
+ filter p l₁ ~ filter p l₂ := by rw [← filterMap_eq_filter]; apply s.filterMap _
#align list.perm.filter List.Perm.filter
theorem filter_append_perm (p : α → Bool) (l : List α) :
@@ -471,7 +471,7 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
theorem Perm.countp_eq (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
countp p l₁ = countp p l₂ := by
- rw [countp_eq_length_filter, countp_eq_length_filter] ; exact (s.filter _).length_eq
+ rw [countp_eq_length_filter, countp_eq_length_filter]; exact (s.filter _).length_eq
#align list.perm.countp_eq List.Perm.countp_eq
theorem Subperm.countp_le (p : α → Bool) {l₁ l₂ : List α} :
@@ -524,8 +524,8 @@ theorem Perm.foldl_eq {f : β → α → β} {l₁ l₂ : List α} (rcomm : Righ
theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : LeftCommutative f) (p : l₁ ~ l₂) :
∀ b, foldr f b l₁ = foldr f b l₂ :=
- perm_induction_on p (fun b => rfl) (fun x t₁ t₂ _p r b => by simp ; rw [r b])
- (fun x y t₁ t₂ _p r b => by simp ; rw [lcomm, r b]) fun t₁ t₂ t₃ _p₁ _p₂ r₁ r₂ a =>
+ perm_induction_on p (fun b => rfl) (fun x t₁ t₂ _p r b => by simp; rw [r b])
+ (fun x y t₁ t₂ _p r b => by simp; rw [lcomm, r b]) fun t₁ t₂ t₃ _p₁ _p₂ r₁ r₂ a =>
Eq.trans (r₁ a) (r₂ a)
#align list.perm.foldr_eq List.Perm.foldr_eq
@@ -774,7 +774,7 @@ theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase
Perm.cons_inv <| (perm_cons_erase h₁).symm.trans <| p.trans (perm_cons_erase h₂)
else by
have h₂ : a ∉ l₂ := mt p.mem_iff.2 h₁
- rw [erase_of_not_mem h₁, erase_of_not_mem h₂] ; exact p
+ rw [erase_of_not_mem h₁, erase_of_not_mem h₂]; exact p
#align list.perm.erase List.Perm.erase
theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.erase a := by
This PR is the result of running
find . -type f -name "*.lean" -exec sed -i -E 's/^( +)\. /\1· /' {} \;
find . -type f -name "*.lean" -exec sed -i -E 'N;s/^( +·)\n +(.*)$/\1 \2/;P;D' {} \;
which firstly replaces .
focusing dots with ·
and secondly removes isolated instances of such dots, unifying them with the following line. A new rule is placed in the style linter to verify this.
@@ -567,10 +567,10 @@ theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (h
l₁.prod = l₂.prod := by
refine h.foldl_eq' ?_ _
apply Pairwise.forall_of_forall
- . intro x y h z
+ · intro x y h z
exact (h z).symm
- . intros; rfl
- . apply hc.imp
+ · intros; rfl
+ · apply hc.imp
intro a b h z
rw [mul_assoc z, mul_assoc z, h]
#align list.perm.prod_eq' List.Perm.prod_eq'
@@ -1190,8 +1190,8 @@ theorem Perm.dropSlice_inter {α} [DecidableEq α] {xs ys : List α} (n m : ℕ)
have : n ≤ n + m := Nat.le_add_right _ _
have h₂ := h.nodup_iff.2 h'
apply Perm.trans _ (Perm.inter_append _).symm
- . exact Perm.append (Perm.take_inter _ h h') (Perm.drop_inter _ h h')
- . exact disjoint_take_drop h₂ this
+ · exact Perm.append (Perm.take_inter _ h h') (Perm.drop_inter _ h h')
+ · exact disjoint_take_drop h₂ this
#align list.perm.slice_inter List.Perm.dropSlice_inter
-- enumerating permutations
@@ -1426,11 +1426,9 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
rw [length_insertNth _ _ hk.le, length_insertNth _ _ (Nat.succ_le_of_lt hk)]
refine' ext_nthLe hl fun n hn hn' => _
rcases lt_trichotomy n k with (H | rfl | H)
- ·
- rw [nthLe_insertNth_of_lt _ _ _ _ H (H.trans hk),
+ · rw [nthLe_insertNth_of_lt _ _ _ _ H (H.trans hk),
nthLe_insertNth_of_lt _ _ _ _ (H.trans (Nat.lt_succ_self _))]
- ·
- rw [nthLe_insertNth_self _ _ _ hk.le, nthLe_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk,
+ · rw [nthLe_insertNth_self _ _ _ hk.le, nthLe_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk,
hk']
· rcases(Nat.succ_le_of_lt H).eq_or_lt with (rfl | H')
· rw [nthLe_insertNth_self _ _ _ (Nat.succ_le_of_lt hk)]
at
and goals (#5387)
Changes are of the form
some_tactic at h⊢
-> some_tactic at h ⊢
some_tactic at h
-> some_tactic at h
@@ -935,7 +935,7 @@ theorem subperm_singleton_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈
theorem Subperm.cons_left {l₁ l₂ : List α} (h : l₁ <+~ l₂) (x : α) (hx : count x l₁ < count x l₂) :
x :: l₁ <+~ l₂ := by
- rw [subperm_ext_iff] at h⊢
+ rw [subperm_ext_iff] at h ⊢
intro y hy
by_cases hy' : y = x
· subst x
@@ -392,7 +392,7 @@ section Subperm
a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
multiplicities of elements, and is used for the `≤` relation on multisets. -/
def Subperm (l₁ l₂ : List α) : Prop :=
- ∃ (l : _)(_ : l ~ l₁), l <+ l₂
+ ∃ (l : _) (_ : l ~ l₁), l <+ l₂
#align list.subperm List.Subperm
/-- `Subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
@@ -1236,15 +1236,15 @@ theorem length_permutations (l : List α) : length (permutations l) = (length l)
#align list.length_permutations List.length_permutations
theorem mem_permutations_of_perm_lemma {is l : List α}
- (H : l ~ [] ++ is → (∃ (ts' : _)(_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
+ (H : l ~ [] ++ is → (∃ (ts' : _) (_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
l ~ is → l ∈ permutations is := by simpa [permutations, perm_nil] using H
#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
theorem mem_permutationsAux_of_perm :
∀ {ts is l : List α},
- l ~ is ++ ts → (∃ (is' : _)(_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
+ l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
show ∀ (ts is l : List α),
- l ~ is ++ ts → (∃ (is' : _)(_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
+ l ~ is ++ ts → (∃ (is' : _) (_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
refine' permutationsAux.rec (by simp) _
intro t ts is IH1 IH2 l p
rw [permutationsAux_cons, mem_foldr_permutationsAux2]
Now that leanprover/lean4#2210 has been merged, this PR:
set_option synthInstance.etaExperiment true
commands (and some etaExperiment%
term elaborators)set_option maxHeartbeats
commandsCo-authored-by: Scott Morrison <scott.morrison@anu.edu.au> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Matthew Ballard <matt@mrb.email>
@@ -1270,8 +1270,8 @@ private theorem DecEq_eq {α : Type _} [DecidableEq α] :
instBEqList = @instBEq (List α) instDecidableEqList :=
congr_arg BEq.mk <| by
funext l₁ l₂
- rw [Bool.eq_iff_eq_true_iff, @beq_iff_eq _ (instBEqList),
- @beq_iff_eq _ (@instBEq (List α) instDecidableEqList)]
+ show (l₁ == l₂) = _
+ rw [Bool.eq_iff_eq_true_iff, @beq_iff_eq _ (_), decide_eq_true_iff]
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
(permutations'Aux a l).bind (permutations'Aux b) ~
This PR fixes two things:
align
statements for definitions and theorems and instances that are separated by two newlines from the relevant declaration (s/\n\n#align/\n#align
). This is often seen in the mathport output after ending calc
blocks.#align
statements. (This was needed for a script I wrote for #3630.)@@ -730,7 +730,6 @@ theorem Subperm.exists_of_length_lt {l₁ l₂ : List α} :
· exact ⟨a, s.eq_of_length h ▸ Subperm.refl _⟩
· exact (IH <| Nat.lt_of_succ_lt_succ h).imp fun a s =>
(swap _ _ _).subperm_right.1 <| (subperm_cons _).2 s
-
#align list.subperm.exists_of_length_lt List.Subperm.exists_of_length_lt
protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ := by
@@ -1162,7 +1161,6 @@ theorem Perm.take_inter {α : Type _} [DecidableEq α] {xs ys : List α} (n :
exact Perm.trans (show xs.take n ~ xs.filter (. ∈ xs.take n) by
conv_lhs => rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')])
(Perm.filter _ h)
-
#align list.perm.take_inter List.Perm.take_inter
theorem Perm.drop_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys) (h' : ys.Nodup) :
Notably incorporates https://github.com/leanprover/std4/pull/98 and https://github.com/leanprover/std4/pull/109.
https://github.com/leanprover/std4/pull/98 moves a number of lemmas from Mathlib to Std, so the bump requires deleting them in Mathlib. I did check on each lemma whether its attributes were kept in the move (and gave attribute markings in Mathlib if they were not present in Std), but a reviewer may wish to re-check.
List.mem_map
changed statement from b ∈ l.map f ↔ ∃ a, a ∈ l ∧ b = f a
to b ∈ l.map f ↔ ∃ a, a ∈ l ∧ f a = b
. Similarly for List.exists_of_mem_map
. This was a deliberate change, so I have simply adjusted proofs (many become simpler, which supports the change). I also deleted List.mem_map'
, List.exists_of_mem_map'
, which were temporary versions in Mathlib while waiting for this change (replacing their uses with the unprimed versions).
Also, the lemma sublist_nil_iff_eq_nil
seems to have been renamed to sublist_nil
during the move, so I added an alias for the old name.
(another issue fixed during review by @digama0) List.Sublist.filter
had an argument change from explicit to implicit. This appears to have been an oversight (cc @JamesGallicchio). I have temporarily introduced List.Sublist.filter'
with the argument explicit, and replaced Mathlib uses of Sublist.filter
with Sublist.filter'
. Later we can fix the argument in Std, and then delete List.Sublist.filter'
.
@@ -1373,7 +1373,7 @@ theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
· subst hx
simpa [takeWhile, Nat.succ_inj', DecEq_eq] using IH _
· rw [takeWhile]
- simp only [mem_map', cons.injEq, Ne.symm hx, false_and, and_false, exists_false,
+ simp only [mem_map, cons.injEq, Ne.symm hx, false_and, and_false, exists_false,
not_false_iff, count_eq_zero_of_not_mem, zero_add, hx, decide_False, length_nil]
#align list.count_permutations'_aux_self List.count_permutations'Aux_self
@@ -1406,7 +1406,7 @@ theorem nodup_permutations'Aux_of_not_mem (s : List α) (x : α) (hx : x ∉ s)
induction' s with y s IH
· simp
· simp only [not_or, mem_cons] at hx
- simp only [permutations'Aux, nodup_cons, mem_map', cons.injEq, exists_eq_right_right, not_and]
+ simp only [permutations'Aux, nodup_cons, mem_map, cons.injEq, exists_eq_right_right, not_and]
refine' ⟨fun _ => Ne.symm hx.left, _⟩
rw [nodup_map_iff]
· exact IH hx.right
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
! This file was ported from Lean 3 source module data.list.perm
-! leanprover-community/mathlib commit 7b78d1776212a91ecc94cf601f83bdcc46b04213
+! leanprover-community/mathlib commit 47adfab39a11a072db552f47594bf8ed2cf8a722
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -215,13 +215,8 @@ theorem singleton_perm {a : α} {l : List α} : [a] ~ l ↔ [a] = l :=
@replicate_perm α 1 a l
#align list.singleton_perm List.singleton_perm
-theorem Perm.eq_singleton {a : α} {l : List α} (p : l ~ [a]) : l = [a] :=
- perm_singleton.1 p
-#align list.perm.eq_singleton List.Perm.eq_singleton
-
-theorem Perm.singleton_eq {a : α} {l : List α} (p : [a] ~ l) : [a] = l :=
- p.symm.eq_singleton.symm
-#align list.perm.singleton_eq List.Perm.singleton_eq
+alias perm_singleton ↔ Perm.eq_singleton _
+alias singleton_perm ↔ Perm.singleton_eq _
theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b := by simp
#align list.singleton_perm_singleton List.singleton_perm_singleton
@@ -841,7 +841,7 @@ theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂
l₁.bagInter t ~ l₂.bagInter t := by
induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t; · simp
· by_cases x ∈ t <;> simp [*, Perm.cons]
- · by_cases x = y
+ · by_cases h : x = y
· simp [h]
by_cases xt : x ∈ t <;> by_cases yt : y ∈ t
· simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (Ne.symm h), erase_comm, swap]
@@ -854,7 +854,7 @@ theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂
theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
l.bagInter t₁ = l.bagInter t₂ := by
induction' l with a l IH generalizing t₁ t₂ p; · simp
- by_cases a ∈ t₁
+ by_cases h : a ∈ t₁
· simp [h, p.subset h, IH (p.erase _)]
· simp [h, mt p.mem_iff.2 h, IH p]
#align list.perm.bag_inter_left List.Perm.bagInter_left
@@ -880,11 +880,11 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
specialize H b
simp at H
contradiction
- · have : a ∈ l₂ := count_pos.1 (by rw [← H] ; simp)
+ · have : a ∈ l₂ := count_pos.1 (by rw [← H]; simp)
refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
specialize H b
rw [(perm_cons_erase this).count_eq] at H
- by_cases b = a <;> simp [h] at H⊢ <;> assumption⟩
+ by_cases h : b = a <;> simpa [h] using H⟩
#align list.perm_iff_count List.perm_iff_count
theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h : a ≠ b) :
This PR is the result of a slight variant on the following "algorithm"
_
and make all uppercase letters into lowercase_
and make all uppercase letters into lowercase(original_lean3_name, OriginalLean4Name)
#align
statement just before the next empty line#align
statement to have been inserted too early)@@ -681,6 +681,8 @@ theorem subperm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ <+~ a :: l₂
#align list.subperm_cons List.subperm_cons
alias subperm_cons ↔ subperm.of_cons subperm.cons
+#align list.subperm.of_cons List.subperm.of_cons
+#align list.subperm.cons List.subperm.cons
--Porting note: commented out
--attribute [protected] subperm.cons
List.perm_replicate_append_replicate
(#1509)
This is a forward-port of leanprover-community/mathlib#18126
Also golf a proof.
@@ -87,29 +87,25 @@ instance isSetoid (α) : Setoid (List α) :=
#align list.is_setoid List.isSetoid
-- Porting note: used rec_on in mathlib3; lean4 eqn compiler still doesn't like it
-theorem Perm.subset {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ := fun a =>
+theorem Perm.mem_iff {a : α} {l₁ l₂ : List α} (p : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
p.rec
- (fun h => h)
- (fun x l₁ l₂ _r hs h => by
- cases h
- . apply Mem.head
- . apply Mem.tail
- apply hs
- assumption)
- (fun x y l h => by
- match h with
- | .head _ => exact Mem.tail x (Mem.head l)
- | .tail _ (.head _) => apply Mem.head
- | .tail _ (.tail _ h) => exact Mem.tail x (Mem.tail y h))
- (fun _ _ h₁ h₂ h => by
- apply h₂
- apply h₁
- assumption)
+ Iff.rfl
+ (fun _ _ _ _ hs => by simp only [mem_cons, hs])
+ (fun _ _ _ => by simp only [mem_cons, or_left_comm])
+ (fun _ _ => Iff.trans)
+#align list.perm.mem_iff List.Perm.mem_iff
+
+theorem Perm.subset {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ :=
+ fun _ => p.mem_iff.mp
#align list.perm.subset List.Perm.subset
-theorem Perm.mem_iff {a : α} {l₁ l₂ : List α} (h : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
- Iff.intro (fun m => h.subset m) fun m => h.symm.subset m
-#align list.perm.mem_iff List.Perm.mem_iff
+theorem Perm.subset_congr_left {l₁ l₂ l₃ : List α} (h : l₁ ~ l₂) : l₁ ⊆ l₃ ↔ l₂ ⊆ l₃ :=
+ ⟨h.symm.subset.trans, h.subset.trans⟩
+#align list.perm.subset_congr_left List.Perm.subset_congr_left
+
+theorem Perm.subset_congr_right {l₁ l₂ l₃ : List α} (h : l₁ ~ l₂) : l₃ ⊆ l₁ ↔ l₃ ⊆ l₂ :=
+ ⟨fun h' => h'.trans h.subset, fun h' => h'.trans h.symm.subset⟩
+#align list.perm.subset_congr_right List.Perm.subset_congr_right
theorem Perm.append_right {l₁ l₂ : List α} (t₁ : List α) (p : l₁ ~ l₂) : l₁ ++ t₁ ~ l₂ ++ t₁ :=
p.rec
@@ -889,6 +885,15 @@ theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l
by_cases b = a <;> simp [h] at H⊢ <;> assumption⟩
#align list.perm_iff_count List.perm_iff_count
+theorem perm_replicate_append_replicate {l : List α} {a b : α} {m n : ℕ} (h : a ≠ b) :
+ l ~ replicate m a ++ replicate n b ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] := by
+ rw [perm_iff_count, ← Decidable.and_forall_ne a, ← Decidable.and_forall_ne b]
+ suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l
+ { simp (config := { contextual := true }) [count_replicate, h, h.symm, this] }
+ simp_rw [Ne.def, ← and_imp, ← not_or, Decidable.not_imp_not, subset_def, mem_cons,
+ not_mem_nil, or_false, or_comm]
+#align list.perm_replicate_append_replicate List.perm_replicate_append_replicate
+
theorem Subperm.cons_right {α : Type _} {l l' : List α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
h.trans (sublist_cons x l').subperm
#align list.subperm.cons_right List.Subperm.cons_right
@@ -583,6 +583,7 @@ theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (h
intro a b h z
rw [mul_assoc z, mul_assoc z, h]
#align list.perm.prod_eq' List.Perm.prod_eq'
+#align list.perm.sum_eq' List.Perm.sum_eq'
-- Porting note: TODO do I need to do anything to handle the to_additive instance?
variable [CommMonoid α]
@@ -591,11 +592,13 @@ variable [CommMonoid α]
theorem Perm.prod_eq {l₁ l₂ : List α} (h : Perm l₁ l₂) : prod l₁ = prod l₂ :=
h.fold_op_eq
#align list.perm.prod_eq List.Perm.prod_eq
+#align list.perm.sum_eq List.Perm.sum_eq
@[to_additive]
theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
(reverse_perm l).prod_eq
#align list.prod_reverse List.prod_reverse
+#align list.sum_reverse List.sum_reverse
end CommMonoid
This was done semi-automatically with some regular expressions in vim in contrast to the fully automatic https://github.com/leanprover-community/mathlib4/pull/1523.
Co-authored-by: Moritz Firsching <firsching@google.com>
@@ -322,8 +322,8 @@ theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p :
⟨r₁, pr.trans pm, sr⟩
#align list.exists_perm_sublist List.exists_perm_sublist
-theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂) : sizeOf l₁ = sizeOf l₂ :=
- by
+theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂) :
+ sizeOf l₁ = sizeOf l₂ := by
induction h with -- hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
| nil => rfl
| cons _ _ h_sz₁₂ => simp [h_sz₁₂]
@@ -983,8 +983,8 @@ theorem perm_insertNth {α} (x : α) (l : List α) {n} (h : n ≤ l.length) :
· apply Perm.swap
#align list.perm_insert_nth List.perm_insertNth
-theorem Perm.union_right {l₁ l₂ : List α} (t₁ : List α) (h : l₁ ~ l₂) : l₁.union t₁ ~ l₂.union t₁ :=
- by
+theorem Perm.union_right {l₁ l₂ : List α} (t₁ : List α) (h : l₁ ~ l₂) :
+ l₁.union t₁ ~ l₂.union t₁ := by
induction' h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2 <;> try simp
· exact ih.insert a
· apply perm_insert_swap
by
line breaks (#1523)
During porting, I usually fix the desired format we seem to want for the line breaks around by
with
awk '{do {{if (match($0, "^ by$") && length(p) < 98) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}' Mathlib/File/Im/Working/On.lean
I noticed there are some more files that slipped through.
This pull request is the result of running this command:
grep -lr "^ by\$" Mathlib | xargs -n 1 awk -i inplace '{do {{if (match($0, "^ by$") && length(p) < 98 && not (match(p, "^[ \t]*--"))) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}'
Co-authored-by: Moritz Firsching <firsching@google.com>
@@ -247,8 +247,7 @@ theorem perm_induction_on {P : List α → List α → Prop} {l₁ l₂ : List
-- Porting note: TODO figure out why invalid congr
-- @[congr]
theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~ l₂) :
- filterMap f l₁ ~ filterMap f l₂ :=
- by
+ filterMap f l₁ ~ filterMap f l₂ := by
induction p with
| nil => simp
| cons x _p IH =>
@@ -271,8 +270,7 @@ theorem Perm.map (f : α → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) : map f
#align list.perm.map List.Perm.map
theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) {H₁ H₂} :
- pmap f l₁ H₁ ~ pmap f l₂ H₂ :=
- by
+ pmap f l₁ H₁ ~ pmap f l₂ H₂ := by
induction p with
| nil => simp
| cons x _p IH => simp [IH, Perm.cons]
@@ -287,8 +285,7 @@ theorem Perm.filter (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
#align list.perm.filter List.Perm.filter
theorem filter_append_perm (p : α → Bool) (l : List α) :
- filter p l ++ filter (fun x => ¬p x) l ~ l :=
- by
+ filter p l ++ filter (fun x => ¬p x) l ~ l := by
induction' l with x l ih
· rfl
· by_cases h : p x
@@ -300,8 +297,7 @@ theorem filter_append_perm (p : α → Bool) (l : List α) :
#align list.filter_append_perm List.filter_append_perm
theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
- ∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
- by
+ ∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' := by
induction p generalizing l₁ with
| nil =>
exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
@@ -344,8 +340,7 @@ variable {γ : Type _} {δ : Type _} {r : α → β → Prop} {p : γ → δ →
-- mathport name: «expr ∘r »
local infixr:80 " ∘r " => Relation.Comp
-theorem perm_comp_perm : (Perm ∘r Perm : List α → List α → Prop) = Perm :=
- by
+theorem perm_comp_perm : (Perm ∘r Perm : List α → List α → Prop) = Perm := by
funext a c; apply propext
constructor
· exact fun ⟨b, hab, hba⟩ => Perm.trans hab hba
@@ -371,8 +366,7 @@ theorem perm_comp_forall₂ {l u v} (hlu : Perm l u) (huv : Forall₂ r u v) :
exact ⟨lb₁, hab₁, Perm.trans h₁₂ h₂₃⟩
#align list.perm_comp_forall₂ List.perm_comp_forall₂
-theorem forall₂_comp_perm_eq_perm_comp_forall₂ : Forall₂ r ∘r Perm = Perm ∘r Forall₂ r :=
- by
+theorem forall₂_comp_perm_eq_perm_comp_forall₂ : Forall₂ r ∘r Perm = Perm ∘r Forall₂ r := by
funext l₁ l₃; apply propext
constructor
· intro h
@@ -547,8 +541,7 @@ theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : Left
theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
(hl : Perm l l') (f_congr : ∀ {a l l' b b'}, Perm l l' → HEq b b' → HEq (f a l b) (f a l' b'))
(f_swap : ∀ {a a' l b}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))) :
- HEq (@List.rec α β b f l) (@List.rec α β b f l') :=
- by
+ HEq (@List.rec α β b f l) (@List.rec α β b f l') := by
induction hl
case nil => rfl
case cons a l l' h ih => exact f_congr h ih
@@ -607,8 +600,7 @@ theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
end CommMonoid
theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} :
- l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂ :=
- by
+ l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂ := by
generalize e₁ : l₁ ++ a :: r₁ = s₁; generalize e₂ : l₂ ++ a :: r₂ = s₂
intro p; revert l₁ l₂ r₁ r₂ e₁ e₂; clear l₁ l₂ β
show ∀ _ _ _ _, _
@@ -674,8 +666,7 @@ theorem perm_append_right_iff {l₁ l₂ : List α} (l) : l₁ ++ l ~ l₂ ++ l
Perm.append_right _⟩
#align list.perm_append_right_iff List.perm_append_right_iff
-theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ :=
- by
+theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ := by
refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
cases' o₁ with a <;> cases' o₂ with b; · rfl
· cases p.length_eq
@@ -696,8 +687,7 @@ alias subperm_cons ↔ subperm.of_cons subperm.cons
--attribute [protected] subperm.cons
theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
- (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ :=
- by
+ (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ := by
rcases s with ⟨l, p, s⟩
induction s generalizing l₁
case slnil => cases h₂
@@ -747,8 +737,7 @@ theorem Subperm.exists_of_length_lt {l₁ l₂ : List α} :
#align list.subperm.exists_of_length_lt List.Subperm.exists_of_length_lt
-protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ :=
- by
+protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ := by
induction' d with a l₁' h d IH
· exact ⟨nil, Perm.nil, nil_sublist _⟩
· cases' forall_mem_cons.1 H with H₁ H₂
@@ -793,8 +782,7 @@ theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase
rw [erase_of_not_mem h₁, erase_of_not_mem h₂] ; exact p
#align list.perm.erase List.Perm.erase
-theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.erase a :=
- by
+theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.erase a := by
by_cases h : a ∈ l
· exact (perm_cons_erase h).subperm
· rw [erase_of_not_mem h]
@@ -828,8 +816,7 @@ theorem Subperm.diff_right {l₁ l₂ : List α} (h : l₁ <+~ l₂) (t : List
#align list.subperm.diff_right List.Subperm.diff_right
theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
- (a :: l).erase b <+~ a :: l.erase b :=
- by
+ (a :: l).erase b <+~ a :: l.erase b := by
by_cases h : a = b
· subst b
rw [erase_cons_head]
@@ -850,8 +837,7 @@ theorem subset_cons_diff {a : α} {l₁ l₂ : List α} : (a :: l₁).diff l₂
#align list.subset_cons_diff List.subset_cons_diff
theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
- l₁.bagInter t ~ l₂.bagInter t :=
- by
+ l₁.bagInter t ~ l₂.bagInter t := by
induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t; · simp
· by_cases x ∈ t <;> simp [*, Perm.cons]
· by_cases x = y
@@ -865,8 +851,7 @@ theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂
#align list.perm.bag_inter_right List.Perm.bagInter_right
theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
- l.bagInter t₁ = l.bagInter t₂ :=
- by
+ l.bagInter t₁ = l.bagInter t₂ := by
induction' l with a l IH generalizing t₁ t₂ p; · simp
by_cases a ∈ t₁
· simp [h, p.subset h, IH (p.erase _)]
@@ -907,8 +892,7 @@ theorem Subperm.cons_right {α : Type _} {l l' : List α} (x : α) (h : l <+~ l'
/-- The list version of `add_tsub_cancel_of_le` for multisets. -/
theorem subperm_append_diff_self_of_count_le {l₁ l₂ : List α}
- (h : ∀ x ∈ l₁, count x l₁ ≤ count x l₂) : l₁ ++ l₂.diff l₁ ~ l₂ :=
- by
+ (h : ∀ x ∈ l₁, count x l₁ ≤ count x l₂) : l₁ ++ l₂.diff l₁ ~ l₂ := by
induction' l₁ with hd tl IH generalizing l₂
· simp
· have : hd ∈ l₂ := by
@@ -1103,8 +1087,7 @@ theorem Perm.bind_left (l : List α) {f g : α → List β} (h : ∀ a ∈ l, f
#align list.perm.bind_left List.Perm.bind_left
theorem bind_append_perm (l : List α) (f g : α → List β) :
- l.bind f ++ l.bind g ~ l.bind fun x => f x ++ g x :=
- by
+ l.bind f ++ l.bind g ~ l.bind fun x => f x ++ g x := by
induction' l with a l IH <;> simp
refine' (Perm.trans _ (IH.append_left _)).append_left _
rw [← append_assoc, ← append_assoc]
@@ -1178,8 +1161,7 @@ theorem Perm.take_inter {α : Type _} [DecidableEq α] {xs ys : List α} (n :
#align list.perm.take_inter List.Perm.take_inter
theorem Perm.drop_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys) (h' : ys.Nodup) :
- xs.drop n ~ ys.inter (xs.drop n) :=
- by
+ xs.drop n ~ ys.inter (xs.drop n) := by
by_cases h'' : n ≤ xs.length
· let n' := xs.length - n
have h₀ : n = xs.length - n' := by
@@ -1235,8 +1217,7 @@ theorem perm_of_mem_permutations {l₁ l₂ : List α} (h : l₁ ∈ permutation
#align list.perm_of_mem_permutations List.perm_of_mem_permutations
theorem length_permutationsAux :
- ∀ ts is : List α, length (permutationsAux ts is) + is.length ! = (length ts + length is)! :=
- by
+ ∀ ts is : List α, length (permutationsAux ts is) + is.length ! = (length ts + length is)! := by
refine' permutationsAux.rec (by simp) _
intro t ts is IH1 IH2
have IH2 : length (permutationsAux is nil) + 1 = is.length ! := by simpa using IH2
@@ -1291,8 +1272,7 @@ private theorem DecEq_eq {α : Type _} [DecidableEq α] :
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
(permutations'Aux a l).bind (permutations'Aux b) ~
- (permutations'Aux b l).bind (permutations'Aux a) :=
- by
+ (permutations'Aux b l).bind (permutations'Aux a) := by
induction' l with c l ih
· simp [swap]
simp [permutations'Aux]
@@ -1314,8 +1294,7 @@ theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
exact perm_append_comm.append (ih.map _)
#align list.perm_permutations'_aux_comm List.perm_permutations'Aux_comm
-theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t :=
- by
+theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
· simp only [permutations']
exact IH.bind_right _
@@ -1381,8 +1360,7 @@ theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
#align list.nth_le_permutations'_aux List.nthLe_permutations'Aux
theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
- count (x :: l) (permutations'Aux x l) = length (takeWhile ((· = ·) x) l) + 1 :=
- by
+ count (x :: l) (permutations'Aux x l) = length (takeWhile ((· = ·) x) l) + 1 := by
induction' l with y l IH generalizing x
· simp [takeWhile, count]
· rw [permutations'Aux, DecEq_eq, count_cons_self]
@@ -1396,8 +1374,7 @@ theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
@[simp]
theorem length_permutations'Aux (s : List α) (x : α) :
- length (permutations'Aux x s) = length s + 1 :=
- by
+ length (permutations'Aux x s) = length s + 1 := by
induction' s with y s IH
· simp
· simpa using IH
@@ -1410,8 +1387,7 @@ theorem permutations'Aux_nthLe_zero (s : List α) (x : α)
nthLe_permutations'Aux _ _ _ _
#align list.permutations'_aux_nth_le_zero List.permutations'Aux_nthLe_zero
-theorem injective_permutations'Aux (x : α) : Function.Injective (permutations'Aux x) :=
- by
+theorem injective_permutations'Aux (x : α) : Function.Injective (permutations'Aux x) := by
intro s t h
apply insertNth_injective s.length x
have hl : s.length = t.length := by simpa using congr_arg length h
@@ -1433,8 +1409,7 @@ theorem nodup_permutations'Aux_of_not_mem (s : List α) (x : α) (hx : x ∉ s)
#align list.nodup_permutations'_aux_of_not_mem List.nodup_permutations'Aux_of_not_mem
set_option linter.deprecated false in
-theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'Aux x s) ↔ x ∉ s :=
- by
+theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'Aux x s) ↔ x ∉ s := by
refine' ⟨fun h => _, nodup_permutations'Aux_of_not_mem _ _⟩
intro H
obtain ⟨k, hk, hk'⟩ := nthLe_of_mem H
@@ -1468,8 +1443,7 @@ theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'
#align list.nodup_permutations'_aux_iff List.nodup_permutations'Aux_iff
set_option linter.deprecated false in
-theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :=
- by
+theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations := by
rw [(permutations_perm_permutations' s).nodup_iff]
induction' hs with x l h h' IH
· simp
List.repeat
(#1579)
Mathlib 3 migrated to list.replicate
in leanprover-community/mathlib#18127 (merged) and leanprover-community/mathlib#18181 (awaiting review).
@@ -196,37 +196,27 @@ theorem perm_cons_append_cons {l l₁ l₂ : List α} (a : α) (p : l ~ l₁ ++
#align list.perm_cons_append_cons List.perm_cons_append_cons
@[simp]
-theorem perm_replicate {a : α} {n : ℕ} {l : List α} :
- l ~ List.replicate n a ↔ l = List.replicate n a :=
+theorem perm_replicate {n : ℕ} {a : α} {l : List α} :
+ l ~ replicate n a ↔ l = replicate n a :=
⟨fun p => eq_replicate.2
⟨p.length_eq.trans <| length_replicate _ _, fun _b m => eq_of_mem_replicate <| p.subset m⟩,
fun h => h ▸ Perm.refl _⟩
-
-set_option linter.deprecated false in
-@[deprecated perm_replicate]
-theorem perm_repeat {a : α} {n : ℕ} {l : List α} : l ~ List.repeat a n ↔ l = List.repeat a n :=
- perm_replicate
-#align list.perm_repeat List.perm_repeat
+#align list.perm_replicate List.perm_replicate
@[simp]
-theorem replicate_perm {a : α} {n : ℕ} {l : List α} :
- List.replicate n a ~ l ↔ List.replicate n a = l :=
+theorem replicate_perm {n : ℕ} {a : α} {l : List α} :
+ replicate n a ~ l ↔ replicate n a = l :=
(perm_comm.trans perm_replicate).trans eq_comm
-
-set_option linter.deprecated false in
-@[deprecated replicate_perm]
-theorem repeat_perm {a : α} {n : ℕ} {l : List α} : List.repeat a n ~ l ↔ List.repeat a n = l :=
- replicate_perm
-#align list.repeat_perm List.repeat_perm
+#align list.replicate_perm List.replicate_perm
@[simp]
theorem perm_singleton {a : α} {l : List α} : l ~ [a] ↔ l = [a] :=
- @perm_replicate α a 1 l
+ @perm_replicate α 1 a l
#align list.perm_singleton List.perm_singleton
@[simp]
theorem singleton_perm {a : α} {l : List α} : [a] ~ l ↔ [a] = l :=
- @replicate_perm α a 1 l
+ @replicate_perm α 1 a l
#align list.singleton_perm List.singleton_perm
theorem Perm.eq_singleton {a : α} {l : List α} (p : l ~ [a]) : l = [a] :=
Co-authored-by: ChrisHughes24 <chrishughes24@gmail.com> Co-authored-by: Ruben Van de Velde <65514131+Ruben-VandeVelde@users.noreply.github.com> Co-authored-by: Reid Barton <rwbarton@gmail.com> Co-authored-by: qawbecrdtey <qawbecrdtey@kaist.ac.kr> Co-authored-by: Chris Hughes <33847686+ChrisHughes24@users.noreply.github.com>
@@ -292,11 +292,11 @@ theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α
exact fun a m => H₂ a (p₂.subset m)
#align list.perm.pmap List.Perm.pmap
-theorem Perm.filter (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
+theorem Perm.filter (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
filter p l₁ ~ filter p l₂ := by rw [← filterMap_eq_filter] ; apply s.filterMap _
#align list.perm.filter List.Perm.filter
-theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
+theorem filter_append_perm (p : α → Bool) (l : List α) :
filter p l ++ filter (fun x => ¬p x) l ~ l :=
by
induction' l with x l ih
@@ -476,7 +476,7 @@ theorem Subperm.subset {l₁ l₂ : List α} : l₁ <+~ l₂ → l₁ ⊆ l₂
| ⟨_l, p, s⟩ => Subset.trans p.symm.subset s.subset
#align list.subperm.subset List.Subperm.subset
-theorem Subperm.filter (p : α → Prop) [DecidablePred p] ⦃l l' : List α⦄ (h : l <+~ l') :
+theorem Subperm.filter (p : α → Bool) ⦃l l' : List α⦄ (h : l <+~ l') :
filter p l <+~ filter p l' := by
obtain ⟨xs, hp, h⟩ := h
exact ⟨_, hp.filter p, h.filter p⟩
@@ -494,19 +494,18 @@ theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ →
⟨l, p.cons a⟩
#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
-theorem Perm.countp_eq (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
+theorem Perm.countp_eq (p : α → Bool) {l₁ l₂ : List α} (s : l₁ ~ l₂) :
countp p l₁ = countp p l₂ := by
rw [countp_eq_length_filter, countp_eq_length_filter] ; exact (s.filter _).length_eq
#align list.perm.countp_eq List.Perm.countp_eq
-theorem Subperm.countp_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} :
+theorem Subperm.countp_le (p : α → Bool) {l₁ l₂ : List α} :
l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
| ⟨_l, p', s⟩ => p'.countp_eq p ▸ s.countp_le p
#align list.subperm.countp_le List.Subperm.countp_le
-theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
- (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
- by
+theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Bool}
+ (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' := by
rw [← s.countp_eq p']
clear s
induction' l₁ with y s hs
@@ -515,9 +514,8 @@ theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred
simp only [countp_cons, hs hp.2, hp.1]
#align list.perm.countp_congr List.Perm.countp_congr
-theorem countp_eq_countp_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
- [DecidablePred q] : l.countp p = (l.filter q).countp p + (l.filter fun a => ¬q a).countp p :=
- by
+theorem countp_eq_countp_filter_add (l : List α) (p q : α → Bool) :
+ l.countp p = (l.filter q).countp p + (l.filter fun a => ¬q a).countp p := by
rw [← countp_append]
exact Perm.countp_eq _ (filter_append_perm _ _).symm
#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_add
@@ -861,7 +859,7 @@ theorem subset_cons_diff {a : α} {l₁ l₂ : List α} : (a :: l₁).diff l₂
subperm_cons_diff.subset
#align list.subset_cons_diff List.subset_cons_diff
-theorem Perm.bag_inter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
+theorem Perm.bagInter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
l₁.bagInter t ~ l₂.bagInter t :=
by
induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t; · simp
@@ -874,21 +872,21 @@ theorem Perm.bag_inter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l
· simp [xt, yt, mt mem_of_mem_erase, Perm.cons]
· simp [xt, yt]
· exact (ih_1 _).trans (ih_2 _)
-#align list.perm.bag_inter_right List.Perm.bag_inter_right
+#align list.perm.bag_inter_right List.Perm.bagInter_right
-theorem Perm.bag_inter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
+theorem Perm.bagInter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
l.bagInter t₁ = l.bagInter t₂ :=
by
induction' l with a l IH generalizing t₁ t₂ p; · simp
by_cases a ∈ t₁
· simp [h, p.subset h, IH (p.erase _)]
· simp [h, mt p.mem_iff.2 h, IH p]
-#align list.perm.bag_inter_left List.Perm.bag_inter_left
+#align list.perm.bag_inter_left List.Perm.bagInter_left
-theorem Perm.bag_inter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
+theorem Perm.bagInter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
l₁.bagInter t₁ ~ l₂.bagInter t₂ :=
- ht.bag_inter_left l₂ ▸ hl.bag_inter_right _
-#align list.perm.bag_inter List.Perm.bag_inter
+ ht.bagInter_left l₂ ▸ hl.bagInter_right _
+#align list.perm.bag_inter List.Perm.bagInter
theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
a :: l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.erase a :=
@@ -2,9 +2,16 @@
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura, Jeremy Avigad, Mario Carneiro
+
+! This file was ported from Lean 3 source module data.list.perm
+! leanprover-community/mathlib commit 7b78d1776212a91ecc94cf601f83bdcc46b04213
+! Please do not edit these lines, except to modify the commit id
+! if you have ported upstream changes.
-/
-import Mathlib.Init.Set
-import Mathlib.Data.List.Pairwise
+import Mathlib.Data.List.Dedup
+import Mathlib.Data.List.Permutation
+import Mathlib.Data.List.Range
+import Mathlib.Data.Nat.Factorial.Basic
/-!
# List Permutations
@@ -17,147 +24,1504 @@ another.
The notation `~` is used for permutation equivalence.
-/
+
+open Nat
+
+universe uu vv
+
namespace List
-/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are Permutations
+variable {α : Type uu} {β : Type vv} {l₁ l₂ : List α}
+
+/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
of each other. This is defined by induction using pairwise swaps. -/
-inductive Perm {α} : List α → List α → Prop
-| nil : Perm [] []
-| cons : ∀ (x : α) {l₁ l₂ : List α}, Perm l₁ l₂ → Perm (x::l₁) (x::l₂)
-| swap : ∀ (x y : α) (l : List α), Perm (y::x::l) (x::y::l)
-| trans : ∀ {l₁ l₂ l₃ : List α}, Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
+inductive Perm : List α → List α → Prop
+ | nil : Perm [] []
+ | cons (x : α) {l₁ l₂ : List α} : Perm l₁ l₂ → Perm (x :: l₁) (x :: l₂)
+ | swap (x y : α) (l : List α) : Perm (y :: x :: l) (x :: y :: l)
+ | trans {l₁ l₂ l₃ : List α} : Perm l₁ l₂ → Perm l₂ l₃ → Perm l₁ l₃
+#align list.perm List.Perm
-open Perm
+open Perm (swap)
+/-- `Perm l₁ l₂` or `l₁ ~ l₂` asserts that `l₁` and `l₂` are permutations
+ of each other. This is defined by induction using pairwise swaps. -/
infixl:50 " ~ " => Perm
-protected theorem Perm.refl : ∀ (l : List α), l ~ l
-| [] => Perm.nil
-| (x::xs) => (Perm.refl xs).cons x
+@[simp, refl]
+protected theorem Perm.refl : ∀ l : List α, l ~ l
+ | [] => Perm.nil
+ | x :: xs => (Perm.refl xs).cons x
+#align list.perm.refl List.Perm.refl
-protected theorem Perm.symm {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₂ ~ l₁ := by
-induction p with
-| nil => exact Perm.nil
-| cons x _ ih => exact Perm.cons x ih
-| swap x y l => exact Perm.swap y x l
-| trans _ _ ih₁ ih₂ => exact Perm.trans ih₂ ih₁
+-- Porting note: used rec_on in mathlib3; lean4 eqn compiler still doesn't like it
+@[symm]
+protected theorem Perm.symm {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₂ ~ l₁ :=
+ p.rec
+ .nil
+ (fun x _ _ _ r₁ => .cons x r₁)
+ (fun x y l => .swap y x l)
+ (fun _ _ r₁ r₂ => .trans r₂ r₁)
+#align list.perm.symm List.Perm.symm
-theorem Perm_comm {l₁ l₂ : List α} : l₁ ~ l₂ ↔ l₂ ~ l₁ := ⟨Perm.symm, Perm.symm⟩
+theorem perm_comm {l₁ l₂ : List α} : l₁ ~ l₂ ↔ l₂ ~ l₁ :=
+ ⟨Perm.symm, Perm.symm⟩
+#align list.perm_comm List.perm_comm
-theorem Perm.swap' (x y : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : y::x::l₁ ~ x::y::l₂ :=
- have h1 : y :: l₁ ~ y :: l₂ := Perm.cons y p
- have h2 : x :: y :: l₁ ~ x :: y :: l₂ := Perm.cons x h1
- have h3 : y :: x :: l₁ ~ x :: y :: l₁ := Perm.swap x y l₁
- Perm.trans h3 h2
+theorem Perm.swap' (x y : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : y :: x :: l₁ ~ x :: y :: l₂ :=
+ (swap _ _ _).trans ((p.cons _).cons _)
+#align list.perm.swap' List.Perm.swap'
-theorem Perm.Equivalence : Equivalence (@Perm α) := ⟨Perm.refl, Perm.symm, Perm.trans⟩
+attribute [trans] Perm.trans
-instance (α : Type u) : Setoid (List α) := ⟨Perm, Perm.Equivalence⟩
+theorem Perm.eqv (α) : Equivalence (@Perm α) :=
+ ⟨Perm.refl, Perm.symm, Perm.trans⟩
+#align list.perm.eqv List.Perm.eqv
-theorem Perm.subset {α : Type u} {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ := by
- induction p with
- | nil => exact nil_subset _
- | cons _ _ ih => exact cons_subset_cons _ ih
- | swap x y l =>
- intro a
- rw [mem_cons]
- exact fun
- | Or.inl rfl => Mem.tail _ (Mem.head ..)
- | Or.inr (Mem.head ..) => Mem.head ..
- | Or.inr (Mem.tail _ a_mem_l) => Mem.tail _ (Mem.tail _ a_mem_l)
- | trans _ _ ih₁ ih₂ => exact Subset.trans ih₁ ih₂
-
-theorem perm_middle {a : α} : ∀ {l₁ l₂ : List α}, l₁++a::l₂ ~ a::(l₁++l₂)
-| [], _ => Perm.refl _
-| b::l₁, l₂ =>
- let h2 := @perm_middle α a l₁ l₂
- (h2.cons _).trans (swap a b _)
-
-theorem perm_insertNth {x : α} : ∀ {l : List α} {n : Nat}, n ≤ l.length →
- insertNth n x l ~ x :: l
-| [], 0, _ => Perm.refl _
-| [], _+1, h => False.elim (Nat.not_succ_le_zero _ h)
-| _::_, 0, _ => Perm.refl _
-| _::_, _+1, h =>
- Perm.trans
- (Perm.cons _ (perm_insertNth (Nat.le_of_succ_le_succ h)))
- (Perm.swap _ _ _)
+--Porting note: new theorem
+theorem Perm.of_eq (h : l₁ = l₂) : l₁ ~ l₂ :=
+ h ▸ Perm.refl l₁
+
+instance isSetoid (α) : Setoid (List α) :=
+ Setoid.mk (@Perm α) (Perm.eqv α)
+#align list.is_setoid List.isSetoid
+
+-- Porting note: used rec_on in mathlib3; lean4 eqn compiler still doesn't like it
+theorem Perm.subset {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ := fun a =>
+ p.rec
+ (fun h => h)
+ (fun x l₁ l₂ _r hs h => by
+ cases h
+ . apply Mem.head
+ . apply Mem.tail
+ apply hs
+ assumption)
+ (fun x y l h => by
+ match h with
+ | .head _ => exact Mem.tail x (Mem.head l)
+ | .tail _ (.head _) => apply Mem.head
+ | .tail _ (.tail _ h) => exact Mem.tail x (Mem.tail y h))
+ (fun _ _ h₁ h₂ h => by
+ apply h₂
+ apply h₁
+ assumption)
+#align list.perm.subset List.Perm.subset
theorem Perm.mem_iff {a : α} {l₁ l₂ : List α} (h : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
- Iff.intro (fun m ↦ h.subset m) fun m ↦ h.symm.subset m
+ Iff.intro (fun m => h.subset m) fun m => h.symm.subset m
+#align list.perm.mem_iff List.Perm.mem_iff
+
+theorem Perm.append_right {l₁ l₂ : List α} (t₁ : List α) (p : l₁ ~ l₂) : l₁ ++ t₁ ~ l₂ ++ t₁ :=
+ p.rec
+ (Perm.refl ([] ++ t₁))
+ (fun x _ _ _ r₁ => r₁.cons x)
+ (fun x y _ => swap x y _)
+ (fun _ _ r₁ r₂ => r₁.trans r₂)
+#align list.perm.append_right List.Perm.append_right
+
+theorem Perm.append_left {t₁ t₂ : List α} : ∀ l : List α, t₁ ~ t₂ → l ++ t₁ ~ l ++ t₂
+ | [], p => p
+ | x :: xs, p => (p.append_left xs).cons x
+#align list.perm.append_left List.Perm.append_left
+
+theorem Perm.append {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ++ t₁ ~ l₂ ++ t₂ :=
+ (p₁.append_right t₁).trans (p₂.append_left l₂)
+#align list.perm.append List.Perm.append
+
+theorem Perm.append_cons (a : α) {h₁ h₂ t₁ t₂ : List α} (p₁ : h₁ ~ h₂) (p₂ : t₁ ~ t₂) :
+ h₁ ++ a :: t₁ ~ h₂ ++ a :: t₂ :=
+ p₁.append (p₂.cons a)
+#align list.perm.append_cons List.Perm.append_cons
+
+@[simp]
+theorem perm_middle {a : α} : ∀ {l₁ l₂ : List α}, l₁ ++ a :: l₂ ~ a :: (l₁ ++ l₂)
+ | [], _ => Perm.refl _
+ | b :: l₁, l₂ => ((@perm_middle a l₁ l₂).cons _).trans (swap a b _)
+#align list.perm_middle List.perm_middle
+
+@[simp]
+theorem perm_append_singleton (a : α) (l : List α) : l ++ [a] ~ a :: l :=
+ perm_middle.trans <| by rw [append_nil]
+#align list.perm_append_singleton List.perm_append_singleton
+
+theorem perm_append_comm : ∀ {l₁ l₂ : List α}, l₁ ++ l₂ ~ l₂ ++ l₁
+ | [], l₂ => by simp
+ | a :: t, l₂ => (perm_append_comm.cons _).trans perm_middle.symm
+#align list.perm_append_comm List.perm_append_comm
+
+theorem concat_perm (l : List α) (a : α) : concat l a ~ a :: l := by simp
+#align list.concat_perm List.concat_perm
+
+theorem Perm.length_eq {l₁ l₂ : List α} (p : l₁ ~ l₂) : length l₁ = length l₂ :=
+ p.rec
+ rfl
+ (fun _x l₁ l₂ _p r => by simp [r])
+ (fun _x _y l => by simp)
+ (fun _p₁ _p₂ r₁ r₂ => Eq.trans r₁ r₂)
+#align list.perm.length_eq List.Perm.length_eq
+
+theorem Perm.eq_nil {l : List α} (p : l ~ []) : l = [] :=
+ eq_nil_of_length_eq_zero p.length_eq
+#align list.perm.eq_nil List.Perm.eq_nil
+
+theorem Perm.nil_eq {l : List α} (p : [] ~ l) : [] = l :=
+ p.symm.eq_nil.symm
+#align list.perm.nil_eq List.Perm.nil_eq
+
+@[simp]
+theorem perm_nil {l₁ : List α} : l₁ ~ [] ↔ l₁ = [] :=
+ ⟨fun p => p.eq_nil, fun e => e ▸ Perm.refl _⟩
+#align list.perm_nil List.perm_nil
+
+@[simp]
+theorem nil_perm {l₁ : List α} : [] ~ l₁ ↔ l₁ = [] :=
+ perm_comm.trans perm_nil
+#align list.nil_perm List.nil_perm
+
+theorem not_perm_nil_cons (x : α) (l : List α) : ¬[] ~ x :: l
+ | p => by injection p.symm.eq_nil
+#align list.not_perm_nil_cons List.not_perm_nil_cons
+
+@[simp]
+theorem reverse_perm : ∀ l : List α, reverse l ~ l
+ | [] => Perm.nil
+ | a :: l => by
+ rw [reverse_cons]
+ exact (perm_append_singleton _ _).trans ((reverse_perm l).cons a)
+#align list.reverse_perm List.reverse_perm
+
+theorem perm_cons_append_cons {l l₁ l₂ : List α} (a : α) (p : l ~ l₁ ++ l₂) :
+ a :: l ~ l₁ ++ a :: l₂ :=
+ (p.cons a).trans perm_middle.symm
+#align list.perm_cons_append_cons List.perm_cons_append_cons
+
+@[simp]
+theorem perm_replicate {a : α} {n : ℕ} {l : List α} :
+ l ~ List.replicate n a ↔ l = List.replicate n a :=
+ ⟨fun p => eq_replicate.2
+ ⟨p.length_eq.trans <| length_replicate _ _, fun _b m => eq_of_mem_replicate <| p.subset m⟩,
+ fun h => h ▸ Perm.refl _⟩
+
+set_option linter.deprecated false in
+@[deprecated perm_replicate]
+theorem perm_repeat {a : α} {n : ℕ} {l : List α} : l ~ List.repeat a n ↔ l = List.repeat a n :=
+ perm_replicate
+#align list.perm_repeat List.perm_repeat
+
+@[simp]
+theorem replicate_perm {a : α} {n : ℕ} {l : List α} :
+ List.replicate n a ~ l ↔ List.replicate n a = l :=
+ (perm_comm.trans perm_replicate).trans eq_comm
+
+set_option linter.deprecated false in
+@[deprecated replicate_perm]
+theorem repeat_perm {a : α} {n : ℕ} {l : List α} : List.repeat a n ~ l ↔ List.repeat a n = l :=
+ replicate_perm
+#align list.repeat_perm List.repeat_perm
+
+@[simp]
+theorem perm_singleton {a : α} {l : List α} : l ~ [a] ↔ l = [a] :=
+ @perm_replicate α a 1 l
+#align list.perm_singleton List.perm_singleton
+
+@[simp]
+theorem singleton_perm {a : α} {l : List α} : [a] ~ l ↔ [a] = l :=
+ @replicate_perm α a 1 l
+#align list.singleton_perm List.singleton_perm
+
+theorem Perm.eq_singleton {a : α} {l : List α} (p : l ~ [a]) : l = [a] :=
+ perm_singleton.1 p
+#align list.perm.eq_singleton List.Perm.eq_singleton
+
+theorem Perm.singleton_eq {a : α} {l : List α} (p : [a] ~ l) : [a] = l :=
+ p.symm.eq_singleton.symm
+#align list.perm.singleton_eq List.Perm.singleton_eq
+
+theorem singleton_perm_singleton {a b : α} : [a] ~ [b] ↔ a = b := by simp
+#align list.singleton_perm_singleton List.singleton_perm_singleton
+
+theorem perm_cons_erase [DecidableEq α] {a : α} {l : List α} (h : a ∈ l) : l ~ a :: l.erase a :=
+ let ⟨_l₁, _l₂, _, e₁, e₂⟩ := exists_erase_eq h
+ e₂.symm ▸ e₁.symm ▸ perm_middle
+#align list.perm_cons_erase List.perm_cons_erase
-/-- The way Lean 4 computes the motive with `elab_as_elim` has changed
-relative to the behaviour of `elab_as_eliminator` in Lean 3.
-See
-https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Potential.20elaboration.20bug.20with.20.60elabAsElim.60/near/299573172
-for an explanation of the change made here relative to mathlib3.
--/
@[elab_as_elim]
-theorem perm_induction_on
- {P : (l₁ : List α) → (l₂ : List α) → l₁ ~ l₂ → Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂)
- (nil : P [] [] .nil)
- (cons : ∀ x l₁ l₂, (h : l₁ ~ l₂) → P l₁ l₂ h → P (x :: l₁) (x :: l₂) (.cons x h))
- (swap : ∀ x y l₁ l₂, (h : l₁ ~ l₂) → P l₁ l₂ h →
- P (y :: x :: l₁) (x :: y :: l₂) (.trans (.swap x y _) (.cons _ (.cons _ h))))
- (trans : ∀ l₁ l₂ l₃, (h₁ : l₁ ~ l₂) → (h₂ : l₂ ~ l₃) → P l₁ l₂ h₁ → P l₂ l₃ h₂ →
- P l₁ l₃ (.trans h₁ h₂)) : P l₁ l₂ p :=
- have P_refl l : P l l (.refl l) :=
- List.recOn l nil fun x xs ih ↦ cons x xs xs (Perm.refl xs) ih
- Perm.recOn p nil cons (fun x y l ↦ swap x y l l (Perm.refl l) (P_refl l)) @trans
+theorem perm_induction_on {P : List α → List α → Prop} {l₁ l₂ : List α} (p : l₁ ~ l₂) (h₁ : P [] [])
+ (h₂ : ∀ x l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (x :: l₁) (x :: l₂))
+ (h₃ : ∀ x y l₁ l₂, l₁ ~ l₂ → P l₁ l₂ → P (y :: x :: l₁) (x :: y :: l₂))
+ (h₄ : ∀ l₁ l₂ l₃, l₁ ~ l₂ → l₂ ~ l₃ → P l₁ l₂ → P l₂ l₃ → P l₁ l₃) : P l₁ l₂ :=
+ have P_refl : ∀ l, P l l := fun l => List.recOn l h₁ fun x xs ih => h₂ x xs xs (Perm.refl xs) ih
+ p.rec h₁ h₂ (fun x y l => h₃ x y l l (Perm.refl l) (P_refl l)) @h₄
+#align list.perm_induction_on List.perm_induction_onₓ
+
+-- Porting note: TODO figure out why invalid congr
+-- @[congr]
+theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~ l₂) :
+ filterMap f l₁ ~ filterMap f l₂ :=
+ by
+ induction p with
+ | nil => simp
+ | cons x _p IH =>
+ simp only [filterMap]
+ cases h : f x
+ <;> simp [h, filterMap, IH, Perm.cons]
+ | swap x y l₂ =>
+ simp only [filterMap]
+ cases hx : f x
+ <;> cases hy : f y
+ <;> simp [hx, hy, filterMap, swap]
+ | trans _p₁ _p₂ IH₁ IH₂ =>
+ exact IH₁.trans IH₂
+#align list.perm.filter_map List.Perm.filterMap
+
+-- Porting note: TODO figure out why invalid congr
+-- @[congr]
+theorem Perm.map (f : α → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) : map f l₁ ~ map f l₂ :=
+ filterMap_eq_map f ▸ p.filterMap _
+#align list.perm.map List.Perm.map
+
+theorem Perm.pmap {p : α → Prop} (f : ∀ a, p a → β) {l₁ l₂ : List α} (p : l₁ ~ l₂) {H₁ H₂} :
+ pmap f l₁ H₁ ~ pmap f l₂ H₂ :=
+ by
+ induction p with
+ | nil => simp
+ | cons x _p IH => simp [IH, Perm.cons]
+ | swap x y => simp [swap]
+ | trans _p₁ p₂ IH₁ IH₂ =>
+ refine' IH₁.trans IH₂
+ exact fun a m => H₂ a (p₂.subset m)
+#align list.perm.pmap List.Perm.pmap
+
+theorem Perm.filter (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
+ filter p l₁ ~ filter p l₂ := by rw [← filterMap_eq_filter] ; apply s.filterMap _
+#align list.perm.filter List.Perm.filter
+
+theorem filter_append_perm (p : α → Prop) [DecidablePred p] (l : List α) :
+ filter p l ++ filter (fun x => ¬p x) l ~ l :=
+ by
+ induction' l with x l ih
+ · rfl
+ · by_cases h : p x
+ · simp only [h, filter_cons_of_pos, filter_cons_of_neg, not_true, not_false_iff, cons_append]
+ exact ih.cons x
+ · simp only [h, filter_cons_of_neg, not_false_iff, filter_cons_of_pos]
+ refine' Perm.trans _ (ih.cons x)
+ exact perm_append_comm.trans (perm_append_comm.cons _)
+#align list.filter_append_perm List.filter_append_perm
+
+theorem exists_perm_sublist {l₁ l₂ l₂' : List α} (s : l₁ <+ l₂) (p : l₂ ~ l₂') :
+ ∃ (l₁' : _) (_ : l₁' ~ l₁), l₁' <+ l₂' :=
+ by
+ induction p generalizing l₁ with
+ | nil =>
+ exact ⟨[], eq_nil_of_sublist_nil s ▸ Perm.refl _, nil_sublist _⟩
+ | cons x _ IH =>
+ cases' s with _ _ _ s l₁ _ _ s
+ · exact
+ let ⟨l₁', p', s'⟩ := IH s
+ ⟨l₁', p', s'.cons _⟩
+ · exact
+ let ⟨l₁', p', s'⟩ := IH s
+ ⟨x :: l₁', p'.cons x, s'.cons₂ _⟩
+ | swap x y _ =>
+ cases' s with _ _ _ s l₁ _ _ s <;> cases' s with _ _ _ s l₁ _ _ s
+ · exact ⟨l₁, Perm.refl _, (s.cons _).cons _⟩
+ · exact ⟨x :: l₁, Perm.refl _, (s.cons _).cons₂ _⟩
+ · exact ⟨y :: l₁, Perm.refl _, (s.cons₂ _).cons _⟩
+ · exact ⟨x :: y :: l₁, Perm.swap _ _ _, (s.cons₂ _).cons₂ _⟩
+ | trans _ _ IH₁ IH₂ =>
+ exact
+ let ⟨m₁, pm, sm⟩ := IH₁ s
+ let ⟨r₁, pr, sr⟩ := IH₂ sm
+ ⟨r₁, pr.trans pm, sr⟩
+#align list.exists_perm_sublist List.exists_perm_sublist
+
+theorem Perm.sizeOf_eq_sizeOf [SizeOf α] {l₁ l₂ : List α} (h : l₁ ~ l₂) : sizeOf l₁ = sizeOf l₂ :=
+ by
+ induction h with -- hd l₁ l₂ h₁₂ h_sz₁₂ a b l l₁ l₂ l₃ h₁₂ h₂₃ h_sz₁₂ h_sz₂₃
+ | nil => rfl
+ | cons _ _ h_sz₁₂ => simp [h_sz₁₂]
+ | swap => simp [add_left_comm]
+ | trans _ _ h_sz₁₂ h_sz₂₃ => simp [h_sz₁₂, h_sz₂₃]
+#align list.perm.sizeof_eq_sizeof List.Perm.sizeOf_eq_sizeOf
+
+section Rel
+
+open Relator
+
+variable {γ : Type _} {δ : Type _} {r : α → β → Prop} {p : γ → δ → Prop}
+
+-- mathport name: «expr ∘r »
+local infixr:80 " ∘r " => Relation.Comp
+
+theorem perm_comp_perm : (Perm ∘r Perm : List α → List α → Prop) = Perm :=
+ by
+ funext a c; apply propext
+ constructor
+ · exact fun ⟨b, hab, hba⟩ => Perm.trans hab hba
+ · exact fun h => ⟨a, Perm.refl a, h⟩
+#align list.perm_comp_perm List.perm_comp_perm
+
+theorem perm_comp_forall₂ {l u v} (hlu : Perm l u) (huv : Forall₂ r u v) :
+ (Forall₂ r ∘r Perm) l v := by
+ induction hlu generalizing v
+ case nil => cases huv; exact ⟨[], Forall₂.nil, Perm.nil⟩
+ case cons a l u _hlu ih =>
+ cases' huv with _ b _ v hab huv'
+ rcases ih huv' with ⟨l₂, h₁₂, h₂₃⟩
+ exact ⟨b :: l₂, Forall₂.cons hab h₁₂, h₂₃.cons _⟩
+ case swap a₁ a₂ h₂₃ =>
+ cases' huv with _ b₁ _ l₂ h₁ hr₂₃
+ cases' hr₂₃ with _ b₂ _ l₂ h₂ h₁₂
+ exact ⟨b₂ :: b₁ :: l₂, Forall₂.cons h₂ (Forall₂.cons h₁ h₁₂), Perm.swap _ _ _⟩
+ case
+ trans la₁ la₂ la₃ _ _ ih₁ ih₂ =>
+ rcases ih₂ huv with ⟨lb₂, hab₂, h₂₃⟩
+ rcases ih₁ hab₂ with ⟨lb₁, hab₁, h₁₂⟩
+ exact ⟨lb₁, hab₁, Perm.trans h₁₂ h₂₃⟩
+#align list.perm_comp_forall₂ List.perm_comp_forall₂
+
+theorem forall₂_comp_perm_eq_perm_comp_forall₂ : Forall₂ r ∘r Perm = Perm ∘r Forall₂ r :=
+ by
+ funext l₁ l₃; apply propext
+ constructor
+ · intro h
+ rcases h with ⟨l₂, h₁₂, h₂₃⟩
+ have : Forall₂ (flip r) l₂ l₁ := h₁₂.flip
+ rcases perm_comp_forall₂ h₂₃.symm this with ⟨l', h₁, h₂⟩
+ exact ⟨l', h₂.symm, h₁.flip⟩
+ · exact fun ⟨l₂, h₁₂, h₂₃⟩ => perm_comp_forall₂ h₁₂ h₂₃
+#align list.forall₂_comp_perm_eq_perm_comp_forall₂ List.forall₂_comp_perm_eq_perm_comp_forall₂
+
+theorem rel_perm_imp (hr : RightUnique r) : (Forall₂ r ⇒ Forall₂ r ⇒ (· → ·)) Perm Perm :=
+ fun a b h₁ c d h₂ h =>
+ have : (flip (Forall₂ r) ∘r Perm ∘r Forall₂ r) b d := ⟨a, h₁, c, h, h₂⟩
+ have : ((flip (Forall₂ r) ∘r Forall₂ r) ∘r Perm) b d := by
+ rwa [← forall₂_comp_perm_eq_perm_comp_forall₂, ← Relation.comp_assoc] at this
+ let ⟨b', ⟨c', hbc, hcb⟩, hbd⟩ := this
+ have : b' = b := right_unique_forall₂' hr hcb hbc
+ this ▸ hbd
+#align list.rel_perm_imp List.rel_perm_imp
+
+theorem rel_perm (hr : BiUnique r) : (Forall₂ r ⇒ Forall₂ r ⇒ (· ↔ ·)) Perm Perm :=
+ fun _a _b hab _c _d hcd =>
+ Iff.intro (rel_perm_imp hr.2 hab hcd) (rel_perm_imp hr.left.flip hab.flip hcd.flip)
+#align list.rel_perm List.rel_perm
+
+end Rel
+
+section Subperm
+
+
+/-- `Subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
+ a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
+ multiplicities of elements, and is used for the `≤` relation on multisets. -/
+def Subperm (l₁ l₂ : List α) : Prop :=
+ ∃ (l : _)(_ : l ~ l₁), l <+ l₂
+#align list.subperm List.Subperm
+
+/-- `Subperm l₁ l₂`, denoted `l₁ <+~ l₂`, means that `l₁` is a sublist of
+ a permutation of `l₂`. This is an analogue of `l₁ ⊆ l₂` which respects
+ multiplicities of elements, and is used for the `≤` relation on multisets. -/
+infixl:50 " <+~ " => Subperm
+
+theorem nil_subperm {l : List α} : [] <+~ l :=
+ ⟨[], Perm.nil, by simp⟩
+#align list.nil_subperm List.nil_subperm
+
+theorem Perm.subperm_left {l l₁ l₂ : List α} (p : l₁ ~ l₂) : l <+~ l₁ ↔ l <+~ l₂ :=
+ suffices ∀ {l₁ l₂ : List α}, l₁ ~ l₂ → l <+~ l₁ → l <+~ l₂ from ⟨this p, this p.symm⟩
+ fun p ⟨_u, pu, su⟩ =>
+ let ⟨v, pv, sv⟩ := exists_perm_sublist su p
+ ⟨v, pv.trans pu, sv⟩
+#align list.perm.subperm_left List.Perm.subperm_left
+
+theorem Perm.subperm_right {l₁ l₂ l : List α} (p : l₁ ~ l₂) : l₁ <+~ l ↔ l₂ <+~ l :=
+ ⟨fun ⟨u, pu, su⟩ => ⟨u, pu.trans p, su⟩, fun ⟨u, pu, su⟩ => ⟨u, pu.trans p.symm, su⟩⟩
+#align list.perm.subperm_right List.Perm.subperm_right
+
+theorem Sublist.subperm {l₁ l₂ : List α} (s : l₁ <+ l₂) : l₁ <+~ l₂ :=
+ ⟨l₁, Perm.refl _, s⟩
+#align list.sublist.subperm List.Sublist.subperm
+
+theorem Perm.subperm {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁ <+~ l₂ :=
+ ⟨l₂, p.symm, Sublist.refl _⟩
+#align list.perm.subperm List.Perm.subperm
+
+@[refl]
+theorem Subperm.refl (l : List α) : l <+~ l :=
+ (Perm.refl _).subperm
+#align list.subperm.refl List.Subperm.refl
+
+@[trans]
+theorem Subperm.trans {l₁ l₂ l₃ : List α} : l₁ <+~ l₂ → l₂ <+~ l₃ → l₁ <+~ l₃
+ | s, ⟨_l₂', p₂, s₂⟩ =>
+ let ⟨l₁', p₁, s₁⟩ := p₂.subperm_left.2 s
+ ⟨l₁', p₁, s₁.trans s₂⟩
+#align list.subperm.trans List.Subperm.trans
+
+theorem Subperm.length_le {l₁ l₂ : List α} : l₁ <+~ l₂ → length l₁ ≤ length l₂
+ | ⟨_l, p, s⟩ => p.length_eq ▸ s.length_le
+#align list.subperm.length_le List.Subperm.length_le
+
+theorem Subperm.perm_of_length_le {l₁ l₂ : List α} : l₁ <+~ l₂ → length l₂ ≤ length l₁ → l₁ ~ l₂
+ | ⟨_l, p, s⟩, h => (s.eq_of_length_le <| p.symm.length_eq ▸ h) ▸ p.symm
+#align list.subperm.perm_of_length_le List.Subperm.perm_of_length_le
+
+theorem Subperm.antisymm {l₁ l₂ : List α} (h₁ : l₁ <+~ l₂) (h₂ : l₂ <+~ l₁) : l₁ ~ l₂ :=
+ h₁.perm_of_length_le h₂.length_le
+#align list.subperm.antisymm List.Subperm.antisymm
+
+theorem Subperm.subset {l₁ l₂ : List α} : l₁ <+~ l₂ → l₁ ⊆ l₂
+ | ⟨_l, p, s⟩ => Subset.trans p.symm.subset s.subset
+#align list.subperm.subset List.Subperm.subset
+
+theorem Subperm.filter (p : α → Prop) [DecidablePred p] ⦃l l' : List α⦄ (h : l <+~ l') :
+ filter p l <+~ filter p l' := by
+ obtain ⟨xs, hp, h⟩ := h
+ exact ⟨_, hp.filter p, h.filter p⟩
+#align list.subperm.filter List.Subperm.filter
+
+end Subperm
+
+theorem Sublist.exists_perm_append : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → ∃ l, l₂ ~ l₁ ++ l
+ | _, _, Sublist.slnil => ⟨nil, Perm.refl _⟩
+ | _, _, Sublist.cons a s =>
+ let ⟨l, p⟩ := Sublist.exists_perm_append s
+ ⟨a :: l, (p.cons a).trans perm_middle.symm⟩
+ | _, _, Sublist.cons₂ a s =>
+ let ⟨l, p⟩ := Sublist.exists_perm_append s
+ ⟨l, p.cons a⟩
+#align list.sublist.exists_perm_append List.Sublist.exists_perm_append
+
+theorem Perm.countp_eq (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} (s : l₁ ~ l₂) :
+ countp p l₁ = countp p l₂ := by
+ rw [countp_eq_length_filter, countp_eq_length_filter] ; exact (s.filter _).length_eq
+#align list.perm.countp_eq List.Perm.countp_eq
+
+theorem Subperm.countp_le (p : α → Prop) [DecidablePred p] {l₁ l₂ : List α} :
+ l₁ <+~ l₂ → countp p l₁ ≤ countp p l₂
+ | ⟨_l, p', s⟩ => p'.countp_eq p ▸ s.countp_le p
+#align list.subperm.countp_le List.Subperm.countp_le
+
+theorem Perm.countp_congr (s : l₁ ~ l₂) {p p' : α → Prop} [DecidablePred p] [DecidablePred p']
+ (hp : ∀ x ∈ l₁, p x = p' x) : l₁.countp p = l₂.countp p' :=
+ by
+ rw [← s.countp_eq p']
+ clear s
+ induction' l₁ with y s hs
+ · rfl
+ · simp only [mem_cons, forall_eq_or_imp] at hp
+ simp only [countp_cons, hs hp.2, hp.1]
+#align list.perm.countp_congr List.Perm.countp_congr
+
+theorem countp_eq_countp_filter_add (l : List α) (p q : α → Prop) [DecidablePred p]
+ [DecidablePred q] : l.countp p = (l.filter q).countp p + (l.filter fun a => ¬q a).countp p :=
+ by
+ rw [← countp_append]
+ exact Perm.countp_eq _ (filter_append_perm _ _).symm
+#align list.countp_eq_countp_filter_add List.countp_eq_countp_filter_add
+
+theorem Perm.count_eq [DecidableEq α] {l₁ l₂ : List α} (p : l₁ ~ l₂) (a) :
+ count a l₁ = count a l₂ :=
+ p.countp_eq _
+#align list.perm.count_eq List.Perm.count_eq
+
+theorem Subperm.count_le [DecidableEq α] {l₁ l₂ : List α} (s : l₁ <+~ l₂) (a) :
+ count a l₁ ≤ count a l₂ :=
+ s.countp_le _
+#align list.subperm.count_le List.Subperm.count_le
+
+theorem Perm.foldl_eq' {f : β → α → β} {l₁ l₂ : List α} (p : l₁ ~ l₂) :
+ (∀ x ∈ l₁, ∀ y ∈ l₁, ∀ (z), f (f z x) y = f (f z y) x) → ∀ b, foldl f b l₁ = foldl f b l₂ :=
+ perm_induction_on p (fun _H b => rfl)
+ (fun x t₁ t₂ _p r H b => r (fun x hx y hy => H _ (.tail _ hx) _ (.tail _ hy)) _)
+ (fun x y t₁ t₂ _p r H b => by
+ simp only [foldl]
+ rw [H x (.tail _ <| .head _) y (.head _)]
+ exact r (fun x hx y hy => H _ (.tail _ <| .tail _ hx) _ (.tail _ <| .tail _ hy)) _)
+ fun t₁ t₂ t₃ p₁ _p₂ r₁ r₂ H b =>
+ Eq.trans (r₁ H b) (r₂ (fun x hx y hy => H _ (p₁.symm.subset hx) _ (p₁.symm.subset hy)) b)
+#align list.perm.foldl_eq' List.Perm.foldl_eq'
+
+theorem Perm.foldl_eq {f : β → α → β} {l₁ l₂ : List α} (rcomm : RightCommutative f) (p : l₁ ~ l₂) :
+ ∀ b, foldl f b l₁ = foldl f b l₂ :=
+ p.foldl_eq' fun x _hx y _hy z => rcomm z x y
+#align list.perm.foldl_eq List.Perm.foldl_eq
+
+theorem Perm.foldr_eq {f : α → β → β} {l₁ l₂ : List α} (lcomm : LeftCommutative f) (p : l₁ ~ l₂) :
+ ∀ b, foldr f b l₁ = foldr f b l₂ :=
+ perm_induction_on p (fun b => rfl) (fun x t₁ t₂ _p r b => by simp ; rw [r b])
+ (fun x y t₁ t₂ _p r b => by simp ; rw [lcomm, r b]) fun t₁ t₂ t₃ _p₁ _p₂ r₁ r₂ a =>
+ Eq.trans (r₁ a) (r₂ a)
+#align list.perm.foldr_eq List.Perm.foldr_eq
+
+theorem Perm.rec_heq {β : List α → Sort _} {f : ∀ a l, β l → β (a :: l)} {b : β []} {l l' : List α}
+ (hl : Perm l l') (f_congr : ∀ {a l l' b b'}, Perm l l' → HEq b b' → HEq (f a l b) (f a l' b'))
+ (f_swap : ∀ {a a' l b}, HEq (f a (a' :: l) (f a' l b)) (f a' (a :: l) (f a l b))) :
+ HEq (@List.rec α β b f l) (@List.rec α β b f l') :=
+ by
+ induction hl
+ case nil => rfl
+ case cons a l l' h ih => exact f_congr h ih
+ case swap a a' l => exact f_swap
+ case trans l₁ l₂ l₃ _h₁ _h₂ ih₁ ih₂ => exact HEq.trans ih₁ ih₂
+#align list.perm.rec_heq List.Perm.rec_heq
+
+section
+
+variable {op : α → α → α} [IA : IsAssociative α op] [IC : IsCommutative α op]
+
+-- mathport name: op
+local notation a " * " b => op a b
+
+-- mathport name: foldl
+local notation l " <*> " a => foldl op a l
+
+theorem Perm.fold_op_eq {l₁ l₂ : List α} {a : α} (h : l₁ ~ l₂) : (l₁ <*> a) = l₂ <*> a :=
+ h.foldl_eq (right_comm _ IC.comm IA.assoc) _
+#align list.perm.fold_op_eq List.Perm.fold_op_eq
+
+end
+
+section CommMonoid
+
+/-- If elements of a list commute with each other, then their product does not
+depend on the order of elements. -/
+@[to_additive
+ "If elements of a list additively commute with each other, then their sum does not
+ depend on the order of elements."]
+theorem Perm.prod_eq' [M : Monoid α] {l₁ l₂ : List α} (h : l₁ ~ l₂) (hc : l₁.Pairwise Commute) :
+ l₁.prod = l₂.prod := by
+ refine h.foldl_eq' ?_ _
+ apply Pairwise.forall_of_forall
+ . intro x y h z
+ exact (h z).symm
+ . intros; rfl
+ . apply hc.imp
+ intro a b h z
+ rw [mul_assoc z, mul_assoc z, h]
+#align list.perm.prod_eq' List.Perm.prod_eq'
+-- Porting note: TODO do I need to do anything to handle the to_additive instance?
+
+variable [CommMonoid α]
+
+@[to_additive]
+theorem Perm.prod_eq {l₁ l₂ : List α} (h : Perm l₁ l₂) : prod l₁ = prod l₂ :=
+ h.fold_op_eq
+#align list.perm.prod_eq List.Perm.prod_eq
+
+@[to_additive]
+theorem prod_reverse (l : List α) : prod l.reverse = prod l :=
+ (reverse_perm l).prod_eq
+#align list.prod_reverse List.prod_reverse
+
+end CommMonoid
theorem perm_inv_core {a : α} {l₁ l₂ r₁ r₂ : List α} :
- l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂ := by
+ l₁ ++ a :: r₁ ~ l₂ ++ a :: r₂ → l₁ ++ r₁ ~ l₂ ++ r₂ :=
+ by
generalize e₁ : l₁ ++ a :: r₁ = s₁; generalize e₂ : l₂ ++ a :: r₂ = s₂
- intro p; induction p using perm_induction_on generalizing l₁ l₂ r₁ r₂ with
- | nil => apply (not_mem_nil a).elim; rw [← e₁]; simp
- | cons x t₁ t₂ p w =>
- rcases l₁ with _ | ⟨y, l₁⟩ <;> rcases l₂ with _ | ⟨z, l₂⟩ <;> injections <;> subst_vars
- · exact p
- · exact p.trans perm_middle
- · exact perm_middle.symm.trans p
- · exact (w rfl rfl).cons z
- | swap x y t₁ t₂ p w =>
- rcases l₁ with _ | ⟨y, _ | ⟨z, l₁⟩⟩ <;> rcases l₂ with _ | ⟨u, _ | ⟨v, l₂⟩⟩ <;>
- injections <;> subst_vars
- · exact p.cons y
- · exact p.cons u
- · exact (p.trans perm_middle).cons u
- · exact p.cons y
- · exact p.cons u
- · exact ((p.trans perm_middle).cons v).trans (swap _ _ _)
- · exact (perm_middle.symm.trans p).cons y
- · exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
- · exact (w rfl rfl).swap' _ _
- | trans t₁ t₂ t₃ p₁ p₂ w₁ w₂ =>
- subst t₁ t₃
- let ⟨l₂, r₂, e₂⟩ := mem_split (p₁.subset (by simp) : a ∈ t₂)
- subst t₂; exact (w₁ rfl rfl).trans (w₂ rfl rfl)
+ intro p; revert l₁ l₂ r₁ r₂ e₁ e₂; clear l₁ l₂ β
+ show ∀ _ _ _ _, _
+ refine
+ perm_induction_on p ?_ (fun x t₁ t₂ p IH => ?_) (fun x y t₁ t₂ p IH => ?_)
+ fun t₁ t₂ t₃ p₁ p₂ IH₁ IH₂ => ?_
+ <;> intro l₁ l₂ r₁ r₂ e₁ e₂
+ · apply (not_mem_nil a).elim
+ rw [← e₁]
+ simp
+ · cases' l₁ with y l₁ <;> cases' l₂ with z l₂ <;> dsimp at e₁ e₂ <;> injections <;> subst x
+ · substs t₁ t₂
+ exact p
+ · substs z t₁ t₂
+ exact p.trans perm_middle
+ · substs y t₁ t₂
+ exact perm_middle.symm.trans p
+ · substs z t₁ t₂
+ exact (IH _ _ _ _ rfl rfl).cons y
+ · rcases l₁ with (_ | ⟨y, _ | ⟨z, l₁⟩⟩) <;> rcases l₂ with (_ | ⟨u, _ | ⟨v, l₂⟩⟩) <;>
+ dsimp at e₁ e₂ <;> injections <;> substs x y
+ · substs r₁ r₂
+ exact p.cons a
+ · substs r₁ r₂
+ exact p.cons u
+ · substs r₁ v t₂
+ exact (p.trans perm_middle).cons u
+ · substs r₁ r₂
+ exact p.cons y
+ · substs r₁ r₂ y u
+ exact p.cons a
+ · substs r₁ u v t₂
+ exact ((p.trans perm_middle).cons y).trans (swap _ _ _)
+ · substs r₂ z t₁
+ exact (perm_middle.symm.trans p).cons y
+ · substs r₂ y z t₁
+ exact (swap _ _ _).trans ((perm_middle.symm.trans p).cons u)
+ · substs u v t₁ t₂
+ exact (IH _ _ _ _ rfl rfl).swap' _ _
+ · substs t₁ t₃
+ have : a ∈ t₂ := p₁.subset (by simp)
+ rcases mem_split this with ⟨l₂, r₂, e₂⟩
+ subst t₂
+ exact (IH₁ _ _ _ _ rfl rfl).trans (IH₂ _ _ _ _ rfl rfl)
+#align list.perm_inv_core List.perm_inv_core
theorem Perm.cons_inv {a : α} {l₁ l₂ : List α} : a :: l₁ ~ a :: l₂ → l₁ ~ l₂ :=
@perm_inv_core _ _ [] [] _ _
+#align list.perm.cons_inv List.Perm.cons_inv
-theorem Perm.length_eq {l₁ l₂ : List α} (p : l₁ ~ l₂) : length l₁ = length l₂ := by
- induction p with
- | nil => simp
- | cons _ _ ih => simp [ih]
- | swap _ _ l => simp
- | trans _ _ ih₁ ih₂ => exact ih₁.trans ih₂
+@[simp]
+theorem perm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ ~ a :: l₂ ↔ l₁ ~ l₂ :=
+ ⟨Perm.cons_inv, Perm.cons a⟩
+#align list.perm_cons List.perm_cons
+
+theorem perm_append_left_iff {l₁ l₂ : List α} : ∀ l, l ++ l₁ ~ l ++ l₂ ↔ l₁ ~ l₂
+ | [] => Iff.rfl
+ | a :: l => (perm_cons a).trans (perm_append_left_iff l)
+#align list.perm_append_left_iff List.perm_append_left_iff
+
+theorem perm_append_right_iff {l₁ l₂ : List α} (l) : l₁ ++ l ~ l₂ ++ l ↔ l₁ ~ l₂ :=
+ ⟨fun p => (perm_append_left_iff _).1 <| perm_append_comm.trans <| p.trans perm_append_comm,
+ Perm.append_right _⟩
+#align list.perm_append_right_iff List.perm_append_right_iff
+
+theorem perm_option_to_list {o₁ o₂ : Option α} : o₁.toList ~ o₂.toList ↔ o₁ = o₂ :=
+ by
+ refine' ⟨fun p => _, fun e => e ▸ Perm.refl _⟩
+ cases' o₁ with a <;> cases' o₂ with b; · rfl
+ · cases p.length_eq
+ · cases p.length_eq
+ · exact Option.mem_toList.1 (p.symm.subset <| by simp)
+#align list.perm_option_to_list List.perm_option_to_list
+
+theorem subperm_cons (a : α) {l₁ l₂ : List α} : a :: l₁ <+~ a :: l₂ ↔ l₁ <+~ l₂ :=
+ ⟨fun ⟨l, p, s⟩ => by
+ cases' s with _ _ _ s' u _ _ s'
+ · exact (p.subperm_left.2 <| (sublist_cons _ _).subperm).trans s'.subperm
+ · exact ⟨u, p.cons_inv, s'⟩, fun ⟨l, p, s⟩ => ⟨a :: l, p.cons a, s.cons₂ _⟩⟩
+#align list.subperm_cons List.subperm_cons
+
+alias subperm_cons ↔ subperm.of_cons subperm.cons
+
+--Porting note: commented out
+--attribute [protected] subperm.cons
+
+theorem cons_subperm_of_mem {a : α} {l₁ l₂ : List α} (d₁ : Nodup l₁) (h₁ : a ∉ l₁) (h₂ : a ∈ l₂)
+ (s : l₁ <+~ l₂) : a :: l₁ <+~ l₂ :=
+ by
+ rcases s with ⟨l, p, s⟩
+ induction s generalizing l₁
+ case slnil => cases h₂
+ case cons r₁ r₂ b s' ih =>
+ simp at h₂
+ cases' h₂ with e m
+ · subst b
+ exact ⟨a :: r₁, p.cons a, s'.cons₂ _⟩
+ · rcases ih d₁ h₁ m p with ⟨t, p', s'⟩
+ exact ⟨t, p', s'.cons _⟩
+ case cons₂ r₁ r₂ b _ ih =>
+ have bm : b ∈ l₁ := p.subset <| mem_cons_self _ _
+ have am : a ∈ r₂ := by
+ simp only [find?, mem_cons] at h₂
+ exact h₂.resolve_left fun e => h₁ <| e.symm ▸ bm
+ rcases mem_split bm with ⟨t₁, t₂, rfl⟩
+ have st : t₁ ++ t₂ <+ t₁ ++ b :: t₂ := by simp
+ rcases ih (d₁.sublist st) (mt (fun x => st.subset x) h₁) am
+ (Perm.cons_inv <| p.trans perm_middle) with
+ ⟨t, p', s'⟩
+ exact
+ ⟨b :: t, (p'.cons b).trans <| (swap _ _ _).trans (perm_middle.symm.cons a), s'.cons₂ _⟩
+#align list.cons_subperm_of_mem List.cons_subperm_of_mem
+
+theorem subperm_append_left {l₁ l₂ : List α} : ∀ l, l ++ l₁ <+~ l ++ l₂ ↔ l₁ <+~ l₂
+ | [] => Iff.rfl
+ | a :: l => (subperm_cons a).trans (subperm_append_left l)
+#align list.subperm_append_left List.subperm_append_left
+
+theorem subperm_append_right {l₁ l₂ : List α} (l) : l₁ ++ l <+~ l₂ ++ l ↔ l₁ <+~ l₂ :=
+ (perm_append_comm.subperm_left.trans perm_append_comm.subperm_right).trans (subperm_append_left l)
+#align list.subperm_append_right List.subperm_append_right
+
+theorem Subperm.exists_of_length_lt {l₁ l₂ : List α} :
+ l₁ <+~ l₂ → length l₁ < length l₂ → ∃ a, a :: l₁ <+~ l₂
+ | ⟨l, p, s⟩, h => by
+ suffices length l < length l₂ → ∃ a : α, a :: l <+~ l₂ from
+ (this <| p.symm.length_eq ▸ h).imp fun a => (p.cons a).subperm_right.1
+ clear h p l₁
+ induction' s with l₁ l₂ a s IH _ _ b _ IH <;> intro h
+ · cases h
+ · cases' lt_or_eq_of_le (Nat.le_of_lt_succ h : length l₁ ≤ length l₂) with h h
+ · exact (IH h).imp fun a s => s.trans (sublist_cons _ _).subperm
+ · exact ⟨a, s.eq_of_length h ▸ Subperm.refl _⟩
+ · exact (IH <| Nat.lt_of_succ_lt_succ h).imp fun a s =>
+ (swap _ _ _).subperm_right.1 <| (subperm_cons _).2 s
+
+#align list.subperm.exists_of_length_lt List.Subperm.exists_of_length_lt
+
+protected theorem Nodup.subperm (d : Nodup l₁) (H : l₁ ⊆ l₂) : l₁ <+~ l₂ :=
+ by
+ induction' d with a l₁' h d IH
+ · exact ⟨nil, Perm.nil, nil_sublist _⟩
+ · cases' forall_mem_cons.1 H with H₁ H₂
+ simp at h
+ exact cons_subperm_of_mem d h H₁ (IH H₂)
+#align list.nodup.subperm List.Nodup.subperm
+
+theorem perm_ext {l₁ l₂ : List α} (d₁ : Nodup l₁) (d₂ : Nodup l₂) :
+ l₁ ~ l₂ ↔ ∀ a, a ∈ l₁ ↔ a ∈ l₂ :=
+ ⟨fun p _ => p.mem_iff, fun H =>
+ (d₁.subperm fun a => (H a).1).antisymm <| d₂.subperm fun a => (H a).2⟩
+#align list.perm_ext List.perm_ext
+
+theorem Nodup.sublist_ext {l₁ l₂ l : List α} (d : Nodup l) (s₁ : l₁ <+ l) (s₂ : l₂ <+ l) :
+ l₁ ~ l₂ ↔ l₁ = l₂ :=
+ ⟨fun h => by
+ induction' s₂ with l₂ l a s₂ IH l₂ l a _ IH generalizing l₁
+ · exact h.eq_nil
+ · simp at d
+ cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
+ · exact IH d.2 s₁ h
+ · apply d.1.elim
+ exact Subperm.subset ⟨_, h.symm, s₂⟩ (mem_cons_self _ _)
+ · simp at d
+ cases' s₁ with _ _ _ s₁ l₁ _ _ s₁
+ · apply d.1.elim
+ exact Subperm.subset ⟨_, h, s₁⟩ (mem_cons_self _ _)
+ · rw [IH d.2 s₁ h.cons_inv], fun h => by rw [h]⟩
+#align list.nodup.sublist_ext List.Nodup.sublist_ext
+
+section
+
+variable [DecidableEq α]
+
+-- attribute [congr]
+theorem Perm.erase (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.erase a ~ l₂.erase a :=
+ if h₁ : a ∈ l₁ then
+ have h₂ : a ∈ l₂ := p.subset h₁
+ Perm.cons_inv <| (perm_cons_erase h₁).symm.trans <| p.trans (perm_cons_erase h₂)
+ else by
+ have h₂ : a ∉ l₂ := mt p.mem_iff.2 h₁
+ rw [erase_of_not_mem h₁, erase_of_not_mem h₂] ; exact p
+#align list.perm.erase List.Perm.erase
+
+theorem subperm_cons_erase (a : α) (l : List α) : l <+~ a :: l.erase a :=
+ by
+ by_cases h : a ∈ l
+ · exact (perm_cons_erase h).subperm
+ · rw [erase_of_not_mem h]
+ exact (sublist_cons _ _).subperm
+#align list.subperm_cons_erase List.subperm_cons_erase
+
+theorem erase_subperm (a : α) (l : List α) : l.erase a <+~ l :=
+ (erase_sublist _ _).subperm
+#align list.erase_subperm List.erase_subperm
+
+theorem Subperm.erase {l₁ l₂ : List α} (a : α) (h : l₁ <+~ l₂) : l₁.erase a <+~ l₂.erase a :=
+ let ⟨l, hp, hs⟩ := h
+ ⟨l.erase a, hp.erase _, hs.erase _⟩
+#align list.subperm.erase List.Subperm.erase
+
+theorem Perm.diff_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) : l₁.diff t ~ l₂.diff t := by
+ induction t generalizing l₁ l₂ h <;> simp [*, Perm.erase]
+#align list.perm.diff_right List.Perm.diff_right
+
+theorem Perm.diff_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.diff t₁ = l.diff t₂ := by
+ induction h generalizing l <;>
+ first |simp [*, Perm.erase, erase_comm]
+#align list.perm.diff_left List.Perm.diff_left
+
+theorem Perm.diff {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) : l₁.diff t₁ ~ l₂.diff t₂ :=
+ ht.diff_left l₂ ▸ hl.diff_right _
+#align list.perm.diff List.Perm.diff
+
+theorem Subperm.diff_right {l₁ l₂ : List α} (h : l₁ <+~ l₂) (t : List α) :
+ l₁.diff t <+~ l₂.diff t := by induction t generalizing l₁ l₂ h <;> simp [*, Subperm.erase]
+#align list.subperm.diff_right List.Subperm.diff_right
+
+theorem erase_cons_subperm_cons_erase (a b : α) (l : List α) :
+ (a :: l).erase b <+~ a :: l.erase b :=
+ by
+ by_cases h : a = b
+ · subst b
+ rw [erase_cons_head]
+ apply subperm_cons_erase
+ · rw [erase_cons_tail _ h]
+#align list.erase_cons_subperm_cons_erase List.erase_cons_subperm_cons_erase
+
+theorem subperm_cons_diff {a : α} : ∀ {l₁ l₂ : List α}, (a :: l₁).diff l₂ <+~ a :: l₁.diff l₂
+ | l₁, [] => ⟨a :: l₁, by simp⟩
+ | l₁, b :: l₂ => by
+ simp only [diff_cons]
+ refine' ((erase_cons_subperm_cons_erase a b l₁).diff_right l₂).trans _
+ apply subperm_cons_diff
+#align list.subperm_cons_diff List.subperm_cons_diff
+
+theorem subset_cons_diff {a : α} {l₁ l₂ : List α} : (a :: l₁).diff l₂ ⊆ a :: l₁.diff l₂ :=
+ subperm_cons_diff.subset
+#align list.subset_cons_diff List.subset_cons_diff
+
+theorem Perm.bag_inter_right {l₁ l₂ : List α} (t : List α) (h : l₁ ~ l₂) :
+ l₁.bagInter t ~ l₂.bagInter t :=
+ by
+ induction' h with x _ _ _ _ x y _ _ _ _ _ _ ih_1 ih_2 generalizing t; · simp
+ · by_cases x ∈ t <;> simp [*, Perm.cons]
+ · by_cases x = y
+ · simp [h]
+ by_cases xt : x ∈ t <;> by_cases yt : y ∈ t
+ · simp [xt, yt, mem_erase_of_ne h, mem_erase_of_ne (Ne.symm h), erase_comm, swap]
+ · simp [xt, yt, mt mem_of_mem_erase, Perm.cons]
+ · simp [xt, yt, mt mem_of_mem_erase, Perm.cons]
+ · simp [xt, yt]
+ · exact (ih_1 _).trans (ih_2 _)
+#align list.perm.bag_inter_right List.Perm.bag_inter_right
+
+theorem Perm.bag_inter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) :
+ l.bagInter t₁ = l.bagInter t₂ :=
+ by
+ induction' l with a l IH generalizing t₁ t₂ p; · simp
+ by_cases a ∈ t₁
+ · simp [h, p.subset h, IH (p.erase _)]
+ · simp [h, mt p.mem_iff.2 h, IH p]
+#align list.perm.bag_inter_left List.Perm.bag_inter_left
+
+theorem Perm.bag_inter {l₁ l₂ t₁ t₂ : List α} (hl : l₁ ~ l₂) (ht : t₁ ~ t₂) :
+ l₁.bagInter t₁ ~ l₂.bagInter t₂ :=
+ ht.bag_inter_left l₂ ▸ hl.bag_inter_right _
+#align list.perm.bag_inter List.Perm.bag_inter
+
+theorem cons_perm_iff_perm_erase {a : α} {l₁ l₂ : List α} :
+ a :: l₁ ~ l₂ ↔ a ∈ l₂ ∧ l₁ ~ l₂.erase a :=
+ ⟨fun h =>
+ have : a ∈ l₂ := h.subset (mem_cons_self a l₁)
+ ⟨this, (h.trans <| perm_cons_erase this).cons_inv⟩,
+ fun ⟨m, h⟩ => (h.cons a).trans (perm_cons_erase m).symm⟩
+#align list.cons_perm_iff_perm_erase List.cons_perm_iff_perm_erase
+
+theorem perm_iff_count {l₁ l₂ : List α} : l₁ ~ l₂ ↔ ∀ a, count a l₁ = count a l₂ :=
+ ⟨Perm.count_eq, fun H => by
+ induction' l₁ with a l₁ IH generalizing l₂
+ · cases' l₂ with b l₂
+ · rfl
+ specialize H b
+ simp at H
+ contradiction
+ · have : a ∈ l₂ := count_pos.1 (by rw [← H] ; simp)
+ refine' ((IH fun b => _).cons a).trans (perm_cons_erase this).symm
+ specialize H b
+ rw [(perm_cons_erase this).count_eq] at H
+ by_cases b = a <;> simp [h] at H⊢ <;> assumption⟩
+#align list.perm_iff_count List.perm_iff_count
+
+theorem Subperm.cons_right {α : Type _} {l l' : List α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
+ h.trans (sublist_cons x l').subperm
+#align list.subperm.cons_right List.Subperm.cons_right
+
+/-- The list version of `add_tsub_cancel_of_le` for multisets. -/
+theorem subperm_append_diff_self_of_count_le {l₁ l₂ : List α}
+ (h : ∀ x ∈ l₁, count x l₁ ≤ count x l₂) : l₁ ++ l₂.diff l₁ ~ l₂ :=
+ by
+ induction' l₁ with hd tl IH generalizing l₂
+ · simp
+ · have : hd ∈ l₂ := by
+ rw [← count_pos]
+ exact lt_of_lt_of_le (count_pos.mpr (mem_cons_self _ _)) (h hd (mem_cons_self _ _))
+ replace := perm_cons_erase this
+ refine' Perm.trans _ this.symm
+ rw [cons_append, diff_cons, perm_cons]
+ refine' IH fun x hx => _
+ specialize h x (mem_cons_of_mem _ hx)
+ rw [perm_iff_count.mp this] at h
+ by_cases hx : x = hd
+ · subst hd
+ simpa [Nat.succ_le_succ_iff] using h
+ · simpa [hx] using h
+#align list.subperm_append_diff_self_of_count_le List.subperm_append_diff_self_of_count_le
+
+/-- The list version of `Multiset.le_iff_count`. -/
+theorem subperm_ext_iff {l₁ l₂ : List α} : l₁ <+~ l₂ ↔ ∀ x ∈ l₁, count x l₁ ≤ count x l₂ := by
+ refine' ⟨fun h x _ => Subperm.count_le h x, fun h => _⟩
+ suffices l₁ <+~ l₂.diff l₁ ++ l₁ by
+ refine' this.trans (Perm.subperm _)
+ exact perm_append_comm.trans (subperm_append_diff_self_of_count_le h)
+ exact (subperm_append_right l₁).mpr nil_subperm
+#align list.subperm_ext_iff List.subperm_ext_iff
+
+instance decidableSubperm : DecidableRel ((· <+~ ·) : List α → List α → Prop) := fun _ _ =>
+ decidable_of_iff _ List.subperm_ext_iff.symm
+#align list.decidable_subperm List.decidableSubperm
+
+@[simp]
+theorem subperm_singleton_iff {α} {l : List α} {a : α} : [a] <+~ l ↔ a ∈ l :=
+ ⟨fun ⟨s, hla, h⟩ => by rwa [perm_singleton.mp hla, singleton_sublist] at h, fun h =>
+ ⟨[a], Perm.refl _, singleton_sublist.mpr h⟩⟩
+#align list.subperm_singleton_iff List.subperm_singleton_iff
+
+theorem Subperm.cons_left {l₁ l₂ : List α} (h : l₁ <+~ l₂) (x : α) (hx : count x l₁ < count x l₂) :
+ x :: l₁ <+~ l₂ := by
+ rw [subperm_ext_iff] at h⊢
+ intro y hy
+ by_cases hy' : y = x
+ · subst x
+ simpa using Nat.succ_le_of_lt hx
+ · rw [count_cons_of_ne hy']
+ refine' h y _
+ simpa [hy'] using hy
+#align list.subperm.cons_left List.Subperm.cons_left
+
+instance decidablePerm : ∀ l₁ l₂ : List α, Decidable (l₁ ~ l₂)
+ | [], [] => isTrue <| Perm.refl _
+ | [], b :: l₂ => isFalse fun h => by have := h.nil_eq; contradiction
+ | a :: l₁, l₂ =>
+ haveI := decidablePerm l₁ (l₂.erase a)
+ decidable_of_iff' _ cons_perm_iff_perm_erase
+#align list.decidable_perm List.decidablePerm
+
+-- @[congr]
+theorem Perm.dedup {l₁ l₂ : List α} (p : l₁ ~ l₂) : dedup l₁ ~ dedup l₂ :=
+ perm_iff_count.2 fun a =>
+ if h : a ∈ l₁ then by simp [nodup_dedup, h, p.subset h] else by simp [h, mt p.mem_iff.2 h]
+#align list.perm.dedup List.Perm.dedup
+
+-- attribute [congr]
+theorem Perm.insert (a : α) {l₁ l₂ : List α} (p : l₁ ~ l₂) : l₁.insert a ~ l₂.insert a :=
+ if h : a ∈ l₁ then by simpa [h, p.subset h] using p
+ else by simpa [h, mt p.mem_iff.2 h] using p.cons a
+#align list.perm.insert List.Perm.insert
+
+theorem perm_insert_swap (x y : α) (l : List α) :
+ List.insert x (List.insert y l) ~ List.insert y (List.insert x l) := by
+ by_cases xl : x ∈ l <;> by_cases yl : y ∈ l <;> simp [xl, yl]
+ by_cases xy : x = y; · simp [xy]
+ simp [List.insert, xl, yl, xy, Ne.symm xy]
+ constructor
+#align list.perm_insert_swap List.perm_insert_swap
+
+theorem perm_insertNth {α} (x : α) (l : List α) {n} (h : n ≤ l.length) :
+ insertNth n x l ~ x :: l := by
+ induction' l with _ _ l_ih generalizing n
+ · cases n
+ rfl
+ cases h
+ cases n
+ · simp [insertNth]
+ · simp only [insertNth, modifyNthTail]
+ refine' Perm.trans (Perm.cons _ (l_ih _)) _
+ · apply Nat.le_of_succ_le_succ h
+ · apply Perm.swap
+#align list.perm_insert_nth List.perm_insertNth
+
+theorem Perm.union_right {l₁ l₂ : List α} (t₁ : List α) (h : l₁ ~ l₂) : l₁.union t₁ ~ l₂.union t₁ :=
+ by
+ induction' h with a _ _ _ ih _ _ _ _ _ _ _ _ ih_1 ih_2 <;> try simp
+ · exact ih.insert a
+ · apply perm_insert_swap
+ · exact ih_1.trans ih_2
+#align list.perm.union_right List.Perm.union_right
+
+theorem Perm.union_left (l : List α) {t₁ t₂ : List α} (h : t₁ ~ t₂) : l.union t₁ ~ l.union t₂ := by
+ induction l <;> simp [*, Perm.insert]
+#align list.perm.union_left List.Perm.union_left
-theorem Perm.eq_nil {l : List α} (p : l ~ []) : l = [] := eq_nil_of_length_eq_zero p.length_eq
+-- @[congr]
+theorem Perm.union {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) :
+ l₁.union t₁ ~ l₂.union t₂ :=
+ (p₁.union_right t₁).trans (p₂.union_left l₂)
+#align list.perm.union List.Perm.union
-theorem Perm.nil_eq {l : List α} (p : [] ~ l) : [] = l := p.symm.eq_nil.symm
+theorem Perm.inter_right {l₁ l₂ : List α} (t₁ : List α) : l₁ ~ l₂ → l₁ ∩ t₁ ~ l₂ ∩ t₁ :=
+ Perm.filter _
+#align list.perm.inter_right List.Perm.inter_right
+
+theorem Perm.inter_left (l : List α) {t₁ t₂ : List α} (p : t₁ ~ t₂) : l ∩ t₁ = l ∩ t₂ :=
+ filter_congr' fun a _ => by simpa using p.mem_iff
+#align list.perm.inter_left List.Perm.inter_left
+
+-- @[congr]
+theorem Perm.inter {l₁ l₂ t₁ t₂ : List α} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) : l₁ ∩ t₁ ~ l₂ ∩ t₂ :=
+ p₂.inter_left l₂ ▸ p₁.inter_right t₁
+#align list.perm.inter List.Perm.inter
+
+theorem Perm.inter_append {l t₁ t₂ : List α} (h : Disjoint t₁ t₂) :
+ l ∩ (t₁ ++ t₂) ~ l ∩ t₁ ++ l ∩ t₂ := by
+ induction l
+ case nil => simp
+ case cons x xs l_ih =>
+ by_cases h₁ : x ∈ t₁
+ · have h₂ : x ∉ t₂ := h h₁
+ simp [*]
+ by_cases h₂ : x ∈ t₂
+ · simp only [*, inter_cons_of_not_mem, false_or_iff, mem_append, inter_cons_of_mem,
+ not_false_iff]
+ refine' Perm.trans (Perm.cons _ l_ih) _
+ change [x] ++ xs ∩ t₁ ++ xs ∩ t₂ ~ xs ∩ t₁ ++ ([x] ++ xs ∩ t₂)
+ rw [← List.append_assoc]
+ solve_by_elim [Perm.append_right, perm_append_comm]
+ · simp [*]
+#align list.perm.inter_append List.Perm.inter_append
+
+end
theorem Perm.pairwise_iff {R : α → α → Prop} (S : Symmetric R) :
- ∀ {l₁ l₂ : List α}, l₁ ~ l₂ → (Pairwise R l₁ ↔ Pairwise R l₂) := by
- suffices ∀ {l₁ l₂}, l₁ ~ l₂ → Pairwise R l₁ → Pairwise R l₂ from
- fun l₁ l₂ p ↦ ⟨this p, this p.symm⟩
- intros l₁ l₂ p d
- induction d generalizing l₂ with
- | nil => rw [← p.nil_eq]; constructor
- | @cons a h d _ ih =>
- obtain ⟨s₂, t₂, rfl⟩ := mem_split (p.subset (.head ..) : a ∈ l₂)
+ ∀ {l₁ l₂ : List α} (_p : l₁ ~ l₂), Pairwise R l₁ ↔ Pairwise R l₂ :=
+ suffices ∀ {l₁ l₂}, l₁ ~ l₂ → Pairwise R l₁ → Pairwise R l₂
+ from fun p => ⟨this p, this p.symm⟩
+ @fun l₁ l₂ p d => by
+ induction' d with a l₁ h _ IH generalizing l₂
+ · rw [← p.nil_eq]
+ constructor
+ · have : a ∈ l₂ := p.subset (mem_cons_self _ _)
+ rcases mem_split this with ⟨s₂, t₂, rfl⟩
have p' := (p.trans perm_middle).cons_inv
- exact (pairwise_middle S).2 (pairwise_cons.2 ⟨fun b m ↦ d _ (p'.symm.subset m), ih p'⟩)
+ refine' (pairwise_middle S).2 (pairwise_cons.2 ⟨fun b m => _, IH _ p'⟩)
+ exact h _ (p'.symm.subset m)
+#align list.perm.pairwise_iff List.Perm.pairwise_iff
+
+
+theorem Pairwise.perm {R : α → α → Prop} {l l' : List α} (hR : l.Pairwise R) (hl : l ~ l')
+ (hsymm : Symmetric R) : l'.Pairwise R :=
+ (hl.pairwise_iff hsymm).mp hR
+#align list.pairwise.perm List.Pairwise.perm
+
+theorem Perm.pairwise {R : α → α → Prop} {l l' : List α} (hl : l ~ l') (hR : l.Pairwise R)
+ (hsymm : Symmetric R) : l'.Pairwise R :=
+ hR.perm hl hsymm
+#align list.perm.pairwise List.Perm.pairwise
theorem Perm.nodup_iff {l₁ l₂ : List α} : l₁ ~ l₂ → (Nodup l₁ ↔ Nodup l₂) :=
Perm.pairwise_iff <| @Ne.symm α
+#align list.perm.nodup_iff List.Perm.nodup_iff
+
+theorem Perm.join {l₁ l₂ : List (List α)} (h : l₁ ~ l₂) : l₁.join ~ l₂.join :=
+ Perm.recOn h (Perm.refl _) (fun x xs₁ xs₂ _ ih => ih.append_left x)
+ (fun x₁ x₂ xs => by simpa only [join, append_assoc] using perm_append_comm.append_right _)
+ @fun xs₁ xs₂ xs₃ _ _ => Perm.trans
+#align list.perm.join List.Perm.join
+
+theorem Perm.bind_right {l₁ l₂ : List α} (f : α → List β) (p : l₁ ~ l₂) : l₁.bind f ~ l₂.bind f :=
+ (p.map _).join
+#align list.perm.bind_right List.Perm.bind_right
+
+theorem Perm.join_congr :
+ ∀ {l₁ l₂ : List (List α)} (_ : List.Forall₂ (· ~ ·) l₁ l₂), l₁.join ~ l₂.join
+ | _, _, Forall₂.nil => Perm.refl _
+ | _ :: _, _ :: _, Forall₂.cons h₁ h₂ => h₁.append (Perm.join_congr h₂)
+#align list.perm.join_congr List.Perm.join_congr
+
+theorem Perm.bind_left (l : List α) {f g : α → List β} (h : ∀ a ∈ l, f a ~ g a) :
+ l.bind f ~ l.bind g :=
+ Perm.join_congr <| by
+ rwa [List.forall₂_map_right_iff, List.forall₂_map_left_iff, List.forall₂_same]
+#align list.perm.bind_left List.Perm.bind_left
+
+theorem bind_append_perm (l : List α) (f g : α → List β) :
+ l.bind f ++ l.bind g ~ l.bind fun x => f x ++ g x :=
+ by
+ induction' l with a l IH <;> simp
+ refine' (Perm.trans _ (IH.append_left _)).append_left _
+ rw [← append_assoc, ← append_assoc]
+ exact perm_append_comm.append_right _
+#align list.bind_append_perm List.bind_append_perm
+
+theorem map_append_bind_perm (l : List α) (f : α → β) (g : α → List β) :
+ l.map f ++ l.bind g ~ l.bind fun x => f x :: g x := by
+ simpa [← map_eq_bind] using bind_append_perm l (fun x => [f x]) g
+#align list.map_append_bind_perm List.map_append_bind_perm
+
+theorem Perm.product_right {l₁ l₂ : List α} (t₁ : List β) (p : l₁ ~ l₂) :
+ product l₁ t₁ ~ product l₂ t₁ :=
+ p.bind_right _
+#align list.perm.product_right List.Perm.product_right
+
+theorem Perm.product_left (l : List α) {t₁ t₂ : List β} (p : t₁ ~ t₂) :
+ product l t₁ ~ product l t₂ :=
+ (Perm.bind_left _) fun _ _ => p.map _
+#align list.perm.product_left List.Perm.product_left
+
+-- @[congr]
+theorem Perm.product {l₁ l₂ : List α} {t₁ t₂ : List β} (p₁ : l₁ ~ l₂) (p₂ : t₁ ~ t₂) :
+ product l₁ t₁ ~ product l₂ t₂ :=
+ (p₁.product_right t₁).trans (p₂.product_left l₂)
+#align list.perm.product List.Perm.product
+
+theorem perm_lookmap (f : α → Option α) {l₁ l₂ : List α}
+ (H : Pairwise (fun a b => ∀ c ∈ f a, ∀ d ∈ f b, a = b ∧ c = d) l₁) (p : l₁ ~ l₂) :
+ lookmap f l₁ ~ lookmap f l₂ := by
+ induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ _ IH₁ IH₂; · simp
+ · cases h : f a
+ · simp [h]
+ exact IH (pairwise_cons.1 H).2
+ · simp [lookmap_cons_some _ _ h, p]
+ · cases' h₁ : f a with c <;> cases' h₂ : f b with d
+ · simp [h₁, h₂]
+ apply swap
+ · simp [h₁, lookmap_cons_some _ _ h₂]
+ apply swap
+ · simp [lookmap_cons_some _ _ h₁, h₂]
+ apply swap
+ · simp [lookmap_cons_some _ _ h₁, lookmap_cons_some _ _ h₂]
+ rcases(pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) _ h₂ _ h₁ with ⟨rfl, rfl⟩
+ exact Perm.refl _
+ · refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
+ exact fun a b h c h₁ d h₂ => (h d h₂ c h₁).imp Eq.symm Eq.symm
+#align list.perm_lookmap List.perm_lookmap
+
+theorem Perm.erasep (f : α → Prop) [DecidablePred f] {l₁ l₂ : List α}
+ (H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ := by
+ induction' p with a l₁ l₂ p IH a b l l₁ l₂ l₃ p₁ _ IH₁ IH₂; · simp
+ · by_cases h : f a
+ · simp [h, p]
+ · simp [h]
+ exact IH (pairwise_cons.1 H).2
+ · by_cases h₁ : f a <;> by_cases h₂ : f b <;> simp [h₁, h₂]
+ · cases (pairwise_cons.1 H).1 _ (mem_cons.2 (Or.inl rfl)) h₂ h₁
+ · apply swap
+ · refine' (IH₁ H).trans (IH₂ ((p₁.pairwise_iff _).1 H))
+ exact fun a b h h₁ h₂ => h h₂ h₁
+#align list.perm.erasep List.Perm.erasep
+
+theorem Perm.take_inter {α : Type _} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys)
+ (h' : ys.Nodup) : xs.take n ~ ys.inter (xs.take n) := by
+ simp only [List.inter]
+ exact Perm.trans (show xs.take n ~ xs.filter (. ∈ xs.take n) by
+ conv_lhs => rw [Nodup.take_eq_filter_mem ((Perm.nodup_iff h).2 h')])
+ (Perm.filter _ h)
+
+#align list.perm.take_inter List.Perm.take_inter
+
+theorem Perm.drop_inter {α} [DecidableEq α] {xs ys : List α} (n : ℕ) (h : xs ~ ys) (h' : ys.Nodup) :
+ xs.drop n ~ ys.inter (xs.drop n) :=
+ by
+ by_cases h'' : n ≤ xs.length
+ · let n' := xs.length - n
+ have h₀ : n = xs.length - n' := by
+ rwa [tsub_tsub_cancel_of_le]
+ have h₁ : n' ≤ xs.length := by apply tsub_le_self
+ have h₂ : xs.drop n = (xs.reverse.take n').reverse := by
+ rw [reverse_take _ h₁, h₀, reverse_reverse]
+ rw [h₂]
+ apply (reverse_perm _).trans
+ rw [inter_reverse]
+ apply Perm.take_inter _ _ h'
+ apply (reverse_perm _).trans; assumption
+ · have : drop n xs = [] := by
+ apply eq_nil_of_length_eq_zero
+ rw [length_drop, tsub_eq_zero_iff_le]
+ apply le_of_not_ge h''
+ simp [this, List.inter]
+#align list.perm.drop_inter List.Perm.drop_inter
+
+theorem Perm.dropSlice_inter {α} [DecidableEq α] {xs ys : List α} (n m : ℕ) (h : xs ~ ys)
+ (h' : ys.Nodup) : List.dropSlice n m xs ~ ys ∩ List.dropSlice n m xs := by
+ simp only [dropSlice_eq]
+ have : n ≤ n + m := Nat.le_add_right _ _
+ have h₂ := h.nodup_iff.2 h'
+ apply Perm.trans _ (Perm.inter_append _).symm
+ . exact Perm.append (Perm.take_inter _ h h') (Perm.drop_inter _ h h')
+ . exact disjoint_take_drop h₂ this
+#align list.perm.slice_inter List.Perm.dropSlice_inter
+
+-- enumerating permutations
+section Permutations
+
+theorem perm_of_mem_permutationsAux :
+ ∀ {ts is l : List α}, l ∈ permutationsAux ts is → l ~ ts ++ is := by
+ show ∀ (ts is l : List α), l ∈ permutationsAux ts is → l ~ ts ++ is
+ refine' permutationsAux.rec (by simp) _
+ introv IH1 IH2 m
+ rw [permutationsAux_cons, permutations, mem_foldr_permutationsAux2] at m
+ rcases m with (m | ⟨l₁, l₂, m, _, e⟩)
+ · exact (IH1 _ m).trans perm_middle
+ · subst e
+ have p : l₁ ++ l₂ ~ is := by
+ simp [permutations] at m
+ cases' m with e m
+ · simp [e]
+ exact is.append_nil ▸ IH2 _ m
+ exact ((perm_middle.trans (p.cons _)).append_right _).trans (perm_append_comm.cons _)
+#align list.perm_of_mem_permutations_aux List.perm_of_mem_permutationsAux
+
+theorem perm_of_mem_permutations {l₁ l₂ : List α} (h : l₁ ∈ permutations l₂) : l₁ ~ l₂ :=
+ (eq_or_mem_of_mem_cons h).elim (fun e => e ▸ Perm.refl _) fun m =>
+ append_nil l₂ ▸ perm_of_mem_permutationsAux m
+#align list.perm_of_mem_permutations List.perm_of_mem_permutations
+
+theorem length_permutationsAux :
+ ∀ ts is : List α, length (permutationsAux ts is) + is.length ! = (length ts + length is)! :=
+ by
+ refine' permutationsAux.rec (by simp) _
+ intro t ts is IH1 IH2
+ have IH2 : length (permutationsAux is nil) + 1 = is.length ! := by simpa using IH2
+ simp [Nat.factorial, Nat.add_succ, mul_comm] at IH1
+ rw [permutationsAux_cons,
+ length_foldr_permutationsAux2' _ _ _ _ _ fun l m => (perm_of_mem_permutations m).length_eq,
+ permutations, length, length, IH2, Nat.succ_add, Nat.factorial_succ, mul_comm (_ + 1),
+ ← Nat.succ_eq_add_one, ← IH1, add_comm (_ * _), add_assoc, Nat.mul_succ, mul_comm]
+#align list.length_permutations_aux List.length_permutationsAux
+
+theorem length_permutations (l : List α) : length (permutations l) = (length l)! :=
+ length_permutationsAux l []
+#align list.length_permutations List.length_permutations
+
+theorem mem_permutations_of_perm_lemma {is l : List α}
+ (H : l ~ [] ++ is → (∃ (ts' : _)(_ : ts' ~ []), l = ts' ++ is) ∨ l ∈ permutationsAux is []) :
+ l ~ is → l ∈ permutations is := by simpa [permutations, perm_nil] using H
+#align list.mem_permutations_of_perm_lemma List.mem_permutations_of_perm_lemma
+
+theorem mem_permutationsAux_of_perm :
+ ∀ {ts is l : List α},
+ l ~ is ++ ts → (∃ (is' : _)(_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is := by
+ show ∀ (ts is l : List α),
+ l ~ is ++ ts → (∃ (is' : _)(_ : is' ~ is), l = is' ++ ts) ∨ l ∈ permutationsAux ts is
+ refine' permutationsAux.rec (by simp) _
+ intro t ts is IH1 IH2 l p
+ rw [permutationsAux_cons, mem_foldr_permutationsAux2]
+ rcases IH1 _ (p.trans perm_middle) with (⟨is', p', e⟩ | m)
+ · clear p
+ subst e
+ rcases mem_split (p'.symm.subset (mem_cons_self _ _)) with ⟨l₁, l₂, e⟩
+ subst is'
+ have p := (perm_middle.symm.trans p').cons_inv
+ cases' l₂ with a l₂'
+ · exact Or.inl ⟨l₁, by simpa using p⟩
+ · exact Or.inr (Or.inr ⟨l₁, a :: l₂', mem_permutations_of_perm_lemma (IH2 _) p, by simp⟩)
+ · exact Or.inr (Or.inl m)
+#align list.mem_permutations_aux_of_perm List.mem_permutationsAux_of_perm
+
+@[simp]
+theorem mem_permutations {s t : List α} : s ∈ permutations t ↔ s ~ t :=
+ ⟨perm_of_mem_permutations, mem_permutations_of_perm_lemma mem_permutationsAux_of_perm⟩
+#align list.mem_permutations List.mem_permutations
+
+--Porting note: temporary theorem to solve diamond issue
+private theorem DecEq_eq {α : Type _} [DecidableEq α] :
+ instBEqList = @instBEq (List α) instDecidableEqList :=
+ congr_arg BEq.mk <| by
+ funext l₁ l₂
+ rw [Bool.eq_iff_eq_true_iff, @beq_iff_eq _ (instBEqList),
+ @beq_iff_eq _ (@instBEq (List α) instDecidableEqList)]
+
+theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
+ (permutations'Aux a l).bind (permutations'Aux b) ~
+ (permutations'Aux b l).bind (permutations'Aux a) :=
+ by
+ induction' l with c l ih
+ · simp [swap]
+ simp [permutations'Aux]
+ apply Perm.swap'
+ have :
+ ∀ a b,
+ (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
+ map (cons b ∘ cons c) (permutations'Aux a l) ++
+ map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
+ intros a' b'
+ simp only [map_bind, permutations'Aux]
+ show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
+ map (cons c) (permutations'Aux _ a))) ~ _
+ refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
+ rw [← map_eq_bind, ← bind_map]
+ exact Perm.refl _
+ refine' (((this _ _).append_left _).trans _).trans ((this _ _).append_left _).symm
+ rw [← append_assoc, ← append_assoc]
+ exact perm_append_comm.append (ih.map _)
+#align list.perm_permutations'_aux_comm List.perm_permutations'Aux_comm
+
+theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t :=
+ by
+ induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
+ · simp only [permutations']
+ exact IH.bind_right _
+ · dsimp [permutations']
+ rw [bind_assoc, bind_assoc]
+ apply Perm.bind_left
+ intro l' _
+ apply perm_permutations'Aux_comm
+ · exact IH₁.trans IH₂
+#align list.perm.permutations' List.Perm.permutations'
+
+theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
+ obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
+ induction' n with n IH generalizing ts; · cases h
+ refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
+ rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
+ have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
+ simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
+ permutationsAux_cons, append_nil]
+ refine'
+ (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
+ (Perm.trans _ perm_append_comm.permutations')
+ rw [map_eq_bind, singleton_append, permutations']
+ refine' (bind_append_perm _ _ _).trans _
+ refine' Perm.of_eq _
+ congr
+ funext _
+ rw [permutations'Aux_eq_permutationsAux2, permutationsAux2_append]
+#align list.permutations_perm_permutations' List.permutations_perm_permutations'
+
+@[simp]
+theorem mem_permutations' {s t : List α} : s ∈ permutations' t ↔ s ~ t :=
+ (permutations_perm_permutations' _).symm.mem_iff.trans mem_permutations
+#align list.mem_permutations' List.mem_permutations'
+
+theorem Perm.permutations {s t : List α} (h : s ~ t) : permutations s ~ permutations t :=
+ (permutations_perm_permutations' _).trans <|
+ h.permutations'.trans (permutations_perm_permutations' _).symm
+#align list.perm.permutations List.Perm.permutations
+
+@[simp]
+theorem perm_permutations_iff {s t : List α} : permutations s ~ permutations t ↔ s ~ t :=
+ ⟨fun h => mem_permutations.1 <| h.mem_iff.1 <| mem_permutations.2 (Perm.refl _),
+ Perm.permutations⟩
+#align list.perm_permutations_iff List.perm_permutations_iff
+
+@[simp]
+theorem perm_permutations'_iff {s t : List α} : permutations' s ~ permutations' t ↔ s ~ t :=
+ ⟨fun h => mem_permutations'.1 <| h.mem_iff.1 <| mem_permutations'.2 (Perm.refl _),
+ Perm.permutations'⟩
+#align list.perm_permutations'_iff List.perm_permutations'_iff
+
+set_option linter.deprecated false in
+theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
+ (hn : n < length (permutations'Aux x s)) :
+ (permutations'Aux x s).nthLe n hn = s.insertNth n x := by
+ induction' s with y s IH generalizing n
+ · simp only [length, zero_add, lt_one_iff] at hn
+ simp [hn]
+ · cases n
+ · simp [nthLe]
+ · simpa [nthLe] using IH _ _
+#align list.nth_le_permutations'_aux List.nthLe_permutations'Aux
+
+theorem count_permutations'Aux_self [DecidableEq α] (l : List α) (x : α) :
+ count (x :: l) (permutations'Aux x l) = length (takeWhile ((· = ·) x) l) + 1 :=
+ by
+ induction' l with y l IH generalizing x
+ · simp [takeWhile, count]
+ · rw [permutations'Aux, DecEq_eq, count_cons_self]
+ by_cases hx : x = y
+ · subst hx
+ simpa [takeWhile, Nat.succ_inj', DecEq_eq] using IH _
+ · rw [takeWhile]
+ simp only [mem_map', cons.injEq, Ne.symm hx, false_and, and_false, exists_false,
+ not_false_iff, count_eq_zero_of_not_mem, zero_add, hx, decide_False, length_nil]
+#align list.count_permutations'_aux_self List.count_permutations'Aux_self
+
+@[simp]
+theorem length_permutations'Aux (s : List α) (x : α) :
+ length (permutations'Aux x s) = length s + 1 :=
+ by
+ induction' s with y s IH
+ · simp
+ · simpa using IH
+#align list.length_permutations'_aux List.length_permutations'Aux
+
+@[simp]
+theorem permutations'Aux_nthLe_zero (s : List α) (x : α)
+ (hn : 0 < length (permutations'Aux x s) := (by simp)) :
+ (permutations'Aux x s).nthLe 0 hn = x :: s :=
+ nthLe_permutations'Aux _ _ _ _
+#align list.permutations'_aux_nth_le_zero List.permutations'Aux_nthLe_zero
+
+theorem injective_permutations'Aux (x : α) : Function.Injective (permutations'Aux x) :=
+ by
+ intro s t h
+ apply insertNth_injective s.length x
+ have hl : s.length = t.length := by simpa using congr_arg length h
+ rw [← nthLe_permutations'Aux s x s.length (by simp), ←
+ nthLe_permutations'Aux t x s.length (by simp [hl])]
+ simp [h, hl]
+#align list.injective_permutations'_aux List.injective_permutations'Aux
+
+theorem nodup_permutations'Aux_of_not_mem (s : List α) (x : α) (hx : x ∉ s) :
+ Nodup (permutations'Aux x s) := by
+ induction' s with y s IH
+ · simp
+ · simp only [not_or, mem_cons] at hx
+ simp only [permutations'Aux, nodup_cons, mem_map', cons.injEq, exists_eq_right_right, not_and]
+ refine' ⟨fun _ => Ne.symm hx.left, _⟩
+ rw [nodup_map_iff]
+ · exact IH hx.right
+ · simp
+#align list.nodup_permutations'_aux_of_not_mem List.nodup_permutations'Aux_of_not_mem
+
+set_option linter.deprecated false in
+theorem nodup_permutations'Aux_iff {s : List α} {x : α} : Nodup (permutations'Aux x s) ↔ x ∉ s :=
+ by
+ refine' ⟨fun h => _, nodup_permutations'Aux_of_not_mem _ _⟩
+ intro H
+ obtain ⟨k, hk, hk'⟩ := nthLe_of_mem H
+ rw [nodup_iff_nthLe_inj] at h
+ suffices k = k + 1 by simp at this
+ refine' h k (k + 1) _ _ _
+ · simpa [Nat.lt_succ_iff] using hk.le
+ · simpa using hk
+ rw [nthLe_permutations'Aux, nthLe_permutations'Aux]
+ have hl : length (insertNth k x s) = length (insertNth (k + 1) x s) := by
+ rw [length_insertNth _ _ hk.le, length_insertNth _ _ (Nat.succ_le_of_lt hk)]
+ refine' ext_nthLe hl fun n hn hn' => _
+ rcases lt_trichotomy n k with (H | rfl | H)
+ ·
+ rw [nthLe_insertNth_of_lt _ _ _ _ H (H.trans hk),
+ nthLe_insertNth_of_lt _ _ _ _ (H.trans (Nat.lt_succ_self _))]
+ ·
+ rw [nthLe_insertNth_self _ _ _ hk.le, nthLe_insertNth_of_lt _ _ _ _ (Nat.lt_succ_self _) hk,
+ hk']
+ · rcases(Nat.succ_le_of_lt H).eq_or_lt with (rfl | H')
+ · rw [nthLe_insertNth_self _ _ _ (Nat.succ_le_of_lt hk)]
+ convert hk' using 1
+ exact nthLe_insertNth_add_succ _ _ _ 0 _
+ · obtain ⟨m, rfl⟩ := Nat.exists_eq_add_of_lt H'
+ erw [length_insertNth _ _ hk.le, Nat.succ_lt_succ_iff, Nat.succ_add] at hn
+ rw [nthLe_insertNth_add_succ]
+ convert nthLe_insertNth_add_succ s x k m.succ (by simpa using hn) using 2
+ · simp [Nat.add_succ, Nat.succ_add]
+ · simp [add_left_comm, add_comm]
+ · simpa [Nat.succ_add] using hn
+#align list.nodup_permutations'_aux_iff List.nodup_permutations'Aux_iff
+
+set_option linter.deprecated false in
+theorem nodup_permutations (s : List α) (hs : Nodup s) : Nodup s.permutations :=
+ by
+ rw [(permutations_perm_permutations' s).nodup_iff]
+ induction' hs with x l h h' IH
+ · simp
+ · rw [permutations']
+ rw [nodup_bind]
+ constructor
+ · intro ys hy
+ rw [mem_permutations'] at hy
+ rw [nodup_permutations'Aux_iff, hy.mem_iff]
+ exact fun H => h x H rfl
+ · refine' IH.pairwise_of_forall_ne fun as ha bs hb H => _
+ rw [disjoint_iff_ne]
+ rintro a ha' b hb' rfl
+ obtain ⟨⟨n, hn⟩, hn'⟩ := get_of_mem ha'
+ obtain ⟨⟨m, hm⟩, hm'⟩ := get_of_mem hb'
+ rw [mem_permutations'] at ha hb
+ have hl : as.length = bs.length := (ha.trans hb.symm).length_eq
+ simp only [Nat.lt_succ_iff, length_permutations'Aux] at hn hm
+ rw [← nthLe, nthLe_permutations'Aux] at hn' hm'
+ have hx :
+ nthLe (insertNth n x as) m (by rwa [length_insertNth _ _ hn, Nat.lt_succ_iff, hl]) = x :=
+ by simp [hn', ← hm', hm]
+ have hx' :
+ nthLe (insertNth m x bs) n (by rwa [length_insertNth _ _ hm, Nat.lt_succ_iff, ← hl]) =
+ x :=
+ by simp [hm', ← hn', hn]
+ rcases lt_trichotomy n m with (ht | ht | ht)
+ · suffices x ∈ bs by exact h x (hb.subset this) rfl
+ rw [← hx', nthLe_insertNth_of_lt _ _ _ _ ht (ht.trans_le hm)]
+ exact nthLe_mem _ _ _
+ · simp only [ht] at hm' hn'
+ rw [← hm'] at hn'
+ exact H (insertNth_injective _ _ hn')
+ · suffices x ∈ as by exact h x (ha.subset this) rfl
+ rw [← hx, nthLe_insertNth_of_lt _ _ _ _ ht (ht.trans_le hn)]
+ exact nthLe_mem _ _ _
+#align list.nodup_permutations List.nodup_permutations
+
+-- TODO: `nodup s.permutations ↔ nodup s`
+-- TODO: `count s s.permutations = (zip_with count s s.tails).prod`
+end Permutations
+
+end List
The unported dependencies are