Skip to content

Instantly share code, notes, and snippets.

@leodemoura
Created August 21, 2015 19:02
Show Gist options
  • Save leodemoura/fa65c20b50a391456d32 to your computer and use it in GitHub Desktop.
Save leodemoura/fa65c20b50a391456d32 to your computer and use it in GitHub Desktop.
import data.nat
open nat subtype function
inductive ltwo_tree_shape (X A : Type) :=
| inl {} : ltwo_tree_shape X A
| inm {} : A → X → ltwo_tree_shape X A
| inr {} : A → X → X → ltwo_tree_shape X A
local notation `shape` := ltwo_tree_shape
namespace ltwo_tree_shape
variables {A X : Type}
notation `⋆` := inl
notation `[`a`,` x `]₁` := inm a x
notation `[`a`,` x₁`,` x₂`]₂` := inr a x₁ x₂
definition is_inl : shape X A → Prop
| ⋆ := true
| _ := false
definition is_inm : shape X A → Prop
| [a, x]₁ := true
| _ := false
definition is_inr : shape X A → Prop
| [a, x₁, x₂]₂ := true
| _ := false
definition pr₁₁ [reducible] : Π {s : shape X A} (H : is_inm s), A
| ⋆ H := false.rec _ H
| [a, x]₁ H := a
| [a, x₁, x₂]₂ H := false.rec _ H
definition pr₁₂ [reducible] : Π {s : shape X A} (H : is_inm s), X
| ⋆ H := false.rec _ H
| [a, x]₁ H := x
| [a, x₁, x₂]₂ H := false.rec _ H
definition pr₂₁ [reducible] : Π {s : shape X A} (H : is_inr s), A
| ⋆ H := false.rec _ H
| [a, x]₁ H := false.rec _ H
| [a, x₁, x₂]₂ H := a
definition pr₂₂ [reducible] : Π {s : shape X A} (H : is_inr s), X
| ⋆ H := false.rec _ H
| [a, x]₁ H := false.rec _ H
| [a, x₁, x₂]₂ H := x₁
definition pr₂₃ [reducible] : Π {s : shape X A} (H : is_inr s), X
| ⋆ H := false.rec _ H
| [a, x]₁ H := false.rec _ H
| [a, x₁, x₂]₂ H := x₂
end ltwo_tree_shape
open ltwo_tree_shape
inductive l_two_tree_approx (A : Type) : ℕ → Type :=
| continue {} : l_two_tree_approx A 0
| nil {} : Π {n : ℕ}, l_two_tree_approx A (n + 1)
| cons : Π {n : ℕ}, A → l_two_tree_approx A n → l_two_tree_approx A (n + 1)
| cons₂ : Π {n : ℕ}, A → l_two_tree_approx A n → l_two_tree_approx A n →
l_two_tree_approx A (n + 1)
namespace l_two_tree_approx
variables {A B X : Type}
definition l_two_tree_approx0_eq_continue : Π (t: l_two_tree_approx A 0), t = continue
| continue := rfl
definition is_nil : Π {n : ℕ}, l_two_tree_approx A n → Prop
| is_nil nil := true
| is_nil _ := false
definition is_cons : Π {n : ℕ}, l_two_tree_approx A n → Prop
| is_cons (cons _ _) := true
| is_cons _ := false
definition is_cons₂ : Π {n : ℕ}, l_two_tree_approx A n → Prop
| is_cons₂ (cons₂ _ _ _) := true
| is_cons₂ _ := false
/- head and tail -/
definition head [reducible] : Π {n : ℕ}, Π {t : l_two_tree_approx A (n + 1)} (H : is_cons t), A
| n nil H := false.rec _ H
| n (cons a t) H := a
| n (cons₂ a t₁ t₂) H := false.rec _ H
definition tail [reducible] : Π {n : ℕ}, Π {t : l_two_tree_approx A (n + 1)} (H : is_cons t), l_two_tree_approx A n
| n nil H := false.rec _ H
| n (cons a t) H := t
| n (cons₂ a t₁ t₂) H := false.rec _ H
definition head₂ : Π {n : ℕ}, Π {t : l_two_tree_approx A (n + 1)} (H : is_cons₂ t), A
| n nil H := false.rec _ H
| n (cons a t) H := false.rec _ H
| n (cons₂ a t₁ t₂) H := a
definition tail₂₁ : Π {n : ℕ}, Π {t : l_two_tree_approx A (n + 1)} (H : is_cons₂ t), l_two_tree_approx A n
| n nil H := false.rec _ H
| n (cons a t) H := false.rec _ H
| n (cons₂ a t₁ t₂) H := t₁
definition tail₂₂ : Π {n : ℕ}, Π {t : l_two_tree_approx A (n + 1)} (H : is_cons₂ t), l_two_tree_approx A n
| n nil H := false.rec _ H
| n (cons a t) H := false.rec _ H
| n (cons₂ a t₁ t₂) H := t₂
theorem tail1_eq_continue : Π {t : l_two_tree_approx A 1} (H : is_cons t), tail H = continue :=
begin intros, cases t, repeat (contradiction | apply l_two_tree_approx0_eq_continue) end
theorem tail₂₁1_eq_continue : Π {t : l_two_tree_approx A 1} (H : is_cons₂ t), tail₂₁ H = continue :=
begin intros, cases t, repeat (contradiction | apply l_two_tree_approx0_eq_continue) end
theorem tail₂₂1_eq_continue : Π {t : l_two_tree_approx A 1} (H : is_cons₂ t), tail₂₂ H = continue :=
begin intros, cases t, repeat (contradiction | apply l_two_tree_approx0_eq_continue) end
/- agreement -/
definition agrees : Π {n : ℕ}, l_two_tree_approx A n → l_two_tree_approx A (n + 1) → Prop
| 0 continue _ := true
| _ nil nil := true
| _ nil _ := false
| _ (cons a t₁) (cons a t₂) := agrees t₁ t₂
| _ (cons a t₁) _ := false
| _ (cons₂ a t₁₁ t₁₂) (cons₂ a t₂₁ t₂₂) := agrees t₁₁ t₂₁ ∧ agrees t₁₂ t₂₂
| _ (cons₂ a₁ t₁ t₁') _ := false
theorem is_nil_of_agrees : Π {n : ℕ}
{t₁ : l_two_tree_approx A n} {t₂ : l_two_tree_approx A (n + 1)}
(H : agrees t₁ t₂) (H' : is_nil t₁), is_nil t₂ :=
begin
intros,
repeat (cases n | cases t₂ | apply trivial | cases t₁ | contradiction)
end
theorem is_cons_of_agrees : Π {n : ℕ}
{t₁ : l_two_tree_approx A n} {t₂ : l_two_tree_approx A (n + 1)}
(H : agrees t₁ t₂) (H' : is_cons t₁), is_cons t₂
:=
begin
intros,
repeat (cases n | cases t₂ | apply trivial | cases t₁ | contradiction)
end
theorem is_cons₂_of_agrees : Π {n : ℕ}
{t₁ : l_two_tree_approx A n} {t₂ : l_two_tree_approx A (n + 1)}
(H : agrees t₁ t₂) (H' : is_cons₂ t₁), is_cons₂ t₂ :=
begin
intros,
repeat (cases n | cases t₂ | apply trivial | cases t₁ | contradiction)
end
theorem agrees_tail : Π {n : ℕ}
{t₁ : l_two_tree_approx A (n + 1)} {t₂ : l_two_tree_approx A (succ n + 1)}
(H : agrees t₁ t₂) (H₁ : is_cons t₁) (H₂ : is_cons t₂), agrees (tail H₁) (tail H₂) :=
begin
intros,
repeat (cases n | cases t₂ | apply trivial | cases t₁ | contradiction | apply H)
end
theorem agrees_tail₂₁ : Π {n : ℕ}
{t₁ : l_two_tree_approx A (n + 1)} {t₂ : l_two_tree_approx A (succ n + 1)}
(H : agrees t₁ t₂) (H₁ : is_cons₂ t₁) (H₂ : is_cons₂ t₂), agrees (tail₂₁ H₁) (tail₂₁ H₂) :=
begin
intros,
repeat (repeat (cases n | cases t₂ | apply trivial | cases t₁ | contradiction);
apply and.left H)
end
theorem agrees_tail₂₂ : Π {n : ℕ}
{t₁ : l_two_tree_approx A (n + 1)} {t₂ : l_two_tree_approx A (succ n + 1)}
(H : agrees t₁ t₂) (H₁ : is_cons₂ t₁) (H₂ : is_cons₂ t₂), agrees (tail₂₂ H₁) (tail₂₂ H₂) :=
begin
intros,
repeat (repeat (cases n | cases t₂ | apply trivial | cases t₁ | contradiction);
apply and.right H)
end
/- map -/
definition map (f : A → B) : Π {n : ℕ}, l_two_tree_approx A n → l_two_tree_approx B n
| map continue := continue
| map (@nil A n) := nil
| map (cons a l) := cons (f a) (map l)
| map (cons₂ a t₁ t₂) := cons₂ (f a) (map t₁) (map t₂)
/- corec -/
definition corec (f : X → shape X A) : Π (n : ℕ), X → l_two_tree_approx A n
| corec 0 x := continue
| corec (n + 1) x :=
match f x with
| ⋆ := nil
| [a, x₁]₁ := cons a (corec n x₁)
| [a, x₁, x₂]₂ := cons₂ a (corec n x₁) (corec n x₂)
end
theorem agrees_corec {f : X → shape X A} {x : X} {n : ℕ} : agrees (corec f n x) (corec f (n + 1) x) :=
begin
revert x,
induction n with n IH:
intro x,
try trivial,
unfold corec,
cases (f x),
repeat (trivial | split | apply IH)
end
theorem corec_f1x {f : X → shape X A} {x : X} : corec f 1 x =
(ltwo_tree_shape.cases_on (f x) nil (λ a x₁, cons a continue) (λ a x₁ x₂, cons₂ a continue continue)):=
rfl
end l_two_tree_approx
definition l_two_tree (A : Type) : Type :=
{s : Π (n : ℕ), l_two_tree_approx A n | ∀ n, l_two_tree_approx.agrees (s n) (s (n + 1))}
namespace l_two_tree
variables {A B X : Type}
definition nth [reducible] (n : nat) (t : l_two_tree A) : l_two_tree_approx A n :=
elt_of t n
definition fst [reducible] (t : l_two_tree A) : l_two_tree_approx A 1 :=
nth 1 t
/- (pseudo) constructors -/
definition s_nil : ∀ n, l_two_tree_approx A n
| 0 := l_two_tree_approx.continue
| (n + 1) := @l_two_tree_approx.nil A n
theorem P_nil : ∀ n, l_two_tree_approx.agrees (@s_nil A n) (@s_nil A (n + 1)) :=
begin
intro n,
cases n,
repeat trivial
end
definition nil : l_two_tree A := tag s_nil P_nil
definition s_cons (a : A) (t : l_two_tree A) : Π n, l_two_tree_approx A n
| 0 := l_two_tree_approx.continue
| (n + 1) := l_two_tree_approx.cons a (elt_of t n)
definition P_cons (a : A) (t : l_two_tree A) :
∀ n, l_two_tree_approx.agrees (s_cons a t n) (s_cons a t (n + 1)):=
begin
intro n,
cases n,
repeat (trivial | apply has_property t)
end
definition cons : A → l_two_tree A → l_two_tree A :=
λ a t, tag (s_cons a t) (P_cons a t)
definition s_cons₂ (a : A) (t₁ t₂ : l_two_tree A) : Π n, l_two_tree_approx A n
| 0 := l_two_tree_approx.continue
| (n + 1) := l_two_tree_approx.cons₂ a (elt_of t₁ n) (elt_of t₂ n)
definition P_cons₂ (a : A) (t₁ t₂ : l_two_tree A) :
∀ n, l_two_tree_approx.agrees (s_cons₂ a t₁ t₂ n) (s_cons₂ a t₁ t₂ (n + 1)):=
begin
intro n,
cases n,
repeat (trivial | apply has_property t₁ | apply has_property t₂ | split)
end
definition cons₂ : A → l_two_tree A → l_two_tree A → l_two_tree A :=
λ a t₁ t₂, tag (s_cons₂ a t₁ t₂) (P_cons₂ a t₁ t₂)
definition is_nil : l_two_tree A → Prop :=
λ t, l_two_tree_approx.is_nil (fst t)
theorem is_nil_of_forall (t : l_two_tree A)
(H : ∀ n, l_two_tree_approx.is_nil (elt_of t (n + 1))) : is_nil t := H 0
theorem forall_is_nil {t : l_two_tree A} (H : is_nil t) (n : ℕ) :
l_two_tree_approx.is_nil(elt_of t (n + 1)) :=
begin
induction n with n IH:
(exact H | exact l_two_tree_approx.is_nil_of_agrees (has_property t (n + 1)) IH)
end
definition is_cons : l_two_tree A → Prop :=
λ t, l_two_tree_approx.is_cons (fst t)
theorem is_cons_of_forall (t : l_two_tree A)
(H : ∀ n, l_two_tree_approx.is_cons (elt_of t (n + 1))) : is_cons t := H 0
theorem forall_is_cons {t : l_two_tree A} (H : is_cons t) :
∀ n, l_two_tree_approx.is_cons (elt_of t (n + 1)) :=
begin
intro n,
induction n with n IH:
(exact H | exact l_two_tree_approx.is_cons_of_agrees (has_property t (n + 1)) IH)
end
definition is_cons₂ : l_two_tree A → Prop :=
λ t, l_two_tree_approx.is_cons₂ (fst t)
theorem is_cons₂_of_forall (t : l_two_tree A)
(H : ∀ n, l_two_tree_approx.is_cons₂ (elt_of t (n + 1))) : is_cons₂ t := H 0
theorem forall_is_cons₂ {t : l_two_tree A} (H : is_cons₂ t) :
∀ n, l_two_tree_approx.is_cons₂ (elt_of t (n + 1)) :=
begin
intro n,
induction n with n IH:
(exact H | exact l_two_tree_approx.is_cons₂_of_agrees (has_property t (n + 1)) IH)
end
theorem is_nil_or_is_cons_or_is_cons₂ {t : l_two_tree A} : is_nil t ∨ is_cons t ∨ is_cons₂ t :=
begin
cases t with elt prop,
rewrite ↑[is_nil, is_cons, is_cons₂, fst, nth],
cases (elt 1),
repeat (append left (append right trivial)) ; now
end
/- head and tail -/
definition head {t : l_two_tree A} (H : is_cons t) : A :=
l_two_tree_approx.head H
definition s_tail {t : l_two_tree A} (H : is_cons t) : Π n, l_two_tree_approx A n :=
λ n, l_two_tree_approx.tail (forall_is_cons H _)
definition P_tail {t : l_two_tree A} (H : is_cons t) :
∀ n, l_two_tree_approx.agrees (s_tail H n) (s_tail H (n + 1)) :=
begin
intro n,
cases n with n : rewrite ↑s_tail,
rewrite l_two_tree_approx.tail1_eq_continue, trivial,
apply l_two_tree_approx.agrees_tail (has_property t (succ n + 1)) (forall_is_cons H (succ n)) (forall_is_cons H (succ (succ n)))
end
definition tail {t : l_two_tree A} (H : is_cons t) : l_two_tree A :=
tag (s_tail H) (P_tail H)
definition head₂ {t : l_two_tree A} (H : is_cons₂ t) : A :=
l_two_tree_approx.head₂ H
definition s_tail₂₁ {t : l_two_tree A} (H : is_cons₂ t) : Π n, l_two_tree_approx A n :=
λ n, l_two_tree_approx.tail₂₁ (forall_is_cons₂ H _)
definition P_tail₂₁ {t : l_two_tree A} (H : is_cons₂ t) :
∀ n, l_two_tree_approx.agrees (s_tail₂₁ H n) (s_tail₂₁ H (n + 1)) :=
begin
intro n,
cases n with n:
rewrite ↑s_tail₂₁,
{rewrite l_two_tree_approx.tail₂₁1_eq_continue,
trivial},
apply l_two_tree_approx.agrees_tail₂₁ (has_property t (succ n + 1)) (forall_is_cons₂ H (succ n)) (forall_is_cons₂ H (succ (succ n)))
end
definition tail₂₁ {t : l_two_tree A} (H : is_cons₂ t) : l_two_tree A :=
tag (s_tail₂₁ H) (P_tail₂₁ H)
definition s_tail₂₂ {t : l_two_tree A} (H : is_cons₂ t) : Π n, l_two_tree_approx A n :=
λ n, l_two_tree_approx.tail₂₂ (forall_is_cons₂ H _)
definition P_tail₂₂ {t : l_two_tree A} (H : is_cons₂ t) :
∀ n, l_two_tree_approx.agrees (s_tail₂₂ H n) (s_tail₂₂ H (n + 1)) :=
begin
intro n,
cases n with n:
rewrite ↑s_tail₂₂,
{rewrite l_two_tree_approx.tail₂₂1_eq_continue, trivial},
apply l_two_tree_approx.agrees_tail₂₂ (has_property t (succ n + 1)) (forall_is_cons₂ H (succ n)) (forall_is_cons₂ H (succ (succ n)))
end
definition tail₂₂ {t : l_two_tree A} (H : is_cons₂ t) : l_two_tree A :=
tag (s_tail₂₂ H) (P_tail₂₂ H)
theorem head_cons (a : A) (t : l_two_tree A) : @head A (cons a t) trivial = a :=
by esimp
theorem tail_cons (a : A) (t : l_two_tree A) : @tail A (cons a t) trivial = t :=
by cases t; esimp
theorem s_eta₁ {t : l_two_tree A} (H : is_cons t) : s_cons (head H) (tail H) = elt_of t :=
funext (λ i,
begin
rewrite ↑s_cons,
cases i with i:
esimp,
{symmetry; apply l_two_tree_approx.l_two_tree_approx0_eq_continue},
rewrite ↑[head, tail, s_tail],
rewrite ↑[is_cons, nth, fst] at H,
exact sorry -- TODO needs a simple lemma, eta rule for l_two_tree_approx
end)
theorem eta₁ {t : l_two_tree A} (H : is_cons t) : cons (head H) (tail H) = t :=
sorry -- TODO
theorem head₂_cons₂ (a : A) (t₁ t₂ : l_two_tree A) :
@head₂ A (cons₂ a t₁ t₂) trivial = a :=
by rewrite ↑head₂
theorem tail₂₁_cons₂ (a : A) (t₁ t₂ : l_two_tree A) : @tail₂₁ A (cons₂ a t₁ t₂) trivial = t₁ :=
by cases t₁; cases t₂; esimp
theorem tail₂₂_cons₂ (a : A) (t₁ t₂ : l_two_tree A) : @tail₂₂ A (cons₂ a t₁ t₂) trivial = t₂ :=
by cases t₁; cases t₂; esimp
/- map -/
definition s_map (f : A → B) (t : l_two_tree A) : Π n, l_two_tree_approx B n :=
λ n, l_two_tree_approx.map f (elt_of t n)
definition P_map (f : A → B) (t : l_two_tree A) :
∀ n, l_two_tree_approx.agrees (s_map f t n) (s_map f t (n + 1)):=
sorry -- TODO
definition map : (A → B) → l_two_tree A → l_two_tree B :=
λ f t, tag (s_map f t) (P_map f t)
/- corec -/
definition s_corec (f : X → shape X A) (x : X) : ∀ n, l_two_tree_approx A n :=
λ n, l_two_tree_approx.corec f n x
definition P_corec (f : X → shape X A) (x : X) :
∀ n, l_two_tree_approx.agrees (s_corec f x n) (s_corec f x (n + 1)) :=
by intro n; apply l_two_tree_approx.agrees_corec
definition corec (f : X → shape X A) (x : X) : l_two_tree A :=
tag (s_corec f x) (P_corec f x)
definition unfolds (f : X → shape X A) (x : X) : l_two_tree A :=
corec f x
-- TODO prove the opposite direction for the theorems below
theorem is_inl_of_is_nil_corec {f : X → shape X A} {x : X} (H : is_nil (corec f x)) : is_inl (f x) :=
begin
rewrite ↑[is_nil, fst, nth, corec, s_corec] at H,
rewrite l_two_tree_approx.corec_f1x at H,
revert H,
cases (f x),
repeat (intros ; (trivial | contradiction))
end
theorem is_nil_corec_of_is_inm {f : X → shape X A} {x : X} (H : is_inl (f x)) : is_nil (corec f x) :=
begin
rewrite ↑[is_nil, corec, fst, nth, s_corec],
rewrite l_two_tree_approx.corec_f1x,
revert H,
cases (f x),
repeat (intros ; (trivial | contradiction))
end
theorem is_inm_of_is_cons_corec {f : X → shape X A} {x : X} (H : is_cons (corec f x)) : is_inm (f x) :=
begin
unfold [is_cons, fst, nth, corec, s_corec] at H,
rewrite l_two_tree_approx.corec_f1x at H,
revert H,
cases (f x),
repeat (intros ; (trivial | contradiction))
end
theorem is_cons_corec_of_is_inm {f : X → shape X A} {x : X} (H : is_inm (f x)) : is_cons (corec f x) :=
begin
rewrite ↑[is_cons, corec, fst, nth, s_corec],
rewrite l_two_tree_approx.corec_f1x,
revert H,
cases (f x),
repeat (intros ; (trivial | contradiction))
end
theorem is_inr_of_is_cons₂_corec {f : X → shape X A} {x : X} (H : is_cons₂ (corec f x)) : is_inr (f x) :=
begin
rewrite ↑[is_cons₂, nth, fst, corec, s_corec] at H,
rewrite l_two_tree_approx.corec_f1x at H,
revert H,
cases (f x),
repeat (intros ; (trivial | contradiction))
end
theorem is_cons₂_corec_of_is_inr {f : X → shape X A} {x : X} (H : is_inr (f x)) : is_cons₂ (corec f x) :=
begin
rewrite ↑[is_cons₂, corec, fst, nth, s_corec],
rewrite l_two_tree_approx.corec_f1x,
revert H,
cases (f x),
repeat (intros ; (trivial | contradiction))
end
-- TODO shorten this proof (too many generalize)
theorem head_corec {f : X → shape X A} {x : X} (H : is_cons (corec f x)) : head H = pr₁₁ (is_inm_of_is_cons_corec H) :=
begin
generalize is_inm_of_is_cons_corec H;
revert H,
unfold [head, pr₁₁, is_cons, fst, nth, corec, s_corec],
rewrite l_two_tree_approx.corec_f1x,
cases (f x),
repeat (intros; reflexivity)
end
end l_two_tree
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment