feat: improvements to simp confluence (#7013)

This PR makes improvements to the simp set for List/Array/Vector/Option
to improve confluence, in preparation for `simp_lc`.
This commit is contained in:
Kim Morrison 2025-02-10 23:17:44 +11:00 committed by GitHub
parent 2aca375cd9
commit c307e8a04f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 211 additions and 56 deletions

View file

@ -70,7 +70,7 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
@[csimp] private theorem pmap_eq_pmapImpl : @pmap = @pmapImpl := by
funext α β p f L h'
cases L
simp only [pmap, pmapImpl, List.attachWith_toArray, List.map_toArray, mk.injEq, List.map_attachWith]
simp only [pmap, pmapImpl, List.attachWith_toArray, List.map_toArray, mk.injEq, List.map_attachWith_eq_pmap]
apply List.pmap_congr_left
intro a m h₁ h₂
congr
@ -318,7 +318,7 @@ See however `foldl_subtype` below.
theorem foldl_attach (l : Array α) (f : β → α → β) (b : β) :
l.attach.foldl (fun acc t => f acc t.1) b = l.foldl f b := by
rcases l with ⟨l⟩
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.map_attach, size_toArray,
simp only [List.attach_toArray, List.attachWith_mem_toArray, size_toArray,
List.length_pmap, List.foldl_toArray', mem_toArray, List.foldl_subtype]
congr
ext
@ -337,7 +337,7 @@ See however `foldr_subtype` below.
theorem foldr_attach (l : Array α) (f : α → β → β) (b : β) :
l.attach.foldr (fun t acc => f t.1 acc) b = l.foldr f b := by
rcases l with ⟨l⟩
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.map_attach, size_toArray,
simp only [List.attach_toArray, List.attachWith_mem_toArray, size_toArray,
List.length_pmap, List.foldr_toArray', mem_toArray, List.foldr_subtype]
congr
ext
@ -354,7 +354,12 @@ theorem attachWith_map {l : Array α} (f : α → β) {P : β → Prop} {H : ∀
cases l
simp [List.attachWith_map]
theorem map_attachWith {l : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
@[simp] theorem map_attachWith {l : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f = l.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by
cases l <;> simp_all
theorem map_attachWith_eq_pmap {l : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f =
l.pmap (fun a (h : a ∈ l ∧ P a) => f ⟨a, H _ h.1⟩) (fun a h => ⟨h, H a h⟩) := by
@ -362,11 +367,14 @@ theorem map_attachWith {l : Array α} {P : α → Prop} {H : ∀ (a : α), a ∈
ext <;> simp
/-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/
theorem map_attach {l : Array α} (f : { x // x ∈ l } → β) :
theorem map_attach_eq_pmap {l : Array α} (f : { x // x ∈ l } → β) :
l.attach.map f = l.pmap (fun a h => f ⟨a, h⟩) (fun _ => id) := by
cases l
ext <;> simp
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
theorem attach_filterMap {l : Array α} {f : α → Option β} :
(l.filterMap f).attach = l.attach.filterMap
fun ⟨x, h⟩ => (f x).pbind (fun b m => some ⟨b, mem_filterMap.mpr ⟨x, h, m⟩⟩) := by
@ -505,7 +513,7 @@ theorem count_attach [DecidableEq α] (l : Array α) (a : {x // x ∈ l}) :
l.attach.count a = l.count ↑a := by
rcases l with ⟨l⟩
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.count_toArray]
rw [List.map_attach, List.count_eq_countP]
rw [List.map_attach_eq_pmap, List.count_eq_countP]
simp only [Subtype.beq_iff]
rw [List.countP_pmap, List.countP_attach (p := (fun x => x == a.1)), List.count]

View file

@ -163,7 +163,7 @@ theorem count_le_size (a : α) (l : Array α) : count a l ≤ l.size := countP_l
theorem count_le_count_push (a b : α) (l : Array α) : count a l ≤ count a (l.push b) := by
simp [count_push]
@[simp] theorem count_singleton (a b : α) : count a #[b] = if b == a then 1 else 0 := by
theorem count_singleton (a b : α) : count a #[b] = if b == a then 1 else 0 := by
simp [count_eq_countP]
@[simp] theorem count_append (a : α) : ∀ l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=

View file

@ -1350,8 +1350,9 @@ theorem map_filter_eq_foldl (f : α → β) (p : α → Bool) (l : Array α) :
simp only [List.filter_cons, List.foldr_cons]
split <;> simp_all
@[simp] theorem filter_append {p : α → Bool} (l₁ l₂ : Array α) :
filter p (l₁ ++ l₂) = filter p l₁ ++ filter p l₂ := by
@[simp] theorem filter_append {p : α → Bool} (l₁ l₂ : Array α) (w : stop = l₁.size + l₂.size) :
filter p (l₁ ++ l₂) 0 stop = filter p l₁ ++ filter p l₂ := by
subst w
rcases l₁ with ⟨l₁⟩
rcases l₂ with ⟨l₂⟩
simp [List.filter_append]
@ -1440,12 +1441,18 @@ theorem _root_.List.filterMap_toArray (f : α → Option β) (l : List α) :
rcases l with ⟨l⟩
simp [h]
@[simp] theorem filterMap_eq_map (f : α → β) (w : stop = as.size ) :
@[simp] theorem filterMap_eq_map (f : α → β) (w : stop = as.size) :
filterMap (some ∘ f) as 0 stop = map f as := by
subst w
cases as
simp
/-- Variant of `filterMap_eq_map` with `some ∘ f` expanded out to a lambda. -/
@[simp]
theorem filterMap_eq_map' (f : α → β) (w : stop = as.size) :
filterMap (fun x => some (f x)) as 0 stop = map f as :=
filterMap_eq_map f w
theorem filterMap_some_fun : filterMap (some : α → Option α) = id := by
funext l
cases l
@ -1514,8 +1521,9 @@ theorem forall_mem_filterMap {f : α → Option β} {l : Array α} {P : β → P
intro a
rw [forall_comm]
@[simp] theorem filterMap_append {α β : Type _} (l l' : Array α) (f : α → Option β) :
filterMap f (l ++ l') = filterMap f l ++ filterMap f l' := by
@[simp] theorem filterMap_append {α β : Type _} (l l' : Array α) (f : α → Option β) (w : stop = l.size + l'.size) :
filterMap f (l ++ l') 0 stop = filterMap f l ++ filterMap f l' := by
subst w
cases l
cases l'
simp
@ -1557,7 +1565,12 @@ theorem filterMap_eq_push_iff {f : α → Option β} {l : Array α} {l' : Array
@[simp] theorem size_append (as bs : Array α) : (as ++ bs).size = as.size + bs.size := by
simp only [size, toList_append, List.length_append]
@[simp] theorem append_push {as bs : Array α} {a : α} : as ++ bs.push a = (as ++ bs).push a := by
@[simp] theorem push_append {a : α} {xs ys : Array α} : (xs ++ ys).push a = xs ++ ys.push a := by
cases xs
cases ys
simp
theorem append_push {as bs : Array α} {a : α} : as ++ bs.push a = (as ++ bs).push a := by
cases as
cases bs
simp
@ -1668,6 +1681,9 @@ theorem getElem_of_append {l l₁ l₂ : Array α} (eq : l = l₁.push a ++ l₂
@[simp] theorem append_singleton {a : α} {as : Array α} : as ++ #[a] = as.push a := rfl
@[simp] theorem append_singleton_assoc {a : α} {as bs : Array α} : as ++ (#[a] ++ bs) = as.push a ++ bs := by
rw [← append_assoc, append_singleton]
theorem push_eq_append {a : α} {as : Array α} : as.push a = as ++ #[a] := rfl
theorem append_inj {s₁ s₂ t₁ t₂ : Array α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : s₁.size = s₂.size) :
@ -1931,15 +1947,17 @@ theorem flatten_eq_flatMap {L : Array (Array α)} : flatten L = L.flatMap id :=
Function.comp_def]
rw [← Function.comp_def, ← List.map_map, flatten_toArray_map]
@[simp] theorem filterMap_flatten (f : α → Option β) (L : Array (Array α)) :
filterMap f (flatten L) = flatten (map (filterMap f) L) := by
@[simp] theorem filterMap_flatten (f : α → Option β) (L : Array (Array α)) (w : stop = L.flatten.size) :
filterMap f (flatten L) 0 stop = flatten (map (filterMap f) L) := by
subst w
induction L using array₂_induction
simp only [flatten_toArray_map, size_toArray, List.length_flatten, List.filterMap_toArray',
List.filterMap_flatten, List.map_toArray, List.map_map, Function.comp_def]
rw [← Function.comp_def, ← List.map_map, flatten_toArray_map]
@[simp] theorem filter_flatten (p : α → Bool) (L : Array (Array α)) :
filter p (flatten L) = flatten (map (filter p) L) := by
@[simp] theorem filter_flatten (p : α → Bool) (L : Array (Array α)) (w : stop = L.flatten.size) :
filter p (flatten L) 0 stop = flatten (map (filter p) L) := by
subst w
induction L using array₂_induction
simp only [flatten_toArray_map, size_toArray, List.length_flatten, List.filter_toArray',
List.filter_flatten, List.map_toArray, List.map_map, Function.comp_def]
@ -2397,11 +2415,25 @@ theorem reverse_eq_iff {as bs : Array α} : as.reverse = bs ↔ as = bs.reverse
@[simp] theorem map_reverse (f : α → β) (l : Array α) : l.reverse.map f = (l.map f).reverse := by
cases l <;> simp [*]
@[simp] theorem filter_reverse (p : α → Bool) (l : Array α) : (l.reverse.filter p) = (l.filter p).reverse := by
/-- Variant of `filter_reverse` with a hypothesis giving the stop condition. -/
@[simp] theorem filter_reverse' (p : α → Bool) (l : Array α) (w : stop = l.size) :
(l.reverse.filter p 0 stop) = (l.filter p).reverse := by
subst w
cases l
simp
@[simp] theorem filterMap_reverse (f : α → Option β) (l : Array α) : (l.reverse.filterMap f) = (l.filterMap f).reverse := by
theorem filter_reverse (p : α → Bool) (l : Array α) : (l.reverse.filter p) = (l.filter p).reverse := by
cases l
simp
/-- Variant of `filterMap_reverse` with a hypothesis giving the stop condition. -/
@[simp] theorem filterMap_reverse' (f : α → Option β) (l : Array α) (w : stop = l.size) :
(l.reverse.filterMap f 0 stop) = (l.filterMap f).reverse := by
subst w
cases l
simp
theorem filterMap_reverse (f : α → Option β) (l : Array α) : (l.reverse.filterMap f) = (l.filterMap f).reverse := by
cases l
simp
@ -2877,17 +2909,57 @@ rather than `(arr.push a).size` as the argument.
(h : start = arr.size + 1) : (arr.push a).foldr f init start = arr.foldr f (f a init) :=
foldrM_push' _ _ _ _ h
@[simp] theorem foldl_push_eq_append (l l' : Array α) : l.foldl push l' = l' ++ l := by
cases l
cases l'
@[simp] theorem foldl_push_eq_append {as : Array α} {bs : Array β} {f : α → β} (w : stop = as.size) :
as.foldl (fun b a => Array.push b (f a)) bs 0 stop = bs ++ as.map f := by
subst w
rcases as with ⟨as⟩
rcases bs with ⟨bs⟩
simp only [List.foldl_toArray']
induction as generalizing bs <;> simp [*]
@[simp] theorem foldl_cons_eq_append {as : Array α} {bs : List β} {f : α → β} (w : stop = as.size) :
as.foldl (fun b a => (f a) :: b) bs 0 stop = (as.map f).reverse.toList ++ bs := by
subst w
rcases as with ⟨as⟩
simp
@[simp] theorem foldr_flip_push_eq_append (l l' : Array α) :
l.foldr (fun x y => push y x) l' = l' ++ l.reverse := by
cases l
cases l'
@[simp] theorem foldr_cons_eq_append {as : Array α} {bs : List β} {f : α → β} (w : start = as.size) :
as.foldr (fun a b => (f a) :: b) bs start 0 = (as.map f).toList ++ bs := by
subst w
rcases as with ⟨as⟩
simp
/-- Variant of `foldr_cons_eq_append` specialized to `f = id`. -/
@[simp] theorem foldr_cons_eq_append' {as : Array α} {bs : List α} (w : start = as.size) :
as.foldr List.cons bs start 0 = as.toList ++ bs := by
subst w
rcases as with ⟨as⟩
simp
@[simp] theorem foldr_append_eq_append (l : Array α) (f : α → Array β) (l' : Array β) :
l.foldr (f · ++ ·) l' = (l.map f).flatten ++ l' := by
rcases l with ⟨l⟩
rcases l' with ⟨l'⟩
induction l <;> simp_all [Function.comp_def, flatten_toArray]
@[simp] theorem foldl_append_eq_append (l : Array α) (f : α → Array β) (l' : Array β) :
l.foldl (· ++ f ·) l' = l' ++ (l.map f).flatten := by
rcases l with ⟨l⟩
rcases l' with ⟨l'⟩
induction l generalizing l'<;> simp_all [Function.comp_def, flatten_toArray]
@[simp] theorem foldr_flip_append_eq_append (l : Array α) (f : α → Array β) (l' : Array β) :
l.foldr (fun x y => y ++ f x) l' = l' ++ (l.map f).reverse.flatten := by
rcases l with ⟨l⟩
rcases l' with ⟨l'⟩
induction l generalizing l' <;> simp_all [Function.comp_def, flatten_toArray]
@[simp] theorem foldl_flip_append_eq_append (l : Array α) (f : α → Array β) (l' : Array β) :
l.foldl (fun x y => f y ++ x) l' = (l.map f).reverse.flatten ++ l':= by
rcases l with ⟨l⟩
rcases l' with ⟨l'⟩
induction l generalizing l' <;> simp_all [Function.comp_def, flatten_toArray]
theorem foldl_map' (f : β₁ → β₂) (g : α → β₂ → α) (l : Array β₁) (init : α) (w : stop = l.size) :
(l.map f).foldl g init 0 stop = l.foldl (fun x y => g x (f y)) init := by
subst w
@ -3040,6 +3112,13 @@ theorem foldl_eq_foldr_reverse (l : Array α) (f : β → α → β) (b) :
theorem foldr_eq_foldl_reverse (l : Array α) (f : α → β → β) (b) :
l.foldr f b = l.reverse.foldl (fun x y => f y x) b := by simp
@[simp] theorem foldr_push_eq_append {as : Array α} {bs : Array β} {f : α → β} (w : start = as.size) :
as.foldr (fun a b => Array.push b (f a)) bs start 0 = bs ++ (as.map f).reverse := by
subst w
rw [foldr_eq_foldl_reverse, foldl_push_eq_append rfl, map_reverse]
@[deprecated foldr_push_eq_append (since := "2025-02-09")] abbrev foldr_flip_push_eq_append := @foldr_push_eq_append
theorem foldl_assoc {op : ααα} [ha : Std.Associative op] {l : Array α} {a₁ a₂} :
l.foldl op (op a₁ a₂) = op a₁ (l.foldl op a₂) := by
rcases l with ⟨l⟩
@ -3445,11 +3524,11 @@ theorem map_induction (as : Array α) (f : α → β) (motive : Nat → Prop) (h
(motive := fun i arr => motive i ∧ arr.size = i ∧ ∀ i h2, p i arr[i.1])
(init := #[]) (f := fun r a => r.push (f a)) ?_ ?_
obtain ⟨m, eq, w⟩ := t
· refine ⟨m, by simpa [map_eq_foldl] using eq, ?_⟩
· refine ⟨m, by simp, ?_⟩
intro i h
simp only [eq] at w
specialize w ⟨i, h⟩ h
simpa [map_eq_foldl] using w
simpa using w
· exact ⟨h0, rfl, nofun⟩
· intro i b ⟨m, ⟨eq, w⟩⟩
refine ⟨?_, ?_, ?_⟩

View file

@ -416,7 +416,12 @@ theorem attachWith_map {l : List α} (f : α → β) {P : β → Prop} {H : ∀
fun ⟨x, h⟩ => ⟨f x, h⟩ := by
induction l <;> simp [*]
theorem map_attachWith {l : List α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
@[simp] theorem map_attachWith {l : List α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f = l.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by
induction l <;> simp_all
theorem map_attachWith_eq_pmap {l : List α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f =
l.pmap (fun a (h : a ∈ l ∧ P a) => f ⟨a, H _ h.1⟩) (fun a h => ⟨h, H a h⟩) := by
@ -428,7 +433,7 @@ theorem map_attachWith {l : List α} {P : α → Prop} {H : ∀ (a : α), a ∈
simp
/-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/
theorem map_attach {l : List α} (f : { x // x ∈ l } → β) :
theorem map_attach_eq_pmap {l : List α} (f : { x // x ∈ l } → β) :
l.attach.map f = l.pmap (fun a h => f ⟨a, h⟩) (fun _ => id) := by
induction l with
| nil => rfl
@ -437,6 +442,9 @@ theorem map_attach {l : List α} (f : { x // x ∈ l } → β) :
apply pmap_congr_left
simp
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
theorem attach_filterMap {l : List α} {f : α → Option β} :
(l.filterMap f).attach = l.attach.filterMap
fun ⟨x, h⟩ => (f x).pbind (fun b m => some ⟨b, mem_filterMap.mpr ⟨x, h, m⟩⟩) := by

View file

@ -225,10 +225,23 @@ def lex [BEq α] (l₁ l₂ : List α) (lt : αα → Bool := by exact (·
| _, [] => false
| a :: as, b :: bs => lt a b || (a == b && lex as bs lt)
@[simp] theorem lex_nil_nil [BEq α] : lex ([] : List α) [] lt = false := rfl
@[simp] theorem lex_nil_cons [BEq α] {b} {bs : List α} : lex [] (b :: bs) lt = true := rfl
@[simp] theorem lex_cons_nil [BEq α] {a} {as : List α} : lex (a :: as) [] lt = false := rfl
@[simp] theorem lex_cons_cons [BEq α] {a b} {as bs : List α} :
theorem nil_lex_nil [BEq α] : lex ([] : List α) [] lt = false := rfl
@[simp] theorem nil_lex_cons [BEq α] {b} {bs : List α} : lex [] (b :: bs) lt = true := rfl
theorem cons_lex_nil [BEq α] {a} {as : List α} : lex (a :: as) [] lt = false := rfl
@[simp] theorem cons_lex_cons [BEq α] {a b} {as bs : List α} :
lex (a :: as) (b :: bs) lt = (lt a b || (a == b && lex as bs lt)) := rfl
@[simp] theorem lex_nil [BEq α] {as : List α} : lex as [] lt = false := by
cases as <;> simp [nil_lex_nil, cons_lex_nil]
@[deprecated nil_lex_nil (since := "2025-02-10")]
theorem lex_nil_nil [BEq α] : lex ([] : List α) [] lt = false := rfl
@[deprecated nil_lex_cons (since := "2025-02-10")]
theorem lex_nil_cons [BEq α] {b} {bs : List α} : lex [] (b :: bs) lt = true := rfl
@[deprecated cons_lex_nil (since := "2025-02-10")]
theorem lex_cons_nil [BEq α] {a} {as : List α} : lex (a :: as) [] lt = false := rfl
@[deprecated cons_lex_cons (since := "2025-02-10")]
theorem lex_cons_cons [BEq α] {a b} {as bs : List α} :
lex (a :: as) (b :: bs) lt = (lt a b || (a == b && lex as bs lt)) := rfl
/-! ## Alternative getters -/

View file

@ -1344,6 +1344,11 @@ theorem head_filter_of_pos {p : α → Bool} {l : List α} (w : l ≠ []) (h : p
theorem filterMap_eq_map (f : α → β) : filterMap (some ∘ f) = map f := by
funext l; induction l <;> simp [*, filterMap_cons]
/-- Variant of `filterMap_eq_map` with `some ∘ f` expanded out to a lambda. -/
@[simp]
theorem filterMap_eq_map' (f : α → β) : filterMap (fun x => some (f x)) = map f :=
filterMap_eq_map f
@[simp] theorem filterMap_some_fun : filterMap (some : α → Option α) = id := by
funext l
erw [filterMap_eq_map]
@ -2516,12 +2521,35 @@ theorem foldr_eq_foldrM (f : α → β → β) (b) (l : List α) :
/-! ### foldl and foldr -/
@[simp] theorem foldr_cons_eq_append (l : List α) : l.foldr cons l' = l ++ l' := by
@[simp] theorem foldr_cons_eq_append (l : List α) (f : α → β) (l' : List β) :
l.foldr (fun x y => f x :: y) l' = l.map f ++ l' := by
induction l <;> simp [*]
/-- Variant of `foldr_cons_eq_append` specalized to `f = id`. -/
@[simp] theorem foldr_cons_eq_append' (l l' : List β) :
l.foldr cons l' = l ++ l' := by
induction l <;> simp [*]
@[deprecated foldr_cons_eq_append (since := "2024-08-22")] abbrev foldr_self_append := @foldr_cons_eq_append
@[simp] theorem foldl_flip_cons_eq_append (l : List α) : l.foldl (fun x y => y :: x) l' = l.reverse ++ l' := by
@[simp] theorem foldl_flip_cons_eq_append (l : List α) (f : α → β) (l' : List β) :
l.foldl (fun x y => f y :: x) l' = (l.map f).reverse ++ l' := by
induction l generalizing l' <;> simp [*]
@[simp] theorem foldr_append_eq_append (l : List α) (f : α → List β) (l' : List β) :
l.foldr (f · ++ ·) l' = (l.map f).flatten ++ l' := by
induction l <;> simp [*]
@[simp] theorem foldl_append_eq_append (l : List α) (f : α → List β) (l' : List β) :
l.foldl (· ++ f ·) l' = l' ++ (l.map f).flatten := by
induction l generalizing l'<;> simp [*]
@[simp] theorem foldr_flip_append_eq_append (l : List α) (f : α → List β) (l' : List β) :
l.foldr (fun x y => y ++ f x) l' = l' ++ (l.map f).reverse.flatten := by
induction l generalizing l' <;> simp [*]
@[simp] theorem foldl_flip_append_eq_append (l : List α) (f : α → List β) (l' : List β) :
l.foldl (fun x y => f y ++ x) l' = (l.map f).reverse.flatten ++ l' := by
induction l generalizing l' <;> simp [*]
theorem foldr_cons_nil (l : List α) : l.foldr cons [] = l := by simp

View file

@ -48,7 +48,9 @@ instance ltIrrefl [LT α] [Std.Irrefl (· < · : αα → Prop)] : Std.Irre
@[simp] theorem le_nil [LT α] (l : List α) : l ≤ [] ↔ l = [] := not_nil_lex_iff
@[simp] theorem nil_lex_cons : Lex r [] (a :: l) := Lex.nil
-- This is named with a prime to avoid conflict with `lex [] (b :: bs) lt = true`.
-- Better naming for the `Lex` vs `lex` distinction would be welcome.
@[simp] theorem nil_lex_cons' : Lex r [] (a :: l) := Lex.nil
@[simp] theorem nil_lt_cons [LT α] (a : α) (l : List α) : [] < a :: l := Lex.nil
@ -333,7 +335,7 @@ theorem lex_eq_true_iff_exists [BEq α] (lt : αα → Bool) :
cases l₂ with
| nil => simp [lex]
| cons b l₂ =>
simp [lex_cons_cons, Bool.or_eq_true, Bool.and_eq_true, ih, isEqv, length_cons]
simp [cons_lex_cons, Bool.or_eq_true, Bool.and_eq_true, ih, isEqv, length_cons]
constructor
· rintro (hab | ⟨hab, ⟨h₁, h₂⟩ | ⟨i, h₁, h₂, w₁, w₂⟩⟩)
· exact .inr ⟨0, by simp [hab]⟩
@ -397,7 +399,7 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
cases l₂ with
| nil => simp [lex]
| cons b l₂ =>
simp [lex_cons_cons, Bool.or_eq_false_iff, Bool.and_eq_false_imp, ih, isEqv,
simp [cons_lex_cons, Bool.or_eq_false_iff, Bool.and_eq_false_imp, ih, isEqv,
Bool.and_eq_true, length_cons]
constructor
· rintro ⟨hab, h⟩

View file

@ -134,16 +134,29 @@ theorem attachWith_map {o : Option α} (f : α → β) {P : β → Prop} {H :
fun ⟨x, h⟩ => ⟨f x, h⟩ := by
cases o <;> simp
theorem map_attach {o : Option α} (f : { x // x ∈ o } → β) :
theorem map_attach_eq_pmap {o : Option α} (f : { x // x ∈ o } → β) :
o.attach.map f = o.pmap (fun a (h : a ∈ o) => f ⟨a, h⟩) (fun _ h => h) := by
cases o <;> simp
theorem map_attachWith {o : Option α} {P : α → Prop} {H : ∀ (a : α), a ∈ o → P a}
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
@[simp] theorem map_attachWith {l : Option α} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f = l.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by
cases l <;> simp_all
theorem map_attachWith_eq_pmap {o : Option α} {P : α → Prop} {H : ∀ (a : α), a ∈ o → P a}
(f : { x // P x } → β) :
(o.attachWith P H).map f =
o.pmap (fun a (h : a ∈ o ∧ P a) => f ⟨a, h.2⟩) (fun a h => ⟨h, H a h⟩) := by
cases o <;> simp
@[simp]
theorem map_attach_eq_attachWith {o : Option α} {p : α → Prop} (f : ∀ a, a ∈ o → p a) :
o.attach.map (fun x => ⟨x.1, f x.1 x.2⟩) = o.attachWith p f := by
cases o <;> simp_all [Function.comp_def]
theorem attach_bind {o : Option α} {f : α → Option β} :
(o.bind f).attach =
o.attach.bind fun ⟨x, h⟩ => (f x).attach.map fun ⟨y, h'⟩ => ⟨y, mem_bind_iff.mpr ⟨x, h, h'⟩⟩ := by

View file

@ -81,7 +81,7 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
@[csimp] private theorem pmap_eq_pmapImpl : @pmap = @pmapImpl := by
funext α β n p f L h'
rcases L with ⟨L, rfl⟩
simp only [pmap, pmapImpl, attachWith_mk, map_mk, Array.map_attachWith, eq_mk]
simp only [pmap, pmapImpl, attachWith_mk, map_mk, Array.map_attachWith_eq_pmap, eq_mk]
apply Array.pmap_congr_left
intro a m h₁ h₂
congr
@ -133,7 +133,7 @@ theorem attachWith_congr {l₁ l₂ : Vector α n} (w : l₁ = l₂) {P : α
(l.push a).attach =
(l.attach.map (fun ⟨x, h⟩ => ⟨x, mem_push_of_mem a h⟩)).push ⟨a, by simp⟩ := by
rcases l with ⟨l, rfl⟩
simp [Array.map_attachWith]
simp [Array.map_attach_eq_pmap]
@[simp] theorem attachWith_push {a : α} {l : Vector α n} {P : α → Prop} {H : ∀ x ∈ l.push a, P x} :
(l.push a).attachWith P H =
@ -145,7 +145,7 @@ theorem pmap_eq_map_attach {p : α → Prop} (f : ∀ a, p a → β) (l : Vector
pmap f l H = l.attach.map fun x => f x.1 (H _ x.2) := by
rcases l with ⟨l, rfl⟩
simp only [pmap_mk, Array.pmap_eq_map_attach, attach_mk, map_mk, eq_mk]
rw [Array.map_attach, Array.map_attachWith]
rw [Array.map_attach_eq_pmap, Array.map_attachWith]
ext i hi₁ hi₂ <;> simp
@[simp]
@ -299,7 +299,13 @@ theorem attachWith_map {l : Vector α n} (f : α → β) {P : β → Prop} {H :
rcases l with ⟨l, rfl⟩
simp [Array.attachWith_map]
theorem map_attachWith {l : Vector α n} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
@[simp] theorem map_attachWith {l : Vector α n} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f = l.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by
rcases l with ⟨l, rfl⟩
simp [Array.map_attachWith]
theorem map_attachWith_eq_pmap {l : Vector α n} {P : α → Prop} {H : ∀ (a : α), a ∈ l → P a}
(f : { x // P x } → β) :
(l.attachWith P H).map f =
l.pmap (fun a (h : a ∈ l ∧ P a) => f ⟨a, H _ h.1⟩) (fun a h => ⟨h, H a h⟩) := by
@ -307,11 +313,14 @@ theorem map_attachWith {l : Vector α n} {P : α → Prop} {H : ∀ (a : α), a
ext <;> simp
/-- See also `pmap_eq_map_attach` for writing `pmap` in terms of `map` and `attach`. -/
theorem map_attach {l : Vector α n} (f : { x // x ∈ l } → β) :
theorem map_attach_eq_pmap {l : Vector α n} (f : { x // x ∈ l } → β) :
l.attach.map f = l.pmap (fun a h => f ⟨a, h⟩) (fun _ => id) := by
cases l
ext <;> simp
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
theorem pmap_pmap {p : α → Prop} {q : β → Prop} (g : ∀ a, p a → β) (f : ∀ b, q b → γ) (l : Vector α n) (H₁ H₂) :
pmap f (pmap g l H₁) H₂ =
pmap (α := { x // x ∈ l }) (fun a h => f (g a h) (H₂ (g a h) (mem_pmap_of_mem a.2))) l.attach
@ -339,7 +348,7 @@ theorem pmap_append' {p : α → Prop} (f : ∀ a : α, p a → β) (l₁ : Vect
ys.attach.map (fun ⟨y, h⟩ => (⟨y, mem_append_right xs h⟩ : { y // y ∈ xs ++ ys })) := by
rcases xs with ⟨xs, rfl⟩
rcases ys with ⟨ys, rfl⟩
simp [Array.map_attachWith]
simp [Array.map_attach_eq_pmap]
@[simp] theorem attachWith_append {P : α → Prop} {xs : Vector α n} {ys : Vector α m}
{H : ∀ (a : α), a ∈ xs ++ ys → P a} :
@ -379,7 +388,7 @@ theorem reverse_attachWith {P : α → Prop} {xs : Vector α n}
theorem reverse_attach (xs : Vector α n) :
xs.attach.reverse = xs.reverse.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by
cases xs
simp [Array.map_attachWith]
simp [Array.map_attach_eq_pmap]
@[simp] theorem back?_pmap {P : α → Prop} (f : (a : α) → P a → β) (xs : Vector α n)
(H : ∀ (a : α), a ∈ xs → P a) :

View file

@ -1471,7 +1471,7 @@ theorem vector₂_induction (P : Vector (Vector α n) m → Prop)
P (mk (xss.attach.map (fun ⟨xs, m⟩ => mk xs (h₂ xs m))) (by simpa using h₁)))
(ass : Vector (Vector α n) m) : P ass := by
specialize of (ass.map toArray).toArray (by simp) (by simp)
simpa [Array.map_attach, Array.pmap_map] using of
simpa [Array.map_attach_eq_pmap, Array.pmap_map] using of
/--
Use this as `induction ass using vector₃_induction` on a hypothesis of the form `ass : Vector (Vector (Vector α n) m) k`.
@ -1489,7 +1489,7 @@ theorem vector₃_induction (P : Vector (Vector (Vector α n) m) k → Prop)
mk x (h₃ xs m x m'))) (by simpa using h₂ xs m))) (by simpa using h₁)))
(ass : Vector (Vector (Vector α n) m) k) : P ass := by
specialize of (ass.map (fun as => (as.map toArray).toArray)).toArray (by simp) (by simp) (by simp)
simpa [Array.map_attach, Array.pmap_map] using of
simpa [Array.map_attach_eq_pmap, Array.pmap_map] using of
/-! ### singleton -/
@ -1800,7 +1800,7 @@ theorem flatten_flatten {L : Vector (Vector (Vector α n) m) k} :
induction L using vector₃_induction with
| of xss h₁ h₂ h₃ =>
-- simp [Array.flatten_flatten] -- FIXME: `simp` produces a bad proof here!
simp [Array.map_attach, Array.flatten_flatten, Array.map_pmap]
simp [Array.map_attach_eq_pmap, Array.flatten_flatten, Array.map_pmap]
/-- Two vectors of constant length vectors are equal iff their flattens coincide. -/
theorem eq_iff_flatten_eq {L L' : Vector (Vector α n) m} :

View file

@ -15,11 +15,6 @@ def treeToList (t : TreeNode) : List String :=
@[simp] theorem treeToList_eq (name : String) (children : List TreeNode) : treeToList (.mkNode name children) = name :: List.flatten (children.map treeToList) := by
simp [treeToList, Id.run]
conv => rhs; rw [← List.singleton_append]
generalize [name] = as
induction children generalizing as with
| nil => simp
| cons c cs ih => simp [ih, List.append_assoc]
mutual
def numNames : TreeNode → Nat