chore: more review of @[grind] annotations (#10340)
This PR completes the review of `@[grind]` annotations without a sigil (e.g. `=` or `←`), replacing most of them with more specific annotations or patterns. --------- Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
This commit is contained in:
parent
176fb1cf0e
commit
01ed345643
27 changed files with 255 additions and 187 deletions
|
|
@ -228,11 +228,12 @@ theorem mem_of_find?_eq_some {xs : Array α} (h : find? p xs = some a) : a ∈ x
|
|||
simp at h
|
||||
simpa using List.mem_of_find?_eq_some h
|
||||
|
||||
@[grind]
|
||||
theorem get_find?_mem {xs : Array α} (h) : (xs.find? p).get h ∈ xs := by
|
||||
cases xs
|
||||
simp [List.get_find?_mem]
|
||||
|
||||
grind_pattern get_find?_mem => (xs.find? p).get h
|
||||
|
||||
@[simp, grind =] theorem find?_filter {xs : Array α} (p q : α → Bool) :
|
||||
(xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by
|
||||
cases xs; simp
|
||||
|
|
|
|||
|
|
@ -380,6 +380,12 @@ theorem not_mem_empty (a : α) : ¬ a ∈ #[] := by simp
|
|||
theorem mem_or_eq_of_mem_push {a b : α} {xs : Array α} :
|
||||
a ∈ xs.push b → a ∈ xs ∨ a = b := Array.mem_push.mp
|
||||
|
||||
-- This pattern may be excessively general:
|
||||
-- it fires anytime we ae thinking about membership of arrays,
|
||||
-- and constructing a list via `push`, even if the elements are unrelated.
|
||||
-- Nevertheless in practice it is quite helpful!
|
||||
grind_pattern mem_or_eq_of_mem_push => xs.push b, a ∈ xs
|
||||
|
||||
theorem mem_push_self {xs : Array α} {x : α} : x ∈ xs.push x :=
|
||||
mem_push.2 (Or.inr rfl)
|
||||
|
||||
|
|
@ -3771,6 +3777,10 @@ theorem contains_iff_exists_mem_beq [BEq α] {xs : Array α} {a : α} :
|
|||
rcases xs with ⟨xs⟩
|
||||
simp [List.contains_iff_exists_mem_beq]
|
||||
|
||||
-- We add this as a `grind` lemma because it is useful without `LawfulBEq α`.
|
||||
-- With `LawfulBEq α`, it would be better to use `contains_iff_mem` directly.
|
||||
grind_pattern contains_iff_exists_mem_beq => xs.contains a
|
||||
|
||||
@[grind _=_]
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.contains a ↔ a ∈ xs := by
|
||||
|
|
|
|||
|
|
@ -192,12 +192,13 @@ theorem mem_pmap {p : α → Prop} {f : ∀ a, p a → β} {l H b} :
|
|||
b ∈ pmap f l H ↔ ∃ (a : _) (h : a ∈ l), f a (H a h) = b := by
|
||||
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
|
||||
|
||||
@[grind]
|
||||
theorem mem_pmap_of_mem {p : α → Prop} {f : ∀ a, p a → β} {l H} {a} (h : a ∈ l) :
|
||||
f a (H a h) ∈ pmap f l H := by
|
||||
rw [mem_pmap]
|
||||
exact ⟨a, h, rfl⟩
|
||||
|
||||
grind_pattern mem_pmap_of_mem => _ ∈ pmap f l H, a ∈ l
|
||||
|
||||
@[simp, grind =]
|
||||
theorem length_pmap {p : α → Prop} {f : ∀ a, p a → β} {l H} : (pmap f l H).length = l.length := by
|
||||
induction l
|
||||
|
|
|
|||
|
|
@ -538,7 +538,7 @@ Example:
|
|||
| some b => b :: filterMap f as
|
||||
|
||||
@[simp, grind =] theorem filterMap_nil {f : α → Option β} : filterMap f [] = [] := rfl
|
||||
@[grind] theorem filterMap_cons {f : α → Option β} {a : α} {l : List α} :
|
||||
@[grind =] theorem filterMap_cons {f : α → Option β} {a : α} {l : List α} :
|
||||
filterMap f (a :: l) =
|
||||
match f a with
|
||||
| none => filterMap f l
|
||||
|
|
@ -749,7 +749,7 @@ def replicate : (n : Nat) → (a : α) → List α
|
|||
| n+1, a => a :: replicate n a
|
||||
|
||||
@[simp, grind =] theorem replicate_zero {a : α} : replicate 0 a = [] := rfl
|
||||
@[grind] theorem replicate_succ {a : α} {n : Nat} : replicate (n+1) a = a :: replicate n a := rfl
|
||||
@[grind =] theorem replicate_succ {a : α} {n : Nat} : replicate (n+1) a = a :: replicate n a := rfl
|
||||
|
||||
@[simp, grind =] theorem length_replicate {n : Nat} {a : α} : (replicate n a).length = n := by
|
||||
induction n with
|
||||
|
|
@ -1440,7 +1440,7 @@ def replace [BEq α] : (l : List α) → (a : α) → (b : α) → List α
|
|||
| false => a :: replace as b c
|
||||
|
||||
@[simp, grind =] theorem replace_nil [BEq α] : ([] : List α).replace a b = [] := rfl
|
||||
@[grind] theorem replace_cons [BEq α] {a : α} :
|
||||
@[grind =] theorem replace_cons [BEq α] {a : α} :
|
||||
(a::as).replace b c = match b == a with | true => c::as | false => a :: replace as b c :=
|
||||
rfl
|
||||
|
||||
|
|
@ -1649,7 +1649,7 @@ def findSome? (f : α → Option β) : List α → Option β
|
|||
| none => findSome? f as
|
||||
|
||||
@[simp, grind =] theorem findSome?_nil : ([] : List α).findSome? f = none := rfl
|
||||
@[grind] theorem findSome?_cons {f : α → Option β} :
|
||||
@[grind =] theorem findSome?_cons {f : α → Option β} :
|
||||
(a::as).findSome? f = match f a with | some b => some b | none => as.findSome? f :=
|
||||
rfl
|
||||
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ variable [BEq α]
|
|||
|
||||
@[simp, grind =] theorem count_nil {a : α} : count a [] = 0 := rfl
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem count_cons {a b : α} {l : List α} :
|
||||
count a (b :: l) = count a l + if b == a then 1 else 0 := by
|
||||
simp [count, countP_cons]
|
||||
|
|
@ -237,7 +237,7 @@ theorem count_eq_countP' {a : α} : count a = countP (· == a) := by
|
|||
theorem count_eq_length_filter {a : α} {l : List α} : count a l = (filter (· == a) l).length := by
|
||||
simp [count, countP_eq_length_filter]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem count_tail : ∀ {l : List α} {a : α},
|
||||
l.tail.count a = l.count a - if l.head? == some a then 1 else 0
|
||||
| [], a => by simp
|
||||
|
|
@ -380,7 +380,7 @@ theorem count_filterMap {α} [BEq β] {b : β} {f : α → Option β} {l : List
|
|||
theorem count_flatMap {α} [BEq β] {l : List α} {f : α → List β} {x : β} :
|
||||
count x (l.flatMap f) = sum (map (count x ∘ f) l) := countP_flatMap
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem count_erase {a b : α} :
|
||||
∀ {l : List α}, count a (l.erase b) = count a l - if b == a then 1 else 0
|
||||
| [] => by simp
|
||||
|
|
|
|||
|
|
@ -508,7 +508,7 @@ theorem Nodup.not_mem_erase [LawfulBEq α] {a : α} (h : Nodup l) : a ∉ l.eras
|
|||
-- Only activate `not_mem_erase` when `l.Nodup` is already available.
|
||||
grind_pattern List.Nodup.not_mem_erase => a ∈ l.erase a, l.Nodup
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
theorem Nodup.erase [LawfulBEq α] (a : α) : Nodup l → Nodup (l.erase a) :=
|
||||
Pairwise.erase a
|
||||
|
||||
|
|
@ -578,21 +578,21 @@ theorem eraseIdx_ne_nil_iff {l : List α} {i : Nat} : eraseIdx l i ≠ [] ↔ 2
|
|||
| [a]
|
||||
| a::b::l => simp
|
||||
|
||||
|
||||
|
||||
@[grind]
|
||||
theorem eraseIdx_sublist : ∀ (l : List α) (k : Nat), eraseIdx l k <+ l
|
||||
| [], _ => by simp
|
||||
| a::l, 0 => by simp
|
||||
| a::l, k + 1 => by simp [eraseIdx_sublist]
|
||||
|
||||
grind_pattern eraseIdx_sublist => l.eraseIdx k, _ <+ l
|
||||
|
||||
theorem mem_of_mem_eraseIdx {l : List α} {i : Nat} {a : α} (h : a ∈ l.eraseIdx i) : a ∈ l :=
|
||||
(eraseIdx_sublist _ _).mem h
|
||||
|
||||
@[grind]
|
||||
theorem eraseIdx_subset {l : List α} {k : Nat} : eraseIdx l k ⊆ l :=
|
||||
(eraseIdx_sublist _ _).subset
|
||||
|
||||
grind_pattern eraseIdx_sublist => l.eraseIdx k, _ ⊆ l
|
||||
|
||||
@[simp]
|
||||
theorem eraseIdx_eq_self : ∀ {l : List α} {k : Nat}, eraseIdx l k = l ↔ length l ≤ k
|
||||
| [], _ => by simp
|
||||
|
|
|
|||
|
|
@ -293,7 +293,6 @@ theorem mem_of_find?_eq_some : ∀ {l}, find? p l = some a → a ∈ l
|
|||
· exact H ▸ .head _
|
||||
· exact .tail _ (mem_of_find?_eq_some H)
|
||||
|
||||
@[grind]
|
||||
theorem get_find?_mem {xs : List α} {p : α → Bool} (h) : (xs.find? p).get h ∈ xs := by
|
||||
induction xs with
|
||||
| nil => simp at h
|
||||
|
|
@ -305,6 +304,8 @@ theorem get_find?_mem {xs : List α} {p : α → Bool} (h) : (xs.find? p).get h
|
|||
right
|
||||
apply ih
|
||||
|
||||
grind_pattern get_find?_mem => (xs.find? p).get h
|
||||
|
||||
@[simp, grind =] theorem find?_filter {xs : List α} {p : α → Bool} {q : α → Bool} :
|
||||
(xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by
|
||||
induction xs with
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ theorem getD_getElem? {l : List α} {i : Nat} {d : α} :
|
|||
match i, h with
|
||||
| 0, _ => rfl
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getElem?_singleton {a : α} {i : Nat} : [a][i]? = if i = 0 then some a else none := by
|
||||
simp [getElem?_cons]
|
||||
|
||||
|
|
@ -382,14 +382,20 @@ theorem get!_eq_getElem! [Inhabited α] (l : List α) (i) : l.get! i = l[i]! :=
|
|||
|
||||
@[simp] theorem not_mem_nil {a : α} : ¬ a ∈ [] := nofun
|
||||
|
||||
@[simp] theorem mem_cons : a ∈ b :: l ↔ a = b ∨ a ∈ l :=
|
||||
@[simp, grind =] theorem mem_cons : a ∈ b :: l ↔ a = b ∨ a ∈ l :=
|
||||
⟨fun h => by cases h <;> simp [Membership.mem, *],
|
||||
fun | Or.inl rfl => by constructor | Or.inr h => by constructor; assumption⟩
|
||||
|
||||
@[grind] theorem eq_or_mem_of_mem_cons {a b : α} {l : List α} :
|
||||
theorem eq_or_mem_of_mem_cons {a b : α} {l : List α} :
|
||||
a ∈ b :: l → a = b ∨ a ∈ l := List.mem_cons.mp
|
||||
|
||||
@[grind] theorem mem_cons_self {a : α} {l : List α} : a ∈ a :: l := .head ..
|
||||
-- This pattern may be excessively general:
|
||||
-- it fires anytime we ae thinking about membership of lists,
|
||||
-- and constructing a list via `cons`, even if the elements are unrelated.
|
||||
-- Nevertheless in practice it is quite helpful!
|
||||
grind_pattern eq_or_mem_of_mem_cons => b :: l, a ∈ l
|
||||
|
||||
theorem mem_cons_self {a : α} {l : List α} : a ∈ a :: l := .head ..
|
||||
|
||||
theorem mem_concat_self {xs : List α} {a : α} : a ∈ xs ++ [a] :=
|
||||
mem_append_right xs mem_cons_self
|
||||
|
|
@ -411,7 +417,7 @@ theorem eq_append_cons_of_mem {a : α} {xs : List α} (h : a ∈ xs) :
|
|||
· obtain ⟨as, bs, rfl, h⟩ := ih h
|
||||
exact ⟨x :: as, bs, rfl, by simp_all⟩
|
||||
|
||||
@[grind] theorem mem_cons_of_mem (y : α) {a : α} {l : List α} : a ∈ l → a ∈ y :: l := .tail _
|
||||
theorem mem_cons_of_mem (y : α) {a : α} {l : List α} : a ∈ l → a ∈ y :: l := .tail _
|
||||
|
||||
-- The argument `l : List α` is intentionally explicit,
|
||||
-- as a tactic may generate `h` without determining `l`.
|
||||
|
|
@ -605,7 +611,7 @@ theorem decide_forall_mem {l : List α} {p : α → Prop} [DecidablePred p] :
|
|||
@[simp] theorem all_eq_false {l : List α} : l.all p = false ↔ ∃ x, x ∈ l ∧ ¬p x := by
|
||||
simp [all_eq]
|
||||
|
||||
@[grind] theorem any_beq [BEq α] {l : List α} {a : α} : (l.any fun x => a == x) = l.contains a := by
|
||||
theorem any_beq [BEq α] {l : List α} {a : α} : (l.any fun x => a == x) = l.contains a := by
|
||||
induction l <;> simp_all [contains_cons]
|
||||
|
||||
/-- Variant of `any_beq` with `==` reversed. -/
|
||||
|
|
@ -613,7 +619,7 @@ theorem any_beq' [BEq α] [PartialEquivBEq α] {l : List α} :
|
|||
(l.any fun x => x == a) = l.contains a := by
|
||||
simp only [BEq.comm, any_beq]
|
||||
|
||||
@[grind] theorem all_bne [BEq α] {l : List α} : (l.all fun x => a != x) = !l.contains a := by
|
||||
theorem all_bne [BEq α] {l : List α} : (l.all fun x => a != x) = !l.contains a := by
|
||||
induction l <;> simp_all [bne]
|
||||
|
||||
/-- Variant of `all_bne` with `!=` reversed. -/
|
||||
|
|
@ -670,14 +676,14 @@ theorem getElem?_set_self' {l : List α} {i : Nat} {a : α} :
|
|||
simp_all
|
||||
· rw [getElem?_eq_none (by simp_all), getElem?_eq_none (by simp_all)]
|
||||
|
||||
@[grind] theorem getElem_set {l : List α} {i j} {a} (h) :
|
||||
@[grind =] theorem getElem_set {l : List α} {i j} {a} (h) :
|
||||
(set l i a)[j]'h = if i = j then a else l[j]'(length_set .. ▸ h) := by
|
||||
if h : i = j then
|
||||
subst h; simp only [getElem_set_self, ↓reduceIte]
|
||||
else
|
||||
simp [h]
|
||||
|
||||
@[grind] theorem getElem?_set {l : List α} {i j : Nat} {a : α} :
|
||||
@[grind =] theorem getElem?_set {l : List α} {i j : Nat} {a : α} :
|
||||
(l.set i a)[j]? = if i = j then if i < l.length then some a else none else l[j]? := by
|
||||
if h : i = j then
|
||||
subst h
|
||||
|
|
@ -825,7 +831,7 @@ theorem length_eq_of_beq [BEq α] {l₁ l₂ : List α} (h : l₁ == l₂) : l
|
|||
|
||||
/-! ### getLast -/
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getLast_eq_getElem : ∀ {l : List α} (h : l ≠ []),
|
||||
getLast l h = l[l.length - 1]'(by
|
||||
match l with
|
||||
|
|
@ -888,7 +894,7 @@ theorem getLast?_eq_getLast : ∀ {l : List α} h, l.getLast? = some (l.getLast
|
|||
| [], h => nomatch h rfl
|
||||
| _ :: _, _ => rfl
|
||||
|
||||
@[grind] theorem getLast?_eq_getElem? : ∀ {l : List α}, l.getLast? = l[l.length - 1]?
|
||||
@[grind =] theorem getLast?_eq_getElem? : ∀ {l : List α}, l.getLast? = l[l.length - 1]?
|
||||
| [] => rfl
|
||||
| a::l => by
|
||||
rw [getLast?_eq_getLast (l := a :: l) nofun, getLast_eq_getElem, getElem?_eq_getElem]
|
||||
|
|
@ -901,14 +907,14 @@ theorem getLast_eq_iff_getLast?_eq_some {xs : List α} (h) :
|
|||
-- `getLast?_eq_none_iff`, `getLast?_eq_some_iff`, `getLast?_isSome`, and `getLast_mem`
|
||||
-- are proved later once more `reverse` theorems are available.
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getLast?_cons {a : α} : (a::l).getLast? = some (l.getLast?.getD a) := by
|
||||
cases l <;> simp [getLast?, getLast]
|
||||
|
||||
@[simp] theorem getLast?_cons_cons : (a :: b :: l).getLast? = (b :: l).getLast? := by
|
||||
simp [getLast?_cons]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getLast?_concat {l : List α} {a : α} : (l ++ [a]).getLast? = some a := by
|
||||
simp [getLast?_eq_getElem?, Nat.succ_sub_succ]
|
||||
|
||||
|
|
@ -927,7 +933,7 @@ theorem getLast!_nil [Inhabited α] : ([] : List α).getLast! = default := rfl
|
|||
theorem getLast!_of_getLast? [Inhabited α] : ∀ {l : List α}, getLast? l = some a → getLast! l = a
|
||||
| _ :: _, rfl => rfl
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getLast!_eq_getElem! [Inhabited α] {l : List α} : l.getLast! = l[l.length - 1]! := by
|
||||
cases l with
|
||||
| nil => simp
|
||||
|
|
@ -955,7 +961,7 @@ theorem head?_eq_getElem? : ∀ {l : List α}, l.head? = l[0]?
|
|||
|
||||
theorem head_singleton {a : α} : head [a] (by simp) = a := by simp
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem head_eq_getElem {l : List α} (h : l ≠ []) : head l h = l[0]'(length_pos_iff.mpr h) := by
|
||||
cases l with
|
||||
| nil => simp at h
|
||||
|
|
@ -1276,7 +1282,7 @@ theorem getLastD_map {f : α → β} {l : List α} {a : α} : (map f l).getLastD
|
|||
@[simp] theorem filter_cons_of_neg {p : α → Bool} {a : α} {l} (pa : ¬ p a) :
|
||||
filter p (a :: l) = filter p l := by rw [filter, eq_false_of_ne_true pa]
|
||||
|
||||
@[grind] theorem filter_cons :
|
||||
@[grind =] theorem filter_cons :
|
||||
(x :: xs : List α).filter p = if p x then x :: (xs.filter p) else xs.filter p := by
|
||||
split <;> simp [*]
|
||||
|
||||
|
|
@ -1330,10 +1336,12 @@ theorem forall_mem_filter {l : List α} {p : α → Bool} {P : α → Prop} :
|
|||
(∀ (i) (_ : i ∈ l.filter p), P i) ↔ ∀ (j) (_ : j ∈ l), p j → P j := by
|
||||
simp
|
||||
|
||||
@[grind] theorem getElem_filter {xs : List α} {p : α → Bool} {i : Nat} (h : i < (xs.filter p).length) :
|
||||
theorem getElem_filter {xs : List α} {p : α → Bool} {i : Nat} (h : i < (xs.filter p).length) :
|
||||
p (xs.filter p)[i] :=
|
||||
(mem_filter.mp (getElem_mem h)).2
|
||||
|
||||
grind_pattern getElem_filter => (xs.filter p)[i]
|
||||
|
||||
theorem getElem?_filter {xs : List α} {p : α → Bool} {i : Nat} (h : i < (xs.filter p).length)
|
||||
(w : (xs.filter p)[i]? = some a) : p a := by
|
||||
rw [getElem?_eq_getElem] at w
|
||||
|
|
@ -1477,14 +1485,14 @@ theorem filterMap_eq_filter {p : α → Bool} :
|
|||
| nil => rfl
|
||||
| cons a l IH => by_cases pa : p a <;> simp [Option.guard, pa, ← IH]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem filterMap_filterMap {f : α → Option β} {g : β → Option γ} {l : List α} :
|
||||
filterMap g (filterMap f l) = filterMap (fun x => (f x).bind g) l := by
|
||||
induction l with
|
||||
| nil => rfl
|
||||
| cons a l IH => cases h : f a <;> simp [filterMap_cons, *]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem map_filterMap {f : α → Option β} {g : β → γ} {l : List α} :
|
||||
map g (filterMap f l) = filterMap (fun x => (f x).map g) l := by
|
||||
simp only [← filterMap_eq_map, filterMap_filterMap, Option.map_eq_bind]
|
||||
|
|
@ -1611,7 +1619,7 @@ theorem forall_mem_append {p : α → Prop} {l₁ l₂ : List α} :
|
|||
(∀ (x) (_ : x ∈ l₁ ++ l₂), p x) ↔ (∀ (x) (_ : x ∈ l₁), p x) ∧ (∀ (x) (_ : x ∈ l₂), p x) := by
|
||||
simp only [mem_append, or_imp, forall_and]
|
||||
|
||||
@[grind] theorem getElem_append {l₁ l₂ : List α} {i : Nat} (h : i < (l₁ ++ l₂).length) :
|
||||
@[grind =] theorem getElem_append {l₁ l₂ : List α} {i : Nat} (h : i < (l₁ ++ l₂).length) :
|
||||
(l₁ ++ l₂)[i] = if h' : i < l₁.length then l₁[i] else l₂[i - l₁.length]'(by simp at h h'; exact Nat.sub_lt_left_of_lt_add h' h) := by
|
||||
split <;> rename_i h'
|
||||
· rw [getElem_append_left h']
|
||||
|
|
@ -1630,7 +1638,7 @@ theorem getElem?_append_right : ∀ {l₁ l₂ : List α} {i : Nat}, l₁.length
|
|||
rw [cons_append]
|
||||
simp [Nat.succ_sub_succ_eq_sub, getElem?_append_right (Nat.lt_succ.1 h₁)]
|
||||
|
||||
@[grind] theorem getElem?_append {l₁ l₂ : List α} {i : Nat} :
|
||||
@[grind =] theorem getElem?_append {l₁ l₂ : List α} {i : Nat} :
|
||||
(l₁ ++ l₂)[i]? = if i < l₁.length then l₁[i]? else l₂[i - l₁.length]? := by
|
||||
split <;> rename_i h
|
||||
· exact getElem?_append_left h
|
||||
|
|
@ -1743,7 +1751,7 @@ theorem append_eq_append_iff {ws xs ys zs : List α} :
|
|||
match l, w₂ with
|
||||
| a :: l, _ => rfl
|
||||
|
||||
@[grind] theorem head_append {l₁ l₂ : List α} (w : l₁ ++ l₂ ≠ []) :
|
||||
@[grind =] theorem head_append {l₁ l₂ : List α} (w : l₁ ++ l₂ ≠ []) :
|
||||
head (l₁ ++ l₂) w =
|
||||
if h : l₁.isEmpty then
|
||||
head l₂ (by simp_all [isEmpty_iff])
|
||||
|
|
@ -1771,21 +1779,21 @@ theorem head_append_right {l₁ l₂ : List α} (w : l₁ ++ l₂ ≠ []) (h : l
|
|||
-- `getLast_append_of_ne_nil`, `getLast_append` and `getLast?_append`
|
||||
-- are stated and proved later in the `reverse` section.
|
||||
|
||||
@[grind] theorem tail?_append {l l' : List α} : (l ++ l').tail? = (l.tail?.map (· ++ l')).or l'.tail? := by
|
||||
@[grind =] theorem tail?_append {l l' : List α} : (l ++ l').tail? = (l.tail?.map (· ++ l')).or l'.tail? := by
|
||||
cases l <;> simp
|
||||
|
||||
theorem tail?_append_of_ne_nil {l l' : List α} (_ : l ≠ []) : (l ++ l').tail? = some (l.tail ++ l') :=
|
||||
match l with
|
||||
| _ :: _ => by simp
|
||||
|
||||
@[grind] theorem tail_append {l l' : List α} : (l ++ l').tail = if l.isEmpty then l'.tail else l.tail ++ l' := by
|
||||
@[grind =] theorem tail_append {l l' : List α} : (l ++ l').tail = if l.isEmpty then l'.tail else l.tail ++ l' := by
|
||||
cases l <;> simp
|
||||
|
||||
@[simp] theorem tail_append_of_ne_nil {xs ys : List α} (h : xs ≠ []) :
|
||||
(xs ++ ys).tail = xs.tail ++ ys := by
|
||||
simp_all [tail_append]
|
||||
|
||||
@[grind] theorem set_append {s t : List α} :
|
||||
@[grind =] theorem set_append {s t : List α} :
|
||||
(s ++ t).set i x = if i < s.length then s.set i x ++ t else s ++ t.set (i - s.length) x := by
|
||||
induction s generalizing i with
|
||||
| nil => simp
|
||||
|
|
@ -1916,7 +1924,7 @@ theorem eq_nil_or_concat : ∀ l : List α, l = [] ∨ ∃ l' b, l = concat l' b
|
|||
| cons =>
|
||||
simp [flatten, length_append, *]
|
||||
|
||||
@[grind] theorem flatten_singleton {l : List α} : [l].flatten = l := by simp
|
||||
@[grind =] theorem flatten_singleton {l : List α} : [l].flatten = l := by simp
|
||||
|
||||
@[simp] theorem mem_flatten : ∀ {L : List (List α)}, a ∈ L.flatten ↔ ∃ l, l ∈ L ∧ a ∈ l
|
||||
| [] => by simp
|
||||
|
|
@ -2118,7 +2126,7 @@ theorem flatMap_singleton (f : α → List β) (x : α) : [x].flatMap f = f x :=
|
|||
@[simp] theorem flatMap_singleton' (l : List α) : (l.flatMap fun x => [x]) = l := by
|
||||
induction l <;> simp [*]
|
||||
|
||||
@[grind] theorem head?_flatMap {l : List α} {f : α → List β} :
|
||||
@[grind =] theorem head?_flatMap {l : List α} {f : α → List β} :
|
||||
(l.flatMap f).head? = l.findSome? fun a => (f a).head? := by
|
||||
induction l with
|
||||
| nil => rfl
|
||||
|
|
@ -2200,7 +2208,7 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} :
|
|||
(replicate n a)[i] = a :=
|
||||
eq_of_mem_replicate (getElem_mem _)
|
||||
|
||||
@[grind] theorem getElem?_replicate : (replicate n a)[i]? = if i < n then some a else none := by
|
||||
@[grind =] theorem getElem?_replicate : (replicate n a)[i]? = if i < n then some a else none := by
|
||||
by_cases h : i < n
|
||||
· rw [getElem?_eq_getElem (by simpa), getElem_replicate, if_pos h]
|
||||
· rw [getElem?_eq_none (by simpa using h), if_neg h]
|
||||
|
|
@ -2208,7 +2216,7 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} :
|
|||
@[simp] theorem getElem?_replicate_of_lt {n : Nat} {i : Nat} (h : i < n) : (replicate n a)[i]? = some a := by
|
||||
simp [h]
|
||||
|
||||
@[grind] theorem head?_replicate {a : α} {n : Nat} : (replicate n a).head? = if n = 0 then none else some a := by
|
||||
@[grind =] theorem head?_replicate {a : α} {n : Nat} : (replicate n a).head? = if n = 0 then none else some a := by
|
||||
cases n <;> simp [replicate_succ]
|
||||
|
||||
@[simp] theorem head_replicate (w : replicate n a ≠ []) : (replicate n a).head w = a := by
|
||||
|
|
@ -2297,7 +2305,7 @@ theorem replicate_eq_append_iff {l₁ l₂ : List α} {a : α} :
|
|||
simp only [getElem?_map, getElem?_replicate]
|
||||
split <;> simp
|
||||
|
||||
@[grind] theorem filter_replicate : (replicate n a).filter p = if p a then replicate n a else [] := by
|
||||
@[grind =] theorem filter_replicate : (replicate n a).filter p = if p a then replicate n a else [] := by
|
||||
cases n with
|
||||
| zero => simp
|
||||
| succ n =>
|
||||
|
|
@ -2533,10 +2541,10 @@ theorem flatten_reverse {L : List (List α)} :
|
|||
L.reverse.flatten = (L.map reverse).flatten.reverse := by
|
||||
induction L <;> simp_all
|
||||
|
||||
@[grind] theorem reverse_flatMap {β} {l : List α} {f : α → List β} : (l.flatMap f).reverse = l.reverse.flatMap (reverse ∘ f) := by
|
||||
@[grind =] theorem reverse_flatMap {β} {l : List α} {f : α → List β} : (l.flatMap f).reverse = l.reverse.flatMap (reverse ∘ f) := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[grind] theorem flatMap_reverse {β} {l : List α} {f : α → List β} : (l.reverse.flatMap f) = (l.flatMap (reverse ∘ f)).reverse := by
|
||||
@[grind =] theorem flatMap_reverse {β} {l : List α} {f : α → List β} : (l.reverse.flatMap f) = (l.flatMap (reverse ∘ f)).reverse := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[simp] theorem reverseAux_eq {as bs : List α} : reverseAux as bs = reverse as ++ bs :=
|
||||
|
|
@ -2598,9 +2606,7 @@ theorem id_run_foldrM {f : α → β → Id β} {b : β} {l : List α} :
|
|||
|
||||
/-! ### foldl and foldr -/
|
||||
|
||||
-- TODO: a multi-pattern is being selected there because E-matching does not go inside lambdas.
|
||||
-- foldr_cons_eq_append: [@foldr #4 (List #3) _ #0 #2, @map _ _ #1 #2]
|
||||
@[simp, grind] theorem foldr_cons_eq_append {l : List α} {f : α → β} {l' : List β} :
|
||||
@[simp] theorem foldr_cons_eq_append {l : List α} {f : α → β} {l' : List β} :
|
||||
l.foldr (fun x ys => f x :: ys) l' = l.map f ++ l' := by
|
||||
induction l <;> simp [*]
|
||||
|
||||
|
|
@ -2609,34 +2615,28 @@ theorem id_run_foldrM {f : α → β → Id β} {b : β} {l : List α} :
|
|||
l.foldr cons l' = l ++ l' := by
|
||||
induction l <;> simp [*]
|
||||
|
||||
-- TODO: a multi-pattern is being selected there because E-matching does not go inside lambdas.
|
||||
-- foldl_flip_cons_eq_append: [@foldl (List #3) #4 _ #0 #2, @map _ _ #1 #2]
|
||||
@[simp, grind] theorem foldl_flip_cons_eq_append {l : List α} {f : α → β} {l' : List β} :
|
||||
@[simp] theorem foldl_flip_cons_eq_append {l : List α} {f : α → β} {l' : List β} :
|
||||
l.foldl (fun xs y => f y :: xs) l' = (l.map f).reverse ++ l' := by
|
||||
induction l generalizing l' <;> simp [*]
|
||||
|
||||
/-- Variant of `foldl_flip_cons_eq_append` specalized to `f = id`. -/
|
||||
@[grind] theorem foldl_flip_cons_eq_append' {l l' : List α} :
|
||||
theorem foldl_flip_cons_eq_append' {l l' : List α} :
|
||||
l.foldl (fun xs y => y :: xs) l' = l.reverse ++ l' := by
|
||||
simp
|
||||
|
||||
-- TODO: a multi-pattern is being selected there because E-matching does not go inside lambdas.
|
||||
@[simp, grind] theorem foldr_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
@[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 [*]
|
||||
|
||||
-- TODO: a multi-pattern is being selected there because E-matching does not go inside lambdas.
|
||||
@[simp, grind] theorem foldl_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
@[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 [*]
|
||||
|
||||
-- TODO: a multi-pattern is being selected there because E-matching does not go inside lambdas.
|
||||
@[simp, grind] theorem foldr_flip_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
@[simp] theorem foldr_flip_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
l.foldr (fun x ys => ys ++ f x) l' = l' ++ (l.map f).reverse.flatten := by
|
||||
induction l generalizing l' <;> simp [*]
|
||||
|
||||
-- TODO: a multi-pattern is being selected there because E-matching does not go inside lambdas.
|
||||
@[simp, grind] theorem foldl_flip_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
@[simp] theorem foldl_flip_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
l.foldl (fun xs y => f y ++ xs) l' = (l.map f).reverse.flatten ++ l' := by
|
||||
induction l generalizing l' <;> simp [*]
|
||||
|
||||
|
|
@ -2690,11 +2690,11 @@ theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β →
|
|||
@[simp, grind _=_] theorem foldr_append {f : α → β → β} {b : β} {l l' : List α} :
|
||||
(l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM, -foldrM_pure]
|
||||
|
||||
@[grind] theorem foldl_flatten {f : β → α → β} {b : β} {L : List (List α)} :
|
||||
@[grind =] theorem foldl_flatten {f : β → α → β} {b : β} {L : List (List α)} :
|
||||
(flatten L).foldl f b = L.foldl (fun b l => l.foldl f b) b := by
|
||||
induction L generalizing b <;> simp_all
|
||||
|
||||
@[grind] theorem foldr_flatten {f : α → β → β} {b : β} {L : List (List α)} :
|
||||
@[grind =] theorem foldr_flatten {f : α → β → β} {b : β} {L : List (List α)} :
|
||||
(flatten L).foldr f b = L.foldr (fun l b => l.foldr f b) b := by
|
||||
induction L <;> simp_all
|
||||
|
||||
|
|
@ -2899,7 +2899,7 @@ theorem head_eq_getLast_reverse {l : List α} (h : l ≠ []) :
|
|||
simp only [getLast_eq_head_reverse, reverse_append]
|
||||
rw [head_append_of_ne_nil]
|
||||
|
||||
@[grind] theorem getLast_append {l : List α} (h : l ++ l' ≠ []) :
|
||||
@[grind =] theorem getLast_append {l : List α} (h : l ++ l' ≠ []) :
|
||||
(l ++ l').getLast h =
|
||||
if h' : l'.isEmpty then
|
||||
l.getLast (by simp_all [isEmpty_iff])
|
||||
|
|
@ -2985,6 +2985,10 @@ theorem contains_iff_exists_mem_beq [BEq α] {l : List α} {a : α} :
|
|||
l.contains a ↔ ∃ a' ∈ l, a == a' := by
|
||||
induction l <;> simp_all
|
||||
|
||||
-- We add this as a `grind` lemma because it is useful without `LawfulBEq α`.
|
||||
-- With `LawfulBEq α`, it would be better to use `contains_iff_mem` directly.
|
||||
grind_pattern contains_iff_exists_mem_beq => l.contains a
|
||||
|
||||
@[grind _=_]
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
l.contains a ↔ a ∈ l := by
|
||||
|
|
@ -3078,7 +3082,7 @@ are often used for theorems about `Array.pop`.
|
|||
| _ :: _ :: _, 0, _ => rfl
|
||||
| _ :: _ :: _, _ + 1, h => getElem_dropLast (Nat.add_one_lt_add_one_iff.mp h)
|
||||
|
||||
@[grind] theorem getElem?_dropLast {xs : List α} {i : Nat} :
|
||||
@[grind =] theorem getElem?_dropLast {xs : List α} {i : Nat} :
|
||||
xs.dropLast[i]? = if i < xs.length - 1 then xs[i]? else none := by
|
||||
split
|
||||
· rw [getElem?_eq_getElem, getElem?_eq_getElem, getElem_dropLast]
|
||||
|
|
@ -3350,7 +3354,7 @@ variable [BEq α]
|
|||
simp only [replace_cons]
|
||||
split <;> simp_all
|
||||
|
||||
@[grind] theorem getElem?_replace [LawfulBEq α] {l : List α} {i : Nat} :
|
||||
@[grind =] theorem getElem?_replace [LawfulBEq α] {l : List α} {i : Nat} :
|
||||
(l.replace a b)[i]? = if l[i]? == some a then if a ∈ l.take i then some a else some b else l[i]? := by
|
||||
induction l generalizing i with
|
||||
| nil => cases i <;> simp
|
||||
|
|
@ -3363,7 +3367,7 @@ theorem getElem?_replace_of_ne [LawfulBEq α] {l : List α} {i : Nat} (h : l[i]?
|
|||
(l.replace a b)[i]? = l[i]? := by
|
||||
simp_all [getElem?_replace]
|
||||
|
||||
@[grind] theorem getElem_replace [LawfulBEq α] {l : List α} {i : Nat} (h : i < l.length) :
|
||||
@[grind =] theorem getElem_replace [LawfulBEq α] {l : List α} {i : Nat} (h : i < l.length) :
|
||||
(l.replace a b)[i]'(by simpa) = if l[i] == a then if a ∈ l.take i then a else b else l[i] := by
|
||||
apply Option.some.inj
|
||||
rw [← getElem?_eq_getElem, getElem?_replace]
|
||||
|
|
@ -3393,7 +3397,7 @@ theorem head_replace {l : List α} {a b : α} (w) :
|
|||
apply Option.some.inj
|
||||
rw [← head?_eq_head, head?_replace, head?_eq_head]
|
||||
|
||||
@[grind] theorem replace_append [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
@[grind =] theorem replace_append [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
(l₁ ++ l₂).replace a b = if a ∈ l₁ then l₁.replace a b ++ l₂ else l₁ ++ l₂.replace a b := by
|
||||
induction l₁ with
|
||||
| nil => simp
|
||||
|
|
@ -3480,7 +3484,7 @@ theorem eq_or_mem_of_mem_insert {l : List α} (h : a ∈ l.insert b) : a = b ∨
|
|||
@[simp] theorem length_insert_of_not_mem {l : List α} (h : a ∉ l) :
|
||||
length (l.insert a) = length l + 1 := by rw [insert_of_not_mem h]; rfl
|
||||
|
||||
@[grind] theorem length_insert {l : List α} :
|
||||
@[grind =] theorem length_insert {l : List α} :
|
||||
(l.insert a).length = l.length + if a ∈ l then 0 else 1 := by
|
||||
split <;> simp_all
|
||||
|
||||
|
|
@ -3515,13 +3519,13 @@ theorem getElem?_insert_succ {l : List α} {a : α} {i : Nat} :
|
|||
simp only [insert_eq]
|
||||
split <;> simp
|
||||
|
||||
@[grind] theorem getElem?_insert {l : List α} {a : α} {i : Nat} :
|
||||
@[grind =] theorem getElem?_insert {l : List α} {a : α} {i : Nat} :
|
||||
(l.insert a)[i]? = if a ∈ l then l[i]? else if i = 0 then some a else l[i-1]? := by
|
||||
cases i
|
||||
· simp [getElem?_insert_zero]
|
||||
· simp [getElem?_insert_succ]
|
||||
|
||||
@[grind] theorem getElem_insert {l : List α} {a : α} {i : Nat} (h : i < l.length) :
|
||||
@[grind =] theorem getElem_insert {l : List α} {a : α} {i : Nat} (h : i < l.length) :
|
||||
(l.insert a)[i]'(Nat.lt_of_lt_of_le h length_le_length_insert) =
|
||||
if a ∈ l then l[i] else if i = 0 then a else l[i-1]'(Nat.lt_of_le_of_lt (Nat.pred_le _) h) := by
|
||||
apply Option.some.inj
|
||||
|
|
@ -3545,7 +3549,7 @@ theorem head_insert {l : List α} {a : α} (w) :
|
|||
apply Option.some.inj
|
||||
rw [← head?_eq_head, head?_insert]
|
||||
|
||||
@[grind] theorem insert_append {l₁ l₂ : List α} {a : α} :
|
||||
@[grind =] theorem insert_append {l₁ l₂ : List α} {a : α} :
|
||||
(l₁ ++ l₂).insert a = if a ∈ l₂ then l₁ ++ l₂ else l₁.insert a ++ l₂ := by
|
||||
simp only [insert_eq, mem_append]
|
||||
(repeat split) <;> simp_all
|
||||
|
|
|
|||
|
|
@ -248,11 +248,10 @@ theorem pairwise_le_range {n : Nat} : Pairwise (· ≤ ·) (range n) :=
|
|||
theorem nodup_range {n : Nat} : Nodup (range n) := by
|
||||
simp +decide only [range_eq_range', nodup_range']
|
||||
|
||||
@[simp, grind =] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat → Bool} :
|
||||
@[simp] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat → Bool} :
|
||||
(range n).find? p = some i ↔ p i ∧ i ∈ range n ∧ ∀ j, j < i → !p j := by
|
||||
simp [range_eq_range']
|
||||
|
||||
@[grind]
|
||||
theorem find?_range_eq_none {n : Nat} {p : Nat → Bool} :
|
||||
(range n).find? p = none ↔ ∀ i, i < n → !p i := by
|
||||
simp
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : ∀ {a'}, a' ∈ l →
|
|||
(pairwise_cons.1 p).2
|
||||
|
||||
set_option linter.unusedVariables false in
|
||||
@[grind] theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail
|
||||
@[grind ←] theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail
|
||||
| [], h => h
|
||||
| _ :: _, h => h.of_cons
|
||||
|
||||
|
|
@ -103,7 +103,7 @@ theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pa
|
|||
· exact h₃.1 _ hx
|
||||
· exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy
|
||||
|
||||
@[grind] theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
|
||||
@[grind ←] theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
|
||||
|
||||
@[grind =] theorem pairwise_pair {a b : α} : Pairwise R [a, b] ↔ R a b := by simp
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
|
|||
(p : Pairwise S (map f l)) : Pairwise R l :=
|
||||
(pairwise_map.1 p).imp (H _ _)
|
||||
|
||||
@[grind] theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
|
||||
@[grind <=] theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
|
||||
(p : Pairwise R l) : Pairwise S (map f l) :=
|
||||
pairwise_map.2 <| p.imp (H _ _)
|
||||
|
||||
|
|
@ -136,7 +136,7 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
|
|||
simpa [IH, e] using fun _ =>
|
||||
⟨fun h a ha b hab => h _ _ ha hab, fun h a b ha hab => h _ ha _ hab⟩
|
||||
|
||||
@[grind] theorem Pairwise.filterMap {S : β → β → Prop} (f : α → Option β)
|
||||
@[grind <=] theorem Pairwise.filterMap {S : β → β → Prop} (f : α → Option β)
|
||||
(H : ∀ a a' : α, R a a' → ∀ b, f a = some b → ∀ b', f a' = some b' → S b b') {l : List α} (p : Pairwise R l) :
|
||||
Pairwise S (filterMap f l) :=
|
||||
pairwise_filterMap.2 <| p.imp (H _ _)
|
||||
|
|
@ -146,7 +146,7 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
|
|||
rw [← filterMap_eq_filter, pairwise_filterMap]
|
||||
simp
|
||||
|
||||
@[grind] theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
|
||||
@[grind ←] theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
|
||||
Pairwise.sublist filter_sublist
|
||||
|
||||
@[grind =] theorem pairwise_append {l₁ l₂ : List α} :
|
||||
|
|
@ -207,10 +207,10 @@ theorem pairwise_append_comm {R : α → α → Prop} (s : ∀ {x y}, R x y →
|
|||
simp
|
||||
· exact ⟨fun _ => h, Or.inr h⟩
|
||||
|
||||
@[grind] theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
|
||||
@[grind ←] theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
|
||||
h.sublist (drop_sublist _ _)
|
||||
|
||||
@[grind] theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
|
||||
@[grind ←] theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
|
||||
h.sublist (take_sublist _ _)
|
||||
|
||||
-- This theorem is not annotated with `grind` because it leads to a loop of instantiations with `Pairwise.sublist`.
|
||||
|
|
@ -266,7 +266,7 @@ theorem pairwise_of_forall_mem_list {l : List α} {r : α → α → Prop} (h :
|
|||
rintro H _ b hb rfl
|
||||
exact H b hb _ _
|
||||
|
||||
@[grind] theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β}
|
||||
@[grind <=] theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β}
|
||||
(h : ∀ x ∈ l, p x) {S : β → β → Prop}
|
||||
(hS : ∀ ⦃x⦄ (hx : p x) ⦃y⦄ (hy : p y), R x y → S (f x hx) (f y hy)) :
|
||||
Pairwise S (l.pmap f h) := by
|
||||
|
|
|
|||
|
|
@ -202,12 +202,18 @@ theorem sublist_or_mem_of_sublist (h : l <+ l₁ ++ a :: l₂) : l <+ l₁ ++ l
|
|||
protected theorem Sublist.mem (hx : a ∈ l₁) (hl : l₁ <+ l₂) : a ∈ l₂ :=
|
||||
hl.subset hx
|
||||
|
||||
@[grind] theorem Sublist.head_mem (s : ys <+ xs) (h) : ys.head h ∈ xs :=
|
||||
theorem Sublist.head_mem (s : ys <+ xs) (h) : ys.head h ∈ xs :=
|
||||
s.mem (List.head_mem h)
|
||||
|
||||
@[grind] theorem Sublist.getLast_mem (s : ys <+ xs) (h) : ys.getLast h ∈ xs :=
|
||||
grind_pattern Sublist.head_mem => ys <+ xs, ys.head h
|
||||
grind_pattern Sublist.head_mem => ys.head h ∈ xs -- This is somewhat aggressive, as it initiates sublist based reasoning.
|
||||
|
||||
theorem Sublist.getLast_mem (s : ys <+ xs) (h) : ys.getLast h ∈ xs :=
|
||||
s.mem (List.getLast_mem h)
|
||||
|
||||
grind_pattern Sublist.getLast_mem => ys <+ xs, ys.getLast h
|
||||
grind_pattern Sublist.getLast_mem => ys.getLast h ∈ xs -- This is somewhat aggressive, as it initiates sublist based reasoning.
|
||||
|
||||
instance : Trans (@Sublist α) Subset Subset :=
|
||||
⟨fun h₁ h₂ => trans h₁.subset h₂⟩
|
||||
|
||||
|
|
@ -248,12 +254,13 @@ theorem Sublist.eq_of_length_le (s : l₁ <+ l₂) (h : length l₂ ≤ length l
|
|||
theorem Sublist.length_eq (s : l₁ <+ l₂) : length l₁ = length l₂ ↔ l₁ = l₂ :=
|
||||
⟨s.eq_of_length, congrArg _⟩
|
||||
|
||||
@[grind]
|
||||
theorem tail_sublist : ∀ l : List α, tail l <+ l
|
||||
| [] => .slnil
|
||||
| a::l => sublist_cons_self a l
|
||||
|
||||
@[grind]
|
||||
grind_pattern tail_sublist => tail l <+ _
|
||||
|
||||
@[grind ←]
|
||||
protected theorem Sublist.tail : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → tail l₁ <+ tail l₂
|
||||
| _, _, slnil => .slnil
|
||||
| _, _, Sublist.cons _ h => (tail_sublist _).trans h
|
||||
|
|
@ -263,7 +270,7 @@ protected theorem Sublist.tail : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → tai
|
|||
theorem Sublist.of_cons_cons {l₁ l₂ : List α} {a b : α} (h : a :: l₁ <+ b :: l₂) : l₁ <+ l₂ :=
|
||||
h.tail
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
protected theorem Sublist.map (f : α → β) {l₁ l₂} (s : l₁ <+ l₂) : map f l₁ <+ map f l₂ := by
|
||||
induction s with
|
||||
| slnil => simp
|
||||
|
|
@ -275,7 +282,7 @@ protected theorem Sublist.map (f : α → β) {l₁ l₂} (s : l₁ <+ l₂) : m
|
|||
grind_pattern Sublist.map => l₁ <+ l₂, map f l₁
|
||||
grind_pattern Sublist.map => l₁ <+ l₂, map f l₂
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
protected theorem Sublist.filterMap (f : α → Option β) (s : l₁ <+ l₂) :
|
||||
filterMap f l₁ <+ filterMap f l₂ := by
|
||||
induction s <;> simp [filterMap_cons] <;> split <;> simp [*, cons]
|
||||
|
|
@ -283,7 +290,7 @@ protected theorem Sublist.filterMap (f : α → Option β) (s : l₁ <+ l₂) :
|
|||
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₁
|
||||
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₂
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
protected theorem Sublist.filter (p : α → Bool) {l₁ l₂} (s : l₁ <+ l₂) : filter p l₁ <+ filter p l₂ := by
|
||||
rw [← filterMap_eq_filter]; apply s.filterMap
|
||||
|
||||
|
|
@ -481,7 +488,7 @@ theorem Sublist.of_sublist_append_right (w : ∀ a, a ∈ l → a ∉ l₁) (h :
|
|||
exact fun x m => w x (mem_append_left l₂' m) (h₁.mem m)
|
||||
simp_all
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
theorem Sublist.middle {l : List α} (h : l <+ l₁ ++ l₂) (a : α) : l <+ l₁ ++ a :: l₂ := by
|
||||
rw [sublist_append_iff] at h
|
||||
obtain ⟨l₁', l₂', rfl, h₁, h₂⟩ := h
|
||||
|
|
@ -624,7 +631,7 @@ theorem flatten_sublist_iff {L : List (List α)} {l} :
|
|||
instance [DecidableEq α] (l₁ l₂ : List α) : Decidable (l₁ <+ l₂) :=
|
||||
decidable_of_iff (l₁.isSublist l₂) isSublist_iff_sublist
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
protected theorem Sublist.drop : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → ∀ i, l₁.drop i <+ l₂.drop i
|
||||
| _, _, h, 0 => h
|
||||
| _, _, h, i + 1 => by rw [← drop_tail, ← drop_tail]; exact h.tail.drop i
|
||||
|
|
@ -1108,24 +1115,36 @@ theorem infix_of_mem_flatten : ∀ {L : List (List α)}, l ∈ L → l <:+: flat
|
|||
theorem prefix_cons_inj (a) : a :: l₁ <+: a :: l₂ ↔ l₁ <+: l₂ :=
|
||||
prefix_append_right_inj [a]
|
||||
|
||||
@[grind] theorem take_prefix (i) (l : List α) : take i l <+: l :=
|
||||
theorem take_prefix (i) (l : List α) : take i l <+: l :=
|
||||
⟨_, take_append_drop _ _⟩
|
||||
|
||||
@[grind] theorem drop_suffix (i) (l : List α) : drop i l <:+ l :=
|
||||
grind_pattern take_prefix => take i l <+: _
|
||||
|
||||
theorem drop_suffix (i) (l : List α) : drop i l <:+ l :=
|
||||
⟨_, take_append_drop _ _⟩
|
||||
|
||||
@[grind] theorem take_sublist (i) (l : List α) : take i l <+ l :=
|
||||
grind_pattern drop_suffix => drop i l <+: _
|
||||
|
||||
theorem take_sublist (i) (l : List α) : take i l <+ l :=
|
||||
(take_prefix i l).sublist
|
||||
|
||||
@[grind] theorem drop_sublist (i) (l : List α) : drop i l <+ l :=
|
||||
grind_pattern take_sublist => take i l <+ l
|
||||
|
||||
theorem drop_sublist (i) (l : List α) : drop i l <+ l :=
|
||||
(drop_suffix i l).sublist
|
||||
|
||||
grind_pattern drop_sublist => drop i l <+ l
|
||||
|
||||
theorem take_subset (i) (l : List α) : take i l ⊆ l :=
|
||||
(take_sublist i l).subset
|
||||
|
||||
grind_pattern take_subset => take i l ⊆ l
|
||||
|
||||
theorem drop_subset (i) (l : List α) : drop i l ⊆ l :=
|
||||
(drop_sublist i l).subset
|
||||
|
||||
grind_pattern drop_subset => drop i l ⊆ l
|
||||
|
||||
theorem mem_of_mem_take {l : List α} (h : a ∈ l.take i) : a ∈ l :=
|
||||
take_subset _ _ h
|
||||
|
||||
|
|
@ -1138,64 +1157,84 @@ theorem drop_suffix_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l
|
|||
|
||||
-- See `Init.Data.List.Nat.TakeDrop` for `take_prefix_take_left`.
|
||||
|
||||
@[grind] theorem drop_sublist_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l <+ drop i l :=
|
||||
@[grind ←] theorem drop_sublist_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l <+ drop i l :=
|
||||
(drop_suffix_drop_left l h).sublist
|
||||
|
||||
@[grind] theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l ⊆ drop i l :=
|
||||
@[grind ←] theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l ⊆ drop i l :=
|
||||
(drop_sublist_drop_left l h).subset
|
||||
|
||||
@[grind] theorem takeWhile_prefix (p : α → Bool) : l.takeWhile p <+: l :=
|
||||
theorem takeWhile_prefix (p : α → Bool) : l.takeWhile p <+: l :=
|
||||
⟨l.dropWhile p, takeWhile_append_dropWhile⟩
|
||||
|
||||
@[grind] theorem dropWhile_suffix (p : α → Bool) : l.dropWhile p <:+ l :=
|
||||
grind_pattern takeWhile_prefix => l.takeWhile p <+: _
|
||||
|
||||
theorem dropWhile_suffix (p : α → Bool) : l.dropWhile p <:+ l :=
|
||||
⟨l.takeWhile p, takeWhile_append_dropWhile⟩
|
||||
|
||||
@[grind] theorem takeWhile_sublist (p : α → Bool) : l.takeWhile p <+ l :=
|
||||
grind_pattern dropWhile_suffix => l.dropWhile p <+: _
|
||||
|
||||
theorem takeWhile_sublist (p : α → Bool) : l.takeWhile p <+ l :=
|
||||
(takeWhile_prefix p).sublist
|
||||
|
||||
@[grind] theorem dropWhile_sublist (p : α → Bool) : l.dropWhile p <+ l :=
|
||||
grind_pattern takeWhile_sublist => l.takeWhile p <+ _
|
||||
|
||||
theorem dropWhile_sublist (p : α → Bool) : l.dropWhile p <+ l :=
|
||||
(dropWhile_suffix p).sublist
|
||||
|
||||
grind_pattern dropWhile_sublist => l.dropWhile p <+ _
|
||||
|
||||
theorem takeWhile_subset {l : List α} (p : α → Bool) : l.takeWhile p ⊆ l :=
|
||||
(takeWhile_sublist p).subset
|
||||
|
||||
grind_pattern takeWhile_subset => l.takeWhile p ⊆ _
|
||||
|
||||
theorem dropWhile_subset {l : List α} (p : α → Bool) : l.dropWhile p ⊆ l :=
|
||||
(dropWhile_sublist p).subset
|
||||
|
||||
@[grind] theorem dropLast_prefix : ∀ l : List α, l.dropLast <+: l
|
||||
grind_pattern dropWhile_subset => l.dropWhile p ⊆ _
|
||||
|
||||
theorem dropLast_prefix : ∀ l : List α, l.dropLast <+: l
|
||||
| [] => ⟨nil, by rw [dropLast, List.append_nil]⟩
|
||||
| a :: l => ⟨_, dropLast_concat_getLast (cons_ne_nil a l)⟩
|
||||
|
||||
@[grind] theorem dropLast_sublist (l : List α) : l.dropLast <+ l :=
|
||||
grind_pattern dropLast_prefix => l.dropLast <+: _
|
||||
|
||||
theorem dropLast_sublist (l : List α) : l.dropLast <+ l :=
|
||||
(dropLast_prefix l).sublist
|
||||
|
||||
grind_pattern dropLast_sublist => l.dropLast <+ _
|
||||
|
||||
theorem dropLast_subset (l : List α) : l.dropLast ⊆ l :=
|
||||
(dropLast_sublist l).subset
|
||||
|
||||
@[grind] theorem tail_suffix (l : List α) : tail l <:+ l := by rw [← drop_one]; apply drop_suffix
|
||||
grind_pattern dropLast_subset => l.dropLast ⊆ _
|
||||
|
||||
@[grind] theorem IsPrefix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) : l₁.map f <+: l₂.map f := by
|
||||
theorem tail_suffix (l : List α) : tail l <:+ l := by rw [← drop_one]; apply drop_suffix
|
||||
|
||||
grind_pattern tail_suffix => tail l <+: _
|
||||
|
||||
@[grind ←] theorem IsPrefix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) : l₁.map f <+: l₂.map f := by
|
||||
obtain ⟨r, rfl⟩ := h
|
||||
rw [map_append]; apply prefix_append
|
||||
|
||||
grind_pattern IsPrefix.map => l₁ <+: l₂, l₁.map f
|
||||
grind_pattern IsPrefix.map => l₁ <+: l₂, l₂.map f
|
||||
|
||||
@[grind] theorem IsSuffix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) : l₁.map f <:+ l₂.map f := by
|
||||
@[grind ←] theorem IsSuffix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) : l₁.map f <:+ l₂.map f := by
|
||||
obtain ⟨r, rfl⟩ := h
|
||||
rw [map_append]; apply suffix_append
|
||||
|
||||
grind_pattern IsSuffix.map => l₁ <:+ l₂, l₁.map f
|
||||
grind_pattern IsSuffix.map => l₁ <:+ l₂, l₂.map f
|
||||
|
||||
@[grind] theorem IsInfix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) : l₁.map f <:+: l₂.map f := by
|
||||
@[grind ←] theorem IsInfix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) : l₁.map f <:+: l₂.map f := by
|
||||
obtain ⟨r₁, r₂, rfl⟩ := h
|
||||
rw [map_append, map_append]; apply infix_append
|
||||
|
||||
grind_pattern IsInfix.map => l₁ <:+: l₂, l₁.map f
|
||||
grind_pattern IsInfix.map => l₁ <:+: l₂, l₂.map f
|
||||
|
||||
@[grind] theorem IsPrefix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
@[grind ←] theorem IsPrefix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
l₁.filter p <+: l₂.filter p := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filter_append]; apply prefix_append
|
||||
|
|
@ -1203,7 +1242,7 @@ grind_pattern IsInfix.map => l₁ <:+: l₂, l₂.map f
|
|||
grind_pattern IsPrefix.filter => l₁ <+: l₂, l₁.filter p
|
||||
grind_pattern IsPrefix.filter => l₁ <+: l₂, l₂.filter p
|
||||
|
||||
@[grind] theorem IsSuffix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
@[grind ←] theorem IsSuffix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
l₁.filter p <:+ l₂.filter p := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filter_append]; apply suffix_append
|
||||
|
|
@ -1211,7 +1250,7 @@ grind_pattern IsPrefix.filter => l₁ <+: l₂, l₂.filter p
|
|||
grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₁.filter p
|
||||
grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₂.filter p
|
||||
|
||||
@[grind] theorem IsInfix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
@[grind ←] theorem IsInfix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
l₁.filter p <:+: l₂.filter p := by
|
||||
obtain ⟨xs, ys, rfl⟩ := h
|
||||
rw [filter_append, filter_append]; apply infix_append _
|
||||
|
|
@ -1219,7 +1258,7 @@ grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₂.filter p
|
|||
grind_pattern IsInfix.filter => l₁ <:+: l₂, l₁.filter p
|
||||
grind_pattern IsInfix.filter => l₁ <:+: l₂, l₂.filter p
|
||||
|
||||
@[grind] theorem IsPrefix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
@[grind ←] theorem IsPrefix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
filterMap f l₁ <+: filterMap f l₂ := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filterMap_append]; apply prefix_append
|
||||
|
|
@ -1227,7 +1266,7 @@ grind_pattern IsInfix.filter => l₁ <:+: l₂, l₂.filter p
|
|||
grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₁
|
||||
grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₂
|
||||
|
||||
@[grind] theorem IsSuffix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
@[grind ←] theorem IsSuffix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
filterMap f l₁ <:+ filterMap f l₂ := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filterMap_append]; apply suffix_append
|
||||
|
|
@ -1235,7 +1274,7 @@ grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₂
|
|||
grind_pattern IsSuffix.filterMap => l₁ <:+ l₂, filterMap f l₁
|
||||
grind_pattern IsSuffix.filterMap => l₁ <:+ l₂, filterMap f l₂
|
||||
|
||||
@[grind] theorem IsInfix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
@[grind ←] theorem IsInfix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
filterMap f l₁ <:+: filterMap f l₂ := by
|
||||
obtain ⟨xs, ys, rfl⟩ := h
|
||||
rw [filterMap_append, filterMap_append]; apply infix_append
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ theorem attach_eq_some : ∀ (o : Option α) (x : {x // o = some x}), o.attach =
|
|||
| none, ⟨x, h⟩ => by simp at h
|
||||
| some a, ⟨x, h⟩ => by simpa using h
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
theorem mem_attach : ∀ (o : Option α) (x : {x // o = some x}), x ∈ o.attach :=
|
||||
attach_eq_some
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Option
|
|||
@[deprecated mem_def (since := "2025-04-07")]
|
||||
theorem mem_iff {a : α} {b : Option α} : a ∈ b ↔ b = some a := .rfl
|
||||
|
||||
@[grind] theorem mem_some {a b : α} : a ∈ some b ↔ b = a := by simp
|
||||
@[grind =] theorem mem_some {a b : α} : a ∈ some b ↔ b = a := by simp
|
||||
|
||||
theorem mem_some_iff {a b : α} : a ∈ some b ↔ b = a := mem_some
|
||||
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ theorem LawfulEqOrd.compare_eq_iff_eq [Ord α] [LawfulEqOrd α] {a b : α} :
|
|||
LawfulEqCmp.compare_eq_iff_eq
|
||||
|
||||
/-- The corresponding lemma for `LawfulEqCmp` is `LawfulEqCmp.compare_beq_iff_eq` -/
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem LawfulEqOrd.compare_beq_iff_eq [Ord α] [LawfulEqOrd α] {a b : α} :
|
||||
compare a b == .eq ↔ a = b :=
|
||||
LawfulEqCmp.compare_beq_iff_eq
|
||||
|
|
|
|||
|
|
@ -211,12 +211,13 @@ theorem mem_pmap {p : α → Prop} {f : ∀ a, p a → β} {xs : Vector α n} {H
|
|||
b ∈ pmap f xs H ↔ ∃ (a : _) (h : a ∈ xs), f a (H a h) = b := by
|
||||
simp only [pmap_eq_map_attach, mem_map, mem_attach, true_and, Subtype.exists, eq_comm]
|
||||
|
||||
@[grind]
|
||||
theorem mem_pmap_of_mem {p : α → Prop} {f : ∀ a, p a → β} {xs : Vector α n} {H} {a} (h : a ∈ xs) :
|
||||
f a (H a h) ∈ pmap f xs H := by
|
||||
rw [mem_pmap]
|
||||
exact ⟨a, h, rfl⟩
|
||||
|
||||
grind_pattern mem_pmap_of_mem => _ ∈ pmap f xs H, a ∈ xs
|
||||
|
||||
theorem pmap_eq_self {xs : Vector α n} {p : α → Prop} {hp : ∀ (a : α), a ∈ xs → p a}
|
||||
{f : (a : α) → p a → α} : xs.pmap f hp = xs ↔ ∀ a (h : a ∈ xs), f a (hp a h) = a := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ open Nat
|
|||
@[simp, grind =] theorem findSome?_push {xs : Vector α n} : (xs.push a).findSome? f = (xs.findSome? f).or (f a) := by
|
||||
cases xs; simp
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem findSome?_singleton {a : α} {f : α → Option β} : #v[a].findSome? f = f a := by
|
||||
simp
|
||||
|
||||
|
|
@ -228,11 +228,12 @@ theorem mem_of_find?_eq_some {xs : Vector α n} (h : find? p xs = some a) : a
|
|||
simp at h
|
||||
simpa using Array.mem_of_find?_eq_some h
|
||||
|
||||
@[grind]
|
||||
theorem get_find?_mem {xs : Vector α n} (h) : (xs.find? p).get h ∈ xs := by
|
||||
cases xs
|
||||
simp [Array.get_find?_mem]
|
||||
|
||||
grind_pattern get_find?_mem => (xs.find? p).get h
|
||||
|
||||
@[simp, grind =] theorem find?_map {f : β → α} {xs : Vector β n} :
|
||||
find? p (xs.map f) = (xs.find? (p ∘ f)).map f := by
|
||||
cases xs; simp
|
||||
|
|
|
|||
|
|
@ -789,7 +789,7 @@ theorem singleton_inj : #v[a] = #v[b] ↔ a = b := by
|
|||
@[deprecated replicate_zero (since := "2025-03-18")]
|
||||
abbrev replicate_mkVector := @replicate_zero
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem replicate_succ : replicate (n + 1) a = (replicate n a).push a := by
|
||||
simp [replicate, Array.replicate_succ]
|
||||
|
||||
|
|
@ -895,7 +895,7 @@ theorem getElem?_push_size {xs : Vector α n} {x : α} : (xs.push x)[n]? = some
|
|||
theorem getElem_singleton {a : α} (h : i < 1) : #v[a][i] = a := by
|
||||
simp
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a else none := by
|
||||
simp [List.getElem?_singleton]
|
||||
|
||||
|
|
@ -907,14 +907,21 @@ theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a
|
|||
|
||||
theorem not_mem_empty (a : α) : ¬ a ∈ #v[] := nofun
|
||||
|
||||
@[simp] theorem mem_push {xs : Vector α n} {x y : α} : x ∈ xs.push y ↔ x ∈ xs ∨ x = y := by
|
||||
@[simp, grind =] theorem mem_push {xs : Vector α n} {x y : α} : x ∈ xs.push y ↔ x ∈ xs ∨ x = y := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[grind] theorem mem_or_eq_of_mem_push {a b : α} {xs : Vector α n} :
|
||||
theorem mem_or_eq_of_mem_push {a b : α} {xs : Vector α n} :
|
||||
a ∈ xs.push b → a ∈ xs ∨ a = b := Vector.mem_push.mp
|
||||
|
||||
@[grind] theorem mem_push_self {xs : Vector α n} {x : α} : x ∈ xs.push x :=
|
||||
-- This pattern may be excessively general:
|
||||
-- it fires anytime we ae thinking about membership of vectors,
|
||||
-- and constructing a list via `push`, even if the elements are unrelated.
|
||||
-- Nevertheless in practice it is quite helpful!
|
||||
grind_pattern mem_or_eq_of_mem_push => xs.push b, a ∈ xs
|
||||
|
||||
|
||||
theorem mem_push_self {xs : Vector α n} {x : α} : x ∈ xs.push x :=
|
||||
mem_push.2 (Or.inr rfl)
|
||||
|
||||
theorem eq_push_append_of_mem {xs : Vector α n} {x : α} (h : x ∈ xs) :
|
||||
|
|
@ -926,7 +933,7 @@ theorem eq_push_append_of_mem {xs : Vector α n} {x : α} (h : x ∈ xs) :
|
|||
obtain rfl := h
|
||||
exact ⟨_, _, as.toVector, bs.toVector, by simp, by simp, by simpa using w⟩
|
||||
|
||||
@[grind] theorem mem_push_of_mem {xs : Vector α n} {x : α} (y : α) (h : x ∈ xs) : x ∈ xs.push y :=
|
||||
theorem mem_push_of_mem {xs : Vector α n} {x : α} (y : α) (h : x ∈ xs) : x ∈ xs.push y :=
|
||||
mem_push.2 (Or.inl h)
|
||||
|
||||
theorem exists_mem_of_size_pos {xs : Vector α n} (h : 0 < n) : ∃ x, x ∈ xs := by
|
||||
|
|
@ -1213,7 +1220,7 @@ theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} :
|
|||
instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a ∈ as) :=
|
||||
decidable_of_decidable_of_iff contains_iff
|
||||
|
||||
@[grind] theorem contains_empty [BEq α] : (#v[] : Vector α 0).contains a = false := by simp
|
||||
@[grind =] theorem contains_empty [BEq α] : (#v[] : Vector α 0).contains a = false := by simp
|
||||
|
||||
@[simp, grind =] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {as : Vector α n} :
|
||||
as.contains a = decide (a ∈ as) := by
|
||||
|
|
@ -1236,7 +1243,7 @@ instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a ∈
|
|||
|
||||
/-! ### set -/
|
||||
|
||||
@[grind] theorem getElem_set {xs : Vector α n} {i : Nat} {x : α} (hi : i < n) {j : Nat} (hj : j < n) :
|
||||
@[grind =] theorem getElem_set {xs : Vector α n} {i : Nat} {x : α} (hi : i < n) {j : Nat} (hj : j < n) :
|
||||
(xs.set i x hi)[j] = if i = j then x else xs[j] := by
|
||||
cases xs
|
||||
split <;> simp_all
|
||||
|
|
@ -1249,7 +1256,7 @@ instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a ∈
|
|||
@[simp] theorem getElem_set_ne {xs : Vector α n} {x : α} (hi : i < n) (hj : j < n) (h : i ≠ j) :
|
||||
(xs.set i x hi)[j] = xs[j] := by simp [getElem_set, h]
|
||||
|
||||
@[grind] theorem getElem?_set {xs : Vector α n} {x : α} (hi : i < n) :
|
||||
@[grind =] theorem getElem?_set {xs : Vector α n} {x : α} (hi : i < n) :
|
||||
(xs.set i x hi)[j]? = if i = j then some x else xs[j]? := by
|
||||
cases xs
|
||||
split <;> simp_all
|
||||
|
|
@ -1297,7 +1304,7 @@ grind_pattern mem_or_eq_of_mem_set => a ∈ xs.set i b
|
|||
@[simp, grind =] theorem setIfInBounds_empty {i : Nat} {a : α} :
|
||||
#v[].setIfInBounds i a = #v[] := rfl
|
||||
|
||||
@[grind] theorem getElem_setIfInBounds {xs : Vector α n} {x : α} (hj : j < n) :
|
||||
@[grind =] theorem getElem_setIfInBounds {xs : Vector α n} {x : α} (hj : j < n) :
|
||||
(xs.setIfInBounds i x)[j] = if i = j then x else xs[j] := by
|
||||
cases xs
|
||||
split <;> simp_all
|
||||
|
|
@ -1310,7 +1317,7 @@ grind_pattern mem_or_eq_of_mem_set => a ∈ xs.set i b
|
|||
@[simp] theorem getElem_setIfInBounds_ne {xs : Vector α n} {x : α} (hj : j < n) (h : i ≠ j) :
|
||||
(xs.setIfInBounds i x)[j] = xs[j] := by simp [getElem_setIfInBounds, h]
|
||||
|
||||
@[grind] theorem getElem?_setIfInBounds {xs : Vector α n} {x : α} :
|
||||
@[grind =] theorem getElem?_setIfInBounds {xs : Vector α n} {x : α} :
|
||||
(xs.setIfInBounds i x)[j]? = if i = j then if i < n then some x else none else xs[j]? := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.getElem?_setIfInBounds]
|
||||
|
|
@ -1410,16 +1417,16 @@ abbrev mkVector_beq_mkVector := @replicate_beq_replicate
|
|||
|
||||
/-! ### back -/
|
||||
|
||||
@[grind] theorem back_singleton {a : α} : #v[a].back = a := by simp
|
||||
@[grind =] theorem back_singleton {a : α} : #v[a].back = a := by simp
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem back_eq_getElem [NeZero n] {xs : Vector α n} : xs.back = xs[n - 1]'(by have := NeZero.ne n; omega) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.back_eq_getElem]
|
||||
|
||||
@[grind] theorem back?_empty : (#v[] : Vector α 0).back? = none := by simp
|
||||
@[grind =] theorem back?_empty : (#v[] : Vector α 0).back? = none := by simp
|
||||
|
||||
@[grind] theorem back?_eq_getElem? {xs : Vector α n} : xs.back? = xs[n - 1]? := by
|
||||
@[grind =] theorem back?_eq_getElem? {xs : Vector α n} : xs.back? = xs[n - 1]? := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.back?_eq_getElem?]
|
||||
|
||||
|
|
@ -1441,7 +1448,7 @@ theorem back_eq_getElem [NeZero n] {xs : Vector α n} : xs.back = xs[n - 1]'(by
|
|||
simp
|
||||
|
||||
/-- The empty vector maps to the empty vector. -/
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem map_empty {f : α → β} : map f #v[] = #v[] := by
|
||||
simp
|
||||
|
||||
|
|
@ -1665,7 +1672,7 @@ theorem empty_append {xs : Vector α n} : (#v[] : Vector α 0) ++ xs = xs.cast (
|
|||
theorem append_empty {xs : Vector α n} : xs ++ (#v[] : Vector α 0) = xs := by
|
||||
rw [← toArray_inj, toArray_append, Array.append_empty]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getElem_append {xs : Vector α n} {ys : Vector α m} (hi : i < n + m) :
|
||||
(xs ++ ys)[i] = if h : i < n then xs[i] else ys[i - n] := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
|
@ -1692,7 +1699,7 @@ theorem getElem?_append_right {xs : Vector α n} {ys : Vector α m} (h : n ≤ i
|
|||
rcases ys with ⟨ys, rfl⟩
|
||||
simp [Array.getElem?_append_right, h]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getElem?_append {xs : Vector α n} {ys : Vector α m} {i : Nat} :
|
||||
(xs ++ ys)[i]? = if i < n then xs[i]? else ys[i - n]? := by
|
||||
split <;> rename_i h
|
||||
|
|
@ -1779,14 +1786,14 @@ theorem append_eq_append_iff {ws : Vector α n} {xs : Vector α m} {ys : Vector
|
|||
simp [Array.append_assoc]
|
||||
|
||||
-- Variant for rewriting the other direction: we can't use `append_assoc` as it has a `cast` on the right-hand side.
|
||||
@[grind] theorem append_assoc_symm {xs : Vector α n} {ys : Vector α m} {zs : Vector α k} :
|
||||
@[grind =] theorem append_assoc_symm {xs : Vector α n} {ys : Vector α m} {zs : Vector α k} :
|
||||
xs ++ (ys ++ zs) = ((xs ++ ys) ++ zs).cast (by omega) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
rcases zs with ⟨zs, rfl⟩
|
||||
simp [Array.append_assoc]
|
||||
|
||||
@[grind] theorem set_append {xs : Vector α n} {ys : Vector α m} {i : Nat} {x : α} (h : i < n + m) :
|
||||
@[grind =] theorem set_append {xs : Vector α n} {ys : Vector α m} {i : Nat} {x : α} (h : i < n + m) :
|
||||
(xs ++ ys).set i x =
|
||||
if h' : i < n then
|
||||
xs.set i x ++ ys
|
||||
|
|
@ -1806,7 +1813,7 @@ theorem append_eq_append_iff {ws : Vector α n} {xs : Vector α m} {ys : Vector
|
|||
(xs ++ ys).set i x = xs ++ ys.set (i - n) x := by
|
||||
rw [set_append, dif_neg (by omega)]
|
||||
|
||||
@[grind] theorem setIfInBounds_append {xs : Vector α n} {ys : Vector α m} {i : Nat} {x : α} :
|
||||
@[grind =] theorem setIfInBounds_append {xs : Vector α n} {ys : Vector α m} {i : Nat} {x : α} :
|
||||
(xs ++ ys).setIfInBounds i x =
|
||||
if i < n then
|
||||
xs.setIfInBounds i x ++ ys
|
||||
|
|
@ -1928,11 +1935,11 @@ theorem forall_mem_flatten {p : α → Prop} {xss : Vector (Vector α n) m} :
|
|||
induction xss₂ using vector₂_induction
|
||||
simp
|
||||
|
||||
@[grind] theorem append_flatten {xss₁ : Vector (Vector α n) m₁} {xss₂ : Vector (Vector α n) m₂} :
|
||||
@[grind =] theorem append_flatten {xss₁ : Vector (Vector α n) m₁} {xss₂ : Vector (Vector α n) m₂} :
|
||||
flatten xss₁ ++ flatten xss₂ = (flatten (xss₁ ++ xss₂)).cast (by simp [Nat.add_mul]) := by
|
||||
simp
|
||||
|
||||
@[grind] theorem flatten_push {xss : Vector (Vector α n) m} {xs : Vector α n} :
|
||||
@[grind =] theorem flatten_push {xss : Vector (Vector α n) m} {xs : Vector α n} :
|
||||
flatten (xss.push xs) = (flatten xss ++ xs).cast (by simp [Nat.add_mul]) := by
|
||||
induction xss using vector₂_induction
|
||||
rcases xs with ⟨xs⟩
|
||||
|
|
@ -2101,7 +2108,7 @@ abbrev forall_mem_mkVector := @forall_mem_replicate
|
|||
@[deprecated getElem_replicate (since := "2025-03-18")]
|
||||
abbrev getElem_mkVector := @getElem_replicate
|
||||
|
||||
@[grind] theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by
|
||||
@[grind =] theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by
|
||||
simp [getElem?_def]
|
||||
|
||||
@[deprecated getElem?_replicate (since := "2025-03-18")]
|
||||
|
|
@ -2285,7 +2292,7 @@ theorem reverse_eq_iff {xs ys : Vector α n} : xs.reverse = ys ↔ xs = ys.rever
|
|||
rcases ys with ⟨ys, rfl⟩
|
||||
simp [Array.reverse_append]
|
||||
|
||||
@[grind] theorem append_reverse {xs : Vector α n} {ys : Vector α m} :
|
||||
@[grind =] theorem append_reverse {xs : Vector α n} {ys : Vector α m} :
|
||||
ys.reverse ++ xs.reverse = (xs ++ ys).reverse.cast (by omega) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
|
|
@ -2345,7 +2352,7 @@ set_option linter.indexVariables false in
|
|||
rcases as with ⟨as, rfl⟩
|
||||
simp
|
||||
|
||||
@[grind] theorem extract_empty {start stop : Nat} :
|
||||
@[grind =] theorem extract_empty {start stop : Nat} :
|
||||
(#v[] : Vector α 0).extract start stop = #v[].cast (by simp) := by
|
||||
simp
|
||||
|
||||
|
|
@ -2361,7 +2368,7 @@ theorem foldlM_empty [Monad m] {f : β → α → m β} {init : β} :
|
|||
foldlM f init #v[] = return init := by
|
||||
simp
|
||||
|
||||
@[grind] theorem foldrM_empty [Monad m] {f : α → β → m β} {init : β} :
|
||||
@[grind =] theorem foldrM_empty [Monad m] {f : α → β → m β} {init : β} :
|
||||
foldrM f init #v[] = return init := by
|
||||
simp
|
||||
|
||||
|
|
@ -2417,9 +2424,9 @@ theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Vector α n} :
|
|||
|
||||
/-! ### foldl / foldr -/
|
||||
|
||||
@[grind] theorem foldl_empty {f : β → α → β} {init : β} : (#v[].foldl f init) = init := rfl
|
||||
@[grind =] theorem foldl_empty {f : β → α → β} {init : β} : (#v[].foldl f init) = init := rfl
|
||||
|
||||
@[grind] theorem foldr_empty {f : α → β → β} {init : β} : (#v[].foldr f init) = init := rfl
|
||||
@[grind =] theorem foldr_empty {f : α → β → β} {init : β} : (#v[].foldr f init) = init := rfl
|
||||
|
||||
@[congr]
|
||||
theorem foldl_congr {xs ys : Vector α n} (h₀ : xs = ys) {f g : β → α → β} (h₁ : f = g)
|
||||
|
|
@ -2598,7 +2605,7 @@ theorem back?_eq_some_iff {xs : Vector α n} {a : α} :
|
|||
simp only [mk_append_mk, back_mk]
|
||||
rw [Array.back_append_of_size_pos]
|
||||
|
||||
@[grind] theorem back_append {xs : Vector α n} {ys : Vector α m} [NeZero (n + m)] :
|
||||
@[grind =] theorem back_append {xs : Vector α n} {ys : Vector α m} [NeZero (n + m)] :
|
||||
(xs ++ ys).back =
|
||||
if h' : m = 0 then
|
||||
have : NeZero n := by subst h'; simp_all
|
||||
|
|
@ -2681,6 +2688,10 @@ theorem contains_iff_exists_mem_beq [BEq α] {xs : Vector α n} {a : α} :
|
|||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.contains_iff_exists_mem_beq]
|
||||
|
||||
-- We add this as a `grind` lemma because it is useful without `LawfulBEq α`.
|
||||
-- With `LawfulBEq α`, it would be better to use `contains_iff_mem` directly.
|
||||
grind_pattern contains_iff_exists_mem_beq => xs.contains a
|
||||
|
||||
@[grind _=_]
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Vector α n} {a : α} :
|
||||
xs.contains a ↔ a ∈ xs := by
|
||||
|
|
@ -2760,7 +2771,7 @@ defeq issues in the implicit size argument.
|
|||
@getElem (Vector α n) Nat α (fun _ i => i < n) instGetElemNatLt xs.pop i h = xs[i] :=
|
||||
getElem_pop h
|
||||
|
||||
@[grind] theorem getElem?_pop {xs : Vector α n} {i : Nat} :
|
||||
@[grind =] theorem getElem?_pop {xs : Vector α n} {i : Nat} :
|
||||
xs.pop[i]? = if i < n - 1 then xs[i]? else none := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.getElem?_pop]
|
||||
|
|
@ -2976,7 +2987,7 @@ variable [BEq α]
|
|||
|
||||
@[simp, grind =] theorem replace_empty : (#v[] : Vector α 0).replace a b = #v[] := by simp
|
||||
|
||||
@[grind] theorem replace_singleton {a b c : α} : #v[a].replace b c = #v[if a == b then c else a] := by
|
||||
@[grind =] theorem replace_singleton {a b c : α} : #v[a].replace b c = #v[if a == b then c else a] := by
|
||||
simp
|
||||
|
||||
-- This hypothesis could probably be dropped from some of the lemmas below,
|
||||
|
|
@ -2987,7 +2998,7 @@ variable [LawfulBEq α]
|
|||
rcases xs with ⟨xs, rfl⟩
|
||||
simp_all
|
||||
|
||||
@[grind] theorem getElem?_replace {xs : Vector α n} {i : Nat} :
|
||||
@[grind =] theorem getElem?_replace {xs : Vector α n} {i : Nat} :
|
||||
(xs.replace a b)[i]? = if xs[i]? == some a then if a ∈ xs.take i then some a else some b else xs[i]? := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.getElem?_replace, -beq_iff_eq]
|
||||
|
|
@ -2996,7 +3007,7 @@ theorem getElem?_replace_of_ne {xs : Vector α n} {i : Nat} (h : xs[i]? ≠ some
|
|||
(xs.replace a b)[i]? = xs[i]? := by
|
||||
simp_all [getElem?_replace]
|
||||
|
||||
@[grind] theorem getElem_replace {xs : Vector α n} {i : Nat} (h : i < n) :
|
||||
@[grind =] theorem getElem_replace {xs : Vector α n} {i : Nat} (h : i < n) :
|
||||
(xs.replace a b)[i] = if xs[i] == a then if a ∈ xs.take i then a else b else xs[i] := by
|
||||
apply Option.some.inj
|
||||
rw [← getElem?_eq_getElem, getElem?_replace]
|
||||
|
|
@ -3007,7 +3018,7 @@ theorem getElem_replace_of_ne {xs : Vector α n} {i : Nat} {h : i < n} (h' : xs[
|
|||
rw [getElem_replace h]
|
||||
simp [h']
|
||||
|
||||
@[grind] theorem replace_append {xs : Vector α n} {ys : Vector α m} :
|
||||
@[grind =] theorem replace_append {xs : Vector α n} {ys : Vector α m} :
|
||||
(xs ++ ys).replace a b = if a ∈ xs then xs.replace a b ++ ys else xs ++ ys.replace a b := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
|
|
@ -3022,7 +3033,7 @@ theorem replace_append_right {xs : Vector α n} {ys : Vector α m} (h : ¬ a ∈
|
|||
(xs ++ ys).replace a b = xs ++ ys.replace a b := by
|
||||
simp [replace_append, h]
|
||||
|
||||
@[grind] theorem replace_push {xs : Vector α n} {a b c : α} :
|
||||
@[grind =] theorem replace_push {xs : Vector α n} {a b c : α} :
|
||||
(xs.push a).replace b c = if b ∈ xs then (xs.replace b c).push a else xs.push (if b == a then c else a) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp only [push_mk, replace_mk, Array.replace_push, mem_mk]
|
||||
|
|
@ -3091,7 +3102,7 @@ theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by
|
|||
|
||||
/-! ### swap -/
|
||||
|
||||
@[grind] theorem getElem_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} (hk : k < n) :
|
||||
@[grind =] theorem getElem_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} (hk : k < n) :
|
||||
(xs.swap i j hi hj)[k] = if k = i then xs[j] else if k = j then xs[i] else xs[k] := by
|
||||
cases xs
|
||||
simp_all [Array.getElem_swap]
|
||||
|
|
@ -3108,7 +3119,7 @@ theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by
|
|||
(hi' : k ≠ i) (hj' : k ≠ j) : (xs.swap i j hi hj)[k] = xs[k] := by
|
||||
simp_all [getElem_swap]
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getElem?_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} : (xs.swap i j hi hj)[k]? =
|
||||
if j = k then some xs[i] else if i = k then some xs[j] else xs[k]? := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
|
|
|||
|
|
@ -3185,7 +3185,7 @@ theorem minKey_insert_le_self [TransCmp cmp] {k v} :
|
|||
t.contains (t.minKey he) :=
|
||||
Impl.contains_minKey t.wf
|
||||
|
||||
@[grind] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
t.minKey he ∈ t :=
|
||||
Impl.minKey_mem t.wf
|
||||
|
||||
|
|
@ -3827,7 +3827,7 @@ theorem self_le_maxKey_insert [TransCmp cmp] {k v} :
|
|||
t.contains (t.maxKey he) :=
|
||||
Impl.contains_maxKey t.wf
|
||||
|
||||
@[grind] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
t.maxKey he ∈ t :=
|
||||
Impl.maxKey_mem t.wf
|
||||
|
||||
|
|
|
|||
|
|
@ -3243,7 +3243,7 @@ theorem contains_minKey! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpt
|
|||
t.contains t.minKey! :=
|
||||
Impl.contains_minKey! h he
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
theorem minKey!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) :
|
||||
t.minKey! ∈ t :=
|
||||
Impl.minKey!_mem h he
|
||||
|
|
@ -3740,7 +3740,7 @@ theorem contains_maxKey! [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpt
|
|||
t.contains t.maxKey! :=
|
||||
Impl.contains_maxKey! h he
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
theorem maxKey!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) :
|
||||
t.maxKey! ∈ t :=
|
||||
Impl.maxKey!_mem h he
|
||||
|
|
@ -3887,7 +3887,7 @@ theorem contains_maxKeyD [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fal
|
|||
t.contains (t.maxKeyD fallback) :=
|
||||
Impl.contains_maxKeyD h he
|
||||
|
||||
@[grind]
|
||||
@[grind ←]
|
||||
theorem maxKeyD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} :
|
||||
t.maxKeyD fallback ∈ t :=
|
||||
Impl.maxKeyD_mem h he
|
||||
|
|
|
|||
|
|
@ -3317,7 +3317,7 @@ theorem minKey_insert_le_self [TransCmp cmp] {k v} :
|
|||
t.contains (t.minKey he) :=
|
||||
t.inductionOn (fun _ _ => DTreeMap.contains_minKey) he
|
||||
|
||||
@[grind] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
t.minKey he ∈ t :=
|
||||
t.inductionOn (fun _ _ => DTreeMap.minKey_mem) he
|
||||
|
||||
|
|
@ -3952,7 +3952,7 @@ theorem self_le_maxKey_insert [TransCmp cmp] {k v} :
|
|||
t.contains (t.maxKey he) :=
|
||||
t.inductionOn (fun _ _ => DTreeMap.contains_maxKey) he
|
||||
|
||||
@[grind] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
t.maxKey he ∈ t :=
|
||||
t.inductionOn (fun _ _ => DTreeMap.maxKey_mem) he
|
||||
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ theorem getD_empty [EquivBEq α] [LawfulHashable α] {a fallback : α} :
|
|||
(∅ : ExtHashSet α).getD a fallback = fallback :=
|
||||
ExtHashMap.getKeyD_empty
|
||||
|
||||
@[grind] theorem getD_insert [EquivBEq α] [LawfulHashable α] {k a fallback : α} :
|
||||
@[grind =] theorem getD_insert [EquivBEq α] [LawfulHashable α] {k a fallback : α} :
|
||||
(m.insert k).getD a fallback = if k == a ∧ ¬k ∈ m then k else m.getD a fallback :=
|
||||
ExtHashMap.getKeyD_insertIfNew
|
||||
|
||||
|
|
|
|||
|
|
@ -2077,7 +2077,7 @@ theorem minKey_insert_le_self [TransCmp cmp] {k v} :
|
|||
t.contains (t.minKey he) :=
|
||||
ExtDTreeMap.contains_minKey
|
||||
|
||||
@[grind] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
t.minKey he ∈ t :=
|
||||
ExtDTreeMap.minKey_mem
|
||||
|
||||
|
|
@ -2652,7 +2652,7 @@ theorem self_le_maxKey_insert [TransCmp cmp] {k v} :
|
|||
t.contains (t.maxKey he) :=
|
||||
ExtDTreeMap.contains_maxKey
|
||||
|
||||
@[grind] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
t.maxKey he ∈ t :=
|
||||
ExtDTreeMap.maxKey_mem
|
||||
|
||||
|
|
|
|||
|
|
@ -889,7 +889,7 @@ theorem min_insert_le_self [TransCmp cmp] {k} :
|
|||
t.contains (t.min he) :=
|
||||
ExtTreeMap.contains_minKey
|
||||
|
||||
@[grind] theorem min_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem min_mem [TransCmp cmp] {he} :
|
||||
t.min he ∈ t :=
|
||||
ExtTreeMap.minKey_mem
|
||||
|
||||
|
|
@ -986,7 +986,7 @@ theorem min!_insert_le_self [TransCmp cmp] [Inhabited α] {k} :
|
|||
t.contains t.min! :=
|
||||
ExtTreeMap.contains_minKey! (mt ext he)
|
||||
|
||||
@[grind] theorem min!_mem [TransCmp cmp] [Inhabited α] (he : t ≠ ∅) :
|
||||
@[grind ←] theorem min!_mem [TransCmp cmp] [Inhabited α] (he : t ≠ ∅) :
|
||||
t.min! ∈ t :=
|
||||
ExtTreeMap.minKey!_mem (mt ext he)
|
||||
|
||||
|
|
@ -1077,7 +1077,7 @@ theorem minD_insert_le_self [TransCmp cmp] {k fallback} :
|
|||
t.contains (t.minD fallback) :=
|
||||
ExtTreeMap.contains_minKeyD (mt ext he)
|
||||
|
||||
@[grind] theorem minD_mem [TransCmp cmp] (he : t ≠ ∅) {fallback} :
|
||||
@[grind ←] theorem minD_mem [TransCmp cmp] (he : t ≠ ∅) {fallback} :
|
||||
t.minD fallback ∈ t :=
|
||||
ExtTreeMap.minKeyD_mem (mt ext he)
|
||||
|
||||
|
|
@ -1290,7 +1290,7 @@ theorem self_le_max_insert [TransCmp cmp] {k} :
|
|||
t.contains (t.max he) :=
|
||||
ExtTreeMap.contains_maxKey
|
||||
|
||||
@[grind] theorem max_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem max_mem [TransCmp cmp] {he} :
|
||||
t.max he ∈ t :=
|
||||
ExtTreeMap.maxKey_mem
|
||||
|
||||
|
|
@ -1388,7 +1388,7 @@ theorem self_le_max!_insert [TransCmp cmp] [Inhabited α] {k} :
|
|||
t.contains t.max! :=
|
||||
ExtTreeMap.contains_maxKey! (mt ext he)
|
||||
|
||||
@[grind] theorem max!_mem [TransCmp cmp] [Inhabited α] (he : t ≠ ∅) :
|
||||
@[grind ←] theorem max!_mem [TransCmp cmp] [Inhabited α] (he : t ≠ ∅) :
|
||||
t.max! ∈ t :=
|
||||
ExtTreeMap.maxKey!_mem (mt ext he)
|
||||
|
||||
|
|
@ -1480,7 +1480,7 @@ theorem self_le_maxD_insert [TransCmp cmp] {k fallback} :
|
|||
t.contains (t.maxD fallback) :=
|
||||
ExtTreeMap.contains_maxKeyD (mt ext he)
|
||||
|
||||
@[grind] theorem maxD_mem [TransCmp cmp] (he : t ≠ ∅) {fallback} :
|
||||
@[grind ←] theorem maxD_mem [TransCmp cmp] (he : t ≠ ∅) {fallback} :
|
||||
t.maxD fallback ∈ t :=
|
||||
ExtTreeMap.maxKeyD_mem (mt ext he)
|
||||
|
||||
|
|
|
|||
|
|
@ -2093,7 +2093,7 @@ theorem minKey_insert_le_self [TransCmp cmp] {k v} :
|
|||
t.contains (t.minKey he) :=
|
||||
DTreeMap.contains_minKey
|
||||
|
||||
@[grind] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem minKey_mem [TransCmp cmp] {he} :
|
||||
t.minKey he ∈ t :=
|
||||
DTreeMap.minKey_mem
|
||||
|
||||
|
|
@ -2672,7 +2672,7 @@ theorem self_le_maxKey_insert [TransCmp cmp] {k v} :
|
|||
t.contains (t.maxKey he) :=
|
||||
DTreeMap.contains_maxKey
|
||||
|
||||
@[grind] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem maxKey_mem [TransCmp cmp] {he} :
|
||||
t.maxKey he ∈ t :=
|
||||
DTreeMap.maxKey_mem
|
||||
|
||||
|
|
|
|||
|
|
@ -1795,7 +1795,7 @@ theorem getElem?_modify_self [TransCmp cmp] (h : t.WF) {k : α} {f : β → β}
|
|||
(modify t k f)[k]? = t[k]?.map f :=
|
||||
DTreeMap.Raw.Const.get?_modify_self h
|
||||
|
||||
@[grind]
|
||||
@[grind =]
|
||||
theorem getElem_modify [TransCmp cmp] (h : t.WF) {k k' : α} {f : β → β} {hc : k' ∈ modify t k f} :
|
||||
(modify t k f)[k']'hc =
|
||||
if heq : cmp k k' = .eq then
|
||||
|
|
|
|||
|
|
@ -906,7 +906,7 @@ theorem min_insert_le_self [TransCmp cmp] {k} :
|
|||
t.contains (t.min he) :=
|
||||
TreeMap.contains_minKey
|
||||
|
||||
@[grind] theorem min_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem min_mem [TransCmp cmp] {he} :
|
||||
t.min he ∈ t :=
|
||||
TreeMap.minKey_mem
|
||||
|
||||
|
|
@ -1003,7 +1003,7 @@ theorem min!_insert_le_self [TransCmp cmp] [Inhabited α] {k} :
|
|||
t.contains t.min! :=
|
||||
TreeMap.contains_minKey! he
|
||||
|
||||
@[grind] theorem min!_mem [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) :
|
||||
@[grind ←] theorem min!_mem [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) :
|
||||
t.min! ∈ t :=
|
||||
TreeMap.minKey!_mem he
|
||||
|
||||
|
|
@ -1094,7 +1094,7 @@ theorem minD_insert_le_self [TransCmp cmp] {k fallback} :
|
|||
t.contains (t.minD fallback) :=
|
||||
TreeMap.contains_minKeyD he
|
||||
|
||||
@[grind] theorem minD_mem [TransCmp cmp] (he : t.isEmpty = false) {fallback} :
|
||||
@[grind ←] theorem minD_mem [TransCmp cmp] (he : t.isEmpty = false) {fallback} :
|
||||
t.minD fallback ∈ t :=
|
||||
TreeMap.minKeyD_mem he
|
||||
|
||||
|
|
@ -1308,7 +1308,7 @@ theorem self_le_max_insert [TransCmp cmp] {k} :
|
|||
t.contains (t.max he) :=
|
||||
TreeMap.contains_maxKey
|
||||
|
||||
@[grind] theorem max_mem [TransCmp cmp] {he} :
|
||||
@[grind ←] theorem max_mem [TransCmp cmp] {he} :
|
||||
t.max he ∈ t :=
|
||||
TreeMap.maxKey_mem
|
||||
|
||||
|
|
@ -1406,7 +1406,7 @@ theorem self_le_max!_insert [TransCmp cmp] [Inhabited α] {k} :
|
|||
t.contains t.max! :=
|
||||
TreeMap.contains_maxKey! he
|
||||
|
||||
@[grind] theorem max!_mem [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) :
|
||||
@[grind ←] theorem max!_mem [TransCmp cmp] [Inhabited α] (he : t.isEmpty = false) :
|
||||
t.max! ∈ t :=
|
||||
TreeMap.maxKey!_mem he
|
||||
|
||||
|
|
@ -1498,7 +1498,7 @@ theorem self_le_maxD_insert [TransCmp cmp] {k fallback} :
|
|||
t.contains (t.maxD fallback) :=
|
||||
TreeMap.contains_maxKeyD he
|
||||
|
||||
@[grind] theorem maxD_mem [TransCmp cmp] (he : t.isEmpty = false) {fallback} :
|
||||
@[grind ←] theorem maxD_mem [TransCmp cmp] (he : t.isEmpty = false) {fallback} :
|
||||
t.maxD fallback ∈ t :=
|
||||
TreeMap.maxKeyD_mem he
|
||||
|
||||
|
|
|
|||
|
|
@ -906,7 +906,7 @@ theorem min!_insert_le_self [TransCmp cmp] [Inhabited α] (h : t.WF) {k} :
|
|||
t.contains t.min! :=
|
||||
TreeMap.Raw.contains_minKey! h he
|
||||
|
||||
@[grind] theorem min!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) :
|
||||
@[grind ←] theorem min!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) :
|
||||
t.min! ∈ t :=
|
||||
TreeMap.Raw.minKey!_mem h he
|
||||
|
||||
|
|
@ -993,7 +993,7 @@ theorem minD_insert_le_self [TransCmp cmp] (h : t.WF) {k fallback} :
|
|||
t.contains (t.minD fallback) :=
|
||||
TreeMap.Raw.contains_minKeyD h he
|
||||
|
||||
@[grind] theorem minD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} :
|
||||
@[grind ←] theorem minD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} :
|
||||
t.minD fallback ∈ t :=
|
||||
TreeMap.Raw.minKeyD_mem h he
|
||||
|
||||
|
|
@ -1216,7 +1216,7 @@ theorem self_le_max!_insert [TransCmp cmp] [Inhabited α] (h : t.WF) {k} :
|
|||
t.contains t.max! :=
|
||||
TreeMap.Raw.contains_maxKey! h he
|
||||
|
||||
@[grind] theorem max!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) :
|
||||
@[grind ←] theorem max!_mem [TransCmp cmp] [Inhabited α] (h : t.WF) (he : t.isEmpty = false) :
|
||||
t.max! ∈ t :=
|
||||
TreeMap.Raw.maxKey!_mem h he
|
||||
|
||||
|
|
@ -1303,7 +1303,7 @@ theorem self_le_maxD_insert [TransCmp cmp] (h : t.WF) {k fallback} :
|
|||
t.contains (t.maxD fallback) :=
|
||||
TreeMap.Raw.contains_maxKeyD h he
|
||||
|
||||
@[grind] theorem maxD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} :
|
||||
@[grind ←] theorem maxD_mem [TransCmp cmp] (h : t.WF) (he : t.isEmpty = false) {fallback} :
|
||||
t.maxD fallback ∈ t :=
|
||||
TreeMap.Raw.maxKeyD_mem h he
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue