mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-17 18:34:06 +00:00
Compare commits
1 Commits
array_repl
...
align_coun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d9ade01b2 |
@@ -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
|
||||
|
||||
270
src/Init/Data/Array/Count.lean
Normal file
270
src/Init/Data/Array/Count.lean
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 α]
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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⟩
|
||||
|
||||
233
src/Init/Data/Vector/Count.lean
Normal file
233
src/Init/Data/Vector/Count.lean
Normal 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
|
||||
@@ -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] :
|
||||
|
||||
Reference in New Issue
Block a user