mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-19 19:34:13 +00:00
Compare commits
10 Commits
array_repl
...
align_mapI
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92e44ffdb0 | ||
|
|
878510bca9 | ||
|
|
1b24698303 | ||
|
|
a5b4c4f046 | ||
|
|
a5bdd4a43d | ||
|
|
fad76018cf | ||
|
|
75a4e5aa03 | ||
|
|
dc920cfc04 | ||
|
|
31fc03a22b | ||
|
|
9cf7e005a9 |
@@ -1658,9 +1658,9 @@ theorem getElem_of_append {l l₁ l₂ : Array α} (eq : l = l₁.push a ++ l₂
|
||||
rw [← getElem?_eq_getElem, eq, getElem?_append_left (by simp; omega), ← h]
|
||||
simp
|
||||
|
||||
@[simp 1100] theorem append_singleton {a : α} {as : Array α} : as ++ #[a] = as.push a := by
|
||||
cases as
|
||||
simp
|
||||
@[simp 1100] theorem append_singleton {a : α} {as : Array α} : as ++ #[a] = as.push a := rfl
|
||||
|
||||
theorem push_eq_append {a : α} {as : Array α} : as.push a = as ++ #[a] := rfl
|
||||
|
||||
theorem append_inj {s₁ s₂ t₁ t₂ : Array α} (h : s₁ ++ t₁ = s₂ ++ t₂) (hl : s₁.size = s₂.size) :
|
||||
s₁ = s₂ ∧ t₁ = t₂ := by
|
||||
|
||||
@@ -5,6 +5,7 @@ Authors: Mario Carneiro, Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Array.Lemmas
|
||||
import Init.Data.Array.Attach
|
||||
import Init.Data.List.MapIdx
|
||||
|
||||
namespace Array
|
||||
@@ -111,3 +112,293 @@ namespace List
|
||||
ext <;> simp
|
||||
|
||||
end List
|
||||
|
||||
namespace Array
|
||||
|
||||
/-! ### zipWithIndex -/
|
||||
|
||||
@[simp] theorem getElem_zipWithIndex (a : Array α) (i : Nat) (h : i < a.zipWithIndex.size) :
|
||||
(a.zipWithIndex)[i] = (a[i]'(by simp_all), i) := by
|
||||
simp [zipWithIndex]
|
||||
|
||||
@[simp] theorem zipWithIndex_toArray {l : List α} :
|
||||
l.toArray.zipWithIndex = (l.enum.map fun (i, x) => (x, i)).toArray := by
|
||||
ext i hi₁ hi₂ <;> simp
|
||||
|
||||
@[simp] theorem toList_zipWithIndex (a : Array α) :
|
||||
a.zipWithIndex.toList = a.toList.enum.map (fun (i, a) => (a, i)) := by
|
||||
rcases a with ⟨a⟩
|
||||
simp
|
||||
|
||||
theorem mk_mem_zipWithIndex_iff_getElem? {x : α} {i : Nat} {l : Array α} :
|
||||
(x, i) ∈ l.zipWithIndex ↔ l[i]? = x := by
|
||||
rcases l with ⟨l⟩
|
||||
simp only [zipWithIndex_toArray, mem_toArray, List.mem_map, Prod.mk.injEq, Prod.exists,
|
||||
List.mk_mem_enum_iff_getElem?, List.getElem?_toArray]
|
||||
constructor
|
||||
· rintro ⟨a, b, h, rfl, rfl⟩
|
||||
exact h
|
||||
· intro h
|
||||
exact ⟨i, x, by simp [h]⟩
|
||||
|
||||
theorem mem_enum_iff_getElem? {x : α × Nat} {l : Array α} : x ∈ l.zipWithIndex ↔ l[x.2]? = some x.1 :=
|
||||
mk_mem_zipWithIndex_iff_getElem?
|
||||
|
||||
/-! ### mapFinIdx -/
|
||||
|
||||
@[congr] theorem mapFinIdx_congr {xs ys : Array α} (w : xs = ys)
|
||||
(f : (i : Nat) → α → (h : i < xs.size) → β) :
|
||||
mapFinIdx xs f = mapFinIdx ys (fun i a h => f i a (by simp [w]; omega)) := by
|
||||
subst w
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_empty {f : (i : Nat) → α → (h : i < 0) → β} : mapFinIdx #[] f = #[] :=
|
||||
rfl
|
||||
|
||||
theorem mapFinIdx_eq_ofFn {as : Array α} {f : (i : Nat) → α → (h : i < as.size) → β} :
|
||||
as.mapFinIdx f = Array.ofFn fun i : Fin as.size => f i as[i] i.2 := by
|
||||
cases as
|
||||
simp [List.mapFinIdx_eq_ofFn]
|
||||
|
||||
theorem mapFinIdx_append {K L : Array α} {f : (i : Nat) → α → (h : i < (K ++ L).size) → β} :
|
||||
(K ++ L).mapFinIdx f =
|
||||
K.mapFinIdx (fun i a h => f i a (by simp; omega)) ++
|
||||
L.mapFinIdx (fun i a h => f (i + K.size) a (by simp; omega)) := by
|
||||
cases K
|
||||
cases L
|
||||
simp [List.mapFinIdx_append]
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_push {l : Array α} {a : α} {f : (i : Nat) → α → (h : i < (l.push a).size) → β} :
|
||||
mapFinIdx (l.push a) f =
|
||||
(mapFinIdx l (fun i a h => f i a (by simp; omega))).push (f l.size a (by simp)) := by
|
||||
simp [← append_singleton, mapFinIdx_append]
|
||||
|
||||
theorem mapFinIdx_singleton {a : α} {f : (i : Nat) → α → (h : i < 1) → β} :
|
||||
#[a].mapFinIdx f = #[f 0 a (by simp)] := by
|
||||
simp
|
||||
|
||||
theorem mapFinIdx_eq_zipWithIndex_map {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
l.mapFinIdx f = l.zipWithIndex.attach.map
|
||||
fun ⟨⟨x, i⟩, m⟩ =>
|
||||
f i x (by simp [mk_mem_zipWithIndex_iff_getElem?, getElem?_eq_some_iff] at m; exact m.1) := by
|
||||
ext <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_eq_empty_iff {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
l.mapFinIdx f = #[] ↔ l = #[] := by
|
||||
cases l
|
||||
simp
|
||||
|
||||
theorem mapFinIdx_ne_empty_iff {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
l.mapFinIdx f ≠ #[] ↔ l ≠ #[] := by
|
||||
simp
|
||||
|
||||
theorem exists_of_mem_mapFinIdx {b : β} {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β}
|
||||
(h : b ∈ l.mapFinIdx f) : ∃ (i : Nat) (h : i < l.size), f i l[i] h = b := by
|
||||
rcases l with ⟨l⟩
|
||||
exact List.exists_of_mem_mapFinIdx (by simpa using h)
|
||||
|
||||
@[simp] theorem mem_mapFinIdx {b : β} {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
b ∈ l.mapFinIdx f ↔ ∃ (i : Nat) (h : i < l.size), f i l[i] h = b := by
|
||||
rcases l with ⟨l⟩
|
||||
simp
|
||||
|
||||
theorem mapFinIdx_eq_iff {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
l.mapFinIdx f = l' ↔ ∃ h : l'.size = l.size, ∀ (i : Nat) (h : i < l.size), l'[i] = f i l[i] h := by
|
||||
rcases l with ⟨l⟩
|
||||
rcases l' with ⟨l'⟩
|
||||
simpa using List.mapFinIdx_eq_iff
|
||||
|
||||
@[simp] theorem mapFinIdx_eq_singleton_iff {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} {b : β} :
|
||||
l.mapFinIdx f = #[b] ↔ ∃ (a : α) (w : l = #[a]), f 0 a (by simp [w]) = b := by
|
||||
rcases l with ⟨l⟩
|
||||
simp
|
||||
|
||||
theorem mapFinIdx_eq_append_iff {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} {l₁ l₂ : Array β} :
|
||||
l.mapFinIdx f = l₁ ++ l₂ ↔
|
||||
∃ (l₁' : Array α) (l₂' : Array α) (w : l = l₁' ++ l₂'),
|
||||
l₁'.mapFinIdx (fun i a h => f i a (by simp [w]; omega)) = l₁ ∧
|
||||
l₂'.mapFinIdx (fun i a h => f (i + l₁'.size) a (by simp [w]; omega)) = l₂ := by
|
||||
rcases l with ⟨l⟩
|
||||
rcases l₁ with ⟨l₁⟩
|
||||
rcases l₂ with ⟨l₂⟩
|
||||
simp only [List.mapFinIdx_toArray, List.append_toArray, mk.injEq, List.mapFinIdx_eq_append_iff,
|
||||
toArray_eq_append_iff]
|
||||
constructor
|
||||
· rintro ⟨l₁, l₂, rfl, rfl, rfl⟩
|
||||
refine ⟨l₁.toArray, l₂.toArray, by simp_all⟩
|
||||
· rintro ⟨⟨l₁⟩, ⟨l₂⟩, rfl, h₁, h₂⟩
|
||||
simp [← toList_inj] at h₁ h₂
|
||||
obtain rfl := h₁
|
||||
obtain rfl := h₂
|
||||
refine ⟨l₁, l₂, by simp_all⟩
|
||||
|
||||
theorem mapFinIdx_eq_push_iff {l : Array α} {b : β} {f : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
l.mapFinIdx f = l₂.push b ↔
|
||||
∃ (l₁ : Array α) (a : α) (w : l = l₁.push a),
|
||||
l₁.mapFinIdx (fun i a h => f i a (by simp [w]; omega)) = l₂ ∧ b = f (l.size - 1) a (by simp [w]) := by
|
||||
rw [push_eq_append, mapFinIdx_eq_append_iff]
|
||||
constructor
|
||||
· rintro ⟨l₁, l₂, rfl, rfl, h₂⟩
|
||||
simp only [mapFinIdx_eq_singleton_iff, Nat.zero_add] at h₂
|
||||
obtain ⟨a, rfl, rfl⟩ := h₂
|
||||
exact ⟨l₁, a, by simp⟩
|
||||
· rintro ⟨l₁, a, rfl, rfl, rfl⟩
|
||||
exact ⟨l₁, #[a], by simp⟩
|
||||
|
||||
theorem mapFinIdx_eq_mapFinIdx_iff {l : Array α} {f g : (i : Nat) → α → (h : i < l.size) → β} :
|
||||
l.mapFinIdx f = l.mapFinIdx g ↔ ∀ (i : Nat) (h : i < l.size), f i l[i] h = g i l[i] h := by
|
||||
rw [eq_comm, mapFinIdx_eq_iff]
|
||||
simp
|
||||
|
||||
@[simp] theorem mapFinIdx_mapFinIdx {l : Array α}
|
||||
{f : (i : Nat) → α → (h : i < l.size) → β}
|
||||
{g : (i : Nat) → β → (h : i < (l.mapFinIdx f).size) → γ} :
|
||||
(l.mapFinIdx f).mapFinIdx g = l.mapFinIdx (fun i a h => g i (f i a h) (by simpa using h)) := by
|
||||
simp [mapFinIdx_eq_iff]
|
||||
|
||||
theorem mapFinIdx_eq_mkArray_iff {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} {b : β} :
|
||||
l.mapFinIdx f = mkArray l.size b ↔ ∀ (i : Nat) (h : i < l.size), f i l[i] h = b := by
|
||||
rcases l with ⟨l⟩
|
||||
rw [← toList_inj]
|
||||
simp [List.mapFinIdx_eq_replicate_iff]
|
||||
|
||||
@[simp] theorem mapFinIdx_reverse {l : Array α} {f : (i : Nat) → α → (h : i < l.reverse.size) → β} :
|
||||
l.reverse.mapFinIdx f = (l.mapFinIdx (fun i a h => f (l.size - 1 - i) a (by simp; omega))).reverse := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.mapFinIdx_reverse]
|
||||
|
||||
/-! ### mapIdx -/
|
||||
|
||||
@[simp]
|
||||
theorem mapIdx_empty {f : Nat → α → β} : mapIdx f #[] = #[] :=
|
||||
rfl
|
||||
|
||||
@[simp] theorem mapFinIdx_eq_mapIdx {l : Array α} {f : (i : Nat) → α → (h : i < l.size) → β} {g : Nat → α → β}
|
||||
(h : ∀ (i : Nat) (h : i < l.size), f i l[i] h = g i l[i]) :
|
||||
l.mapFinIdx f = l.mapIdx g := by
|
||||
simp_all [mapFinIdx_eq_iff]
|
||||
|
||||
theorem mapIdx_eq_mapFinIdx {l : Array α} {f : Nat → α → β} :
|
||||
l.mapIdx f = l.mapFinIdx (fun i a _ => f i a) := by
|
||||
simp [mapFinIdx_eq_mapIdx]
|
||||
|
||||
theorem mapIdx_eq_zipWithIndex_map {l : Array α} {f : Nat → α → β} :
|
||||
l.mapIdx f = l.zipWithIndex.map fun ⟨a, i⟩ => f i a := by
|
||||
ext <;> simp
|
||||
|
||||
theorem mapIdx_append {K L : Array α} :
|
||||
(K ++ L).mapIdx f = K.mapIdx f ++ L.mapIdx fun i => f (i + K.size) := by
|
||||
rcases K with ⟨K⟩
|
||||
rcases L with ⟨L⟩
|
||||
simp [List.mapIdx_append]
|
||||
|
||||
@[simp]
|
||||
theorem mapIdx_push {l : Array α} {a : α} :
|
||||
mapIdx f (l.push a) = (mapIdx f l).push (f l.size a) := by
|
||||
simp [← append_singleton, mapIdx_append]
|
||||
|
||||
theorem mapIdx_singleton {a : α} : mapIdx f #[a] = #[f 0 a] := by
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem mapIdx_eq_empty_iff {l : Array α} : mapIdx f l = #[] ↔ l = #[] := by
|
||||
rcases l with ⟨l⟩
|
||||
simp
|
||||
|
||||
theorem mapIdx_ne_empty_iff {l : Array α} :
|
||||
mapIdx f l ≠ #[] ↔ l ≠ #[] := by
|
||||
simp
|
||||
|
||||
theorem exists_of_mem_mapIdx {b : β} {l : Array α}
|
||||
(h : b ∈ mapIdx f l) : ∃ (i : Nat) (h : i < l.size), f i l[i] = b := by
|
||||
rw [mapIdx_eq_mapFinIdx] at h
|
||||
simpa [Fin.exists_iff] using exists_of_mem_mapFinIdx h
|
||||
|
||||
@[simp] theorem mem_mapIdx {b : β} {l : Array α} :
|
||||
b ∈ mapIdx f l ↔ ∃ (i : Nat) (h : i < l.size), f i l[i] = b := by
|
||||
constructor
|
||||
· intro h
|
||||
exact exists_of_mem_mapIdx h
|
||||
· rintro ⟨i, h, rfl⟩
|
||||
rw [mem_iff_getElem]
|
||||
exact ⟨i, by simpa using h, by simp⟩
|
||||
|
||||
theorem mapIdx_eq_push_iff {l : Array α} {b : β} :
|
||||
mapIdx f l = l₂.push b ↔
|
||||
∃ (a : α) (l₁ : Array α), l = l₁.push a ∧ mapIdx f l₁ = l₂ ∧ f l₁.size a = b := by
|
||||
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_push_iff]
|
||||
simp only [mapFinIdx_eq_mapIdx, exists_and_left, exists_prop]
|
||||
constructor
|
||||
· rintro ⟨l₁, rfl, a, rfl, rfl⟩
|
||||
exact ⟨a, l₁, by simp⟩
|
||||
· rintro ⟨a, l₁, rfl, rfl, rfl⟩
|
||||
exact ⟨l₁, rfl, a, by simp⟩
|
||||
|
||||
@[simp] theorem mapIdx_eq_singleton_iff {l : Array α} {f : Nat → α → β} {b : β} :
|
||||
mapIdx f l = #[b] ↔ ∃ (a : α), l = #[a] ∧ f 0 a = b := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.mapIdx_eq_singleton_iff]
|
||||
|
||||
theorem mapIdx_eq_append_iff {l : Array α} {f : Nat → α → β} {l₁ l₂ : Array β} :
|
||||
mapIdx f l = l₁ ++ l₂ ↔
|
||||
∃ (l₁' : Array α) (l₂' : Array α), l = l₁' ++ l₂' ∧
|
||||
l₁'.mapIdx f = l₁ ∧
|
||||
l₂'.mapIdx (fun i => f (i + l₁'.size)) = l₂ := by
|
||||
rcases l with ⟨l⟩
|
||||
rcases l₁ with ⟨l₁⟩
|
||||
rcases l₂ with ⟨l₂⟩
|
||||
simp only [List.mapIdx_toArray, List.append_toArray, mk.injEq, List.mapIdx_eq_append_iff,
|
||||
toArray_eq_append_iff]
|
||||
constructor
|
||||
· rintro ⟨l₁, l₂, rfl, rfl, rfl⟩
|
||||
exact ⟨l₁.toArray, l₂.toArray, by simp⟩
|
||||
· rintro ⟨⟨l₁⟩, ⟨l₂⟩, rfl, h₁, h₂⟩
|
||||
simp only [List.mapIdx_toArray, mk.injEq, size_toArray] at h₁ h₂
|
||||
obtain rfl := h₁
|
||||
obtain rfl := h₂
|
||||
exact ⟨l₁, l₂, by simp⟩
|
||||
|
||||
theorem mapIdx_eq_iff {l : Array α} : mapIdx f l = l' ↔ ∀ i : Nat, l'[i]? = l[i]?.map (f i) := by
|
||||
rcases l with ⟨l⟩
|
||||
rcases l' with ⟨l'⟩
|
||||
simp [List.mapIdx_eq_iff]
|
||||
|
||||
theorem mapIdx_eq_mapIdx_iff {l : Array α} :
|
||||
mapIdx f l = mapIdx g l ↔ ∀ i : Nat, (h : i < l.size) → f i l[i] = g i l[i] := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.mapIdx_eq_mapIdx_iff]
|
||||
|
||||
@[simp] theorem mapIdx_set {l : Array α} {i : Nat} {h : i < l.size} {a : α} :
|
||||
(l.set i a).mapIdx f = (l.mapIdx f).set i (f i a) (by simpa) := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.mapIdx_set]
|
||||
|
||||
@[simp] theorem mapIdx_setIfInBounds {l : Array α} {i : Nat} {a : α} :
|
||||
(l.setIfInBounds i a).mapIdx f = (l.mapIdx f).setIfInBounds i (f i a) := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.mapIdx_set]
|
||||
|
||||
@[simp] theorem back?_mapIdx {l : Array α} {f : Nat → α → β} :
|
||||
(mapIdx f l).back? = (l.back?).map (f (l.size - 1)) := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.getLast?_mapIdx]
|
||||
|
||||
@[simp] theorem mapIdx_mapIdx {l : Array α} {f : Nat → α → β} {g : Nat → β → γ} :
|
||||
(l.mapIdx f).mapIdx g = l.mapIdx (fun i => g i ∘ f i) := by
|
||||
simp [mapIdx_eq_iff]
|
||||
|
||||
theorem mapIdx_eq_mkArray_iff {l : Array α} {f : Nat → α → β} {b : β} :
|
||||
mapIdx f l = mkArray l.size b ↔ ∀ (i : Nat) (h : i < l.size), f i l[i] = b := by
|
||||
rcases l with ⟨l⟩
|
||||
rw [← toList_inj]
|
||||
simp [List.mapIdx_eq_replicate_iff]
|
||||
|
||||
@[simp] theorem mapIdx_reverse {l : Array α} {f : Nat → α → β} :
|
||||
l.reverse.mapIdx f = (mapIdx (fun i => f (l.size - 1 - i)) l).reverse := by
|
||||
rcases l with ⟨l⟩
|
||||
simp [List.mapIdx_reverse]
|
||||
|
||||
end Array
|
||||
|
||||
@@ -17,12 +17,13 @@ namespace List
|
||||
|
||||
/-! ### mapIdx -/
|
||||
|
||||
|
||||
/--
|
||||
Given a list `as = [a₀, a₁, ...]` function `f : Fin as.length → α → β`, returns the list
|
||||
`[f 0 a₀, f 1 a₁, ...]`.
|
||||
-/
|
||||
@[inline] def mapFinIdx (as : List α) (f : (i : Nat) → α → (h : i < as.length) → β) : List β := go as #[] (by simp) where
|
||||
@[inline] def mapFinIdx (as : List α) (f : (i : Nat) → α → (h : i < as.length) → β) : List β :=
|
||||
go as #[] (by simp)
|
||||
where
|
||||
/-- Auxiliary for `mapFinIdx`:
|
||||
`mapFinIdx.go [a₀, a₁, ...] acc = acc.toList ++ [f 0 a₀, f 1 a₁, ...]` -/
|
||||
@[specialize] go : (bs : List α) → (acc : Array β) → bs.length + acc.size = as.length → List β
|
||||
@@ -43,6 +44,12 @@ Given a function `f : Nat → α → β` and `as : List α`, `as = [a₀, a₁,
|
||||
|
||||
/-! ### mapFinIdx -/
|
||||
|
||||
@[congr] theorem mapFinIdx_congr {xs ys : List α} (w : xs = ys)
|
||||
(f : (i : Nat) → α → (h : i < xs.length) → β) :
|
||||
mapFinIdx xs f = mapFinIdx ys (fun i a h => f i a (by simp [w]; omega)) := by
|
||||
subst w
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_nil {f : (i : Nat) → α → (h : i < 0) → β} : mapFinIdx [] f = [] :=
|
||||
rfl
|
||||
@@ -188,6 +195,49 @@ theorem mapFinIdx_eq_iff {l : List α} {f : (i : Nat) → α → (h : i < l.leng
|
||||
· rintro ⟨h, w⟩
|
||||
apply ext_getElem <;> simp_all
|
||||
|
||||
@[simp] theorem mapFinIdx_eq_singleton_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} {b : β} :
|
||||
l.mapFinIdx f = [b] ↔ ∃ (a : α) (w : l = [a]), f 0 a (by simp [w]) = b := by
|
||||
simp [mapFinIdx_eq_cons_iff]
|
||||
|
||||
theorem mapFinIdx_eq_append_iff {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
|
||||
l.mapFinIdx f = l₁ ++ l₂ ↔
|
||||
∃ (l₁' : List α) (l₂' : List α) (w : l = l₁' ++ l₂'),
|
||||
l₁'.mapFinIdx (fun i a h => f i a (by simp [w]; omega)) = l₁ ∧
|
||||
l₂'.mapFinIdx (fun i a h => f (i + l₁'.length) a (by simp [w]; omega)) = l₂ := by
|
||||
rw [mapFinIdx_eq_iff]
|
||||
constructor
|
||||
· intro ⟨h, w⟩
|
||||
simp only [length_append] at h
|
||||
refine ⟨l.take l₁.length, l.drop l₁.length, by simp, ?_⟩
|
||||
constructor
|
||||
· apply ext_getElem
|
||||
· simp
|
||||
omega
|
||||
· intro i hi₁ hi₂
|
||||
simp only [getElem_mapFinIdx, getElem_take]
|
||||
specialize w i (by omega)
|
||||
rw [getElem_append_left hi₂] at w
|
||||
exact w.symm
|
||||
· apply ext_getElem
|
||||
· simp
|
||||
omega
|
||||
· intro i hi₁ hi₂
|
||||
simp only [getElem_mapFinIdx, getElem_take]
|
||||
simp only [length_take, getElem_drop]
|
||||
have : l₁.length ≤ l.length := by omega
|
||||
simp only [Nat.min_eq_left this, Nat.add_comm]
|
||||
specialize w (i + l₁.length) (by omega)
|
||||
rw [getElem_append_right (by omega)] at w
|
||||
simpa using w.symm
|
||||
· rintro ⟨l₁', l₂', rfl, rfl, rfl⟩
|
||||
refine ⟨by simp, fun i h => ?_⟩
|
||||
rw [getElem_append]
|
||||
split <;> rename_i h'
|
||||
· simp [getElem_append_left (by simpa using h')]
|
||||
· simp only [length_mapFinIdx, Nat.not_lt] at h'
|
||||
have : i - l₁'.length + l₁'.length = i := by omega
|
||||
simp [getElem_append_right h', this]
|
||||
|
||||
theorem mapFinIdx_eq_mapFinIdx_iff {l : List α} {f g : (i : Nat) → α → (h : i < l.length) → β} :
|
||||
l.mapFinIdx f = l.mapFinIdx g ↔ ∀ (i : Nat) (h : i < l.length), f i l[i] h = g i l[i] h := by
|
||||
rw [eq_comm, mapFinIdx_eq_iff]
|
||||
@@ -338,6 +388,10 @@ theorem mapIdx_eq_cons_iff' {l : List α} {b : β} :
|
||||
l.head?.map (f 0) = some b ∧ l.tail?.map (mapIdx fun i => f (i + 1)) = some l₂ := by
|
||||
cases l <;> simp
|
||||
|
||||
@[simp] theorem mapIdx_eq_singleton_iff {l : List α} {f : Nat → α → β} {b : β} :
|
||||
mapIdx f l = [b] ↔ ∃ (a : α), l = [a] ∧ f 0 a = b := by
|
||||
simp [mapIdx_eq_cons_iff]
|
||||
|
||||
theorem mapIdx_eq_iff {l : List α} : mapIdx f l = l' ↔ ∀ i : Nat, l'[i]? = l[i]?.map (f i) := by
|
||||
constructor
|
||||
· intro w i
|
||||
@@ -346,6 +400,19 @@ theorem mapIdx_eq_iff {l : List α} : mapIdx f l = l' ↔ ∀ i : Nat, l'[i]? =
|
||||
ext1 i
|
||||
simp [w]
|
||||
|
||||
theorem mapIdx_eq_append_iff {l : List α} :
|
||||
mapIdx f l = l₁ ++ l₂ ↔
|
||||
∃ (l₁' : List α) (l₂' : List α), l = l₁' ++ l₂' ∧
|
||||
mapIdx f l₁' = l₁ ∧
|
||||
mapIdx (fun i => f (i + l₁'.length)) l₂' = l₂ := by
|
||||
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_append_iff]
|
||||
simp only [mapFinIdx_eq_mapIdx, exists_and_left, exists_prop]
|
||||
constructor
|
||||
· rintro ⟨l₁, rfl, l₂, rfl, h⟩
|
||||
refine ⟨l₁, l₂, by simp_all⟩
|
||||
· rintro ⟨l₁, l₂, rfl, rfl, rfl⟩
|
||||
refine ⟨l₁, rfl, l₂, by simp_all⟩
|
||||
|
||||
theorem mapIdx_eq_mapIdx_iff {l : List α} :
|
||||
mapIdx f l = mapIdx g l ↔ ∀ i : Nat, (h : i < l.length) → f i l[i] = g i l[i] := by
|
||||
constructor
|
||||
|
||||
@@ -5,3 +5,6 @@ Authors: Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Vector.Basic
|
||||
import Init.Data.Vector.Lemmas
|
||||
import Init.Data.Vector.Lex
|
||||
import Init.Data.Vector.MapIdx
|
||||
|
||||
@@ -6,6 +6,7 @@ Authors: Shreyas Srinivas, François G. Dorais, Kim Morrison
|
||||
|
||||
prelude
|
||||
import Init.Data.Array.Lemmas
|
||||
import Init.Data.Array.MapIdx
|
||||
import Init.Data.Range
|
||||
|
||||
/-!
|
||||
@@ -90,14 +91,12 @@ of bounds.
|
||||
/-- The last element of a vector. Panics if the vector is empty. -/
|
||||
@[inline] def back! [Inhabited α] (v : Vector α n) : α := v.toArray.back!
|
||||
|
||||
/-- The last element of a vector, or `none` if the array is empty. -/
|
||||
/-- The last element of a vector, or `none` if the vector is empty. -/
|
||||
@[inline] def back? (v : Vector α n) : Option α := v.toArray.back?
|
||||
|
||||
/-- The last element of a non-empty vector. -/
|
||||
@[inline] def back [NeZero n] (v : Vector α n) : α :=
|
||||
-- TODO: change to just `v[n]`
|
||||
have : Inhabited α := ⟨v[0]'(Nat.pos_of_neZero n)⟩
|
||||
v.back!
|
||||
v[n - 1]'(Nat.sub_one_lt (NeZero.ne n))
|
||||
|
||||
/-- The first element of a non-empty vector. -/
|
||||
@[inline] def head [NeZero n] (v : Vector α n) := v[0]'(Nat.pos_of_neZero n)
|
||||
@@ -170,6 +169,15 @@ result is empty. If `stop` is greater than the size of the vector, the size is u
|
||||
@[inline] def map (f : α → β) (v : Vector α n) : Vector β n :=
|
||||
⟨v.toArray.map f, by simp⟩
|
||||
|
||||
/-- Maps elements of a vector using the function `f`, which also receives the index of the element. -/
|
||||
@[inline] def mapIdx (f : Nat → α → β) (v : Vector α n) : Vector β n :=
|
||||
⟨v.toArray.mapIdx f, by simp⟩
|
||||
|
||||
/-- Maps elements of a vector using the function `f`,
|
||||
which also receives the index of the element, and the fact that the index is less than the size of the vector. -/
|
||||
@[inline] def mapFinIdx (v : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) : Vector β n :=
|
||||
⟨v.toArray.mapFinIdx (fun i a h => f i a (by simpa [v.size_toArray] using h)), by simp⟩
|
||||
|
||||
@[inline] def flatten (v : Vector (Vector α n) m) : Vector α (m * n) :=
|
||||
⟨(v.toArray.map Vector.toArray).flatten,
|
||||
by rcases v; simp_all [Function.comp_def, Array.map_const']⟩
|
||||
@@ -177,6 +185,9 @@ result is empty. If `stop` is greater than the size of the vector, the size is u
|
||||
@[inline] def flatMap (v : Vector α n) (f : α → Vector β m) : Vector β (n * m) :=
|
||||
⟨v.toArray.flatMap fun a => (f a).toArray, by simp [Array.map_const']⟩
|
||||
|
||||
@[inline] def zipWithIndex (v : Vector α n) : Vector (α × Nat) n :=
|
||||
⟨v.toArray.zipWithIndex, by simp⟩
|
||||
|
||||
/-- Maps corresponding elements of two vectors of equal size using the function `f`. -/
|
||||
@[inline] def zipWith (a : Vector α n) (b : Vector β n) (f : α → β → φ) : Vector φ n :=
|
||||
⟨Array.zipWith a.toArray b.toArray f, by simp⟩
|
||||
|
||||
@@ -23,7 +23,6 @@ end Array
|
||||
|
||||
namespace Vector
|
||||
|
||||
|
||||
/-! ### mk lemmas -/
|
||||
|
||||
theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a := rfl
|
||||
@@ -70,6 +69,10 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
|
||||
@[simp] theorem back?_mk (a : Array α) (h : a.size = n) :
|
||||
(Vector.mk a h).back? = a.back? := rfl
|
||||
|
||||
@[simp] theorem back_mk [NeZero n] (a : Array α) (h : a.size = n) :
|
||||
(Vector.mk a h).back =
|
||||
a[n - 1]'(Nat.lt_of_lt_of_eq (Nat.sub_one_lt (NeZero.ne n)) h.symm) := rfl
|
||||
|
||||
@[simp] theorem foldlM_mk [Monad m] (f : β → α → m β) (b : β) (a : Array α) (h : a.size = n) :
|
||||
(Vector.mk a h).foldlM f b = a.foldlM f b := rfl
|
||||
|
||||
@@ -111,6 +114,13 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
|
||||
@[simp] theorem map_mk (a : Array α) (h : a.size = n) (f : α → β) :
|
||||
(Vector.mk a h).map f = Vector.mk (a.map f) (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem mapIdx_mk (a : Array α) (h : a.size = n) (f : Nat → α → β) :
|
||||
(Vector.mk a h).mapIdx f = Vector.mk (a.mapIdx f) (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem mapFinIdx_mk (a : Array α) (h : a.size = n) (f : (i : Nat) → α → (h : i < n) → β) :
|
||||
(Vector.mk a h).mapFinIdx f =
|
||||
Vector.mk (a.mapFinIdx fun i a h' => f i a (by simpa [h] using h')) (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem reverse_mk (a : Array α) (h : a.size = n) :
|
||||
(Vector.mk a h).reverse = Vector.mk a.reverse (by simp [h]) := rfl
|
||||
|
||||
@@ -141,6 +151,9 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
|
||||
@[simp] theorem take_mk (a : Array α) (h : a.size = n) (m) :
|
||||
(Vector.mk a h).take m = Vector.mk (a.take m) (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem zipWithIndex_mk (a : Array α) (h : a.size = n) :
|
||||
(Vector.mk a h).zipWithIndex = Vector.mk (a.zipWithIndex) (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem mk_zipWith_mk (f : α → β → γ) (a : Array α) (b : Array β)
|
||||
(ha : a.size = n) (hb : b.size = n) : zipWith (Vector.mk a ha) (Vector.mk b hb) f =
|
||||
Vector.mk (Array.zipWith a b f) (by simp [ha, hb]) := rfl
|
||||
@@ -204,6 +217,14 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
|
||||
@[simp] theorem toArray_map (f : α → β) (a : Vector α n) :
|
||||
(a.map f).toArray = a.toArray.map f := rfl
|
||||
|
||||
@[simp] theorem toArray_mapIdx (f : Nat → α → β) (a : Vector α n) :
|
||||
(a.mapIdx f).toArray = a.toArray.mapIdx f := rfl
|
||||
|
||||
@[simp] theorem toArray_mapFinIdx (f : (i : Nat) → α → (h : i < n) → β) (v : Vector α n) :
|
||||
(v.mapFinIdx f).toArray =
|
||||
v.toArray.mapFinIdx (fun i a h => f i a (by simpa [v.size_toArray] using h)) :=
|
||||
rfl
|
||||
|
||||
@[simp] theorem toArray_ofFn (f : Fin n → α) : (Vector.ofFn f).toArray = Array.ofFn f := rfl
|
||||
|
||||
@[simp] theorem toArray_pop (a : Vector α n) : a.pop.toArray = a.toArray.pop := rfl
|
||||
@@ -246,6 +267,9 @@ theorem toArray_mk (a : Array α) (h : a.size = n) : (Vector.mk a h).toArray = a
|
||||
|
||||
@[simp] theorem toArray_take (a : Vector α n) (m) : (a.take m).toArray = a.toArray.take m := rfl
|
||||
|
||||
@[simp] theorem toArray_zipWithIndex (a : Vector α n) :
|
||||
(a.zipWithIndex).toArray = a.toArray.zipWithIndex := rfl
|
||||
|
||||
@[simp] theorem toArray_zipWith (f : α → β → γ) (a : Vector α n) (b : Vector β n) :
|
||||
(Vector.zipWith a b f).toArray = Array.zipWith a.toArray b.toArray f := rfl
|
||||
|
||||
@@ -298,6 +322,8 @@ protected theorem ext {a b : Vector α n} (h : (i : Nat) → (_ : i < n) → a[i
|
||||
|
||||
/-! ### toList -/
|
||||
|
||||
theorem toArray_toList (a : Vector α n) : a.toArray.toList = a.toList := rfl
|
||||
|
||||
@[simp] theorem getElem_toList {α n} (xs : Vector α n) (i : Nat) (h : i < xs.toList.length) :
|
||||
xs.toList[i] = xs[i]'(by simpa using h) := by
|
||||
cases xs
|
||||
@@ -337,6 +363,14 @@ theorem toList_extract (a : Vector α n) (start stop) :
|
||||
theorem toList_map (f : α → β) (a : Vector α n) :
|
||||
(a.map f).toList = a.toList.map f := by simp
|
||||
|
||||
theorem toList_mapIdx (f : Nat → α → β) (a : Vector α n) :
|
||||
(a.mapIdx f).toList = a.toList.mapIdx f := by simp
|
||||
|
||||
theorem toList_mapFinIdx (f : (i : Nat) → α → (h : i < n) → β) (v : Vector α n) :
|
||||
(v.mapFinIdx f).toList =
|
||||
v.toList.mapFinIdx (fun i a h => f i a (by simpa [v.size_toArray] using h)) := by
|
||||
simp
|
||||
|
||||
theorem toList_ofFn (f : Fin n → α) : (Vector.ofFn f).toList = List.ofFn f := by simp
|
||||
|
||||
theorem toList_pop (a : Vector α n) : a.pop.toList = a.toList.dropLast := rfl
|
||||
@@ -1860,7 +1894,7 @@ defeq issues in the implicit size argument.
|
||||
· simp [h]
|
||||
· replace h : i = v.size - 1 := by rw [size_toArray]; omega
|
||||
subst h
|
||||
simp [pop, back, back!, ← Array.eq_push_pop_back!_of_size_ne_zero]
|
||||
simp [back]
|
||||
|
||||
/-! ### extract -/
|
||||
|
||||
|
||||
333
src/Init/Data/Vector/MapIdx.lean
Normal file
333
src/Init/Data/Vector/MapIdx.lean
Normal file
@@ -0,0 +1,333 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Array.MapIdx
|
||||
import Init.Data.Vector.Lemmas
|
||||
|
||||
namespace Vector
|
||||
|
||||
/-! ### mapFinIdx -/
|
||||
|
||||
@[simp] theorem getElem_mapFinIdx (a : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) (i : Nat)
|
||||
(h : i < n) :
|
||||
(a.mapFinIdx f)[i] = f i a[i] h := by
|
||||
rcases a with ⟨a, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem getElem?_mapFinIdx (a : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) (i : Nat) :
|
||||
(a.mapFinIdx f)[i]? =
|
||||
a[i]?.pbind fun b h => f i b (getElem?_eq_some_iff.1 h).1 := by
|
||||
simp only [getElem?_def, getElem_mapFinIdx]
|
||||
split <;> simp_all
|
||||
|
||||
/-! ### mapIdx -/
|
||||
|
||||
@[simp] theorem getElem_mapIdx (f : Nat → α → β) (a : Vector α n) (i : Nat) (h : i < n) :
|
||||
(a.mapIdx f)[i] = f i (a[i]'(by simp_all)) := by
|
||||
rcases a with ⟨a, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem getElem?_mapIdx (f : Nat → α → β) (a : Vector α n) (i : Nat) :
|
||||
(a.mapIdx f)[i]? = a[i]?.map (f i) := by
|
||||
rcases a with ⟨a, rfl⟩
|
||||
simp
|
||||
|
||||
end Vector
|
||||
|
||||
namespace Array
|
||||
|
||||
@[simp] theorem mapFinIdx_toVector (l : Array α) (f : (i : Nat) → α → (h : i < l.size) → β) :
|
||||
l.toVector.mapFinIdx f = (l.mapFinIdx f).toVector.cast (by simp) := by
|
||||
ext <;> simp
|
||||
|
||||
@[simp] theorem mapIdx_toVector (f : Nat → α → β) (l : Array α) :
|
||||
l.toVector.mapIdx f = (l.mapIdx f).toVector.cast (by simp) := by
|
||||
ext <;> simp
|
||||
|
||||
end Array
|
||||
|
||||
namespace Vector
|
||||
|
||||
/-! ### zipWithIndex -/
|
||||
|
||||
@[simp] theorem toList_zipWithIndex (a : Vector α n) :
|
||||
a.zipWithIndex.toList = a.toList.enum.map (fun (i, a) => (a, i)) := by
|
||||
rcases a with ⟨a, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem getElem_zipWithIndex (a : Vector α n) (i : Nat) (h : i < n) :
|
||||
(a.zipWithIndex)[i] = (a[i]'(by simp_all), i) := by
|
||||
rcases a with ⟨a, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem zipWithIndex_toVector {l : Array α} :
|
||||
l.toVector.zipWithIndex = l.zipWithIndex.toVector.cast (by simp) := by
|
||||
ext <;> simp
|
||||
|
||||
theorem mk_mem_zipWithIndex_iff_getElem? {x : α} {i : Nat} {l : Vector α n} :
|
||||
(x, i) ∈ l.zipWithIndex ↔ l[i]? = x := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp [Array.mk_mem_zipWithIndex_iff_getElem?]
|
||||
|
||||
theorem mem_enum_iff_getElem? {x : α × Nat} {l : Vector α n} :
|
||||
x ∈ l.zipWithIndex ↔ l[x.2]? = some x.1 :=
|
||||
mk_mem_zipWithIndex_iff_getElem?
|
||||
|
||||
/-! ### mapFinIdx -/
|
||||
|
||||
@[congr] theorem mapFinIdx_congr {xs ys : Vector α n} (w : xs = ys)
|
||||
(f : (i : Nat) → α → (h : i < n) → β) :
|
||||
mapFinIdx xs f = mapFinIdx ys f := by
|
||||
subst w
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_empty {f : (i : Nat) → α → (h : i < 0) → β} : mapFinIdx #v[] f = #v[] :=
|
||||
rfl
|
||||
|
||||
theorem mapFinIdx_eq_ofFn {as : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} :
|
||||
as.mapFinIdx f = Vector.ofFn fun i : Fin n => f i as[i] i.2 := by
|
||||
rcases as with ⟨as, rfl⟩
|
||||
simp [Array.mapFinIdx_eq_ofFn]
|
||||
|
||||
theorem mapFinIdx_append {K : Vector α n} {L : Vector α m} {f : (i : Nat) → α → (h : i < n + m) → β} :
|
||||
(K ++ L).mapFinIdx f =
|
||||
K.mapFinIdx (fun i a h => f i a (by omega)) ++
|
||||
L.mapFinIdx (fun i a h => f (i + n) a (by omega)) := by
|
||||
rcases K with ⟨K, rfl⟩
|
||||
rcases L with ⟨L, rfl⟩
|
||||
simp [Array.mapFinIdx_append]
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_push {l : Vector α n} {a : α} {f : (i : Nat) → α → (h : i < n + 1) → β} :
|
||||
mapFinIdx (l.push a) f =
|
||||
(mapFinIdx l (fun i a h => f i a (by omega))).push (f l.size a (by simp)) := by
|
||||
simp [← append_singleton, mapFinIdx_append]
|
||||
|
||||
theorem mapFinIdx_singleton {a : α} {f : (i : Nat) → α → (h : i < 1) → β} :
|
||||
#v[a].mapFinIdx f = #v[f 0 a (by simp)] := by
|
||||
simp
|
||||
|
||||
-- FIXME this lemma can't be stated until we've aligned `List/Array/Vector.attach`:
|
||||
-- theorem mapFinIdx_eq_zipWithIndex_map {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} :
|
||||
-- l.mapFinIdx f = l.zipWithIndex.attach.map
|
||||
-- fun ⟨⟨x, i⟩, m⟩ =>
|
||||
-- f i x (by simp [mk_mem_zipWithIndex_iff_getElem?, getElem?_eq_some_iff] at m; exact m.1) := by
|
||||
-- ext <;> simp
|
||||
|
||||
theorem exists_of_mem_mapFinIdx {b : β} {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β}
|
||||
(h : b ∈ l.mapFinIdx f) : ∃ (i : Nat) (h : i < n), f i l[i] h = b := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
exact List.exists_of_mem_mapFinIdx (by simpa using h)
|
||||
|
||||
@[simp] theorem mem_mapFinIdx {b : β} {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} :
|
||||
b ∈ l.mapFinIdx f ↔ ∃ (i : Nat) (h : i < n), f i l[i] h = b := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp
|
||||
|
||||
theorem mapFinIdx_eq_iff {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} :
|
||||
l.mapFinIdx f = l' ↔ ∀ (i : Nat) (h : i < n), l'[i] = f i l[i] h := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
rcases l' with ⟨l', h⟩
|
||||
simp [mapFinIdx_mk, eq_mk, getElem_mk, Array.mapFinIdx_eq_iff, h]
|
||||
|
||||
@[simp] theorem mapFinIdx_eq_singleton_iff {l : Vector α 1} {f : (i : Nat) → α → (h : i < 1) → β} {b : β} :
|
||||
l.mapFinIdx f = #v[b] ↔ ∃ (a : α), l = #v[a] ∧ f 0 a (by omega) = b := by
|
||||
rcases l with ⟨l, h⟩
|
||||
simp only [mapFinIdx_mk, eq_mk, Array.mapFinIdx_eq_singleton_iff]
|
||||
constructor
|
||||
· rintro ⟨a, rfl, rfl⟩
|
||||
exact ⟨a, by simp⟩
|
||||
· rintro ⟨a, rfl, rfl⟩
|
||||
exact ⟨a, by simp⟩
|
||||
|
||||
theorem mapFinIdx_eq_append_iff {l : Vector α (n + m)} {f : (i : Nat) → α → (h : i < n + m) → β}
|
||||
{l₁ : Vector β n} {l₂ : Vector β m} :
|
||||
l.mapFinIdx f = l₁ ++ l₂ ↔
|
||||
∃ (l₁' : Vector α n) (l₂' : Vector α m), l = l₁' ++ l₂' ∧
|
||||
l₁'.mapFinIdx (fun i a h => f i a (by omega)) = l₁ ∧
|
||||
l₂'.mapFinIdx (fun i a h => f (i + n) a (by omega)) = l₂ := by
|
||||
rcases l with ⟨l, h⟩
|
||||
rcases l₁ with ⟨l₁, rfl⟩
|
||||
rcases l₂ with ⟨l₂, rfl⟩
|
||||
simp only [mapFinIdx_mk, mk_append_mk, eq_mk, Array.mapFinIdx_eq_append_iff, toArray_mapFinIdx,
|
||||
mk_eq, toArray_append, exists_and_left, exists_prop]
|
||||
constructor
|
||||
· rintro ⟨l₁', l₂', rfl, h₁, h₂⟩
|
||||
have h₁' := congrArg Array.size h₁
|
||||
have h₂' := congrArg Array.size h₂
|
||||
simp only [Array.size_mapFinIdx] at h₁' h₂'
|
||||
exact ⟨⟨l₁', h₁'⟩, ⟨l₂', h₂'⟩, by simp_all⟩
|
||||
· rintro ⟨⟨l₁, s₁⟩, ⟨l₂, s₂⟩, rfl, h₁, h₂⟩
|
||||
refine ⟨l₁, l₂, by simp_all⟩
|
||||
|
||||
theorem mapFinIdx_eq_push_iff {l : Vector α (n + 1)} {b : β} {f : (i : Nat) → α → (h : i < n + 1) → β} {l₂ : Vector β n} :
|
||||
l.mapFinIdx f = l₂.push b ↔
|
||||
∃ (l₁ : Vector α n) (a : α), l = l₁.push a ∧
|
||||
l₁.mapFinIdx (fun i a h => f i a (by omega)) = l₂ ∧ b = f n a (by omega) := by
|
||||
rcases l with ⟨l, h⟩
|
||||
rcases l₂ with ⟨l₂, rfl⟩
|
||||
simp only [mapFinIdx_mk, push_mk, eq_mk, Array.mapFinIdx_eq_push_iff, mk_eq, toArray_push,
|
||||
toArray_mapFinIdx]
|
||||
constructor
|
||||
· rintro ⟨l₁, a, rfl, h₁, rfl⟩
|
||||
simp only [Array.size_push, Nat.add_right_cancel_iff] at h
|
||||
exact ⟨⟨l₁, h⟩, a, by simp_all⟩
|
||||
· rintro ⟨⟨l₁, h⟩, a, rfl, h₁, rfl⟩
|
||||
exact ⟨l₁, a, by simp_all⟩
|
||||
|
||||
theorem mapFinIdx_eq_mapFinIdx_iff {l : Vector α n} {f g : (i : Nat) → α → (h : i < n) → β} :
|
||||
l.mapFinIdx f = l.mapFinIdx g ↔ ∀ (i : Nat) (h : i < n), f i l[i] h = g i l[i] h := by
|
||||
rw [eq_comm, mapFinIdx_eq_iff]
|
||||
simp
|
||||
|
||||
@[simp] theorem mapFinIdx_mapFinIdx {l : Vector α n}
|
||||
{f : (i : Nat) → α → (h : i < n) → β}
|
||||
{g : (i : Nat) → β → (h : i < n) → γ} :
|
||||
(l.mapFinIdx f).mapFinIdx g = l.mapFinIdx (fun i a h => g i (f i a h) h) := by
|
||||
simp [mapFinIdx_eq_iff]
|
||||
|
||||
theorem mapFinIdx_eq_mkVector_iff {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} {b : β} :
|
||||
l.mapFinIdx f = mkVector n b ↔ ∀ (i : Nat) (h : i < n), f i l[i] h = b := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp [Array.mapFinIdx_eq_mkArray_iff]
|
||||
|
||||
@[simp] theorem mapFinIdx_reverse {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} :
|
||||
l.reverse.mapFinIdx f = (l.mapFinIdx (fun i a h => f (n - 1 - i) a (by omega))).reverse := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp
|
||||
|
||||
/-! ### mapIdx -/
|
||||
|
||||
@[simp]
|
||||
theorem mapIdx_empty {f : Nat → α → β} : mapIdx f #v[] = #v[] :=
|
||||
rfl
|
||||
|
||||
@[simp] theorem mapFinIdx_eq_mapIdx {l : Vector α n} {f : (i : Nat) → α → (h : i < n) → β} {g : Nat → α → β}
|
||||
(h : ∀ (i : Nat) (h : i < n), f i l[i] h = g i l[i]) :
|
||||
l.mapFinIdx f = l.mapIdx g := by
|
||||
simp_all [mapFinIdx_eq_iff]
|
||||
|
||||
theorem mapIdx_eq_mapFinIdx {l : Vector α n} {f : Nat → α → β} :
|
||||
l.mapIdx f = l.mapFinIdx (fun i a _ => f i a) := by
|
||||
simp [mapFinIdx_eq_mapIdx]
|
||||
|
||||
theorem mapIdx_eq_zipWithIndex_map {l : Vector α n} {f : Nat → α → β} :
|
||||
l.mapIdx f = l.zipWithIndex.map fun ⟨a, i⟩ => f i a := by
|
||||
ext <;> simp
|
||||
|
||||
theorem mapIdx_append {K : Vector α n} {L : Vector α m} :
|
||||
(K ++ L).mapIdx f = K.mapIdx f ++ L.mapIdx fun i => f (i + K.size) := by
|
||||
rcases K with ⟨K, rfl⟩
|
||||
rcases L with ⟨L, rfl⟩
|
||||
simp [Array.mapIdx_append]
|
||||
|
||||
@[simp]
|
||||
theorem mapIdx_push {l : Vector α n} {a : α} :
|
||||
mapIdx f (l.push a) = (mapIdx f l).push (f l.size a) := by
|
||||
simp [← append_singleton, mapIdx_append]
|
||||
|
||||
theorem mapIdx_singleton {a : α} : mapIdx f #v[a] = #v[f 0 a] := by
|
||||
simp
|
||||
|
||||
theorem exists_of_mem_mapIdx {b : β} {l : Vector α n}
|
||||
(h : b ∈ l.mapIdx f) : ∃ (i : Nat) (h : i < n), f i l[i] = b := by
|
||||
rw [mapIdx_eq_mapFinIdx] at h
|
||||
simpa [Fin.exists_iff] using exists_of_mem_mapFinIdx h
|
||||
|
||||
@[simp] theorem mem_mapIdx {b : β} {l : Vector α n} :
|
||||
b ∈ l.mapIdx f ↔ ∃ (i : Nat) (h : i < n), f i l[i] = b := by
|
||||
constructor
|
||||
· intro h
|
||||
exact exists_of_mem_mapIdx h
|
||||
· rintro ⟨i, h, rfl⟩
|
||||
rw [mem_iff_getElem]
|
||||
exact ⟨i, by simpa using h, by simp⟩
|
||||
|
||||
theorem mapIdx_eq_push_iff {l : Vector α (n + 1)} {b : β} :
|
||||
mapIdx f l = l₂.push b ↔
|
||||
∃ (a : α) (l₁ : Vector α n), l = l₁.push a ∧ mapIdx f l₁ = l₂ ∧ f l₁.size a = b := by
|
||||
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_push_iff]
|
||||
simp only [mapFinIdx_eq_mapIdx, exists_and_left, exists_prop]
|
||||
constructor
|
||||
· rintro ⟨l₁, a, rfl, rfl, rfl⟩
|
||||
exact ⟨a, l₁, by simp⟩
|
||||
· rintro ⟨a, l₁, rfl, rfl, rfl⟩
|
||||
exact ⟨l₁, a, rfl, by simp⟩
|
||||
|
||||
@[simp] theorem mapIdx_eq_singleton_iff {l : Vector α 1} {f : Nat → α → β} {b : β} :
|
||||
mapIdx f l = #v[b] ↔ ∃ (a : α), l = #v[a] ∧ f 0 a = b := by
|
||||
rcases l with ⟨l⟩
|
||||
simp
|
||||
|
||||
theorem mapIdx_eq_append_iff {l : Vector α (n + m)} {f : Nat → α → β} {l₁ : Vector β n} {l₂ : Vector β m} :
|
||||
mapIdx f l = l₁ ++ l₂ ↔
|
||||
∃ (l₁' : Vector α n) (l₂' : Vector α m), l = l₁' ++ l₂' ∧
|
||||
l₁'.mapIdx f = l₁ ∧
|
||||
l₂'.mapIdx (fun i => f (i + l₁'.size)) = l₂ := by
|
||||
rcases l with ⟨l, h⟩
|
||||
rcases l₁ with ⟨l₁, rfl⟩
|
||||
rcases l₂ with ⟨l₂, rfl⟩
|
||||
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_append_iff]
|
||||
simp
|
||||
|
||||
theorem mapIdx_eq_iff {l : Vector α n} :
|
||||
mapIdx f l = l' ↔ ∀ (i : Nat) (h : i < n), f i l[i] = l'[i] := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
rcases l' with ⟨l', h⟩
|
||||
simp only [mapIdx_mk, eq_mk, Array.mapIdx_eq_iff, getElem_mk]
|
||||
constructor
|
||||
· rintro h' i h
|
||||
specialize h' i
|
||||
simp_all
|
||||
· intro h' i
|
||||
specialize h' i
|
||||
by_cases w : i < l.size
|
||||
· specialize h' w
|
||||
simp_all
|
||||
· simp only [Nat.not_lt] at w
|
||||
simp_all [Array.getElem?_eq_none_iff.mpr w]
|
||||
|
||||
theorem mapIdx_eq_mapIdx_iff {l : Vector α n} :
|
||||
mapIdx f l = mapIdx g l ↔ ∀ (i : Nat) (h : i < n), f i l[i] = g i l[i] := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp [Array.mapIdx_eq_mapIdx_iff]
|
||||
|
||||
@[simp] theorem mapIdx_set {l : Vector α n} {i : Nat} {h : i < n} {a : α} :
|
||||
(l.set i a).mapIdx f = (l.mapIdx f).set i (f i a) (by simpa) := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem mapIdx_setIfInBounds {l : Vector α n} {i : Nat} {a : α} :
|
||||
(l.setIfInBounds i a).mapIdx f = (l.mapIdx f).setIfInBounds i (f i a) := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem back?_mapIdx {l : Vector α n} {f : Nat → α → β} :
|
||||
(mapIdx f l).back? = (l.back?).map (f (l.size - 1)) := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem back_mapIdx [NeZero n] {l : Vector α n} {f : Nat → α → β} :
|
||||
(mapIdx f l).back = f (l.size - 1) (l.back) := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem mapIdx_mapIdx {l : Vector α n} {f : Nat → α → β} {g : Nat → β → γ} :
|
||||
(l.mapIdx f).mapIdx g = l.mapIdx (fun i => g i ∘ f i) := by
|
||||
simp [mapIdx_eq_iff]
|
||||
|
||||
theorem mapIdx_eq_mkVector_iff {l : Vector α n} {f : Nat → α → β} {b : β} :
|
||||
mapIdx f l = mkVector n b ↔ ∀ (i : Nat) (h : i < n), f i l[i] = b := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp [Array.mapIdx_eq_mkArray_iff]
|
||||
|
||||
@[simp] theorem mapIdx_reverse {l : Vector α n} {f : Nat → α → β} :
|
||||
l.reverse.mapIdx f = (mapIdx (fun i => f (l.size - 1 - i)) l).reverse := by
|
||||
rcases l with ⟨l, rfl⟩
|
||||
simp [Array.mapIdx_reverse]
|
||||
|
||||
end Vector
|
||||
Reference in New Issue
Block a user