(* -----  exists forms of the binding constructors ----------- *)

(* Specifications: *)
Axiom An_Pi_exists : forall x G rho A B,
x `notin` dom G \u fv_tm_tm_tm B
→ AnnTyping ([(x, Tm A)] ++ G)
(open_tm_wrt_tm B (a_Var_f x)) a_Star
→ AnnTyping G A a_Star
→ AnnTyping G (a_Pi rho A B) a_Star.
Axiom An_Abs_exists :   forall x (G:context) rho (A a B:tm),
x \notin dom G \u fv_tm_tm_tm a \u fv_tm_tm_tm B ->
AnnTyping G A a_Star ->
AnnTyping  (( x ~ Tm  A) ++ G) (open_tm_wrt_tm a (a_Var_f x))
(open_tm_wrt_tm B (a_Var_f x))  ->
RhoCheck rho x (erase_tm (open_tm_wrt_tm a (a_Var_f x))) ->
AnnTyping G (a_Abs rho A a) (a_Pi rho A B).
Axiom An_CPi_exists :  ∀ c (G : context) (phi : constraint) (B : tm),
c \notin dom G \u fv_co_co_tm B ->
AnnPropWff G phi
→ AnnTyping ([(c, Co phi)] ++ G) (open_tm_wrt_co B (g_Var_f c)) a_Star
→ AnnTyping G (a_CPi phi B) a_Star.
Axiom An_CAbs_exists :  ∀ c (G : context) (phi : constraint) (a B : tm),
c \notin dom G \u fv_co_co_tm a \u fv_co_co_tm B ->
AnnPropWff G phi
→ AnnTyping ([(c, Co phi)] ++ G) (open_tm_wrt_co a (g_Var_f c))
(open_tm_wrt_co B (g_Var_f c))
→ AnnTyping G (a_CAbs phi a) (a_CPi phi B).
Axiom An_CAbs_inversion : ∀ (G : context) (phi : constraint) (a A : tm),
AnnTyping G (a_CAbs phi a) A ->
exists B, A = (a_CPi phi B) /\
forall c, c  `notin` dom G (* \u fv_co_co_tm a \u fv_co_co_tm B *) ->
AnnPropWff G phi /\
AnnTyping ([(c, Co phi)] ++ G) (open_tm_wrt_co a (g_Var_f c))
(open_tm_wrt_co B (g_Var_f c)).
Axiom An_AbsCong_exists : ∀ x1 x2 (G : context) D rho (g1 g2 : co) (A1 b1 A2 b3 b2 B : tm),
x1 `notin` (dom G \u fv_tm_tm_tm b1 \u fv_tm_tm_tm b2 \u  fv_tm_tm_co g2)
-> x2 `notin` (dom G \u fv_tm_tm_tm b2 \u fv_tm_tm_tm b3 \u  fv_tm_tm_co g1)
->  AnnDefEq G D g1 A1 A2
→ (AnnDefEq ([(x1, Tm A1)] ++ G) D  (open_co_wrt_tm g2 (a_Var_f x1))
(open_tm_wrt_tm b1 (a_Var_f x1)) (open_tm_wrt_tm b2 (a_Var_f x1)))
→ (open_tm_wrt_tm b3 (a_Var_f x2) =
open_tm_wrt_tm b2 (a_Conv (a_Var_f x2) (g_Sym g1)))
→ AnnTyping G A1 a_Star
→ AnnTyping G A2 a_Star
→ RhoCheck rho x1 (erase_tm (open_tm_wrt_tm b1 (a_Var_f x1)))
→ RhoCheck rho x2 (erase_tm (open_tm_wrt_tm b3 (a_Var_f x2)))
→ AnnTyping G (a_Abs rho A1 b2) B
→ AnnDefEq G D (g_AbsCong rho g1 g2) (a_Abs rho A1 b1) (a_Abs rho A2 b3).
Axiom An_AbsCong_inversion :
forall G D rho g1 g2 B1 B2,
AnnDefEq G D (g_AbsCong rho g1 g2) B1 B2 ->
exists A1 A2 b1 b2 b3 B,
B1 = (a_Abs rho A1 b1) /\
B2 = (a_Abs rho A2 b3) /\
AnnTyping G A1 a_Star  /\
AnnTyping G A2 a_Star  /\
AnnDefEq G D g1 A1 A2  /\
AnnTyping G (a_Abs rho A1 b2) B /\
(forall x, x \notin dom G  (* \u fv_tm_tm_tm b1 \u fv_tm_tm_tm b2 \u fv_tm_tm_tm b3 *) ->
AnnDefEq  (( x ~ Tm A1) ++  G) D (open_co_wrt_tm g2 (a_Var_f x)) (open_tm_wrt_tm b1 (a_Var_f x))  ((open_tm_wrt_tm b2 (a_Var_f x))) /\
(open_tm_wrt_tm b3 (a_Var_f x)) = (open_tm_wrt_tm b2 (a_Conv (a_Var_f x) (g_Sym g1))) /\
(RhoCheck rho x  (erase_tm (open_tm_wrt_tm b1 (a_Var_f x)))) /\
(RhoCheck rho x  (erase_tm (open_tm_wrt_tm b3 (a_Var_f x))))).
Axiom An_CPiCong_exists : ∀ c1 c2 (G : context) D (g1 g3 : co) (phi1 : constraint)
(B1 : tm) (phi2 : constraint) (B3 B2 : tm),
AnnIso G D g1 phi1 phi2
-> c1 `notin` D \u fv_co_co_tm B2 \u fv_co_co_tm B1 \u fv_co_co_co g3
-> c2 `notin` fv_co_co_co g1 \u fv_co_co_tm B2 \u fv_co_co_tm B3
→ (AnnDefEq ([(c1, Co phi1)] ++ G) D (open_co_wrt_co g3 (g_Var_f c1))
(open_tm_wrt_co B1 (g_Var_f c1)) (open_tm_wrt_co B2 (g_Var_f c1)))
→ (open_tm_wrt_co B3 (g_Var_f c2) =
open_tm_wrt_co B2 (g_Cast (g_Var_f c2) (g_Sym g1)))
→ AnnTyping G (a_CPi phi1 B1) a_Star
→ AnnTyping G (a_CPi phi2 B3) a_Star
-> AnnTyping G (a_CPi phi1 B2) a_Star
→ AnnDefEq G D (g_CPiCong g1 g3) (a_CPi phi1 B1)
(a_CPi phi2 B3).
Axiom An_CPiCong_inversion :  ∀ (G : context) D (g1 g3 : co) (A1 A2 : tm),
AnnDefEq G D (g_CPiCong g1 g3) A1 A2 ->
exists phi1 phi2 B1 B2 B3,
A1 = (a_CPi phi1 B1) /\
A2 = (a_CPi phi2 B3) /\
AnnIso G D g1 phi1 phi2 /\
AnnTyping G (a_CPi phi1 B1) a_Star /\
AnnTyping G (a_CPi phi2 B3) a_Star /\
AnnTyping G (a_CPi phi1 B2) a_Star /\
(forall c, c `notin` dom G (* \u D \u fv_co_co_tm B2 \u fv_co_co_tm B1
\u fv_co_co_co g3 \u
fv_co_co_co g1 \u fv_co_co_tm B3 *) →
(AnnDefEq ([(c, Co phi1)] ++ G) D (open_co_wrt_co g3 (g_Var_f c))
(open_tm_wrt_co B1 (g_Var_f c)) (open_tm_wrt_co B2 (g_Var_f c))) /\
(open_tm_wrt_co B3 (g_Var_f c) = open_tm_wrt_co B2 (g_Cast (g_Var_f c) (g_Sym g1)))).
Axiom An_PiCong_exists : forall x1 x2 (G:context) D rho
(g1 g2 : co) (A1 B1 A2 B3 B2 : tm),
x1 `notin` (dom G \u fv_tm_tm_tm B1 \u fv_tm_tm_tm B2 \u  fv_tm_tm_co g2)
-> x2 `notin` (dom G \u fv_tm_tm_tm B2 \u fv_tm_tm_tm B3 \u  fv_tm_tm_co g1)
->  AnnDefEq G D g1 A1 A2
→ AnnDefEq ([(x1, Tm A1)] ++ G) D (open_co_wrt_tm g2 (a_Var_f x1))
(open_tm_wrt_tm B1 (a_Var_f x1)) (open_tm_wrt_tm B2 (a_Var_f x1))
→ (open_tm_wrt_tm B3 (a_Var_f x2) =
open_tm_wrt_tm B2 (a_Conv (a_Var_f x2) (g_Sym g1)))
→ AnnTyping G (a_Pi rho A1 B1) a_Star
→ AnnTyping G (a_Pi rho A2 B3) a_Star
→ AnnTyping G (a_Pi rho A1 B2) a_Star
→ AnnDefEq G D (g_PiCong rho g1 g2) (a_Pi rho A1 B1) (a_Pi rho A2 B3).
Axiom An_PiCong_inversion : forall (G:context) (D:available_props) (rho:relflag) (g1 g2:co) (C1 C2 :tm),
AnnDefEq G D (g_PiCong rho g1 g2) C1 C2 ->
exists A1 B1 A2 B2 B3,
C1 = (a_Pi rho A1 B1) /\
C2 = (a_Pi rho A2 B3) /\
AnnTyping G (a_Pi rho A1 B1) a_Star /\
AnnTyping G (a_Pi rho A2 B3) a_Star /\
AnnTyping G (a_Pi rho A1 B2) a_Star /\
AnnDefEq G D g1 A1 A2 /\
(forall x , x \notin dom G  ->
AnnDefEq  ((x ~ Tm  A1) ++ G) D (open_co_wrt_tm g2 (a_Var_f x)) (open_tm_wrt_tm B1 (a_Var_f x)) ((open_tm_wrt_tm B2 (a_Var_f x)))  /\
(open_tm_wrt_tm B3 (a_Var_f x)  = (open_tm_wrt_tm  B2 (a_Conv (a_Var_f x) (g_Sym g1))))).
Axiom An_CAbsCong_exists :
forall c1 c2 (G : context) (D : available_props) (g1 g3 g4 : co)
(phi1 : constraint) (a1 : tm) (phi2 : constraint) (a3 a2 B1 B2 B: tm),
AnnIso G D g1 phi1 phi2
-> c1 `notin` D \u fv_co_co_tm a2 \u fv_co_co_tm a1 \u fv_co_co_co g3
-> c2 `notin` fv_co_co_co g1 \u fv_co_co_tm a2 \u fv_co_co_tm a3
→ (AnnDefEq ([(c1, Co phi1)] ++ G) D (open_co_wrt_co g3 (g_Var_f c1))
(open_tm_wrt_co a1 (g_Var_f c1)) (open_tm_wrt_co a2 (g_Var_f c1)))
→ (open_tm_wrt_co a3 (g_Var_f c2) =
open_tm_wrt_co a2 (g_Cast (g_Var_f c2) (g_Sym g1)))
→ AnnTyping G (a_CAbs phi1 a1) (a_CPi phi1 B1)
→ AnnTyping G (a_CAbs phi2 a3) (a_CPi phi2 B2)
→ AnnDefEq G (dom G) g4 (a_CPi phi1 B1) (a_CPi phi2 B2)
-> AnnTyping G (a_CAbs phi1 a2) B
→ AnnDefEq G D (g_CAbsCong g1 g3 g4) (a_CAbs phi1 a1) (a_CAbs phi2 a3).
Axiom An_CAbsCong_inversion :
forall (G : context) (D : available_props) (g1 g3 g4 : co) A1 A2,
AnnDefEq G D (g_CAbsCong g1 g3 g4) A1 A2
-> exists phi1 phi2 a1 a2 a3 B1 B2 B,
A1 = (a_CAbs phi1 a1) /\
A2 = (a_CAbs phi2 a3) /\
AnnIso G D g1 phi1 phi2 /\
AnnTyping G (a_CAbs phi1 a1) (a_CPi phi1 B1) /\
AnnTyping G (a_CAbs phi2 a3) (a_CPi phi2 B2) /\
AnnTyping G (a_CAbs phi1 a2) B /\
AnnDefEq G (dom G) g4 (a_CPi phi1 B1) (a_CPi phi2 B2) /\
forall c1,
c1`notin` dom G (* \u D \u fv_co_co_tm a2 \u fv_co_co_tm a1 \u fv_co_co_co g3
\u fv_co_co_co g1 \u fv_co_co_tm a3 *)
→ (AnnDefEq ([(c1, Co phi1)] ++ G) D (open_co_wrt_co g3 (g_Var_f c1))
(open_tm_wrt_co a1 (g_Var_f c1)) (open_tm_wrt_co a2 (g_Var_f c1))) /\
(open_tm_wrt_co a3 (g_Var_f c1) =
open_tm_wrt_co a2 (g_Cast (g_Var_f c1) (g_Sym g1))).