(* --------------------------------------------------- *)
Inductive context_DefEq : available_props -> context -> context -> Prop :=
| Nul_Eqcontext: forall D, context_DefEq D nil nil
| Factor_Eqcontext_tm: forall G1 G2 D A A' x,
context_DefEq D G1 G2 ->
DefEq G1 D A A' a_Star ->
DefEq G2 D A A' a_Star ->
context_DefEq D ([(x, Tm A)] ++ G1) ([(x, Tm A')] ++ G2)
| Factor_Eqcontext_co: forall D G1 G2 Phi1 Phi2 c,
context_DefEq D G1 G2 ->
Iso G1 D Phi1 Phi2 ->
Iso G2 D Phi1 Phi2 ->
context_DefEq D ([(c, Co Phi1)] ++ G1) ([(c, Co Phi2)] ++ G2).
Hint Constructors context_DefEq.

(* Specifications: *)
Lemma context_tm_binding_defeq: forall D (G1 G2: context) A x,
Ctx G1 -> Ctx G2 -> context_DefEq D G1 G2 ->
binds x (Tm A) G1 -> exists A', (binds x (Tm A') G2) /\ DefEq G2 D A A' a_Star.
Lemma context_co_binding_defeq:
forall D (G1 G2: context) phi1 c,
Ctx G1 ->
Ctx G2 -> context_DefEq D G1 G2 ->
binds c (Co phi1) G1 ->
exists phi2, (binds c (Co phi2) G2) /\ Iso G2 D phi1 phi2.
Lemma context_DefEq_sub :
forall D G1 G2, context_DefEq D G1 G2 -> forall D', D [<=] D' -> context_DefEq D' G1 G2.
Lemma same_dom : forall D (G1 : context) G2,
context_DefEq D G1 G2 -> (@dom ett_ott.sort G1) = (@dom ett_ott.sort G2).
Lemma context_DefEq_weaken_available :
forall D G1 G2, context_DefEq D G1 G2 -> context_DefEq (dom G1) G1 G2.
Lemma context_DefEq_mutual:
(forall G1  a A,   Typing G1 a A -> forall D G2,
Ctx G2 -> context_DefEq D G1 G2 -> Typing G2 a A) /\
(forall G1  phi,   PropWff G1 phi -> forall D G2,
Ctx G2 -> context_DefEq D G1 G2 -> PropWff G2 phi) /\
(forall G1 D p1 p2, Iso G1 D p1 p2 ->
forall G2, Ctx G2 -> context_DefEq D G1 G2 -> Iso G2 D p1 p2) /\
(forall G1 D1 A B T,   DefEq G1 D1 A B T -> forall G2, Ctx G2 -> context_DefEq D1 G1 G2 ->
DefEq G2 D1 A B T) /\
(forall G1 ,       Ctx G1 -> forall G2 D x A, Ctx G2 -> context_DefEq D G1 G2
-> binds x (Tm A) G1 -> Typing G2 A a_Star).
Lemma context_DefEq_typing:
forall G1  a A,
Typing G1 a A -> forall D G2, Ctx G2 -> context_DefEq D G1 G2 -> Typing G2 a A.
Lemma refl_context_defeq: forall G D, Ctx G -> context_DefEq D G G.
Lemma co_subst_co_tm_var_eq : forall a g c,
lc_co g ->
erased_tm a ->
co_subst_co_tm g_Triv c a = co_subst_co_tm g c a.
Lemma Typing_swap_co : forall x1 x G a A B,
x1 `notin` fv_co_co_tm a \u fv_co_co_tm B
-> x `notin` dom G \u {{ x1 }}
-> Typing ([(x1, Co A)] ++ G) (open_tm_wrt_co a (g_Var_f x1))
(open_tm_wrt_co B (g_Var_f x1))
-> Typing ([(x, Co A)] ++ G) (open_tm_wrt_co a (g_Var_f x))
(open_tm_wrt_co B (g_Var_f x)).
Lemma E_CAbs_exists :  forall c (G : context) (phi : constraint) (a B : tm),
c `notin` fv_co_co_tm a \u fv_co_co_tm B
-> Typing ([(c, Co phi)] ++ G) (open_tm_wrt_co a (g_Var_f c))
(open_tm_wrt_co B (g_Var_f c))
-> PropWff G phi
-> Typing G (a_UCAbs a) (a_CPi phi B).
Lemma DefEqIso_regularity :
(forall G0 a A, Typing G0 a A -> True ) /\
(forall G0 phi,  PropWff G0 phi -> True ) /\
(forall G D p1 p2, Iso G D p1 p2 ->
PropWff G p1 /\ PropWff G p2) /\
(forall G D A B T,   DefEq G D A B T ->
Typing G A T /\ Typing G B T) /\
(forall G0, Ctx G0 -> True).
Lemma DefEq_regularity :
forall G D A B T, DefEq G D A B T -> PropWff G (Eq A B T).
Lemma Iso_regularity :
forall G D phi1 phi2, Iso G D phi1 phi2 -> PropWff G phi1 /\ PropWff G phi2.
Lemma PropWff_regularity :
forall G A B T, PropWff G (Eq A B T) ->  Typing G A T /\ Typing  G B T.