Compare commits

...

1 Commits

Author SHA1 Message Date
Kim Morrison
3d9ade01b2 feat: align List/Array/Vector.count theorems 2025-01-20 20:58:39 +11:00
10 changed files with 673 additions and 20 deletions

View File

@@ -579,9 +579,18 @@ def foldr {α : Type u} {β : Type v} (f : α → β → β) (init : β) (as : A
/-- Sum of an array.
`Array.sum #[a, b, c] = a + (b + (c + 0))` -/
@[inline]
def sum {α} [Add α] [Zero α] : Array α α :=
foldr (· + ·) 0
@[inline]
def countP {α : Type u} (p : α Bool) (as : Array α) : Nat :=
as.foldr (init := 0) fun a acc => bif p a then acc + 1 else acc
@[inline]
def count {α : Type u} [BEq α] (a : α) (as : Array α) : Nat :=
countP (· == a) as
@[inline]
def map {α : Type u} {β : Type v} (f : α β) (as : Array α) : Array β :=
Id.run <| as.mapM f

View File

@@ -0,0 +1,270 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
prelude
import Init.Data.Array.Lemmas
import Init.Data.List.Nat.Count
/-!
# Lemmas about `Array.countP` and `Array.count`.
-/
namespace Array
open Nat
/-! ### countP -/
section countP
variable (p q : α Bool)
@[simp] theorem countP_empty : countP p #[] = 0 := rfl
@[simp] theorem countP_push_of_pos (l) (pa : p a) : countP p (l.push a) = countP p l + 1 := by
rcases l with l
simp_all
@[simp] theorem countP_push_of_neg (l) (pa : ¬p a) : countP p (l.push a) = countP p l := by
rcases l with l
simp_all
theorem countP_push (a : α) (l) : countP p (l.push a) = countP p l + if p a then 1 else 0 := by
rcases l with l
simp_all
@[simp] theorem countP_singleton (a : α) : countP p #[a] = if p a then 1 else 0 := by
simp [countP_push]
theorem size_eq_countP_add_countP (l) : l.size = countP p l + countP (fun a => ¬p a) l := by
cases l
simp [List.length_eq_countP_add_countP (p := p)]
theorem countP_eq_size_filter (l) : countP p l = (filter p l).size := by
cases l
simp [List.countP_eq_length_filter]
theorem countP_eq_size_filter' : countP p = size filter p := by
funext l
apply countP_eq_size_filter
theorem countP_le_size : countP p l l.size := by
simp only [countP_eq_size_filter]
apply size_filter_le
@[simp] theorem countP_append (l₁ l₂) : countP p (l₁ ++ l₂) = countP p l₁ + countP p l₂ := by
cases l₁
cases l₂
simp
@[simp] theorem countP_pos_iff {p} : 0 < countP p l a l, p a := by
cases l
simp
@[simp] theorem one_le_countP_iff {p} : 1 countP p l a l, p a :=
countP_pos_iff
@[simp] theorem countP_eq_zero {p} : countP p l = 0 a l, ¬p a := by
cases l
simp
@[simp] theorem countP_eq_size {p} : countP p l = l.size a l, p a := by
cases l
simp
theorem countP_mkArray (p : α Bool) (a : α) (n : Nat) :
countP p (mkArray n a) = if p a then n else 0 := by
simp [ List.toArray_replicate, List.countP_replicate]
theorem boole_getElem_le_countP (p : α Bool) (l : Array α) (i : Nat) (h : i < l.size) :
(if p l[i] then 1 else 0) l.countP p := by
cases l
simp [List.boole_getElem_le_countP]
theorem countP_set (p : α Bool) (l : Array α) (i : Nat) (a : α) (h : i < l.size) :
(l.set i a).countP p = l.countP p - (if p l[i] then 1 else 0) + (if p a then 1 else 0) := by
cases l
simp [List.countP_set, h]
theorem countP_filter (l : Array α) :
countP p (filter q l) = countP (fun a => p a && q a) l := by
cases l
simp [List.countP_filter]
@[simp] theorem countP_true : (countP fun (_ : α) => true) = size := by
funext l
simp
@[simp] theorem countP_false : (countP fun (_ : α) => false) = Function.const _ 0 := by
funext l
simp
@[simp] theorem countP_map (p : β Bool) (f : α β) (l : Array α) :
countP p (map f l) = countP (p f) l := by
cases l
simp
theorem size_filterMap_eq_countP (f : α Option β) (l : Array α) :
(filterMap f l).size = countP (fun a => (f a).isSome) l := by
cases l
simp [List.length_filterMap_eq_countP]
theorem countP_filterMap (p : β Bool) (f : α Option β) (l : Array α) :
countP p (filterMap f l) = countP (fun a => ((f a).map p).getD false) l := by
cases l
simp [List.countP_filterMap]
@[simp] theorem countP_flatten (l : Array (Array α)) :
countP p l.flatten = (l.map (countP p)).sum := by
cases l using array₂_induction
simp [List.countP_flatten, Function.comp_def]
theorem countP_flatMap (p : β Bool) (l : Array α) (f : α Array β) :
countP p (l.flatMap f) = sum (map (countP p f) l) := by
cases l
simp [List.countP_flatMap, Function.comp_def]
@[simp] theorem countP_reverse (l : Array α) : countP p l.reverse = countP p l := by
cases l
simp [List.countP_reverse]
variable {p q}
theorem countP_mono_left (h : x l, p x q x) : countP p l countP q l := by
cases l
simpa using List.countP_mono_left (by simpa using h)
theorem countP_congr (h : x l, p x q x) : countP p l = countP q l :=
Nat.le_antisymm
(countP_mono_left fun x hx => (h x hx).1)
(countP_mono_left fun x hx => (h x hx).2)
end countP
/-! ### count -/
section count
variable [BEq α]
@[simp] theorem count_empty (a : α) : count a #[] = 0 := rfl
theorem count_push (a b : α) (l : Array α) :
count a (l.push b) = count a l + if b == a then 1 else 0 := by
simp [count, countP_push]
theorem count_eq_countP (a : α) (l : Array α) : count a l = countP (· == a) l := rfl
theorem count_eq_countP' {a : α} : count a = countP (· == a) := by
funext l
apply count_eq_countP
theorem count_le_size (a : α) (l : Array α) : count a l l.size := countP_le_size _
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
simp [count_eq_countP]
@[simp] theorem count_append (a : α) : l₁ l₂, count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
countP_append _
@[simp] theorem count_flatten (a : α) (l : Array (Array α)) :
count a l.flatten = (l.map (count a)).sum := by
cases l using array₂_induction
simp [List.count_flatten, Function.comp_def]
@[simp] theorem count_reverse (a : α) (l : Array α) : count a l.reverse = count a l := by
cases l
simp
theorem boole_getElem_le_count (a : α) (l : Array α) (i : Nat) (h : i < l.size) :
(if l[i] == a then 1 else 0) l.count a := by
rw [count_eq_countP]
apply boole_getElem_le_countP (· == a)
theorem count_set (a b : α) (l : Array α) (i : Nat) (h : i < l.size) :
(l.set i a).count b = l.count b - (if l[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
simp [count_eq_countP, countP_set, h]
variable [LawfulBEq α]
@[simp] theorem count_push_self (a : α) (l : Array α) : count a (l.push a) = count a l + 1 := by
simp [count_push]
@[simp] theorem count_push_of_ne (h : b a) (l : Array α) : count a (l.push b) = count a l := by
simp_all [count_push, h]
theorem count_singleton_self (a : α) : count a #[a] = 1 := by simp
@[simp]
theorem count_pos_iff {a : α} {l : Array α} : 0 < count a l a l := by
simp only [count, countP_pos_iff, beq_iff_eq, exists_eq_right]
@[simp] theorem one_le_count_iff {a : α} {l : Array α} : 1 count a l a l :=
count_pos_iff
theorem count_eq_zero_of_not_mem {a : α} {l : Array α} (h : a l) : count a l = 0 :=
Decidable.byContradiction fun h' => h <| count_pos_iff.1 (Nat.pos_of_ne_zero h')
theorem not_mem_of_count_eq_zero {a : α} {l : Array α} (h : count a l = 0) : a l :=
fun h' => Nat.ne_of_lt (count_pos_iff.2 h') h.symm
theorem count_eq_zero {l : Array α} : count a l = 0 a l :=
not_mem_of_count_eq_zero, count_eq_zero_of_not_mem
theorem count_eq_size {l : Array α} : count a l = l.size b l, a = b := by
rw [count, countP_eq_size]
refine fun h b hb => Eq.symm ?_, fun h b hb => ?_
· simpa using h b hb
· rw [h b hb, beq_self_eq_true]
@[simp] theorem count_mkArray_self (a : α) (n : Nat) : count a (mkArray n a) = n := by
simp [ List.toArray_replicate]
theorem count_mkArray (a b : α) (n : Nat) : count a (mkArray n b) = if b == a then n else 0 := by
simp [ List.toArray_replicate, List.count_replicate]
theorem filter_beq (l : Array α) (a : α) : l.filter (· == a) = mkArray (count a l) a := by
cases l
simp [List.filter_beq]
theorem filter_eq {α} [DecidableEq α] (l : Array α) (a : α) : l.filter (· = a) = mkArray (count a l) a :=
filter_beq l a
theorem mkArray_count_eq_of_count_eq_size {l : Array α} (h : count a l = l.size) :
mkArray (count a l) a = l := by
cases l
rw [ toList_inj]
simp [List.replicate_count_eq_of_count_eq_length (by simpa using h)]
@[simp] theorem count_filter {l : Array α} (h : p a) : count a (filter p l) = count a l := by
cases l
simp [List.count_filter, h]
theorem count_le_count_map [DecidableEq β] (l : Array α) (f : α β) (x : α) :
count x l count (f x) (map f l) := by
cases l
simp [List.count_le_count_map, countP_map]
theorem count_filterMap {α} [BEq β] (b : β) (f : α Option β) (l : Array α) :
count b (filterMap f l) = countP (fun a => f a == some b) l := by
cases l
simp [List.count_filterMap, countP_filterMap]
theorem count_flatMap {α} [BEq β] (l : Array α) (f : α Array β) (x : β) :
count x (l.flatMap f) = sum (map (count x f) l) := by
simp [count_eq_countP, countP_flatMap, Function.comp_def]
-- FIXME these theorems can be restored once `List.erase` and `Array.erase` have been related.
-- theorem count_erase (a b : α) (l : Array α) : count a (l.erase b) = count a l - if b == a then 1 else 0 := by
-- sorry
-- @[simp] theorem count_erase_self (a : α) (l : Array α) :
-- count a (l.erase a) = count a l - 1 := by rw [count_erase, if_pos (by simp)]
-- @[simp] theorem count_erase_of_ne (ab : a ≠ b) (l : Array α) : count a (l.erase b) = count a l := by
-- rw [count_erase, if_neg (by simpa using ab.symm), Nat.sub_zero]
end count

View File

@@ -3762,6 +3762,27 @@ namespace Array
cases a
simp
/-! ### countP and count -/
@[simp] theorem _root_.List.countP_toArray (l : List α) : countP p l.toArray = l.countP p := by
simp [countP]
induction l with
| nil => rfl
| cons head tail ih =>
simp only [List.foldr_cons, ih, List.countP_cons]
split <;> simp_all
@[simp] theorem countP_toList (as : Array α) : as.toList.countP p = countP p as := by
cases as
simp
@[simp] theorem _root_.List.count_toArray [BEq α] (l : List α) (a : α) : count a l.toArray = l.count a := by
simp [count, List.count_eq_countP]
@[simp] theorem count_toList [BEq α] (as : Array α) (a : α) : as.toList.count a = as.count a := by
cases as
simp
end Array
namespace List

View File

@@ -40,7 +40,7 @@ protected theorem countP_go_eq_add (l) : countP.go p l n = n + countP.go p l 0 :
theorem countP_cons (a : α) (l) : countP p (a :: l) = countP p l + if p a then 1 else 0 := by
by_cases h : p a <;> simp [h]
theorem countP_singleton (a : α) : countP p [a] = if p a then 1 else 0 := by
@[simp] theorem countP_singleton (a : α) : countP p [a] = if p a then 1 else 0 := by
simp [countP_cons]
theorem length_eq_countP_add_countP (l) : length l = countP p l + countP (fun a => ¬p a) l := by

View File

@@ -6,6 +6,7 @@ Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, M
-/
prelude
import Init.Data.List.Pairwise
import Init.Data.List.Find
/-!
# Lemmas about `List.eraseP` and `List.erase`.
@@ -572,4 +573,19 @@ protected theorem IsPrefix.eraseIdx {l l' : List α} (h : l <+: l') (k : Nat) :
-- See also `mem_eraseIdx_iff_getElem` and `mem_eraseIdx_iff_getElem?` in
-- `Init/Data/List/Nat/Basic.lean`.
theorem erase_eq_eraseIdx [BEq α] [LawfulBEq α] (l : List α) (a : α) (i : Nat) (w : l.indexOf a = i) :
l.erase a = l.eraseIdx i := by
subst w
rw [erase_eq_iff]
by_cases h : a l
· right
obtain as, bs, rfl, h' := eq_append_cons_of_mem h
refine as, bs, h', by simp, ?_
rw [indexOf_append, if_neg h', indexOf_cons_self, eraseIdx_append_of_length_le] <;>
simp
· left
refine h, ?_
rw [eq_comm, eraseIdx_eq_self]
exact Nat.le_of_eq (indexOf_eq_length h).symm
end List

View File

@@ -884,14 +884,68 @@ theorem IsInfix.findIdx?_eq_none {l₁ l₂ : List α} {p : α → Bool} (h : l
List.findIdx? p l₂ = none List.findIdx? p l₁ = none :=
h.sublist.findIdx?_eq_none
/-! ### indexOf -/
/-! ### indexOf
The verification API for `indexOf` is still incomplete.
The lemmas below should be made consistent with those for `findIdx` (and proved using them).
-/
theorem indexOf_cons [BEq α] :
(x :: xs : List α).indexOf y = bif x == y then 0 else xs.indexOf y + 1 := by
dsimp [indexOf]
simp [findIdx_cons]
@[simp] theorem indexOf_cons_self [BEq α] [ReflBEq α] {l : List α} : (a :: l).indexOf a = 0 := by
simp [indexOf_cons]
theorem indexOf_append [BEq α] [LawfulBEq α] {l₁ l₂ : List α} {a : α} :
(l₁ ++ l₂).indexOf a = if a l₁ then l₁.indexOf a else l₂.indexOf a + l₁.length := by
rw [indexOf, findIdx_append]
split <;> rename_i h
· rw [if_pos]
simpa using h
· rw [if_neg]
simpa using h
theorem indexOf_eq_length [BEq α] [LawfulBEq α] {l : List α} (h : a l) : l.indexOf a = l.length := by
induction l with
| nil => rfl
| cons x xs ih =>
simp only [mem_cons, not_or] at h
simp only [indexOf_cons, cond_eq_if, beq_iff_eq]
split <;> simp_all
theorem indexOf_lt_length [BEq α] [LawfulBEq α] {l : List α} (h : a l) : l.indexOf a < l.length := by
induction l with
| nil => simp at h
| cons x xs ih =>
simp only [mem_cons] at h
obtain rfl | h := h
· simp
· simp only [indexOf_cons, cond_eq_if, beq_iff_eq, length_cons]
specialize ih h
split
· exact zero_lt_succ xs.length
· exact Nat.add_lt_add_right ih 1
/-! ### indexOf?
The verification API for `indexOf?` is still incomplete.
The lemmas below should be made consistent with those for `findIdx?` (and proved using them).
-/
@[simp] theorem indexOf?_eq_none_iff [BEq α] [LawfulBEq α] {l : List α} {a : α} :
l.indexOf? a = none a l := by
simp only [indexOf?, findIdx?_eq_none_iff, beq_eq_false_iff_ne, ne_eq]
constructor
· intro w h
specialize w _ h
simp at w
· rintro w x h rfl
contradiction
/-! ### lookup -/
section lookup
variable [BEq α] [LawfulBEq α]

View File

@@ -8,3 +8,4 @@ import Init.Data.Vector.Basic
import Init.Data.Vector.Lemmas
import Init.Data.Vector.Lex
import Init.Data.Vector.MapIdx
import Init.Data.Vector.Count

View File

@@ -312,6 +312,14 @@ no element of the index matches the given value.
@[inline] def all (v : Vector α n) (p : α Bool) : Bool :=
v.toArray.all p
/-- Count the number of elements of a vector that satisfy the predicate `p`. -/
@[inline] def countP (p : α Bool) (v : Vector α n) : Nat :=
v.toArray.countP p
/-- Count the number of elements of a vector that are equal to `a`. -/
@[inline] def count [BEq α] (a : α) (v : Vector α n) : Nat :=
v.toArray.count a
/-! ### Lexicographic ordering -/
instance instLT [LT α] : LT (Vector α n) := fun v w => v.toArray < w.toArray

View File

@@ -0,0 +1,233 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Kim Morrison
-/
prelude
import Init.Data.Array.Count
import Init.Data.Vector.Lemmas
/-!
# Lemmas about `Vector.countP` and `Vector.count`.
-/
namespace Vector
open Nat
/-! ### countP -/
section countP
variable (p q : α Bool)
@[simp] theorem countP_empty : countP p #v[] = 0 := rfl
@[simp] theorem countP_push_of_pos (l : Vector α n) (pa : p a) : countP p (l.push a) = countP p l + 1 := by
rcases l with l
simp_all
@[simp] theorem countP_push_of_neg (l : Vector α n) (pa : ¬p a) : countP p (l.push a) = countP p l := by
rcases l with l, rfl
simp_all
theorem countP_push (a : α) (l : Vector α n) : countP p (l.push a) = countP p l + if p a then 1 else 0 := by
rcases l with l, rfl
simp [Array.countP_push]
@[simp] theorem countP_singleton (a : α) : countP p #v[a] = if p a then 1 else 0 := by
simp [countP_push]
theorem size_eq_countP_add_countP (l : Vector α n) : n = countP p l + countP (fun a => ¬p a) l := by
rcases l with l, rfl
simp [List.length_eq_countP_add_countP (p := p)]
theorem countP_le_size {l : Vector α n} : countP p l n := by
rcases l with l, rfl
simp [Array.countP_le_size (p := p)]
@[simp] theorem countP_append (l₁ : Vector α n) (l₂ : Vector α m) : countP p (l₁ ++ l₂) = countP p l₁ + countP p l₂ := by
cases l₁
cases l₂
simp
@[simp] theorem countP_pos_iff {p} : 0 < countP p l a l, p a := by
cases l
simp
@[simp] theorem one_le_countP_iff {p} : 1 countP p l a l, p a :=
countP_pos_iff
@[simp] theorem countP_eq_zero {p} : countP p l = 0 a l, ¬p a := by
cases l
simp
@[simp] theorem countP_eq_size {p} : countP p l = l.size a l, p a := by
cases l
simp
@[simp] theorem countP_cast (p : α Bool) (l : Vector α n) : countP p (l.cast h) = countP p l := by
rcases l with l, rfl
simp
theorem countP_mkVector (p : α Bool) (a : α) (n : Nat) :
countP p (mkVector n a) = if p a then n else 0 := by
simp only [mkVector_eq_toVector_mkArray, countP_cast, countP_mk]
simp [Array.countP_mkArray]
theorem boole_getElem_le_countP (p : α Bool) (l : Vector α n) (i : Nat) (h : i < n) :
(if p l[i] then 1 else 0) l.countP p := by
rcases l with l, rfl
simp [Array.boole_getElem_le_countP]
theorem countP_set (p : α Bool) (l : Vector α n) (i : Nat) (a : α) (h : i < n) :
(l.set i a).countP p = l.countP p - (if p l[i] then 1 else 0) + (if p a then 1 else 0) := by
cases l
simp [Array.countP_set, h]
@[simp] theorem countP_true : (countP fun (_ : α) => true) = (fun (_ : Vector α n) => n) := by
funext l
rw [countP]
simp only [Array.countP_true, l.2]
@[simp] theorem countP_false : (countP fun (_ : α) => false) = (fun (_ : Vector α n) => 0) := by
funext l
simp
@[simp] theorem countP_map (p : β Bool) (f : α β) (l : Vector α n) :
countP p (map f l) = countP (p f) l := by
rcases l with l, rfl
simp
@[simp] theorem countP_flatten (l : Vector (Vector α m) n) :
countP p l.flatten = (l.map (countP p)).sum := by
rcases l with l, rfl
simp [Function.comp_def]
theorem countP_flatMap (p : β Bool) (l : Vector α n) (f : α Vector β m) :
countP p (l.flatMap f) = (map (countP p f) l).sum := by
rcases l with l, rfl
simp [Array.countP_flatMap, Function.comp_def]
@[simp] theorem countP_reverse (l : Vector α n) : countP p l.reverse = countP p l := by
cases l
simp
variable {p q}
theorem countP_mono_left (h : x l, p x q x) : countP p l countP q l := by
cases l
simpa using Array.countP_mono_left (by simpa using h)
theorem countP_congr (h : x l, p x q x) : countP p l = countP q l :=
Nat.le_antisymm
(countP_mono_left fun x hx => (h x hx).1)
(countP_mono_left fun x hx => (h x hx).2)
end countP
/-! ### count -/
section count
variable [BEq α]
@[simp] theorem count_empty (a : α) : count a #v[] = 0 := rfl
theorem count_push (a b : α) (l : Vector α n) :
count a (l.push b) = count a l + if b == a then 1 else 0 := by
rcases l with l, rfl
simp [Array.count_push]
theorem count_eq_countP (a : α) (l : Vector α n) : count a l = countP (· == a) l := rfl
theorem count_eq_countP' {a : α} : count (n := n) a = countP (· == a) := by
funext l
apply count_eq_countP
theorem count_le_size (a : α) (l : Vector α n) : count a l n := countP_le_size _
theorem count_le_count_push (a b : α) (l : Vector α n) : count a l count a (l.push b) := by
rcases l with l, rfl
simp [Array.count_push]
@[simp] theorem count_singleton (a b : α) : count a #v[b] = if b == a then 1 else 0 := by
simp [count_eq_countP]
@[simp] theorem count_append (a : α) (l₁ : Vector α n) (l₂ : Vector α m) :
count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
countP_append ..
@[simp] theorem count_flatten (a : α) (l : Vector (Vector α m) n) :
count a l.flatten = (l.map (count a)).sum := by
rcases l with l, rfl
simp [Array.count_flatten, Function.comp_def]
@[simp] theorem count_reverse (a : α) (l : Vector α n) : count a l.reverse = count a l := by
rcases l with l, rfl
simp
theorem boole_getElem_le_count (a : α) (l : Vector α n) (i : Nat) (h : i < n) :
(if l[i] == a then 1 else 0) l.count a := by
rcases l with l, rfl
simp [Array.boole_getElem_le_count, h]
theorem count_set (a b : α) (l : Vector α n) (i : Nat) (h : i < n) :
(l.set i a).count b = l.count b - (if l[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
rcases l with l, rfl
simp [Array.count_set, h]
@[simp] theorem count_cast (l : Vector α n) : (l.cast h).count a = l.count a := by
rcases l with l, rfl
simp
variable [LawfulBEq α]
@[simp] theorem count_push_self (a : α) (l : Vector α n) : count a (l.push a) = count a l + 1 := by
rcases l with l, rfl
simp [Array.count_push_self]
@[simp] theorem count_push_of_ne (h : b a) (l : Vector α n) : count a (l.push b) = count a l := by
rcases l with l, rfl
simp [Array.count_push_of_ne, h]
theorem count_singleton_self (a : α) : count a #v[a] = 1 := by simp
@[simp]
theorem count_pos_iff {a : α} {l : Vector α n} : 0 < count a l a l := by
rcases l with l, rfl
simp [Array.count_pos_iff, beq_iff_eq, exists_eq_right]
@[simp] theorem one_le_count_iff {a : α} {l : Vector α n} : 1 count a l a l :=
count_pos_iff
theorem count_eq_zero_of_not_mem {a : α} {l : Vector α n} (h : a l) : count a l = 0 :=
Decidable.byContradiction fun h' => h <| count_pos_iff.1 (Nat.pos_of_ne_zero h')
theorem not_mem_of_count_eq_zero {a : α} {l : Vector α n} (h : count a l = 0) : a l :=
fun h' => Nat.ne_of_lt (count_pos_iff.2 h') h.symm
theorem count_eq_zero {l : Vector α n} : count a l = 0 a l :=
not_mem_of_count_eq_zero, count_eq_zero_of_not_mem
theorem count_eq_size {l : Vector α n} : count a l = l.size b l, a = b := by
rcases l with l, rfl
simp [Array.count_eq_size]
@[simp] theorem count_mkVector_self (a : α) (n : Nat) : count a (mkVector n a) = n := by
simp only [mkVector_eq_toVector_mkArray, count_cast, count_mk]
simp
theorem count_mkVector (a b : α) (n : Nat) : count a (mkVector n b) = if b == a then n else 0 := by
simp only [mkVector_eq_toVector_mkArray, count_cast, count_mk]
simp [Array.count_mkArray]
theorem count_le_count_map [DecidableEq β] (l : Vector α n) (f : α β) (x : α) :
count x l count (f x) (map f l) := by
rcases l with l, rfl
simp [Array.count_le_count_map]
theorem count_flatMap {α} [BEq β] (l : Vector α n) (f : α Vector β m) (x : β) :
count x (l.flatMap f) = (map (count x f) l).sum := by
rcases l with l, rfl
simp [Array.count_flatMap, Function.comp_def]
end count

View File

@@ -170,6 +170,12 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
@[simp] theorem all_mk (p : α Bool) (a : Array α) (h : a.size = n) :
(Vector.mk a h).all p = a.all p := rfl
@[simp] theorem countP_mk (p : α Bool) (a : Array α) (h : a.size = n) :
(Vector.mk a h).countP p = a.countP p := rfl
@[simp] theorem count_mk [BEq α] (a : Array α) (h : a.size = n) (b : α) :
(Vector.mk a h).count b = a.count b := rfl
@[simp] theorem eq_mk : v = Vector.mk a h v.toArray = a := by
cases v
simp
@@ -293,6 +299,16 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
cases v
simp
@[simp] theorem countP_toArray (p : α Bool) (v : Vector α n) :
v.toArray.countP p = v.countP p := by
cases v
simp
@[simp] theorem count_toArray [BEq α] (a : α) (v : Vector α n) :
v.toArray.count a = v.count a := by
cases v
simp
@[simp] theorem toArray_mkVector : (mkVector n a).toArray = mkArray n a := rfl
@[simp] theorem toArray_inj {v w : Vector α n} : v.toArray = w.toArray v = w := by
@@ -423,6 +439,16 @@ theorem toList_swap (a : Vector α n) (i j) (hi hj) :
cases v
simp
@[simp] theorem countP_toList (p : α Bool) (v : Vector α n) :
v.toList.countP p = v.countP p := by
cases v
simp
@[simp] theorem count_toList [BEq α] (a : α) (v : Vector α n) :
v.toList.count a = v.count a := by
cases v
simp
@[simp] theorem toList_mkVector : (mkVector n a).toList = List.replicate n a := rfl
theorem toList_inj {v w : Vector α n} : v.toList = w.toList v = w := by
@@ -502,6 +528,32 @@ theorem exists_push {xs : Vector α (n + 1)} :
theorem singleton_inj : #v[a] = #v[b] a = b := by
simp
/-! ### cast -/
@[simp] theorem getElem_cast (a : Vector α n) (h : n = m) (i : Nat) (hi : i < m) :
(a.cast h)[i] = a[i] := by
cases a
simp
@[simp] theorem getElem?_cast {l : Vector α n} {m : Nat} {w : n = m} {i : Nat} :
(l.cast w)[i]? = l[i]? := by
rcases l with l, rfl
simp
@[simp] theorem mem_cast {a : α} {l : Vector α n} {m : Nat} {w : n = m} :
a l.cast w a l := by
rcases l with l, rfl
simp
@[simp] theorem cast_cast {l : Vector α n} {w : n = m} {w' : m = k} :
(l.cast w).cast w' = l.cast (w.trans w') := by
rcases l with l, rfl
simp
@[simp] theorem cast_rfl {l : Vector α n} : l.cast rfl = l := by
rcases l with l, rfl
simp
/-! ### mkVector -/
@[simp] theorem mkVector_zero : mkVector 0 a = #v[] := rfl
@@ -512,6 +564,13 @@ theorem mkVector_succ : mkVector (n + 1) a = (mkVector n a).push a := by
@[simp] theorem mkVector_inj : mkVector n a = mkVector n b n = 0 a = b := by
simp [ toArray_inj, toArray_mkVector, Array.mkArray_inj]
@[simp] theorem _root_.Array.toVector_mkArray (a : α) (n : Nat) :
(Array.mkArray n a).toVector = (mkVector n a).cast (by simp) := rfl
theorem mkVector_eq_toVector_mkArray (a : α) (n : Nat) :
mkVector n a = (Array.mkArray n a).toVector.cast (by simp) := by
simp
/-! ## L[i] and L[i]? -/
@[simp] theorem getElem?_eq_none_iff {a : Vector α n} : a[i]? = none n i := by
@@ -731,24 +790,6 @@ theorem forall_getElem {l : Vector α n} {p : α → Prop} :
rcases l with l, rfl
simp [Array.forall_getElem]
/-! ### cast -/
@[simp] theorem getElem_cast (a : Vector α n) (h : n = m) (i : Nat) (hi : i < m) :
(a.cast h)[i] = a[i] := by
cases a
simp
@[simp] theorem getElem?_cast {l : Vector α n} {m : Nat} {w : n = m} {i : Nat} :
(l.cast w)[i]? = l[i]? := by
rcases l with l, rfl
simp
@[simp] theorem mem_cast {a : α} {l : Vector α n} {m : Nat} {w : n = m} :
a l.cast w a l := by
rcases l with l, rfl
simp
/-! ### Decidability of bounded quantifiers -/
instance {xs : Vector α n} {p : α Prop} [DecidablePred p] :