Skip to content

Commit 885c514

Browse files
committed
chore: upstream Pairwise lemmas
1 parent e0cfe58 commit 885c514

File tree

1 file changed

+254
-37
lines changed

1 file changed

+254
-37
lines changed

src/Init/Data/List/Lemmas.lean

Lines changed: 254 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4319,23 +4319,17 @@ end countP
43194319

43204320
section count
43214321

4322-
variable [DecidableEq α]
4322+
variable [BEq α]
43234323

43244324
@[simp] theorem count_nil (a : α) : count a [] = 0 := rfl
43254325

43264326
theorem count_cons (a b : α) (l : List α) :
4327-
count a (b :: l) = count a l + if a = b then 1 else 0 := by
4328-
simp [count, countP_cons, eq_comm (a := a)]
4329-
4330-
@[simp] theorem count_cons_self (a : α) (l : List α) : count a (a :: l) = count a l + 1 := by
4331-
simp [count_cons]
4332-
4333-
@[simp] theorem count_cons_of_ne (h : a ≠ b) (l : List α) : count a (b :: l) = count a l := by
4334-
simp [count_cons, h]
4327+
count a (b :: l) = count a l + if b == a then 1 else 0 := by
4328+
simp [count, countP_cons]
43354329

43364330
theorem count_tail : ∀ (l : List α) (a : α) (h : l ≠ []),
4337-
l.tail.count a = l.count a - if a = l.head h then 1 else 0
4338-
| head :: tail, a, h => by simp [count_cons]
4331+
l.tail.count a = l.count a - if l.head h == a then 1 else 0
4332+
| head :: tail, a, _ => by simp [count_cons]
43394333

43404334
theorem count_le_length (a : α) (l : List α) : count a l ≤ l.length := countP_le_length _
43414335

@@ -4344,14 +4338,25 @@ theorem Sublist.count_le (h : l₁ <+ l₂) (a : α) : count a l₁ ≤ count a
43444338
theorem count_le_count_cons (a b : α) (l : List α) : count a l ≤ count a (b :: l) :=
43454339
(sublist_cons_self _ _).count_le _
43464340

4347-
theorem count_singleton_self (a : α) : count a [a] = 1 := by simp
4348-
4349-
theorem count_singleton (a b : α) : count a [b] = if a = b then 1 else 0 := by simp [count_cons]
4341+
theorem count_singleton (a b : α) : count a [b] = if b == a then 1 else 0 := by
4342+
simp [count_cons]
43504343

43514344
@[simp] theorem count_append (a : α) : ∀ l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
43524345
countP_append _
43534346

4354-
theorem count_concat_self (a : α) (l : List α) : count a (concat l a) = (count a l) + 1 := by simp
4347+
variable [LawfulBEq α]
4348+
4349+
@[simp] theorem count_cons_self (a : α) (l : List α) : count a (a :: l) = count a l + 1 := by
4350+
simp [count_cons]
4351+
4352+
@[simp] theorem count_cons_of_ne (h : a ≠ b) (l : List α) : count a (b :: l) = count a l := by
4353+
simp only [count_cons, cond_eq_if, beq_iff_eq]
4354+
split <;> simp_all
4355+
4356+
theorem count_singleton_self (a : α) : count a [a] = 1 := by simp
4357+
4358+
theorem count_concat_self (a : α) (l : List α) :
4359+
count a (concat l a) = (count a l) + 1 := by simp
43554360

43564361
@[simp]
43574362
theorem count_pos_iff_mem {a : α} {l : List α} : 0 < count a l ↔ a ∈ l := by
@@ -4375,29 +4380,21 @@ theorem count_eq_length {l : List α} : count a l = l.length ↔ ∀ b ∈ l, a
43754380
@[simp] theorem count_replicate_self (a : α) (n : Nat) : count a (replicate n a) = n :=
43764381
(count_eq_length.2 <| fun _ h => (eq_of_mem_replicate h).symm).trans (length_replicate ..)
43774382

4378-
theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if a = b then n else 0 := by
4379-
split
4380-
· exact ‹a = b› ▸ count_replicate_self ..
4381-
· exact count_eq_zero.2 <| mt eq_of_mem_replicate ‹a ≠ b›
4383+
theorem count_replicate (a b : α) (n : Nat) : count a (replicate n b) = if b == a then n else 0 := by
4384+
split <;> (rename_i h; simp only [beq_iff_eq] at h)
4385+
· exact ‹b = a› ▸ count_replicate_self ..
4386+
· exact count_eq_zero.2 <| mt eq_of_mem_replicate (Ne.symm h)
43824387

