2014-12-22 20:33:29 +00:00
|
|
|
|
/-
|
|
|
|
|
Copyright (c) 2014 Floris van Doorn. All rights reserved.
|
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
Author: Floris van Doorn, Leonardo de Moura
|
|
|
|
|
-/
|
2015-03-09 15:41:36 +00:00
|
|
|
|
import data.nat data.list data.fin
|
|
|
|
|
open nat prod fin
|
2014-12-22 20:33:29 +00:00
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
inductive vector (A : Type) : nat → Type :=
|
2015-02-26 01:00:10 +00:00
|
|
|
|
| nil {} : vector A zero
|
|
|
|
|
| cons : Π {n}, A → vector A n → vector A (succ n)
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-09-19 23:15:04 +00:00
|
|
|
|
namespace vector
|
2014-10-21 21:08:07 +00:00
|
|
|
|
notation a :: b := cons a b
|
2015-03-14 05:25:21 +00:00
|
|
|
|
notation `[` l:(foldr `,` (h t, cons h t) nil `]`) := l
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
variables {A B C : Type}
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
protected definition is_inhabited [instance] [h : inhabited A] : ∀ (n : nat), inhabited (vector A n)
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 := inhabited.mk []
|
|
|
|
|
| (n+1) := inhabited.mk (inhabited.value h :: inhabited.value (is_inhabited n))
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem vector0_eq_nil : ∀ (v : vector A 0), v = []
|
|
|
|
|
| [] := rfl
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition head : Π {n : nat}, vector A (succ n) → A
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| n (a::v) := a
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition tail : Π {n : nat}, vector A (succ n) → vector A n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| n (a::v) := v
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem head_cons {n : nat} (h : A) (t : vector A n) : head (h :: t) = h :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem tail_cons {n : nat} (h : A) (t : vector A n) : tail (h :: t) = t :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
theorem eta : ∀ {n : nat} (v : vector A (succ n)), head v :: tail v = v
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| n (a::v) := rfl
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition last : Π {n : nat}, vector A (succ n) → A
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| last [a] := a
|
|
|
|
|
| last (a::v) := last v
|
2014-11-16 04:21:18 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem last_singleton (a : A) : last [a] = a :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem last_cons {n : nat} (a : A) (v : vector A (succ n)) : last (a :: v) = last v :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition const : Π (n : nat), A → vector A n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 a := []
|
|
|
|
|
| (succ n) a := a :: const n a
|
2014-11-16 04:21:18 +00:00
|
|
|
|
|
2014-11-16 06:36:52 +00:00
|
|
|
|
theorem head_const (n : nat) (a : A) : head (const (succ n) a) = a :=
|
2014-11-16 04:21:18 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
theorem last_const : ∀ (n : nat) (a : A), last (const (succ n) a) = a
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 a := rfl
|
|
|
|
|
| (n+1) a := last_const n a
|
2014-11-16 04:21:18 +00:00
|
|
|
|
|
2015-03-09 15:41:36 +00:00
|
|
|
|
definition nth : Π {n : nat}, vector A n → fin n → A
|
2015-06-05 17:32:24 +00:00
|
|
|
|
| ⌞0⌟ [] i := elim0 i
|
|
|
|
|
| ⌞n+1⌟ (a :: v) (mk 0 _) := a
|
|
|
|
|
| ⌞n+1⌟ (a :: v) (mk (succ i) h) := nth v (mk_pred i h)
|
|
|
|
|
|
|
|
|
|
lemma nth_zero {n : nat} (a : A) (v : vector A n) (h : 0 < succ n) : nth (a::v) (mk 0 h) = a :=
|
|
|
|
|
rfl
|
|
|
|
|
|
|
|
|
|
lemma nth_succ {n : nat} (a : A) (v : vector A n) (i : nat) (h : succ i < succ n)
|
|
|
|
|
: nth (a::v) (mk (succ i) h) = nth v (mk_pred i h) :=
|
|
|
|
|
rfl
|
2015-03-09 15:41:36 +00:00
|
|
|
|
|
|
|
|
|
definition tabulate : Π {n : nat}, (fin n → A) → vector A n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 f := []
|
2015-06-05 17:32:24 +00:00
|
|
|
|
| (n+1) f := f (@zero n) :: tabulate (λ i : fin n, f (succ i))
|
2015-03-09 15:41:36 +00:00
|
|
|
|
|
|
|
|
|
theorem nth_tabulate : ∀ {n : nat} (f : fin n → A) (i : fin n), nth (tabulate f) i = f i
|
2015-06-05 17:32:24 +00:00
|
|
|
|
| 0 f i := elim0 i
|
|
|
|
|
| (n+1) f (mk 0 h) := rfl
|
|
|
|
|
| (n+1) f (mk (succ i) h) :=
|
2015-03-09 15:41:36 +00:00
|
|
|
|
begin
|
2015-06-05 17:32:24 +00:00
|
|
|
|
change nth (f (@zero n) :: tabulate (λ i : fin n, f (succ i))) (mk (succ i) h) = f (mk (succ i) h),
|
|
|
|
|
rewrite nth_succ,
|
2015-03-09 15:41:36 +00:00
|
|
|
|
rewrite nth_tabulate
|
|
|
|
|
end
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition map (f : A → B) : Π {n : nat}, vector A n → vector B n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| map [] := []
|
2015-02-26 00:20:44 +00:00
|
|
|
|
| map (a::v) := f a :: map v
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem map_nil (f : A → B) : map f [] = [] :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem map_cons {n : nat} (f : A → B) (h : A) (t : vector A n) : map f (h :: t) = f h :: map f t :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-03-09 15:41:36 +00:00
|
|
|
|
theorem nth_map (f : A → B) : ∀ {n : nat} (v : vector A n) (i : fin n), nth (map f v) i = f (nth v i)
|
2015-06-05 17:32:24 +00:00
|
|
|
|
| 0 v i := elim0 i
|
|
|
|
|
| (succ n) (a :: t) (mk 0 h) := rfl
|
|
|
|
|
| (succ n) (a :: t) (mk (succ i) h) := by rewrite [map_cons, *nth_succ, nth_map]
|
2015-03-09 15:41:36 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition map2 (f : A → B → C) : Π {n : nat}, vector A n → vector B n → vector C n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| map2 [] [] := []
|
2015-02-26 00:20:44 +00:00
|
|
|
|
| map2 (a::va) (b::vb) := f a b :: map2 va vb
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem map2_nil (f : A → B → C) : map2 f [] [] = [] :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem map2_cons {n : nat} (f : A → B → C) (h₁ : A) (h₂ : B) (t₁ : vector A n) (t₂ : vector B n) :
|
|
|
|
|
map2 f (h₁ :: t₁) (h₂ :: t₂) = f h₁ h₂ :: map2 f t₁ t₂ :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition append : Π {n m : nat}, vector A n → vector A m → vector A (n ⊕ m)
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 m [] w := w
|
2015-03-07 01:37:03 +00:00
|
|
|
|
| (succ n) m (a::v) w := a :: (append v w)
|
2014-11-12 06:33:47 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem nil_append {n : nat} (v : vector A n) : append [] v = v :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem append_cons {n m : nat} (h : A) (t : vector A n) (v : vector A m) :
|
|
|
|
|
append (h::t) v = h :: (append t v) :=
|
2014-11-12 06:33:47 +00:00
|
|
|
|
rfl
|
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem append_nil : Π {n : nat} (v : vector A n), append v [] == v
|
|
|
|
|
| 0 [] := !heq.refl
|
|
|
|
|
| (n+1) (h::t) :=
|
2015-03-09 05:51:11 +00:00
|
|
|
|
begin
|
2015-03-14 05:25:21 +00:00
|
|
|
|
change (h :: append t [] == h :: t),
|
|
|
|
|
have H₁ : append t [] == t, from append_nil t,
|
|
|
|
|
revert H₁, generalize (append t []),
|
2015-03-09 05:51:11 +00:00
|
|
|
|
rewrite [-add_eq_addl, add_zero],
|
2015-04-30 18:00:39 +00:00
|
|
|
|
intro w H₁,
|
2015-05-25 23:48:33 +00:00
|
|
|
|
rewrite [heq.to_eq H₁]
|
2015-03-09 05:51:11 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
theorem map_append (f : A → B) : ∀ {n m : nat} (v : vector A n) (w : vector A m), map f (append v w) = append (map f v) (map f w)
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 m [] w := rfl
|
|
|
|
|
| (n+1) m (h :: t) w :=
|
2015-03-09 05:51:11 +00:00
|
|
|
|
begin
|
|
|
|
|
change (f h :: map f (append t w) = f h :: append (map f t) (map f w)),
|
|
|
|
|
rewrite map_append
|
|
|
|
|
end
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition unzip : Π {n : nat}, vector (A × B) n → vector A n × vector B n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| unzip [] := ([], [])
|
2015-02-26 00:20:44 +00:00
|
|
|
|
| unzip ((a, b) :: v) := (a :: pr₁ (unzip v), b :: pr₂ (unzip v))
|
2014-11-16 06:19:23 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem unzip_nil : unzip (@nil (A × B)) = ([], []) :=
|
2015-01-08 19:17:28 +00:00
|
|
|
|
rfl
|
2014-11-16 06:19:23 +00:00
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem unzip_cons {n : nat} (a : A) (b : B) (v : vector (A × B) n) :
|
|
|
|
|
unzip ((a, b) :: v) = (a :: pr₁ (unzip v), b :: pr₂ (unzip v)) :=
|
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition zip : Π {n : nat}, vector A n → vector B n → vector (A × B) n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| zip [] [] := []
|
2015-02-26 00:20:44 +00:00
|
|
|
|
| zip (a::va) (b::vb) := ((a, b) :: zip va vb)
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem zip_nil_nil : zip (@nil A) (@nil B) = nil :=
|
2014-11-16 06:36:52 +00:00
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem zip_cons_cons {n : nat} (a : A) (b : B) (va : vector A n) (vb : vector B n) :
|
|
|
|
|
zip (a::va) (b::vb) = ((a, b) :: zip va vb) :=
|
2014-11-16 06:36:52 +00:00
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
theorem unzip_zip : ∀ {n : nat} (v₁ : vector A n) (v₂ : vector B n), unzip (zip v₁ v₂) = (v₁, v₂)
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] [] := rfl
|
|
|
|
|
| (n+1) (a::va) (b::vb) := calc
|
2015-01-08 19:17:28 +00:00
|
|
|
|
unzip (zip (a :: va) (b :: vb))
|
|
|
|
|
= (a :: pr₁ (unzip (zip va vb)), b :: pr₂ (unzip (zip va vb))) : rfl
|
2015-03-09 05:51:11 +00:00
|
|
|
|
... = (a :: pr₁ (va, vb), b :: pr₂ (va, vb)) : by rewrite unzip_zip
|
2015-01-08 19:17:28 +00:00
|
|
|
|
... = (a :: va, b :: vb) : rfl
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
theorem zip_unzip : ∀ {n : nat} (v : vector (A × B) n), zip (pr₁ (unzip v)) (pr₂ (unzip v)) = v
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] := rfl
|
|
|
|
|
| (n+1) ((a, b) :: v) := calc
|
2015-01-08 19:17:28 +00:00
|
|
|
|
zip (pr₁ (unzip ((a, b) :: v))) (pr₂ (unzip ((a, b) :: v)))
|
|
|
|
|
= (a, b) :: zip (pr₁ (unzip v)) (pr₂ (unzip v)) : rfl
|
2015-03-09 05:51:11 +00:00
|
|
|
|
... = (a, b) :: v : by rewrite zip_unzip
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2014-12-22 20:33:29 +00:00
|
|
|
|
/- Concat -/
|
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
definition concat : Π {n : nat}, vector A n → A → vector A (succ n)
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| concat [] a := [a]
|
2015-02-26 00:20:44 +00:00
|
|
|
|
| concat (b::v) a := b :: concat v a
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-03-14 05:25:21 +00:00
|
|
|
|
theorem concat_nil (a : A) : concat [] a = [a] :=
|
2014-11-16 06:36:52 +00:00
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-01-08 19:17:28 +00:00
|
|
|
|
theorem concat_cons {n : nat} (b : A) (v : vector A n) (a : A) : concat (b :: v) a = b :: concat v a :=
|
|
|
|
|
rfl
|
2014-09-05 16:45:01 +00:00
|
|
|
|
|
2015-02-26 00:20:44 +00:00
|
|
|
|
theorem last_concat : ∀ {n : nat} (v : vector A n) (a : A), last (concat v a) = a
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] a := rfl
|
|
|
|
|
| (n+1) (b::v) a := calc
|
2015-01-08 19:17:28 +00:00
|
|
|
|
last (concat (b::v) a) = last (concat v a) : rfl
|
|
|
|
|
... = a : last_concat v a
|
2015-03-09 05:51:11 +00:00
|
|
|
|
|
|
|
|
|
/- Reverse -/
|
|
|
|
|
|
|
|
|
|
definition reverse : Π {n : nat}, vector A n → vector A n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] := []
|
|
|
|
|
| (n+1) (x :: xs) := concat (reverse xs) x
|
2015-03-09 05:51:11 +00:00
|
|
|
|
|
|
|
|
|
theorem reverse_concat : Π {n : nat} (xs : vector A n) (a : A), reverse (concat xs a) = a :: reverse xs
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] a := rfl
|
|
|
|
|
| (n+1) (x :: xs) a :=
|
2015-03-09 05:51:11 +00:00
|
|
|
|
begin
|
|
|
|
|
change (concat (reverse (concat xs a)) x = a :: reverse (x :: xs)),
|
|
|
|
|
rewrite reverse_concat
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
theorem reverse_reverse : Π {n : nat} (xs : vector A n), reverse (reverse xs) = xs
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] := rfl
|
|
|
|
|
| (n+1) (x :: xs) :=
|
2015-03-09 05:51:11 +00:00
|
|
|
|
begin
|
|
|
|
|
change (reverse (concat (reverse xs) x) = x :: xs),
|
|
|
|
|
rewrite [reverse_concat, reverse_reverse]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
/- list <-> vector -/
|
|
|
|
|
|
|
|
|
|
definition of_list {A : Type} : Π (l : list A), vector A (list.length l)
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| list.nil := []
|
2015-03-09 05:51:11 +00:00
|
|
|
|
| (list.cons a l) := a :: (of_list l)
|
|
|
|
|
|
|
|
|
|
definition to_list {A : Type} : Π {n : nat}, vector A n → list A
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] := list.nil
|
|
|
|
|
| (n+1) (a :: vs) := list.cons a (to_list vs)
|
2015-03-09 05:51:11 +00:00
|
|
|
|
|
|
|
|
|
theorem to_list_of_list {A : Type} : ∀ (l : list A), to_list (of_list l) = l
|
|
|
|
|
| list.nil := rfl
|
|
|
|
|
| (list.cons a l) :=
|
|
|
|
|
begin
|
|
|
|
|
change (list.cons a (to_list (of_list l)) = list.cons a l),
|
|
|
|
|
rewrite to_list_of_list
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
theorem length_to_list {A : Type} : ∀ {n : nat} (v : vector A n), list.length (to_list v) = n
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| 0 [] := rfl
|
|
|
|
|
| (n+1) (a :: vs) :=
|
2015-03-09 05:51:11 +00:00
|
|
|
|
begin
|
|
|
|
|
change (succ (list.length (to_list vs)) = succ n),
|
|
|
|
|
rewrite length_to_list
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
theorem of_list_to_list {A : Type} : ∀ {n : nat} (v : vector A n), of_list (to_list v) == v
|
2015-05-25 23:48:33 +00:00
|
|
|
|
| 0 [] := by reflexivity
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| (n+1) (a :: vs) :=
|
2015-03-09 05:51:11 +00:00
|
|
|
|
begin
|
|
|
|
|
change (a :: of_list (to_list vs) == a :: vs),
|
|
|
|
|
have H₁ : of_list (to_list vs) == vs, from of_list_to_list vs,
|
|
|
|
|
revert H₁,
|
|
|
|
|
generalize (of_list (to_list vs)),
|
|
|
|
|
rewrite length_to_list at *,
|
|
|
|
|
intro vs', intro H,
|
|
|
|
|
have H₂ : vs' = vs, from heq.to_eq H,
|
2015-05-25 23:48:33 +00:00
|
|
|
|
substvars
|
2015-03-09 05:51:11 +00:00
|
|
|
|
end
|
|
|
|
|
|
2015-05-25 23:48:33 +00:00
|
|
|
|
|
2015-03-09 15:41:36 +00:00
|
|
|
|
/- decidable equality -/
|
|
|
|
|
open decidable
|
|
|
|
|
definition decidable_eq [H : decidable_eq A] : ∀ {n : nat} (v₁ v₂ : vector A n), decidable (v₁ = v₂)
|
2015-05-04 04:40:33 +00:00
|
|
|
|
| ⌞0⌟ [] [] := by left; reflexivity
|
2015-03-14 05:25:21 +00:00
|
|
|
|
| ⌞n+1⌟ (a::v₁) (b::v₂) :=
|
2015-03-09 15:41:36 +00:00
|
|
|
|
match H a b with
|
|
|
|
|
| inl Hab :=
|
|
|
|
|
match decidable_eq v₁ v₂ with
|
2015-05-04 04:40:33 +00:00
|
|
|
|
| inl He := by left; congruence; repeat assumption
|
2015-05-25 17:43:28 +00:00
|
|
|
|
| inr Hn := by right; intro h; injection h; contradiction
|
2015-03-09 15:41:36 +00:00
|
|
|
|
end
|
2015-05-25 17:43:28 +00:00
|
|
|
|
| inr Hnab := by right; intro h; injection h; contradiction
|
2015-03-09 15:41:36 +00:00
|
|
|
|
end
|
2014-09-19 23:15:04 +00:00
|
|
|
|
end vector
|