|
| 1 | +/- |
| 2 | +Copyright (c) 2016 Microsoft Corporation. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Leonardo de Moura |
| 5 | +-/ |
| 6 | +import Mathlib.Mathport.Rename |
| 7 | +import Std.Data.List.Basic |
| 8 | +import Std.Data.List.Lemmas |
| 9 | +import Mathlib.Init.Data.List.Basic |
| 10 | +import Mathlib.Init.Data.List.Lemmas |
| 11 | + |
| 12 | +/-! |
| 13 | +The type `Vector` represents lists with fixed length. |
| 14 | +-/ |
| 15 | + |
| 16 | +universe u v w |
| 17 | +/-- `Vector α n` is the type of lists of length `n` with elements of type `α`. -/ |
| 18 | +def Vector (α : Type u) (n : ℕ) := |
| 19 | + { l : List α // l.length = n } |
| 20 | +#align vector Vector |
| 21 | + |
| 22 | +namespace Vector |
| 23 | + |
| 24 | +variable {α : Type u} {β : Type v} {φ : Type w} |
| 25 | + |
| 26 | +variable {n : ℕ} |
| 27 | + |
| 28 | +instance [DecidableEq α] : DecidableEq (Vector α n) := by |
| 29 | + unfold Vector |
| 30 | + infer_instance |
| 31 | + |
| 32 | +/-- The empty vector with elements of type `α` -/ |
| 33 | +@[match_pattern] |
| 34 | +def nil : Vector α 0 := |
| 35 | + ⟨[], rfl⟩ |
| 36 | +#align vector.nil Vector.nil |
| 37 | + |
| 38 | +/-- If `a : α` and `l : Vector α n`, then `cons a l`, is the vector of length `n + 1` |
| 39 | +whose first element is a and with l as the rest of the list. -/ |
| 40 | +@[match_pattern] |
| 41 | +def cons : α → Vector α n → Vector α (Nat.succ n) |
| 42 | + | a, ⟨v, h⟩ => ⟨a :: v, congrArg Nat.succ h⟩ |
| 43 | +#align vector.cons Vector.cons |
| 44 | + |
| 45 | + |
| 46 | +/-- The length of a vector. -/ |
| 47 | +@[reducible, nolint unusedArguments] |
| 48 | +def length (_ : Vector α n) : ℕ := |
| 49 | + n |
| 50 | +#align vector.length Vector.length |
| 51 | + |
| 52 | +open Nat |
| 53 | + |
| 54 | +/-- The first element of a vector with length at least `1`. -/ |
| 55 | +def head : Vector α (Nat.succ n) → α |
| 56 | + | ⟨[], h⟩ => by contradiction |
| 57 | + | ⟨a :: _, _⟩ => a |
| 58 | +#align vector.head Vector.head |
| 59 | + |
| 60 | +/-- The head of a vector obtained by prepending is the element prepended. -/ |
| 61 | +theorem head_cons (a : α) : ∀ v : Vector α n, head (cons a v) = a |
| 62 | + | ⟨_, _⟩ => rfl |
| 63 | +#align vector.head_cons Vector.head_cons |
| 64 | + |
| 65 | +/-- The tail of a vector, with an empty vector having empty tail. -/ |
| 66 | +def tail : Vector α n → Vector α (n - 1) |
| 67 | + | ⟨[], h⟩ => ⟨[], congrArg pred h⟩ |
| 68 | + | ⟨_ :: v, h⟩ => ⟨v, congrArg pred h⟩ |
| 69 | +#align vector.tail Vector.tail |
| 70 | + |
| 71 | +/-- The tail of a vector obtained by prepending is the vector prepended. to -/ |
| 72 | +theorem tail_cons (a : α) : ∀ v : Vector α n, tail (cons a v) = v |
| 73 | + | ⟨_, _⟩ => rfl |
| 74 | +#align vector.tail_cons Vector.tail_cons |
| 75 | + |
| 76 | +/-- Prepending the head of a vector to its tail gives the vector. -/ |
| 77 | +@[simp] |
| 78 | +theorem cons_head_tail : ∀ v : Vector α (succ n), cons (head v) (tail v) = v |
| 79 | + | ⟨[], h⟩ => by contradiction |
| 80 | + | ⟨a :: v, h⟩ => rfl |
| 81 | +#align vector.cons_head_tail Vector.cons_head_tail |
| 82 | + |
| 83 | +/-- The list obtained from a vector. -/ |
| 84 | +def toList (v : Vector α n) : List α := |
| 85 | + v.1 |
| 86 | +#align vector.to_list Vector.toList |
| 87 | + |
| 88 | +/-- nth element of a vector, indexed by a `Fin` type. -/ |
| 89 | +def nth : ∀ _ : Vector α n, Fin n → α |
| 90 | + | ⟨l, h⟩, i => l.nthLe i.1 (by rw [h] ; exact i.2) |
| 91 | +#align vector.nth Vector.nth |
| 92 | + |
| 93 | +/-- Appending a vector to another. -/ |
| 94 | +def append {n m : Nat} : Vector α n → Vector α m → Vector α (n + m) |
| 95 | + | ⟨l₁, h₁⟩, ⟨l₂, h₂⟩ => ⟨l₁ ++ l₂, by simp [*]⟩ |
| 96 | +#align vector.append Vector.append |
| 97 | + |
| 98 | +/- warning: vector.elim -> Vector.elim is a dubious translation: |
| 99 | +lean 3 declaration is |
| 100 | + forall {α : Type.{u_1}} {C : forall {n : ℕ}, |
| 101 | + (Vector.{u_1} α n) -> Sort.{u}}, (forall (l : List.{u_1} α), |
| 102 | + C (List.length.{u_1} α l) (Subtype.mk.{succ u_1} (List.{u_1} α) |
| 103 | + (fun (l_1 : List.{u_1} α) => Eq.{1} ℕ (List.length.{u_1} α l_1) |
| 104 | + (List.length.{u_1} α l)) l (Vector.Elim._proof_1.{u_1} α l))) -> |
| 105 | + (forall {n : ℕ} (v : Vector.{u_1} α n), C n v) |
| 106 | +but is expected to have type |
| 107 | + forall {α : Type.{_aux_param_0}} {C : forall {n : ℕ}, (Vector.{_aux_param_0} α n) -> Sort.{u}}, |
| 108 | + (forall (l : List.{_aux_param_0} α), |
| 109 | + C (List.length.{_aux_param_0} α l) (Subtype.mk.{succ _aux_param_0} (List.{_aux_param_0} α) |
| 110 | + (fun (l_1 : List.{_aux_param_0} α) => Eq.{1} ℕ (List.length.{_aux_param_0} α l_1) |
| 111 | + (List.length.{_aux_param_0} α l)) l (rfl.{1} ℕ (List.length.{_aux_param_0} α l)))) -> |
| 112 | + (forall {n : ℕ} (v : Vector.{_aux_param_0} α n), C n v) |
| 113 | +Case conversion may be inaccurate. Consider using '#align vector.elim Vector.elimₓ'. -/ |
| 114 | +/-- Elimination rule for `Vector`. -/ |
| 115 | +@[elab_as_elim] |
| 116 | +def elim {α} {C : ∀ {n}, Vector α n → Sort u} |
| 117 | + (H : ∀ l : List α, C ⟨l, rfl⟩) {n : ℕ} : ∀ v : Vector α n, C v |
| 118 | + | ⟨l, h⟩ => |
| 119 | + match n, h with |
| 120 | + | _, rfl => H l |
| 121 | +#align vector.elim Vector.elim |
| 122 | + |
| 123 | +/-- Map a vector under a function. -/ |
| 124 | +def map (f : α → β) : Vector α n → Vector β n |
| 125 | + | ⟨l, h⟩ => ⟨List.map f l, by simp [*]⟩ |
| 126 | +#align vector.map Vector.map |
| 127 | + |
| 128 | +/-- A `nil` vector maps to a `nil` vector. -/ |
| 129 | +@[simp] |
| 130 | +theorem map_nil (f : α → β) : map f nil = nil := |
| 131 | + rfl |
| 132 | +#align vector.map_nil Vector.map_nil |
| 133 | + |
| 134 | +/-- `map` is natural with respect to `cons`. -/ |
| 135 | +theorem map_cons (f : α → β) (a : α) : ∀ v : Vector α n, map f (cons a v) = cons (f a) (map f v) |
| 136 | + | ⟨_, _⟩ => rfl |
| 137 | +#align vector.map_cons Vector.map_cons |
| 138 | + |
| 139 | +/-- Mapping two vectors under a curried function of two variables. -/ |
| 140 | +def map₂ (f : α → β → φ) : Vector α n → Vector β n → Vector φ n |
| 141 | + | ⟨x, _⟩, ⟨y, _⟩ => ⟨List.map₂ f x y, by simp [*]⟩ |
| 142 | +#align vector.map₂ Vector.map₂ |
| 143 | + |
| 144 | +/-- Vector obtained by repeating an element. -/ |
| 145 | +def «repeat» (a : α) (n : ℕ) : Vector α n := |
| 146 | + ⟨List.repeat a n, List.length_repeat a n⟩ |
| 147 | +#align vector.repeat Vector.repeat |
| 148 | + |
| 149 | +/-- Drop `i` elements from a vector of length `n`; we can have `i > n`. -/ |
| 150 | +def drop (i : ℕ) : Vector α n → Vector α (n - i) |
| 151 | + | ⟨l, p⟩ => ⟨List.drop i l, by simp [*]⟩ |
| 152 | +#align vector.drop Vector.drop |
| 153 | + |
| 154 | +/-- Take `i` elements from a vector of length `n`; we can have `i > n`. -/ |
| 155 | +def take (i : ℕ) : Vector α n → Vector α (min i n) |
| 156 | + | ⟨l, p⟩ => ⟨List.take i l, by simp [*]⟩ |
| 157 | +#align vector.take Vector.take |
| 158 | + |
| 159 | +/-- Remove the element at position `i` from a vector of length `n`. -/ |
| 160 | +def removeNth (i : Fin n) : Vector α n → Vector α (n - 1) |
| 161 | + | ⟨l, p⟩ => ⟨List.removeNth l i.1, by rw [l.length_removeNth] <;> rw [p] ; exact i.2⟩ |
| 162 | +#align vector.remove_nth Vector.removeNth |
| 163 | + |
| 164 | +/-- Vector of length `n` from a function on `Fin n`. -/ |
| 165 | +def ofFn : ∀ {n}, (Fin n → α) → Vector α n |
| 166 | + | 0, _ => nil |
| 167 | + | _ + 1, f => cons (f 0) (ofFn fun i ↦ f i.succ) |
| 168 | +#align vector.of_fn Vector.ofFn |
| 169 | + |
| 170 | +section Accum |
| 171 | + |
| 172 | +open Prod |
| 173 | + |
| 174 | +variable {σ : Type} |
| 175 | + |
| 176 | +/-- Runs a function over a vector returning the intermediate results and a |
| 177 | +a final result. |
| 178 | +-/ |
| 179 | +def mapAccumr (f : α → σ → σ × β) : Vector α n → σ → σ × Vector β n |
| 180 | + | ⟨x, px⟩, c => |
| 181 | + let res := List.mapAccumr f x c |
| 182 | + ⟨res.1, res.2, by simp [*]⟩ |
| 183 | +#align vector.map_accumr Vector.mapAccumr |
| 184 | + |
| 185 | +/-- Runs a function over a pair of vectors returning the intermediate results and a |
| 186 | +a final result. |
| 187 | +-/ |
| 188 | +def mapAccumr₂ {α β σ φ : Type} (f : α → β → σ → σ × φ) : |
| 189 | + Vector α n → Vector β n → σ → σ × Vector φ n |
| 190 | + | ⟨x, px⟩, ⟨y, py⟩, c => |
| 191 | + let res := List.mapAccumr₂ f x y c |
| 192 | + ⟨res.1, res.2, by simp [*]⟩ |
| 193 | +#align vector.map_accumr₂ Vector.mapAccumr₂ |
| 194 | + |
| 195 | +end Accum |
| 196 | + |
| 197 | +/-- Vector is determined by the underlying list. -/ |
| 198 | +protected theorem eq {n : ℕ} : ∀ a1 a2 : Vector α n, toList a1 = toList a2 → a1 = a2 |
| 199 | + | ⟨_, _⟩, ⟨_, _⟩, rfl => rfl |
| 200 | +#align vector.eq Vector.eq |
| 201 | + |
| 202 | +/-- A vector of length `0` is a `nil` vector. -/ |
| 203 | +protected theorem eq_nil (v : Vector α 0) : v = nil := |
| 204 | + v.eq nil (List.eq_nil_of_length_eq_zero v.2) |
| 205 | +#align vector.eq_nil Vector.eq_nil |
| 206 | + |
| 207 | +/-- Vector of length from a list `v` |
| 208 | +with witness that `v` has length `n` maps to `v` under `toList`. -/ |
| 209 | +@[simp] |
| 210 | +theorem toList_mk (v : List α) (P : List.length v = n) : toList (Subtype.mk v P) = v := |
| 211 | + rfl |
| 212 | +#align vector.to_list_mk Vector.toList_mk |
| 213 | + |
| 214 | +/-- A nil vector maps to a nil list. -/ |
| 215 | +@[simp] |
| 216 | +theorem to_list_nil : toList nil = @List.nil α := |
| 217 | + rfl |
| 218 | +#align vector.to_list_nil Vector.to_list_nil |
| 219 | + |
| 220 | +/-- The length of the list to which a vector of length `n` maps is `n`. -/ |
| 221 | +@[simp] |
| 222 | +theorem to_list_length (v : Vector α n) : (toList v).length = n := |
| 223 | + v.2 |
| 224 | +#align vector.to_list_length Vector.to_list_length |
| 225 | + |
| 226 | +/-- `toList` of `cons` of a vector and an element is |
| 227 | +the `cons` of the list obtained by `toList` and the element -/ |
| 228 | +@[simp] |
| 229 | +theorem to_list_cons (a : α) (v : Vector α n) : toList (cons a v) = a :: toList v := by |
| 230 | + cases v ; rfl |
| 231 | +#align vector.to_list_cons Vector.to_list_cons |
| 232 | + |
| 233 | +/-- Appending of vectors corresponds under `toList` to appending of lists. -/ |
| 234 | +@[simp] |
| 235 | +theorem to_list_append {n m : ℕ} (v : Vector α n) (w : Vector α m) : |
| 236 | + toList (append v w) = toList v ++ toList w := by |
| 237 | + cases v |
| 238 | + cases w |
| 239 | + rfl |
| 240 | +#align vector.to_list_append Vector.to_list_append |
| 241 | + |
| 242 | +/-- `drop` of vectors corresponds under `toList` to `drop` of lists. -/ |
| 243 | +@[simp] |
| 244 | +theorem to_list_drop {n m : ℕ} (v : Vector α m) : toList (drop n v) = List.drop n (toList v) := by |
| 245 | + cases v |
| 246 | + rfl |
| 247 | +#align vector.to_list_drop Vector.to_list_drop |
| 248 | + |
| 249 | +/-- `take` of vectors corresponds under `toList` to `take` of lists. -/ |
| 250 | +@[simp] |
| 251 | +theorem to_list_take {n m : ℕ} (v : Vector α m) : toList (take n v) = List.take n (toList v) := by |
| 252 | + cases v |
| 253 | + rfl |
| 254 | +#align vector.to_list_take Vector.to_list_take |
| 255 | + |
| 256 | +end Vector |
0 commit comments