43834388
theorem filter_beq (l : List α) (a : α) : l.filter (· == a) = replicate (count a l) a := by
43844389
simp only [count, countP_eq_length_filter, eq_replicate, mem_filter, beq_iff_eq]
43854390
exact ⟨trivial, fun _ h => h.2
43864391

4387-
theorem filter_eq (l : List α) (a : α) : l.filter (· = a) = replicate (count a l) a :=
4392+
theorem filter_eq {α} [DecidableEq α] (l : List α) (a : α) : l.filter (· = a) = replicate (count a l) a :=
43884393
filter_beq l a
43894394

4390-
@[deprecated filter_eq (since := "2023-12-14")]
4391-
theorem filter_eq' (l : List α) (a : α) : l.filter (a = ·) = replicate (count a l) a := by
4392-
simpa only [eq_comm] using filter_eq l a
4393-
4394-
@[deprecated filter_beq (since := "2023-12-14")]
4395-
theorem filter_beq' (l : List α) (a : α) : l.filter (a == ·) = replicate (count a l) a := by
4396-
simpa only [eq_comm (b := a)] using filter_eq l a
4397-
43984395
theorem le_count_iff_replicate_sublist {l : List α} : n ≤ count a l ↔ replicate n a <+ l := by
43994396
refine ⟨fun h => ?_, fun h => ?_⟩
4400-
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_eq l a ▸ filter_sublist _
4397+
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq l a ▸ filter_sublist _
44014398
· simpa only [count_replicate_self] using h.count_le a
44024399

44034400
theorem replicate_count_eq_of_count_eq_length {l : List α} (h : count a l = length l) :
@@ -4407,7 +4404,6 @@ theorem replicate_count_eq_of_count_eq_length {l : List α} (h : count a l = len
44074404

44084405
@[simp] theorem count_filter {l : List α} (h : p a) : count a (filter p l) = count a l := by
44094406
rw [count, countP_filter]; congr; funext b
4410-
rw [(by rfl : (b == a) = decide (b = a)), decide_eq_decide]
44114407
simp; rintro rfl; exact h
44124408

44134409
theorem count_le_count_map [DecidableEq β] (l : List α) (f : α → β) (x : α) :
@@ -4416,7 +4412,7 @@ theorem count_le_count_map [DecidableEq β] (l : List α) (f : α → β) (x :
44164412
apply countP_mono_left; simp (config := { contextual := true })
44174413

44184414
theorem count_erase (a b : α) :
4419-
∀ l : List α, count a (l.erase b) = count a l - if a = b then 1 else 0
4415+
∀ l : List α, count a (l.erase b) = count a l - if b == a then 1 else 0
44204416
| [] => by simp
44214417
| c :: l => by
44224418
rw [erase_cons]
@@ -4426,17 +4422,17 @@ theorem count_erase (a b : α) :
44264422
else
44274423
have hc_beq := beq_false_of_ne hc
44284424
simp only [hc_beq, if_false, count_cons, count_cons, count_erase a b l]
4429-
if ha : a = b then
4430-
rw [ha, eq_comm] at hc
4431-
rw [if_pos ha, if_neg hc, Nat.add_zero, Nat.add_zero]
4425+
if ha : b = a then
4426+
rw [ha, eq_comm] at hc
4427+
rw [if_pos ((beq_iff_eq _ _).2 ha), if_neg (by simpa using Ne.symm hc), Nat.add_zero, Nat.add_zero]
44324428
else
4433-
rw [if_neg ha, Nat.sub_zero, Nat.sub_zero]
4429+
rw [if_neg (by simpa using ha), Nat.sub_zero, Nat.sub_zero]
44344430

44354431
@[simp] theorem count_erase_self (a : α) (l : List α) :
4436-
count a (List.erase l a) = count a l - 1 := by rw [count_erase, if_pos rfl]
4432+
count a (List.erase l a) = count a l - 1 := by rw [count_erase, if_pos (by simp)]
44374433

44384434
@[simp] theorem count_erase_of_ne (ab : a ≠ b) (l : List α) : count a (l.erase b) = count a l := by
4439-
rw [count_erase, if_neg ab, Nat.sub_zero]
4435+
rw [count_erase, if_neg (by simpa using ab.symm), Nat.sub_zero]
44404436

44414437
end count
44424438

@@ -5124,3 +5120,224 @@ theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] (f : α → m β) (l : List α)
51245120
induction l₁ <;> simp [*]
51255121

51265122
end List
5123+
5124+
5125+
namespace List
5126+
5127+
/-! ### Pairwise -/
5128+
5129+
theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : ∀ {a'}, a' ∈ l → R a a' :=
5130+
(pairwise_cons.1 p).1 _
5131+
5132+
theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
5133+
(pairwise_cons.1 p).2
5134+
5135+
theorem Pairwise.tail : ∀ {l : List α} (_p : Pairwise R l), Pairwise R l.tail
5136+
| [], h => h
5137+
| _ :: _, h => h.of_cons
5138+
5139+
theorem Pairwise.drop : ∀ {l : List α} {n : Nat}, List.Pairwise R l → List.Pairwise R (l.drop n)
5140+
| _, 0, h => h
5141+
| [], _ + 1, _ => List.Pairwise.nil
5142+
| _ :: _, n + 1, h => Pairwise.drop (n := n) (pairwise_cons.mp h).right
5143+
5144+
theorem Pairwise.imp_of_mem {S : α → α → Prop}
5145+
(H : ∀ {a b}, a ∈ l → b ∈ l → R a b → S a b) (p : Pairwise R l) : Pairwise S l := by
5146+
induction p with
5147+
| nil => constructor
5148+
| @cons a l r _ ih =>
5149+
constructor
5150+
· exact fun x h => H (mem_cons_self ..) (mem_cons_of_mem _ h) <| r x h
5151+
· exact ih fun m m' => H (mem_cons_of_mem _ m) (mem_cons_of_mem _ m')
5152+
5153+
theorem Pairwise.and (hR : Pairwise R l) (hS : Pairwise S l) :
5154+
l.Pairwise fun a b => R a b ∧ S a b := by
5155+
induction hR with
5156+
| nil => simp only [Pairwise.nil]
5157+
| cons R1 _ IH =>
5158+
simp only [Pairwise.nil, pairwise_cons] at hS ⊢
5159+
exact ⟨fun b bl => ⟨R1 b bl, hS.1 b bl⟩, IH hS.2
5160+
5161+
theorem pairwise_and_iff : l.Pairwise (fun a b => R a b ∧ S a b) ↔ Pairwise R l ∧ Pairwise S l :=
5162+
fun h => ⟨h.imp fun h => h.1, h.imp fun h => h.2⟩, fun ⟨hR, hS⟩ => hR.and hS⟩
5163+
5164+
theorem Pairwise.imp₂ (H : ∀ a b, R a b → S a b → T a b)
5165+
(hR : Pairwise R l) (hS : l.Pairwise S) : l.Pairwise T :=
5166+
(hR.and hS).imp fun ⟨h₁, h₂⟩ => H _ _ h₁ h₂
5167+
5168+
theorem Pairwise.iff_of_mem {S : α → α → Prop} {l : List α}
5169+
(H : ∀ {a b}, a ∈ l → b ∈ l → (R a b ↔ S a b)) : Pairwise R l ↔ Pairwise S l :=
5170+
⟨Pairwise.imp_of_mem fun m m' => (H m m').1, Pairwise.imp_of_mem fun m m' => (H m m').2
5171+
5172+
theorem Pairwise.iff {S : α → α → Prop} (H : ∀ a b, R a b ↔ S a b) {l : List α} :
5173+
Pairwise R l ↔ Pairwise S l :=
5174+
Pairwise.iff_of_mem fun _ _ => H ..
5175+
5176+
theorem pairwise_of_forall {l : List α} (H : ∀ x y, R x y) : Pairwise R l := by
5177+
induction l <;> simp [*]
5178+
5179+
theorem Pairwise.and_mem {l : List α} :
5180+
Pairwise R l ↔ Pairwise (fun x y => x ∈ l ∧ y ∈ l ∧ R x y) l :=
5181+
Pairwise.iff_of_mem <| by simp (config := { contextual := true })
5182+
5183+
theorem Pairwise.imp_mem {l : List α} :
5184+
Pairwise R l ↔ Pairwise (fun x y => x ∈ l → y ∈ l → R x y) l :=
5185+
Pairwise.iff_of_mem <| by simp (config := { contextual := true })
5186+
5187+
theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pairwise R l)
5188+
(h₃ : l.Pairwise (flip R)) : ∀ ⦃x⦄, x ∈ l → ∀ ⦃y⦄, y ∈ l → R x y := by
5189+
induction l with
5190+
| nil => exact forall_mem_nil _
5191+
| cons a l ih =>
5192+
rw [pairwise_cons] at h₂ h₃
5193+
simp only [mem_cons]
5194+
rintro x (rfl | hx) y (rfl | hy)
5195+
· exact h₁ _ (l.mem_cons_self _)
5196+
· exact h₂.1 _ hy
5197+
· exact h₃.1 _ hx
5198+
· exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy
5199+
5200+
theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
5201+
5202+
theorem pairwise_pair {a b : α} : Pairwise R [a, b] ↔ R a b := by simp
5203+
5204+
theorem pairwise_append_comm {R : α → α → Prop} (s : ∀ {x y}, R x y → R y x) {l₁ l₂ : List α} :
5205+
Pairwise R (l₁ ++ l₂) ↔ Pairwise R (l₂ ++ l₁) := by
5206+
have (l₁ l₂ : List α) (H : ∀ x : α, x ∈ l₁ → ∀ y : α, y ∈ l₂ → R x y)
5207+
(x : α) (xm : x ∈ l₂) (y : α) (ym : y ∈ l₁) : R x y := s (H y ym x xm)
5208+
simp only [pairwise_append, and_left_comm]; rw [Iff.intro (this l₁ l₂) (this l₂ l₁)]
5209+
5210+
theorem pairwise_middle {R : α → α → Prop} (s : ∀ {x y}, R x y → R y x) {a : α} {l₁ l₂ : List α} :
5211+
Pairwise R (l₁ ++ a :: l₂) ↔ Pairwise R (a :: (l₁ ++ l₂)) := by
5212+
show Pairwise R (l₁ ++ ([a] ++ l₂)) ↔ Pairwise R ([a] ++ l₁ ++ l₂)
5213+
rw [← append_assoc, pairwise_append, @pairwise_append _ _ ([a] ++ l₁), pairwise_append_comm s]
5214+
simp only [mem_append, or_comm]
5215+
5216+
theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, S (f a) (f b) → R a b)
5217+
(p : Pairwise S (map f l)) : Pairwise R l :=
5218+
(pairwise_map.1 p).imp (H _ _)
5219+
5220+
theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
5221+
(p : Pairwise R l) : Pairwise S (map f l) :=
5222+
pairwise_map.2 <| p.imp (H _ _)
5223+
5224+
theorem pairwise_filterMap (f : β → Option α) {l : List β} :
5225+
Pairwise R (filterMap f l) ↔ Pairwise (fun a a' : β => ∀ b ∈ f a, ∀ b' ∈ f a', R b b') l := by
5226+
let _S (a a' : β) := ∀ b ∈ f a, ∀ b' ∈ f a', R b b'
5227+
simp only [Option.mem_def]
5228+
induction l with
5229+
| nil => simp only [filterMap, Pairwise.nil]
5230+
| cons a l IH => ?_
5231+
match e : f a with
5232+
| none =>
5233+
rw [filterMap_cons_none e, pairwise_cons]
5234+
simp only [e, false_implies, implies_true, true_and, IH]
5235+
| some b =>
5236+
rw [filterMap_cons_some e]
5237+
simpa [IH, e] using fun _ =>
5238+
fun h a ha b hab => h _ _ ha hab, fun h a b ha hab => h _ ha _ hab⟩
5239+
5240+
theorem Pairwise.filter_map {S : β → β → Prop} (f : α → Option β)
5241+
(H : ∀ a a' : α, R a a' → ∀ b ∈ f a, ∀ b' ∈ f a', S b b') {l : List α} (p : Pairwise R l) :
5242+
Pairwise S (filterMap f l) :=
5243+
(pairwise_filterMap _).2 <| p.imp (H _ _)
5244+
5245+
theorem pairwise_filter (p : α → Prop) [DecidablePred p] {l : List α} :
5246+
Pairwise R (filter p l) ↔ Pairwise (fun x y => p x → p y → R x y) l := by
5247+
rw [← filterMap_eq_filter, pairwise_filterMap]
5248+
simp
5249+
5250+
theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
5251+
Pairwise.sublist (filter_sublist _)
5252+
5253+
theorem pairwise_join {L : List (List α)} :
5254+
Pairwise R (join L) ↔
5255+
(∀ l ∈ L, Pairwise R l) ∧ Pairwise (fun l₁ l₂ => ∀ x ∈ l₁, ∀ y ∈ l₂, R x y) L := by
5256+
induction L with
5257+
| nil => simp
5258+
| cons l L IH =>
5259+
simp only [join, pairwise_append, IH, mem_join, exists_imp, and_imp, forall_mem_cons,
5260+
pairwise_cons, and_assoc, and_congr_right_iff]
5261+
rw [and_comm, and_congr_left_iff]
5262+
intros; exact ⟨fun h a b c d e => h c d e a b, fun h c d e a b => h a b c d e⟩
5263+
5264+
theorem pairwise_bind {R : β → β → Prop} {l : List α} {f : α → List β} :
5265+
List.Pairwise R (l.bind f) ↔
5266+
(∀ a ∈ l, Pairwise R (f a)) ∧ Pairwise (fun a₁ a₂ => ∀ x ∈ f a₁, ∀ y ∈ f a₂, R x y) l := by
5267+
simp [List.bind, pairwise_join, pairwise_map]
5268+
5269+
theorem pairwise_iff_forall_sublist : l.Pairwise R ↔ (∀ {a b}, [a,b] <+ l → R a b) := by
5270+
induction l with
5271+
| nil => simp
5272+
| cons hd tl IH =>
5273+
rw [List.pairwise_cons]
5274+
constructor <;> intro h
5275+
· intro
5276+
| a, b, .cons _ hab => exact IH.mp h.2 hab
5277+
| _, b, .cons₂ _ hab => refine h.1 _ (hab.subset ?_); simp
5278+
· constructor
5279+
· intro x hx
5280+
apply h
5281+
rw [List.cons_sublist_cons, List.singleton_sublist]
5282+
exact hx
5283+
· apply IH.mpr
5284+
intro a b hab
5285+
apply h; exact hab.cons _
5286+
5287+
5288+
/-- given a list `is` of monotonically increasing indices into `l`, getting each index
5289+
produces a sublist of `l`. -/
5290+
theorem map_get_sublist {l : List α} {is : List (Fin l.length)} (h : is.Pairwise (·.val < ·.val)) :
5291+
is.map (get l) <+ l := by
5292+
suffices ∀ n l', l' = l.drop n → (∀ i ∈ is, n ≤ i) → map (get l) is <+ l'
5293+
from this 0 l (by simp) (by simp)
5294+
intro n l' hl' his
5295+
induction is generalizing n l' with
5296+
| nil => simp
5297+
| cons hd tl IH =>
5298+
simp; cases hl'
5299+
have := IH h.of_cons (hd+1) _ rfl (pairwise_cons.mp h).1
5300+
specialize his hd (.head _)
5301+
have := (drop_eq_getElem_cons ..).symm ▸ this.cons₂ (get l hd)
5302+
have := Sublist.append (nil_sublist (take hd l |>.drop n)) this
5303+
rwa [nil_append, ← (drop_append_of_le_length ?_), take_append_drop] at this
5304+
simp [Nat.min_eq_left (Nat.le_of_lt hd.isLt), his]
5305+
5306+
/-- given a sublist `l' <+ l`, there exists a list of indices `is` such that
5307+
`l' = map (get l) is`. -/
5308+
theorem sublist_eq_map_get (h : l' <+ l) : ∃ is : List (Fin l.length),
5309+
l' = map (get l) is ∧ is.Pairwise (· < ·) := by
5310+
induction h with
5311+
| slnil => exact ⟨[], by simp⟩
5312+
| cons _ _ IH =>
5313+
let ⟨is, IH⟩ := IH
5314+
refine ⟨is.map (·.succ), ?_⟩
5315+
simp [comp, pairwise_map]
5316+
exact IH
5317+
| cons₂ _ _ IH =>
5318+
rcases IH with ⟨is,IH⟩
5319+
refine ⟨⟨0, by simp [Nat.zero_lt_succ]⟩ :: is.map (·.succ), ?_⟩
5320+
simp [comp_def, pairwise_map, IH, ← get_eq_getElem]
5321+
5322+
theorem pairwise_iff_getElem : Pairwise R l ↔
5323+
∀ (i j : Nat) (_hi : i < l.length) (_hj : j < l.length) (_hij : i < j), R l[i] l[j] := by
5324+
rw [pairwise_iff_forall_sublist]
5325+
constructor <;> intro h
5326+
· intros i j hi hj h'
5327+
apply h
5328+
simpa [h'] using map_get_sublist (is := [⟨i, hi⟩, ⟨j, hj⟩])
5329+
· intros a b h'
5330+
have ⟨is, h', hij⟩ := sublist_eq_map_get h'
5331+
rcases is with ⟨⟩ | ⟨a', ⟨⟩ | ⟨b', ⟨⟩⟩⟩ <;> simp at h'
5332+
rcases h' with ⟨rfl, rfl⟩
5333+
apply h; simpa using hij
5334+
5335+
theorem pairwise_iff_get : Pairwise R l ↔ ∀ (i j) (_hij : i < j), R (get l i) (get l j) := by
5336+
rw [pairwise_iff_getElem]
5337+
constructor <;> intro h
5338+
· intros i j h'
5339+
exact h _ _ _ _ h'
5340+
· intros i j hi hj h'
5341+
exact h ⟨i, hi⟩ ⟨j, hj⟩ h'
5342+
5343+
end List

0 commit comments

Comments
 (0)