(* generated by Ott 0.28, locally-nameless from: ett.ott *)
Require Import Metatheory.
(** syntax *)
Definition tmvar := var. (*r variables *)
Definition covar := var. (*r coercion variables *)
Definition datacon := atom.
Definition const := atom.
Definition index := nat. (*r indices *)

Inductive relflag : Set :=  (*r relevance flag *)
 | Rel : relflag
 | Irrel : relflag.

Inductive role : Set :=  (*r Role *)
 | Nom : role
 | Rep : role.

Inductive appflag : Set :=  (*r applicative flag *)
 | Role (R:role)
 | Rho (rho:relflag).

Inductive App : Set :=
 | A_Tm (nu:appflag)
 | A_Co : App.

Inductive Apps : Set :=
 | A_nil : Apps
 | A_cons (App5:App) (Apps5:Apps).

Inductive constraint : Set :=  (*r props *)
 | Eq (a:tm) (b:tm) (A:tm) (R:role)
with tm : Set :=  (*r types and kinds *)
 | a_Star : tm
 | a_Var_b (_:nat)
 | a_Var_f (x:tmvar)
 | a_Abs (rho:relflag) (A:tm) (b:tm)
 | a_UAbs (rho:relflag) (b:tm)
 | a_App (a:tm) (nu:appflag) (b:tm)
 | a_Pi (rho:relflag) (A:tm) (B:tm)
 | a_CAbs (phi:constraint) (b:tm)
 | a_UCAbs (b:tm)
 | a_CApp (a:tm) (g:co)
 | a_CPi (phi:constraint) (B:tm)
 | a_Conv (a:tm) (R:role) (g:co)
 | a_Fam (F:const)
 | a_Bullet : tm
 | a_Pattern (R:role) (a:tm) (F:const) (Apps5:Apps) (b1:tm) (b2:tm)
 | a_DataCon (K:datacon)
 | a_Case (a:tm) (brs5:brs)
 | a_Sub (R:role) (a:tm)
 | a_Coerce : tm
 | a_SrcApp (a:tm) (b:tm)
with brs : Set :=  (*r case branches *)
 | br_None : brs
 | br_One (K:datacon) (a:tm) (brs5:brs)
with co : Set :=  (*r explicit coercions *)
 | g_Triv : co
 | g_Var_b (_:nat)
 | g_Var_f (c:covar)
 | g_Beta (a:tm) (b:tm)
 | g_Refl (a:tm)
 | g_Refl2 (a:tm) (b:tm) (g:co)
 | g_Sym (g:co)
 | g_Trans (g1:co) (g2:co)
 | g_Sub (g:co)
 | g_PiCong (rho:relflag) (R:role) (g1:co) (g2:co)
 | g_AbsCong (rho:relflag) (R:role) (g1:co) (g2:co)
 | g_AppCong (g1:co) (rho:relflag) (R:role) (g2:co)
 | g_PiFst (g:co)
 | g_CPiFst (g:co)
 | g_IsoSnd (g:co)
 | g_PiSnd (g1:co) (g2:co)
 | g_CPiCong (g1:co) (g3:co)
 | g_CAbsCong (g1:co) (g3:co) (g4:co)
 | g_CAppCong (g:co) (g1:co) (g2:co)
 | g_CPiSnd (g:co) (g1:co) (g2:co)
 | g_Cast (g1:co) (R:role) (g2:co)
 | g_EqCong (g1:co) (A:tm) (g2:co)
 | g_IsoConv (phi1:constraint) (phi2:constraint) (g:co)
 | g_Eta (a:tm)
 | g_Left (g:co) (g':co)
 | g_Right (g:co) (g':co).

Definition roles : Set := list role.

Inductive sort : Set :=  (*r binding classifier *)
 | Tm (A:tm)
 | Co (phi:constraint).

Inductive sig_sort : Set :=  (*r signature classifier *)
 | Cs (A:tm) (Rs:roles)
 | Ax (p:tm) (a:tm) (A:tm) (R:role) (Rs:roles).

Inductive pattern_arg : Set :=  (*r Pattern arguments *)
 | p_Tm (nu:appflag) (a:tm)
 | p_Co (g:co).

Definition role_context : Set := list ( atom * role ).

Definition context : Set := list ( atom * sort ).

Definition available_props : Type := atoms.

Definition sig : Set := list (atom * sig_sort).

Definition atom_list : Set := list atom.

Definition pattern_args : Set := list pattern_arg.

Definition Nat : Set := nat.

Definition theta : Set := list ( atom * pattern_arg ).

(* EXPERIMENTAL *)
(** auxiliary functions on the new list types *)
(** library functions *)
(** subrules *)
(** arities *)
(** opening up abstractions *)
Fixpoint open_co_wrt_co_rec (k:nat) (g_5:co) (g__6:co) {struct g__6}: co :=
  match g__6 with
  | g_Triv => g_Triv
  | (g_Var_b nat) => if (k === nat) then g_5 else (g_Var_b nat)
  | (g_Var_f c) => g_Var_f c
  | (g_Beta a b) => g_Beta (open_tm_wrt_co_rec k g_5 a) (open_tm_wrt_co_rec k g_5 b)
  | (g_Refl a) => g_Refl (open_tm_wrt_co_rec k g_5 a)
  | (g_Refl2 a b g) => g_Refl2 (open_tm_wrt_co_rec k g_5 a) (open_tm_wrt_co_rec k g_5 b) (open_co_wrt_co_rec k g_5 g)
  | (g_Sym g) => g_Sym (open_co_wrt_co_rec k g_5 g)
  | (g_Trans g1 g2) => g_Trans (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec k g_5 g2)
  | (g_Sub g) => g_Sub (open_co_wrt_co_rec k g_5 g)
  | (g_PiCong rho R g1 g2) => g_PiCong rho R (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec k g_5 g2)
  | (g_AbsCong rho R g1 g2) => g_AbsCong rho R (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec k g_5 g2)
  | (g_AppCong g1 rho R g2) => g_AppCong (open_co_wrt_co_rec k g_5 g1) rho R (open_co_wrt_co_rec k g_5 g2)
  | (g_PiFst g) => g_PiFst (open_co_wrt_co_rec k g_5 g)
  | (g_CPiFst g) => g_CPiFst (open_co_wrt_co_rec k g_5 g)
  | (g_IsoSnd g) => g_IsoSnd (open_co_wrt_co_rec k g_5 g)
  | (g_PiSnd g1 g2) => g_PiSnd (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec k g_5 g2)
  | (g_CPiCong g1 g3) => g_CPiCong (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec (S k) g_5 g3)
  | (g_CAbsCong g1 g3 g4) => g_CAbsCong (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec (S k) g_5 g3) (open_co_wrt_co_rec k g_5 g4)
  | (g_CAppCong g g1 g2) => g_CAppCong (open_co_wrt_co_rec k g_5 g) (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec k g_5 g2)
  | (g_CPiSnd g g1 g2) => g_CPiSnd (open_co_wrt_co_rec k g_5 g) (open_co_wrt_co_rec k g_5 g1) (open_co_wrt_co_rec k g_5 g2)
  | (g_Cast g1 R g2) => g_Cast (open_co_wrt_co_rec k g_5 g1) R (open_co_wrt_co_rec k g_5 g2)
  | (g_EqCong g1 A g2) => g_EqCong (open_co_wrt_co_rec k g_5 g1) (open_tm_wrt_co_rec k g_5 A) (open_co_wrt_co_rec k g_5 g2)
  | (g_IsoConv phi1 phi2 g) => g_IsoConv (open_constraint_wrt_co_rec k g_5 phi1) (open_constraint_wrt_co_rec k g_5 phi2) (open_co_wrt_co_rec k g_5 g)
  | (g_Eta a) => g_Eta (open_tm_wrt_co_rec k g_5 a)
  | (g_Left g g') => g_Left (open_co_wrt_co_rec k g_5 g) (open_co_wrt_co_rec k g_5 g')
  | (g_Right g g') => g_Right (open_co_wrt_co_rec k g_5 g) (open_co_wrt_co_rec k g_5 g')
end
with open_brs_wrt_co_rec (k:nat) (g5:co) (brs_6:brs) {struct brs_6}: brs :=
  match brs_6 with
  | br_None => br_None
  | (br_One K a brs5) => br_One K (open_tm_wrt_co_rec k g5 a) (open_brs_wrt_co_rec k g5 brs5)
end
with open_tm_wrt_co_rec (k:nat) (g5:co) (a5:tm) {struct a5}: tm :=
  match a5 with
  | a_Star => a_Star
  | (a_Var_b nat) => a_Var_b nat
  | (a_Var_f x) => a_Var_f x
  | (a_Abs rho A b) => a_Abs rho (open_tm_wrt_co_rec k g5 A) (open_tm_wrt_co_rec k g5 b)
  | (a_UAbs rho b) => a_UAbs rho (open_tm_wrt_co_rec k g5 b)
  | (a_App a nu b) => a_App (open_tm_wrt_co_rec k g5 a) nu (open_tm_wrt_co_rec k g5 b)
  | (a_Pi rho A B) => a_Pi rho (open_tm_wrt_co_rec k g5 A) (open_tm_wrt_co_rec k g5 B)
  | (a_CAbs phi b) => a_CAbs (open_constraint_wrt_co_rec k g5 phi) (open_tm_wrt_co_rec (S k) g5 b)
  | (a_UCAbs b) => a_UCAbs (open_tm_wrt_co_rec (S k) g5 b)
  | (a_CApp a g) => a_CApp (open_tm_wrt_co_rec k g5 a) (open_co_wrt_co_rec k g5 g)
  | (a_CPi phi B) => a_CPi (open_constraint_wrt_co_rec k g5 phi) (open_tm_wrt_co_rec (S k) g5 B)
  | (a_Conv a R g) => a_Conv (open_tm_wrt_co_rec k g5 a) R (open_co_wrt_co_rec k g5 g)
  | (a_Fam F) => a_Fam F
  | a_Bullet => a_Bullet
  | (a_Pattern R a F Apps5 b1 b2) => a_Pattern R (open_tm_wrt_co_rec k g5 a) F Apps5 (open_tm_wrt_co_rec k g5 b1) (open_tm_wrt_co_rec k g5 b2)
  | (a_DataCon K) => a_DataCon K
  | (a_Case a brs5) => a_Case (open_tm_wrt_co_rec k g5 a) (open_brs_wrt_co_rec k g5 brs5)
  | (a_Sub R a) => a_Sub R (open_tm_wrt_co_rec k g5 a)
  | a_Coerce => a_Coerce
  | (a_SrcApp a b) => a_SrcApp (open_tm_wrt_co_rec k g5 a) (open_tm_wrt_co_rec k g5 b)
end
with open_constraint_wrt_co_rec (k:nat) (g5:co) (phi5:constraint) : constraint :=
  match phi5 with
  | (Eq a b A R) => Eq (open_tm_wrt_co_rec k g5 a) (open_tm_wrt_co_rec k g5 b) (open_tm_wrt_co_rec k g5 A) R
end.

Fixpoint open_co_wrt_tm_rec (k:nat) (a5:tm) (g_5:co) {struct g_5}: co :=
  match g_5 with
  | g_Triv => g_Triv
  | (g_Var_b nat) => g_Var_b nat
  | (g_Var_f c) => g_Var_f c
  | (g_Beta a b) => g_Beta (open_tm_wrt_tm_rec k a5 a) (open_tm_wrt_tm_rec k a5 b)
  | (g_Refl a) => g_Refl (open_tm_wrt_tm_rec k a5 a)
  | (g_Refl2 a b g) => g_Refl2 (open_tm_wrt_tm_rec k a5 a) (open_tm_wrt_tm_rec k a5 b) (open_co_wrt_tm_rec k a5 g)
  | (g_Sym g) => g_Sym (open_co_wrt_tm_rec k a5 g)
  | (g_Trans g1 g2) => g_Trans (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec k a5 g2)
  | (g_Sub g) => g_Sub (open_co_wrt_tm_rec k a5 g)
  | (g_PiCong rho R g1 g2) => g_PiCong rho R (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec (S k) a5 g2)
  | (g_AbsCong rho R g1 g2) => g_AbsCong rho R (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec (S k) a5 g2)
  | (g_AppCong g1 rho R g2) => g_AppCong (open_co_wrt_tm_rec k a5 g1) rho R (open_co_wrt_tm_rec k a5 g2)
  | (g_PiFst g) => g_PiFst (open_co_wrt_tm_rec k a5 g)
  | (g_CPiFst g) => g_CPiFst (open_co_wrt_tm_rec k a5 g)
  | (g_IsoSnd g) => g_IsoSnd (open_co_wrt_tm_rec k a5 g)
  | (g_PiSnd g1 g2) => g_PiSnd (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec k a5 g2)
  | (g_CPiCong g1 g3) => g_CPiCong (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec k a5 g3)
  | (g_CAbsCong g1 g3 g4) => g_CAbsCong (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec k a5 g3) (open_co_wrt_tm_rec k a5 g4)
  | (g_CAppCong g g1 g2) => g_CAppCong (open_co_wrt_tm_rec k a5 g) (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec k a5 g2)
  | (g_CPiSnd g g1 g2) => g_CPiSnd (open_co_wrt_tm_rec k a5 g) (open_co_wrt_tm_rec k a5 g1) (open_co_wrt_tm_rec k a5 g2)
  | (g_Cast g1 R g2) => g_Cast (open_co_wrt_tm_rec k a5 g1) R (open_co_wrt_tm_rec k a5 g2)
  | (g_EqCong g1 A g2) => g_EqCong (open_co_wrt_tm_rec k a5 g1) (open_tm_wrt_tm_rec k a5 A) (open_co_wrt_tm_rec k a5 g2)
  | (g_IsoConv phi1 phi2 g) => g_IsoConv (open_constraint_wrt_tm_rec k a5 phi1) (open_constraint_wrt_tm_rec k a5 phi2) (open_co_wrt_tm_rec k a5 g)
  | (g_Eta a) => g_Eta (open_tm_wrt_tm_rec k a5 a)
  | (g_Left g g') => g_Left (open_co_wrt_tm_rec k a5 g) (open_co_wrt_tm_rec k a5 g')
  | (g_Right g g') => g_Right (open_co_wrt_tm_rec k a5 g) (open_co_wrt_tm_rec k a5 g')
end
with open_brs_wrt_tm_rec (k:nat) (a5:tm) (brs_6:brs) {struct brs_6}: brs :=
  match brs_6 with
  | br_None => br_None
  | (br_One K a brs5) => br_One K (open_tm_wrt_tm_rec k a5 a) (open_brs_wrt_tm_rec k a5 brs5)
end
with open_tm_wrt_tm_rec (k:nat) (a5:tm) (a_6:tm) {struct a_6}: tm :=
  match a_6 with
  | a_Star => a_Star
  | (a_Var_b nat) => if (k === nat) then a5 else (a_Var_b nat)
  | (a_Var_f x) => a_Var_f x
  | (a_Abs rho A b) => a_Abs rho (open_tm_wrt_tm_rec k a5 A) (open_tm_wrt_tm_rec (S k) a5 b)
  | (a_UAbs rho b) => a_UAbs rho (open_tm_wrt_tm_rec (S k) a5 b)
  | (a_App a nu b) => a_App (open_tm_wrt_tm_rec k a5 a) nu (open_tm_wrt_tm_rec k a5 b)
  | (a_Pi rho A B) => a_Pi rho (open_tm_wrt_tm_rec k a5 A) (open_tm_wrt_tm_rec (S k) a5 B)
  | (a_CAbs phi b) => a_CAbs (open_constraint_wrt_tm_rec k a5 phi) (open_tm_wrt_tm_rec k a5 b)
  | (a_UCAbs b) => a_UCAbs (open_tm_wrt_tm_rec k a5 b)
  | (a_CApp a g) => a_CApp (open_tm_wrt_tm_rec k a5 a) (open_co_wrt_tm_rec k a5 g)
  | (a_CPi phi B) => a_CPi (open_constraint_wrt_tm_rec k a5 phi) (open_tm_wrt_tm_rec k a5 B)
  | (a_Conv a R g) => a_Conv (open_tm_wrt_tm_rec k a5 a) R (open_co_wrt_tm_rec k a5 g)
  | (a_Fam F) => a_Fam F
  | a_Bullet => a_Bullet
  | (a_Pattern R a F Apps5 b1 b2) => a_Pattern R (open_tm_wrt_tm_rec k a5 a) F Apps5 (open_tm_wrt_tm_rec k a5 b1) (open_tm_wrt_tm_rec k a5 b2)
  | (a_DataCon K) => a_DataCon K
  | (a_Case a brs5) => a_Case (open_tm_wrt_tm_rec k a5 a) (open_brs_wrt_tm_rec k a5 brs5)
  | (a_Sub R a) => a_Sub R (open_tm_wrt_tm_rec k a5 a)
  | a_Coerce => a_Coerce
  | (a_SrcApp a b) => a_SrcApp (open_tm_wrt_tm_rec k a5 a) (open_tm_wrt_tm_rec k a5 b)
end
with open_constraint_wrt_tm_rec (k:nat) (a5:tm) (phi5:constraint) : constraint :=
  match phi5 with
  | (Eq a b A R) => Eq (open_tm_wrt_tm_rec k a5 a) (open_tm_wrt_tm_rec k a5 b) (open_tm_wrt_tm_rec k a5 A) R
end.

Definition open_sort_wrt_co_rec (k:nat) (g5:co) (sort5:sort) : sort :=
  match sort5 with
  | (Tm A) => Tm (open_tm_wrt_co_rec k g5 A)
  | (Co phi) => Co (open_constraint_wrt_co_rec k g5 phi)
end.

Definition open_pattern_arg_wrt_tm_rec (k:nat) (a5:tm) (pattern_arg5:pattern_arg) : pattern_arg :=
  match pattern_arg5 with
  | (p_Tm nu a) => p_Tm nu (open_tm_wrt_tm_rec k a5 a)
  | (p_Co g) => p_Co (open_co_wrt_tm_rec k a5 g)
end.

Definition open_sig_sort_wrt_co_rec (k:nat) (g5:co) (sig_sort5:sig_sort) : sig_sort :=
  match sig_sort5 with
  | (Cs A Rs) => Cs (open_tm_wrt_co_rec k g5 A) Rs
  | (Ax p a A R Rs) => Ax (open_tm_wrt_co_rec k g5 p) (open_tm_wrt_co_rec k g5 a) (open_tm_wrt_co_rec k g5 A) R Rs
end.

Definition open_sig_sort_wrt_tm_rec (k:nat) (a5:tm) (sig_sort5:sig_sort) : sig_sort :=
  match sig_sort5 with
  | (Cs A Rs) => Cs (open_tm_wrt_tm_rec k a5 A) Rs
  | (Ax p a A R Rs) => Ax (open_tm_wrt_tm_rec k a5 p) (open_tm_wrt_tm_rec k a5 a) (open_tm_wrt_tm_rec k a5 A) R Rs
end.

Definition open_pattern_arg_wrt_co_rec (k:nat) (g5:co) (pattern_arg5:pattern_arg) : pattern_arg :=
  match pattern_arg5 with
  | (p_Tm nu a) => p_Tm nu (open_tm_wrt_co_rec k g5 a)
  | (p_Co g) => p_Co (open_co_wrt_co_rec k g5 g)
end.

Definition open_sort_wrt_tm_rec (k:nat) (a5:tm) (sort5:sort) : sort :=
  match sort5 with
  | (Tm A) => Tm (open_tm_wrt_tm_rec k a5 A)
  | (Co phi) => Co (open_constraint_wrt_tm_rec k a5 phi)
end.

Definition open_brs_wrt_co g5 brs_6 := open_brs_wrt_co_rec 0 brs_6 g5.

Definition open_tm_wrt_co g5 a5 := open_tm_wrt_co_rec 0 a5 g5.

Definition open_brs_wrt_tm a5 brs_6 := open_brs_wrt_tm_rec 0 brs_6 a5.

Definition open_sort_wrt_co g5 sort5 := open_sort_wrt_co_rec 0 sort5 g5.

Definition open_pattern_arg_wrt_tm a5 pattern_arg5 := open_pattern_arg_wrt_tm_rec 0 pattern_arg5 a5.

Definition open_sig_sort_wrt_co g5 sig_sort5 := open_sig_sort_wrt_co_rec 0 sig_sort5 g5.

Definition open_co_wrt_co g_5 g__6 := open_co_wrt_co_rec 0 g__6 g_5.

Definition open_sig_sort_wrt_tm a5 sig_sort5 := open_sig_sort_wrt_tm_rec 0 sig_sort5 a5.

Definition open_pattern_arg_wrt_co g5 pattern_arg5 := open_pattern_arg_wrt_co_rec 0 pattern_arg5 g5.

Definition open_constraint_wrt_co g5 phi5 := open_constraint_wrt_co_rec 0 phi5 g5.

Definition open_constraint_wrt_tm a5 phi5 := open_constraint_wrt_tm_rec 0 phi5 a5.

Definition open_co_wrt_tm a5 g_5 := open_co_wrt_tm_rec 0 g_5 a5.

Definition open_sort_wrt_tm a5 sort5 := open_sort_wrt_tm_rec 0 sort5 a5.

Definition open_tm_wrt_tm a5 a_6 := open_tm_wrt_tm_rec 0 a_6 a5.

(** terms are locally-closed pre-terms *)
(** definitions *)

(* defns LC_co_brs_tm_constraint *)
Inductive lc_co : co -> Prop :=    (* defn lc_co *)
 | lc_g_Triv :
     (lc_co g_Triv)
 | lc_g_Var_f : forall (c:covar),
     (lc_co (g_Var_f c))
 | lc_g_Beta : forall (a b:tm),
     (lc_tm a) ->
     (lc_tm b) ->
     (lc_co (g_Beta a b))
 | lc_g_Refl : forall (a:tm),
     (lc_tm a) ->
     (lc_co (g_Refl a))
 | lc_g_Refl2 : forall (a b:tm) (g:co),
     (lc_tm a) ->
     (lc_tm b) ->
     (lc_co g) ->
     (lc_co (g_Refl2 a b g))
 | lc_g_Sym : forall (g:co),
     (lc_co g) ->
     (lc_co (g_Sym g))
 | lc_g_Trans : forall (g1 g2:co),
     (lc_co g1) ->
     (lc_co g2) ->
     (lc_co (g_Trans g1 g2))
 | lc_g_Sub : forall (g:co),
     (lc_co g) ->
     (lc_co (g_Sub g))
 | lc_g_PiCong : forall (L:vars) (rho:relflag) (R:role) (g1 g2:co),
     (lc_co g1) ->
      ( forall x , x \notin  L  -> lc_co  ( open_co_wrt_tm g2 (a_Var_f x) )  )  ->
     (lc_co (g_PiCong rho R g1 g2))
 | lc_g_AbsCong : forall (L:vars) (rho:relflag) (R:role) (g1 g2:co),
     (lc_co g1) ->
      ( forall x , x \notin  L  -> lc_co  ( open_co_wrt_tm g2 (a_Var_f x) )  )  ->
     (lc_co (g_AbsCong rho R g1 g2))
 | lc_g_AppCong : forall (g1:co) (rho:relflag) (R:role) (g2:co),
     (lc_co g1) ->
     (lc_co g2) ->
     (lc_co (g_AppCong g1 rho R g2))
 | lc_g_PiFst : forall (g:co),
     (lc_co g) ->
     (lc_co (g_PiFst g))
 | lc_g_CPiFst : forall (g:co),
     (lc_co g) ->
     (lc_co (g_CPiFst g))
 | lc_g_IsoSnd : forall (g:co),
     (lc_co g) ->
     (lc_co (g_IsoSnd g))
 | lc_g_PiSnd : forall (g1 g2:co),
     (lc_co g1) ->
     (lc_co g2) ->
     (lc_co (g_PiSnd g1 g2))
 | lc_g_CPiCong : forall (L:vars) (g1 g3:co),
     (lc_co g1) ->
      ( forall c , c \notin  L  -> lc_co  ( open_co_wrt_co g3 (g_Var_f c) )  )  ->
     (lc_co (g_CPiCong g1 g3))
 | lc_g_CAbsCong : forall (L:vars) (g1 g3 g4:co),
     (lc_co g1) ->
      ( forall c , c \notin  L  -> lc_co  ( open_co_wrt_co g3 (g_Var_f c) )  )  ->
     (lc_co g4) ->
     (lc_co (g_CAbsCong g1 g3 g4))
 | lc_g_CAppCong : forall (g g1 g2:co),
     (lc_co g) ->
     (lc_co g1) ->
     (lc_co g2) ->
     (lc_co (g_CAppCong g g1 g2))
 | lc_g_CPiSnd : forall (g g1 g2:co),
     (lc_co g) ->
     (lc_co g1) ->
     (lc_co g2) ->
     (lc_co (g_CPiSnd g g1 g2))
 | lc_g_Cast : forall (g1:co) (R:role) (g2:co),
     (lc_co g1) ->
     (lc_co g2) ->
     (lc_co (g_Cast g1 R g2))
 | lc_g_EqCong : forall (g1:co) (A:tm) (g2:co),
     (lc_co g1) ->
     (lc_tm A) ->
     (lc_co g2) ->
     (lc_co (g_EqCong g1 A g2))
 | lc_g_IsoConv : forall (phi1 phi2:constraint) (g:co),
     (lc_constraint phi1) ->
     (lc_constraint phi2) ->
     (lc_co g) ->
     (lc_co (g_IsoConv phi1 phi2 g))
 | lc_g_Eta : forall (a:tm),
     (lc_tm a) ->
     (lc_co (g_Eta a))
 | lc_g_Left : forall (g g':co),
     (lc_co g) ->
     (lc_co g') ->
     (lc_co (g_Left g g'))
 | lc_g_Right : forall (g g':co),
     (lc_co g) ->
     (lc_co g') ->
     (lc_co (g_Right g g'))
with lc_brs : brs -> Prop :=    (* defn lc_brs *)
 | lc_br_None :
     (lc_brs br_None)
 | lc_br_One : forall (K:datacon) (a:tm) (brs5:brs),
     (lc_tm a) ->
     (lc_brs brs5) ->
     (lc_brs (br_One K a brs5))
with lc_tm : tm -> Prop :=    (* defn lc_tm *)
 | lc_a_Star :
     (lc_tm a_Star)
 | lc_a_Var_f : forall (x:tmvar),
     (lc_tm (a_Var_f x))
 | lc_a_Abs : forall (L:vars) (rho:relflag) (A b:tm),
     (lc_tm A) ->
      ( forall x , x \notin  L  -> lc_tm  ( open_tm_wrt_tm b (a_Var_f x) )  )  ->
     (lc_tm (a_Abs rho A b))
 | lc_a_UAbs : forall (L:vars) (rho:relflag) (b:tm),
      ( forall x , x \notin  L  -> lc_tm  ( open_tm_wrt_tm b (a_Var_f x) )  )  ->
     (lc_tm (a_UAbs rho b))
 | lc_a_App : forall (a:tm) (nu:appflag) (b:tm),
     (lc_tm a) ->
     (lc_tm b) ->
     (lc_tm (a_App a nu b))
 | lc_a_Pi : forall (L:vars) (rho:relflag) (A B:tm),
     (lc_tm A) ->
      ( forall x , x \notin  L  -> lc_tm  ( open_tm_wrt_tm B (a_Var_f x) )  )  ->
     (lc_tm (a_Pi rho A B))
 | lc_a_CAbs : forall (L:vars) (phi:constraint) (b:tm),
     (lc_constraint phi) ->
      ( forall c , c \notin  L  -> lc_tm  ( open_tm_wrt_co b (g_Var_f c) )  )  ->
     (lc_tm (a_CAbs phi b))
 | lc_a_UCAbs : forall (L:vars) (b:tm),
      ( forall c , c \notin  L  -> lc_tm  ( open_tm_wrt_co b (g_Var_f c) )  )  ->
     (lc_tm (a_UCAbs b))
 | lc_a_CApp : forall (a:tm) (g:co),
     (lc_tm a) ->
     (lc_co g) ->
     (lc_tm (a_CApp a g))
 | lc_a_CPi : forall (L:vars) (phi:constraint) (B:tm),
     (lc_constraint phi) ->
      ( forall c , c \notin  L  -> lc_tm  ( open_tm_wrt_co B (g_Var_f c) )  )  ->
     (lc_tm (a_CPi phi B))
 | lc_a_Conv : forall (a:tm) (R:role) (g:co),
     (lc_tm a) ->
     (lc_co g) ->
     (lc_tm (a_Conv a R g))
 | lc_a_Fam : forall (F:const),
     (lc_tm (a_Fam F))
 | lc_a_Bullet :
     (lc_tm a_Bullet)
 | lc_a_Pattern : forall (R:role) (a:tm) (F:const) (Apps5:Apps) (b1 b2:tm),
     (lc_tm a) ->
     (lc_tm b1) ->
     (lc_tm b2) ->
     (lc_tm (a_Pattern R a F Apps5 b1 b2))
 | lc_a_DataCon : forall (K:datacon),
     (lc_tm (a_DataCon K))
 | lc_a_Case : forall (a:tm) (brs5:brs),
     (lc_tm a) ->
     (lc_brs brs5) ->
     (lc_tm (a_Case a brs5))
 | lc_a_Sub : forall (R:role) (a:tm),
     (lc_tm a) ->
     (lc_tm (a_Sub R a))
 | lc_a_Coerce :
     (lc_tm a_Coerce)
 | lc_a_SrcApp : forall (a b:tm),
     (lc_tm a) ->
     (lc_tm b) ->
     (lc_tm (a_SrcApp a b))
with lc_constraint : constraint -> Prop :=    (* defn lc_constraint *)
 | lc_Eq : forall (a b A:tm) (R:role),
     (lc_tm a) ->
     (lc_tm b) ->
     (lc_tm A) ->
     (lc_constraint (Eq a b A R)).

(* defns LC_sort *)
Inductive lc_sort : sort -> Prop :=    (* defn lc_sort *)
 | lc_Tm : forall (A:tm),
     (lc_tm A) ->
     (lc_sort (Tm A))
 | lc_Co : forall (phi:constraint),
     (lc_constraint phi) ->
     (lc_sort (Co phi)).

(* defns LC_sig_sort *)
Inductive lc_sig_sort : sig_sort -> Prop :=    (* defn lc_sig_sort *)
 | lc_Cs : forall (A:tm) (Rs:roles),
     (lc_tm A) ->
     (lc_sig_sort (Cs A Rs))
 | lc_Ax : forall (p a A:tm) (R:role) (Rs:roles),
     (lc_tm p) ->
     (lc_tm a) ->
     (lc_tm A) ->
     (lc_sig_sort (Ax p a A R Rs)).

(* defns LC_pattern_arg *)
Inductive lc_pattern_arg : pattern_arg -> Prop :=    (* defn lc_pattern_arg *)
 | lc_p_Tm : forall (nu:appflag) (a:tm),
     (lc_tm a) ->
     (lc_pattern_arg (p_Tm nu a))
 | lc_p_Co : forall (g:co),
     (lc_co g) ->
     (lc_pattern_arg (p_Co g)).
(** free variables *)
Fixpoint fv_tm_tm_co (g_5:co) : vars :=
  match g_5 with
  | g_Triv => {}
  | (g_Var_b nat) => {}
  | (g_Var_f c) => {}
  | (g_Beta a b) => (fv_tm_tm_tm a) \u (fv_tm_tm_tm b)
  | (g_Refl a) => (fv_tm_tm_tm a)
  | (g_Refl2 a b g) => (fv_tm_tm_tm a) \u (fv_tm_tm_tm b) \u (fv_tm_tm_co g)
  | (g_Sym g) => (fv_tm_tm_co g)
  | (g_Trans g1 g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_Sub g) => (fv_tm_tm_co g)
  | (g_PiCong rho R g1 g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_AbsCong rho R g1 g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_AppCong g1 rho R g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_PiFst g) => (fv_tm_tm_co g)
  | (g_CPiFst g) => (fv_tm_tm_co g)
  | (g_IsoSnd g) => (fv_tm_tm_co g)
  | (g_PiSnd g1 g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_CPiCong g1 g3) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g3)
  | (g_CAbsCong g1 g3 g4) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g3) \u (fv_tm_tm_co g4)
  | (g_CAppCong g g1 g2) => (fv_tm_tm_co g) \u (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_CPiSnd g g1 g2) => (fv_tm_tm_co g) \u (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_Cast g1 R g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_co g2)
  | (g_EqCong g1 A g2) => (fv_tm_tm_co g1) \u (fv_tm_tm_tm A) \u (fv_tm_tm_co g2)
  | (g_IsoConv phi1 phi2 g) => (fv_tm_tm_constraint phi1) \u (fv_tm_tm_constraint phi2) \u (fv_tm_tm_co g)
  | (g_Eta a) => (fv_tm_tm_tm a)
  | (g_Left g g') => (fv_tm_tm_co g) \u (fv_tm_tm_co g')
  | (g_Right g g') => (fv_tm_tm_co g) \u (fv_tm_tm_co g')
end
with fv_tm_tm_brs (brs_6:brs) : vars :=
  match brs_6 with
  | br_None => {}
  | (br_One K a brs5) => (fv_tm_tm_tm a) \u (fv_tm_tm_brs brs5)
end
with fv_tm_tm_tm (a5:tm) : vars :=
  match a5 with
  | a_Star => {}
  | (a_Var_b nat) => {}
  | (a_Var_f x) => {{x}}
  | (a_Abs rho A b) => (fv_tm_tm_tm A) \u (fv_tm_tm_tm b)
  | (a_UAbs rho b) => (fv_tm_tm_tm b)
  | (a_App a nu b) => (fv_tm_tm_tm a) \u (fv_tm_tm_tm b)
  | (a_Pi rho A B) => (fv_tm_tm_tm A) \u (fv_tm_tm_tm B)
  | (a_CAbs phi b) => (fv_tm_tm_constraint phi) \u (fv_tm_tm_tm b)
  | (a_UCAbs b) => (fv_tm_tm_tm b)
  | (a_CApp a g) => (fv_tm_tm_tm a) \u (fv_tm_tm_co g)
  | (a_CPi phi B) => (fv_tm_tm_constraint phi) \u (fv_tm_tm_tm B)
  | (a_Conv a R g) => (fv_tm_tm_tm a) \u (fv_tm_tm_co g)
  | (a_Fam F) => {}
  | a_Bullet => {}
  | (a_Pattern R a F Apps5 b1 b2) => (fv_tm_tm_tm a) \u (fv_tm_tm_tm b1) \u (fv_tm_tm_tm b2)
  | (a_DataCon K) => {}
  | (a_Case a brs5) => (fv_tm_tm_tm a) \u (fv_tm_tm_brs brs5)
  | (a_Sub R a) => (fv_tm_tm_tm a)
  | a_Coerce => {}
  | (a_SrcApp a b) => (fv_tm_tm_tm a) \u (fv_tm_tm_tm b)
end
with fv_tm_tm_constraint (phi5:constraint) : vars :=
  match phi5 with
  | (Eq a b A R) => (fv_tm_tm_tm a) \u (fv_tm_tm_tm b) \u (fv_tm_tm_tm A)
end.

Fixpoint fv_co_co_co (g_5:co) : vars :=
  match g_5 with
  | g_Triv => {}
  | (g_Var_b nat) => {}
  | (g_Var_f c) => {{c}}
  | (g_Beta a b) => (fv_co_co_tm a) \u (fv_co_co_tm b)
  | (g_Refl a) => (fv_co_co_tm a)
  | (g_Refl2 a b g) => (fv_co_co_tm a) \u (fv_co_co_tm b) \u (fv_co_co_co g)
  | (g_Sym g) => (fv_co_co_co g)
  | (g_Trans g1 g2) => (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_Sub g) => (fv_co_co_co g)
  | (g_PiCong rho R g1 g2) => (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_AbsCong rho R g1 g2) => (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_AppCong g1 rho R g2) => (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_PiFst g) => (fv_co_co_co g)
  | (g_CPiFst g) => (fv_co_co_co g)
  | (g_IsoSnd g) => (fv_co_co_co g)
  | (g_PiSnd g1 g2) => (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_CPiCong g1 g3) => (fv_co_co_co g1) \u (fv_co_co_co g3)
  | (g_CAbsCong g1 g3 g4) => (fv_co_co_co g1) \u (fv_co_co_co g3) \u (fv_co_co_co g4)
  | (g_CAppCong g g1 g2) => (fv_co_co_co g) \u (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_CPiSnd g g1 g2) => (fv_co_co_co g) \u (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_Cast g1 R g2) => (fv_co_co_co g1) \u (fv_co_co_co g2)
  | (g_EqCong g1 A g2) => (fv_co_co_co g1) \u (fv_co_co_tm A) \u (fv_co_co_co g2)
  | (g_IsoConv phi1 phi2 g) => (fv_co_co_constraint phi1) \u (fv_co_co_constraint phi2) \u (fv_co_co_co g)
  | (g_Eta a) => (fv_co_co_tm a)
  | (g_Left g g') => (fv_co_co_co g) \u (fv_co_co_co g')
  | (g_Right g g') => (fv_co_co_co g) \u (fv_co_co_co g')
end
with fv_co_co_brs (brs_6:brs) : vars :=
  match brs_6 with
  | br_None => {}
  | (br_One K a brs5) => (fv_co_co_tm a) \u (fv_co_co_brs brs5)
end
with fv_co_co_tm (a5:tm) : vars :=
  match a5 with
  | a_Star => {}
  | (a_Var_b nat) => {}
  | (a_Var_f x) => {}
  | (a_Abs rho A b) => (fv_co_co_tm A) \u (fv_co_co_tm b)
  | (a_UAbs rho b) => (fv_co_co_tm b)
  | (a_App a nu b) => (fv_co_co_tm a) \u (fv_co_co_tm b)
  | (a_Pi rho A B) => (fv_co_co_tm A) \u (fv_co_co_tm B)
  | (a_CAbs phi b) => (fv_co_co_constraint phi) \u (fv_co_co_tm b)
  | (a_UCAbs b) => (fv_co_co_tm b)
  | (a_CApp a g) => (fv_co_co_tm a) \u (fv_co_co_co g)
  | (a_CPi phi B) => (fv_co_co_constraint phi) \u (fv_co_co_tm B)
  | (a_Conv a R g) => (fv_co_co_tm a) \u (fv_co_co_co g)
  | (a_Fam F) => {}
  | a_Bullet => {}
  | (a_Pattern R a F Apps5 b1 b2) => (fv_co_co_tm a) \u (fv_co_co_tm b1) \u (fv_co_co_tm b2)
  | (a_DataCon K) => {}
  | (a_Case a brs5) => (fv_co_co_tm a) \u (fv_co_co_brs brs5)
  | (a_Sub R a) => (fv_co_co_tm a)
  | a_Coerce => {}
  | (a_SrcApp a b) => (fv_co_co_tm a) \u (fv_co_co_tm b)
end
with fv_co_co_constraint (phi5:constraint) : vars :=
  match phi5 with
  | (Eq a b A R) => (fv_co_co_tm a) \u (fv_co_co_tm b) \u (fv_co_co_tm A)
end.

Definition fv_tm_tm_sort (sort5:sort) : vars :=
  match sort5 with
  | (Tm A) => (fv_tm_tm_tm A)
  | (Co phi) => (fv_tm_tm_constraint phi)
end.

Definition fv_co_co_pattern_arg (pattern_arg5:pattern_arg) : vars :=
  match pattern_arg5 with
  | (p_Tm nu a) => (fv_co_co_tm a)
  | (p_Co g) => (fv_co_co_co g)
end.

Definition fv_co_co_sig_sort (sig_sort5:sig_sort) : vars :=
  match sig_sort5 with
  | (Cs A Rs) => (fv_co_co_tm A)
  | (Ax p a A R Rs) => (fv_co_co_tm p) \u (fv_co_co_tm a) \u (fv_co_co_tm A)
end.

Definition fv_co_co_sort (sort5:sort) : vars :=
  match sort5 with
  | (Tm A) => (fv_co_co_tm A)
  | (Co phi) => (fv_co_co_constraint phi)
end.

Definition fv_tm_tm_pattern_arg (pattern_arg5:pattern_arg) : vars :=
  match pattern_arg5 with
  | (p_Tm nu a) => (fv_tm_tm_tm a)
  | (p_Co g) => (fv_tm_tm_co g)
end.

Definition fv_tm_tm_sig_sort (sig_sort5:sig_sort) : vars :=
  match sig_sort5 with
  | (Cs A Rs) => (fv_tm_tm_tm A)
  | (Ax p a A R Rs) => (fv_tm_tm_tm p) \u (fv_tm_tm_tm a) \u (fv_tm_tm_tm A)
end.

(** substitutions *)
Fixpoint co_subst_co_constraint (g5:co) (c5:covar) (phi5:constraint) {struct phi5} : constraint :=
  match phi5 with
  | (Eq a b A R) => Eq (co_subst_co_tm g5 c5 a) (co_subst_co_tm g5 c5 b) (co_subst_co_tm g5 c5 A) R
end
with co_subst_co_co (g_5:co) (c5:covar) (g__6:co) {struct g__6} : co :=
  match g__6 with
  | g_Triv => g_Triv
  | (g_Var_b nat) => g_Var_b nat
  | (g_Var_f c) => (if eq_var c c5 then g_5 else (g_Var_f c))
  | (g_Beta a b) => g_Beta (co_subst_co_tm g_5 c5 a) (co_subst_co_tm g_5 c5 b)
  | (g_Refl a) => g_Refl (co_subst_co_tm g_5 c5 a)
  | (g_Refl2 a b g) => g_Refl2 (co_subst_co_tm g_5 c5 a) (co_subst_co_tm g_5 c5 b) (co_subst_co_co g_5 c5 g)
  | (g_Sym g) => g_Sym (co_subst_co_co g_5 c5 g)
  | (g_Trans g1 g2) => g_Trans (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g2)
  | (g_Sub g) => g_Sub (co_subst_co_co g_5 c5 g)
  | (g_PiCong rho R g1 g2) => g_PiCong rho R (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g2)
  | (g_AbsCong rho R g1 g2) => g_AbsCong rho R (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g2)
  | (g_AppCong g1 rho R g2) => g_AppCong (co_subst_co_co g_5 c5 g1) rho R (co_subst_co_co g_5 c5 g2)
  | (g_PiFst g) => g_PiFst (co_subst_co_co g_5 c5 g)
  | (g_CPiFst g) => g_CPiFst (co_subst_co_co g_5 c5 g)
  | (g_IsoSnd g) => g_IsoSnd (co_subst_co_co g_5 c5 g)
  | (g_PiSnd g1 g2) => g_PiSnd (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g2)
  | (g_CPiCong g1 g3) => g_CPiCong (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g3)
  | (g_CAbsCong g1 g3 g4) => g_CAbsCong (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g3) (co_subst_co_co g_5 c5 g4)
  | (g_CAppCong g g1 g2) => g_CAppCong (co_subst_co_co g_5 c5 g) (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g2)
  | (g_CPiSnd g g1 g2) => g_CPiSnd (co_subst_co_co g_5 c5 g) (co_subst_co_co g_5 c5 g1) (co_subst_co_co g_5 c5 g2)
  | (g_Cast g1 R g2) => g_Cast (co_subst_co_co g_5 c5 g1) R (co_subst_co_co g_5 c5 g2)
  | (g_EqCong g1 A g2) => g_EqCong (co_subst_co_co g_5 c5 g1) (co_subst_co_tm g_5 c5 A) (co_subst_co_co g_5 c5 g2)
  | (g_IsoConv phi1 phi2 g) => g_IsoConv (co_subst_co_constraint g_5 c5 phi1) (co_subst_co_constraint g_5 c5 phi2) (co_subst_co_co g_5 c5 g)
  | (g_Eta a) => g_Eta (co_subst_co_tm g_5 c5 a)
  | (g_Left g g') => g_Left (co_subst_co_co g_5 c5 g) (co_subst_co_co g_5 c5 g')
  | (g_Right g g') => g_Right (co_subst_co_co g_5 c5 g) (co_subst_co_co g_5 c5 g')
end
with co_subst_co_brs (g5:co) (c5:covar) (brs_6:brs) {struct brs_6} : brs :=
  match brs_6 with
  | br_None => br_None
  | (br_One K a brs5) => br_One K (co_subst_co_tm g5 c5 a) (co_subst_co_brs g5 c5 brs5)
end
with co_subst_co_tm (g5:co) (c5:covar) (a5:tm) {struct a5} : tm :=
  match a5 with
  | a_Star => a_Star
  | (a_Var_b nat) => a_Var_b nat
  | (a_Var_f x) => a_Var_f x
  | (a_Abs rho A b) => a_Abs rho (co_subst_co_tm g5 c5 A) (co_subst_co_tm g5 c5 b)
  | (a_UAbs rho b) => a_UAbs rho (co_subst_co_tm g5 c5 b)
  | (a_App a nu b) => a_App (co_subst_co_tm g5 c5 a) nu (co_subst_co_tm g5 c5 b)
  | (a_Pi rho A B) => a_Pi rho (co_subst_co_tm g5 c5 A) (co_subst_co_tm g5 c5 B)
  | (a_CAbs phi b) => a_CAbs (co_subst_co_constraint g5 c5 phi) (co_subst_co_tm g5 c5 b)
  | (a_UCAbs b) => a_UCAbs (co_subst_co_tm g5 c5 b)
  | (a_CApp a g) => a_CApp (co_subst_co_tm g5 c5 a) (co_subst_co_co g5 c5 g)
  | (a_CPi phi B) => a_CPi (co_subst_co_constraint g5 c5 phi) (co_subst_co_tm g5 c5 B)
  | (a_Conv a R g) => a_Conv (co_subst_co_tm g5 c5 a) R (co_subst_co_co g5 c5 g)
  | (a_Fam F) => a_Fam F
  | a_Bullet => a_Bullet
  | (a_Pattern R a F Apps5 b1 b2) => a_Pattern R (co_subst_co_tm g5 c5 a) F Apps5 (co_subst_co_tm g5 c5 b1) (co_subst_co_tm g5 c5 b2)
  | (a_DataCon K) => a_DataCon K
  | (a_Case a brs5) => a_Case (co_subst_co_tm g5 c5 a) (co_subst_co_brs g5 c5 brs5)
  | (a_Sub R a) => a_Sub R (co_subst_co_tm g5 c5 a)
  | a_Coerce => a_Coerce
  | (a_SrcApp a b) => a_SrcApp (co_subst_co_tm g5 c5 a) (co_subst_co_tm g5 c5 b)
end.

Fixpoint tm_subst_tm_co (a5:tm) (x5:tmvar) (g_5:co) {struct g_5} : co :=
  match g_5 with
  | g_Triv => g_Triv
  | (g_Var_b nat) => g_Var_b nat
  | (g_Var_f c) => g_Var_f c
  | (g_Beta a b) => g_Beta (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_tm a5 x5 b)
  | (g_Refl a) => g_Refl (tm_subst_tm_tm a5 x5 a)
  | (g_Refl2 a b g) => g_Refl2 (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_tm a5 x5 b) (tm_subst_tm_co a5 x5 g)
  | (g_Sym g) => g_Sym (tm_subst_tm_co a5 x5 g)
  | (g_Trans g1 g2) => g_Trans (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g2)
  | (g_Sub g) => g_Sub (tm_subst_tm_co a5 x5 g)
  | (g_PiCong rho R g1 g2) => g_PiCong rho R (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g2)
  | (g_AbsCong rho R g1 g2) => g_AbsCong rho R (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g2)
  | (g_AppCong g1 rho R g2) => g_AppCong (tm_subst_tm_co a5 x5 g1) rho R (tm_subst_tm_co a5 x5 g2)
  | (g_PiFst g) => g_PiFst (tm_subst_tm_co a5 x5 g)
  | (g_CPiFst g) => g_CPiFst (tm_subst_tm_co a5 x5 g)
  | (g_IsoSnd g) => g_IsoSnd (tm_subst_tm_co a5 x5 g)
  | (g_PiSnd g1 g2) => g_PiSnd (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g2)
  | (g_CPiCong g1 g3) => g_CPiCong (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g3)
  | (g_CAbsCong g1 g3 g4) => g_CAbsCong (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g3) (tm_subst_tm_co a5 x5 g4)
  | (g_CAppCong g g1 g2) => g_CAppCong (tm_subst_tm_co a5 x5 g) (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g2)
  | (g_CPiSnd g g1 g2) => g_CPiSnd (tm_subst_tm_co a5 x5 g) (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_co a5 x5 g2)
  | (g_Cast g1 R g2) => g_Cast (tm_subst_tm_co a5 x5 g1) R (tm_subst_tm_co a5 x5 g2)
  | (g_EqCong g1 A g2) => g_EqCong (tm_subst_tm_co a5 x5 g1) (tm_subst_tm_tm a5 x5 A) (tm_subst_tm_co a5 x5 g2)
  | (g_IsoConv phi1 phi2 g) => g_IsoConv (tm_subst_tm_constraint a5 x5 phi1) (tm_subst_tm_constraint a5 x5 phi2) (tm_subst_tm_co a5 x5 g)
  | (g_Eta a) => g_Eta (tm_subst_tm_tm a5 x5 a)
  | (g_Left g g') => g_Left (tm_subst_tm_co a5 x5 g) (tm_subst_tm_co a5 x5 g')
  | (g_Right g g') => g_Right (tm_subst_tm_co a5 x5 g) (tm_subst_tm_co a5 x5 g')
end
with tm_subst_tm_brs (a5:tm) (x5:tmvar) (brs_6:brs) {struct brs_6} : brs :=
  match brs_6 with
  | br_None => br_None
  | (br_One K a brs5) => br_One K (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_brs a5 x5 brs5)
end
with tm_subst_tm_tm (a5:tm) (x5:tmvar) (a_6:tm) {struct a_6} : tm :=
  match a_6 with
  | a_Star => a_Star
  | (a_Var_b nat) => a_Var_b nat
  | (a_Var_f x) => (if eq_var x x5 then a5 else (a_Var_f x))
  | (a_Abs rho A b) => a_Abs rho (tm_subst_tm_tm a5 x5 A) (tm_subst_tm_tm a5 x5 b)
  | (a_UAbs rho b) => a_UAbs rho (tm_subst_tm_tm a5 x5 b)
  | (a_App a nu b) => a_App (tm_subst_tm_tm a5 x5 a) nu (tm_subst_tm_tm a5 x5 b)
  | (a_Pi rho A B) => a_Pi rho (tm_subst_tm_tm a5 x5 A) (tm_subst_tm_tm a5 x5 B)
  | (a_CAbs phi b) => a_CAbs (tm_subst_tm_constraint a5 x5 phi) (tm_subst_tm_tm a5 x5 b)
  | (a_UCAbs b) => a_UCAbs (tm_subst_tm_tm a5 x5 b)
  | (a_CApp a g) => a_CApp (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_co a5 x5 g)
  | (a_CPi phi B) => a_CPi (tm_subst_tm_constraint a5 x5 phi) (tm_subst_tm_tm a5 x5 B)
  | (a_Conv a R g) => a_Conv (tm_subst_tm_tm a5 x5 a) R (tm_subst_tm_co a5 x5 g)
  | (a_Fam F) => a_Fam F
  | a_Bullet => a_Bullet
  | (a_Pattern R a F Apps5 b1 b2) => a_Pattern R (tm_subst_tm_tm a5 x5 a) F Apps5 (tm_subst_tm_tm a5 x5 b1) (tm_subst_tm_tm a5 x5 b2)
  | (a_DataCon K) => a_DataCon K
  | (a_Case a brs5) => a_Case (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_brs a5 x5 brs5)
  | (a_Sub R a) => a_Sub R (tm_subst_tm_tm a5 x5 a)
  | a_Coerce => a_Coerce
  | (a_SrcApp a b) => a_SrcApp (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_tm a5 x5 b)
end
with tm_subst_tm_constraint (a5:tm) (x5:tmvar) (phi5:constraint) {struct phi5} : constraint :=
  match phi5 with
  | (Eq a b A R) => Eq (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_tm a5 x5 b) (tm_subst_tm_tm a5 x5 A) R
end.

Definition co_subst_co_sort (g5:co) (c5:covar) (sort5:sort) : sort :=
  match sort5 with
  | (Tm A) => Tm (co_subst_co_tm g5 c5 A)
  | (Co phi) => Co (co_subst_co_constraint g5 c5 phi)
end.

Definition tm_subst_tm_pattern_arg (a5:tm) (x5:tmvar) (pattern_arg5:pattern_arg) : pattern_arg :=
  match pattern_arg5 with
  | (p_Tm nu a) => p_Tm nu (tm_subst_tm_tm a5 x5 a)
  | (p_Co g) => p_Co (tm_subst_tm_co a5 x5 g)
end.

Definition tm_subst_tm_sig_sort (a5:tm) (x5:tmvar) (sig_sort5:sig_sort) : sig_sort :=
  match sig_sort5 with
  | (Cs A Rs) => Cs (tm_subst_tm_tm a5 x5 A) Rs
  | (Ax p a A R Rs) => Ax (tm_subst_tm_tm a5 x5 p) (tm_subst_tm_tm a5 x5 a) (tm_subst_tm_tm a5 x5 A) R Rs
end.

Definition tm_subst_tm_sort (a5:tm) (x5:tmvar) (sort5:sort) : sort :=
  match sort5 with
  | (Tm A) => Tm (tm_subst_tm_tm a5 x5 A)
  | (Co phi) => Co (tm_subst_tm_constraint a5 x5 phi)
end.

Definition co_subst_co_pattern_arg (g5:co) (c5:covar) (pattern_arg5:pattern_arg) : pattern_arg :=
  match pattern_arg5 with
  | (p_Tm nu a) => p_Tm nu (co_subst_co_tm g5 c5 a)
  | (p_Co g) => p_Co (co_subst_co_co g5 c5 g)
end.

Definition co_subst_co_sig_sort (g5:co) (c5:covar) (sig_sort5:sig_sort) : sig_sort :=
  match sig_sort5 with
  | (Cs A Rs) => Cs (co_subst_co_tm g5 c5 A) Rs
  | (Ax p a A R Rs) => Ax (co_subst_co_tm g5 c5 p) (co_subst_co_tm g5 c5 a) (co_subst_co_tm g5 c5 A) R Rs
end.

Definition min (r1 : role) (r2 : role) : role :=
  match r1 , r2 with
  | Nom, _   => Nom
  | _  , Nom => Nom
  | Rep, Rep => Rep
  end.

Parameter str : bool.
Definition param (r1 : role) (r2 : role) := min r1 r2.

Definition app_role (rr : appflag) (r1 : role) : role :=
  match rr with
  | Rho _ => Nom
  | Role r => param r r1
  end.

Definition app_rho (rr : appflag) : relflag :=
  match rr with
  | Rho p => p
  | Role _ => Rel
  end.

Definition nu_rho (nu : appflag) : Prop :=
 match nu with
 | Rho _ => True
 | Role _ => False
 end.

Definition max (r1 : role) (r2 : role) : role :=
  match r1 , r2 with
  | _, Rep   => Rep
  | Rep, _   => Rep
  | Nom, Nom => Nom
  end.

Definition lte_role (r1 : role) (r2 : role) : bool :=
  match r1 , r2 with
  | Nom, _   => true
  | Rep, Nom => false
  | Rep, Rep => true
  end.

Fixpoint erase_tm (a : tm) (r : role) : tm :=
   match a with
   | a_Star    => a_Star
   | a_Var_b n => a_Var_b n
   | a_Var_f x => a_Var_f x
   | a_Abs rho A b => a_UAbs rho (erase_tm b r)
   | a_UAbs rho b => a_UAbs rho (erase_tm b r)
   | a_App a (Role R) b => a_App (erase_tm a r) (Role R) (erase_tm b r)
   | a_App a (Rho Rel) b => a_App (erase_tm a r) (Rho Rel) (erase_tm b r)
   | a_App a (Rho Irrel) b => a_App (erase_tm a r) (Rho Irrel) a_Bullet
   | a_Fam F => a_Fam F
   | a_Pi rho A B => a_Pi rho (erase_tm A r) (erase_tm B r)
   | a_Conv a r1 g => if (lte_role r1 r) then
                        erase_tm a r else
                                 a_Conv (erase_tm a r) r1 g_Triv
   | a_CPi phi B => a_CPi (erase_constraint phi r) (erase_tm B r)
   | a_CAbs phi b => a_UCAbs (erase_tm b r)
   | a_UCAbs b => a_UCAbs (erase_tm b r)
   | a_CApp a g => a_CApp (erase_tm a r) g_Triv
   | a_DataCon K => a_Star  (* a_DataCon K *)
   | a_Case a brs => a_Star (* a_Case (erase_tm a) (erase_brs brs) *)
   | a_Bullet => a_Bullet
   | a_Pattern R a1 F Apps b1 b2 => a_Pattern R (erase_tm a1 r) F Apps (erase_tm b1 r) (erase_tm b2 r)
   | a => a
   end
with erase_brs (x : brs) (r:role): brs :=
   match x with
   | br_None => br_None
   | br_One k a y => br_One k (erase_tm a r) (erase_brs y r)
   end
with erase_constraint (phi : constraint) (r:role): constraint :=
   match phi with
   | Eq A B A1 R => Eq (erase_tm A R) (erase_tm B R) (erase_tm A1 R) R
   end.

Definition erase_sort s r :=
 match s with
 | Tm a => Tm (erase_tm a r)
 | Co p => Co (erase_constraint p r)
end.

Definition erase_csort s r :=
 match s with
 | Cs a Rs => Cs (erase_tm a r) Rs
 | Ax p a A R Rs => Ax (erase_tm p r) (erase_tm a r) (erase_tm A r) R Rs
end.

Definition erase_context G r := map (fun s => erase_sort s r) G.
Definition erase_sig S r := map (fun s => erase_csort s r) S.

Fixpoint pattern_length (a : tm) : nat := match a with
   a_Fam F => 0
 | a_App a nu b => pattern_length a + 1
 | a_CApp a g_Triv => pattern_length a + 1
 | _ => 0
 end.

Fixpoint vars_Pattern (p : tm) := match p with
   | a_Fam F => nil
   | a_App p1 (Role _) (a_Var_f x) => vars_Pattern p1 ++ [ x ]
   | a_App p1 (Rho Irrel) a_Bullet => vars_Pattern p1
   | a_CApp p1 g_Triv => vars_Pattern p1
   | _ => nil
   end.

Fixpoint apply_pattern_args (a : tm) (args : pattern_args) : tm :=
  match args with
  | nil => a
  | (p_Tm nu b :: rest) =>
    apply_pattern_args (a_App a nu b) rest
  | (p_Co g :: rest) =>
    apply_pattern_args (a_CApp a g) rest
  end.

Fixpoint A_snoc (xs : Apps) (x : App)  : Apps :=
  match xs with
  | A_nil => A_cons x A_nil
  | A_cons y ys => (A_cons y (A_snoc ys x))
  end.

Fixpoint range (L : role_context) : roles :=
  match L with
  | nil => nil
  | (x,R) :: L' => range(L') ++ [ R ]
  end.

(* -------------- A specific signature with Fix ------------ *)

Definition constants :
  { Star    : atom &
  { Fix     : atom &
  { FixVar1 : atom &
  { FixVar2 : atom &
      Fix `notin` singleton Star /\
      FixVar1 `notin` singleton Star  \u (singleton Fix) /\
      FixVar2 `notin` singleton Star \u singleton Fix  \u singleton FixVar1  } } } }.
Proof.
  pick fresh Star.
  pick fresh Fix.
  pick fresh FixVar1.
  pick fresh FixVar2.
  exists Star.
  exists Fix.
  exists FixVar1.
  exists FixVar2.
  repeat split; auto.
Defined.

Definition Star : atom.
  destruct constants as [s _].
  exact s.
Defined.

Definition Fix : atom.
  destruct constants as [_ [f _] ].
  exact f.
Defined.

Lemma noteq : Star <> Fix.
Proof.
  unfold Star, Fix.
  destruct constants as [s [f [f1 [f2 h] ] ] ].
  destruct h as [g _].
  fsetdec.
Qed.

Definition FixVar1 : atom.
  destruct constants as [_ [_ [f1 _] ] ].
  exact f1.
Defined.

Definition FixVar2 : atom.
  destruct constants as [_ [_ [_ [f2 _] ] ] ].
  exact f2.
Defined.

Definition FixPat : tm := a_App (a_App (a_Fam Fix) (Rho Irrel) a_Bullet) (Rho Rel) (a_Var_f FixVar2).

Definition FixDef : tm := a_App (a_Var_f FixVar2) (Rho Rel)
                              (a_App (a_App (a_Fam Fix) (Rho Irrel) a_Bullet) (Rho Rel) (a_Var_f FixVar2)).

Definition FixTy : tm  := a_Pi Irrel a_Star
                             (a_Pi Rel (a_Pi Rel (a_Var_b 0) (a_Var_b 1)) (a_Var_b 1)).

Definition toplevel : sig := Fix ~ Ax FixPat FixDef FixTy Rep (Nom :: [Nom]).

(** definitions *)

(* defns JSubRole *)
Inductive SubRole : role -> role -> Prop :=    (* defn SubRole *)
 | NomBot : forall (R:role),
     SubRole Nom R
 | RepTop : forall (R:role),
     SubRole R Rep
 | Refl : forall (R:role),
     SubRole R R
 | Trans : forall (R1 R3 R2:role),
     SubRole R1 R2 ->
     SubRole R2 R3 ->
     SubRole R1 R3.

(* defns JRolePath *)
Inductive RolePath : tm -> roles -> Prop :=    (* defn RolePath *)
 | RolePath_AbsConst : forall (F:const) (Rs:roles) (A:tm),
      binds  F  ( (Cs A Rs) )   toplevel   ->
     RolePath (a_Fam F) Rs
 | RolePath_Const : forall (F:const) (Rs:roles) (p a A:tm) (R1:role),
      binds  F  ( (Ax p a A R1 Rs) )   toplevel   ->
     RolePath (a_Fam F) Rs
 | RolePath_TApp : forall (a:tm) (R1:role) (b:tm) (Rs:roles),
     lc_tm b ->
     RolePath a  ( R1 :: Rs )  ->
     RolePath (a_App a (Role R1) b) Rs
 | RolePath_App : forall (a b:tm) (Rs:roles),
     lc_tm b ->
     RolePath a  ( Nom :: Rs )  ->
     RolePath (a_App a (Rho Rel) b) Rs
 | RolePath_IApp : forall (a:tm) (Rs:roles),
     RolePath a Rs ->
     RolePath (a_App a (Rho Irrel) a_Bullet) Rs
 | RolePath_CApp : forall (a:tm) (Rs:roles),
     RolePath a Rs ->
     RolePath (a_CApp a g_Triv) Rs.

(* defns JAppsPath *)
Inductive AppsPath : role -> tm -> const -> Apps -> Prop :=    (* defn AppsPath *)
 | AppsPath_AbsConst : forall (R:role) (F:const) (A:tm) (Rs:roles),
      binds  F  ( (Cs A Rs) )   toplevel   ->
     AppsPath R (a_Fam F) F A_nil
 | AppsPath_Const : forall (R:role) (F:const) (p a A:tm) (R1:role) (Rs:roles),
      binds  F  ( (Ax p a A R1 Rs) )   toplevel   ->
      not (  ( SubRole R1 R )  )  ->
     AppsPath R (a_Fam F) F A_nil
 | AppsPath_App : forall (R:role) (a:tm) (R1:role) (b':tm) (F:const) (Apps5:Apps),
     lc_tm b' ->
     AppsPath R a F Apps5 ->
     AppsPath R  ( (a_App a (Role R1) b') )  F  (  (A_snoc  Apps5   (A_Tm (Role R1)) )  )
 | AppsPath_IApp : forall (R:role) (a b:tm) (F:const) (Apps5:Apps),
     lc_tm b ->
     AppsPath R a F Apps5 ->
     AppsPath R  ( (a_App a (Rho Irrel) b) )  F  (  (A_snoc  Apps5   (A_Tm (Rho Irrel)) )  )
 | AppsPath_CApp : forall (R:role) (a:tm) (F:const) (Apps5:Apps),
     AppsPath R a F Apps5 ->
     AppsPath R  ( (a_CApp a g_Triv) )  F  (  (A_snoc  Apps5   A_Co )  ) .

(* defns JSat *)
Inductive AppRoles : Apps -> roles -> Prop :=    (* defn AppRoles *)
 | AR_nil :
     AppRoles A_nil  nil
 | AR_consTApp : forall (R1:role) (Apps5:Apps) (Rs:roles),
     AppRoles Apps5 Rs ->
     AppRoles (A_cons (A_Tm (Role R1)) Apps5)  ( R1 :: Rs )
 | AR_consApp : forall (Apps5:Apps) (Rs:roles),
     AppRoles Apps5 Rs ->
     AppRoles (A_cons (A_Tm (Rho Rel)) Apps5)  ( Nom :: Rs )
 | AR_consIApp : forall (Apps5:Apps) (Rs:roles),
     AppRoles Apps5 Rs ->
     AppRoles (A_cons (A_Tm (Rho Irrel)) Apps5) Rs
 | AR_consCApp : forall (Apps5:Apps) (Rs:roles),
     AppRoles Apps5 Rs ->
     AppRoles (A_cons A_Co Apps5) Rs
with SatApp : const -> Apps -> Prop :=    (* defn SatApp *)
 | Sat_Const : forall (F:const) (Apps5:Apps) (A:tm) (Rs:roles),
      binds  F  ( (Cs A Rs) )   toplevel   ->
     AppRoles Apps5 Rs ->
     SatApp F Apps5
 | Sat_Axiom : forall (F:const) (Apps5:Apps) (p a0 A1:tm) (R1:role) (Rs:roles),
      binds  F  ( (Ax p a0 A1 R1 Rs) )   toplevel   ->
      not (  ( SubRole R1 Nom )  )  ->
     AppRoles Apps5 Rs ->
     SatApp F Apps5.

(* defns JPatCtx *)
Inductive PatternContexts : role_context -> context -> atom_list -> const -> tm -> tm -> tm -> Prop :=    (* defn PatternContexts *)
 | PatCtx_Const : forall (F:const) (A:tm),
     lc_tm A ->
     PatternContexts  nil   nil   nil  F A (a_Fam F) A
 | PatCtx_PiRel : forall (L:vars) (W:role_context) (R:role) (G:context) (A':tm) (V:atom_list) (F:const) (B p A:tm),
     PatternContexts W G V F B p (a_Pi Rel A' A) ->
      ( forall x , x \notin  L  -> PatternContexts  (( x  ~  R ) ++  W )   (( x ~ Tm  A' ) ++  G )  V F B (a_App p (Role R) (a_Var_f x))  ( open_tm_wrt_tm A (a_Var_f x) )  )
 | PatCtx_PiIrr : forall (L:vars) (W:role_context) (G:context) (A':tm) (V:atom_list) (F:const) (B p A:tm),
     PatternContexts W G V F B p (a_Pi Irrel A' A) ->
      ( forall x , x \notin  L  -> PatternContexts W  (( x ~ Tm  A' ) ++  G )   x  ::  V  F B (a_App p (Rho Irrel) a_Bullet)  ( open_tm_wrt_tm A (a_Var_f x) )  )
 | PatCtx_CPi : forall (L:vars) (W:role_context) (G:context) (phi:constraint) (V:atom_list) (F:const) (B p A:tm),
     PatternContexts W G V F B p (a_CPi phi A) ->
      ( forall c , c \notin  L  -> PatternContexts W  (( c ~ Co  phi ) ++  G )  V F B (a_CApp p g_Triv)  ( open_tm_wrt_co A (g_Var_f c) )  ) .

(* defns JRename *)
Inductive Rename : tm -> tm -> tm -> tm -> available_props -> available_props -> Prop :=    (* defn Rename *)
 | Rename_Base : forall (F:const) (a:tm) (D:available_props),
     lc_tm a ->
     Rename (a_Fam F) a (a_Fam F) a D  AtomSetImpl.empty
 | Rename_AppRel : forall (p1:tm) (R:role) (x:tmvar) (a1 p2:tm) (y:tmvar) (a2:tm) (D D':available_props),
     Rename p1 a1 p2 a2 D D' ->
      ~ AtomSetImpl.In  y    (  ( D  `union`  D' )  )   ->
     Rename  ( (a_App p1 (Role R) (a_Var_f x)) )  a1  ( (a_App p2 (Role R) (a_Var_f y)) )   (  (tm_subst_tm_tm  (a_Var_f y)   x   a2 )  )  D  (  (singleton  y  \u  D' )  )
 | Rename_AppIrrel : forall (p1 a1 p2 a2:tm) (D D':available_props),
     Rename p1 a1 p2 a2 D D' ->
     Rename  ( (a_App p1 (Rho Irrel) a_Bullet) )  a1  ( (a_App p2 (Rho Irrel) a_Bullet) )  a2 D D'
 | Rename_CApp : forall (p1 a1 p2 a2:tm) (D D':available_props),
     Rename p1 a1 p2 a2 D D' ->
     Rename  ( (a_CApp p1 g_Triv) )  a1  ( (a_CApp p2 g_Triv) )  a2 D D'.

(* defns JMatchSubst *)
Inductive MatchSubst : tm -> tm -> tm -> tm -> Prop :=    (* defn MatchSubst *)
 | MatchSubst_Const : forall (F:const) (b:tm),
     lc_tm b ->
     MatchSubst (a_Fam F) (a_Fam F) b b
 | MatchSubst_AppRelR : forall (a1:tm) (R:role) (a p1:tm) (x:tmvar) (b1 b2:tm),
     lc_tm a ->
     MatchSubst a1 p1 b1 b2 ->
     MatchSubst  ( (a_App a1 (Role R) a) )   ( (a_App p1 (Role R) (a_Var_f x)) )  b1  (  (tm_subst_tm_tm  a   x   b2 )  )
 | MatchSubst_AppIrrel : forall (a1 a p1 b1 b2:tm),
     lc_tm a ->
     MatchSubst a1 p1 b1 b2 ->
     MatchSubst  ( (a_App a1 (Rho Irrel) a) )   ( (a_App p1 (Rho Irrel) a_Bullet) )  b1 b2
 | MatchSubst_CApp : forall (a1 a2 b1 b2:tm),
     MatchSubst a1 a2 b1 b2 ->
     MatchSubst  ( (a_CApp a1 g_Triv) )   ( (a_CApp a2 g_Triv) )  b1 b2.

(* defns JIsPattern *)
Inductive Pattern : tm -> Prop :=    (* defn Pattern *)
 | Pattern_Head : forall (F:const),
     Pattern (a_Fam F)
 | Pattern_Rel : forall (p:tm) (R:role) (a:tm),
     lc_tm a ->
     Pattern p ->
     Pattern  ( (a_App p (Role R) a) )
 | Pattern_Irrel : forall (p a:tm),
     lc_tm a ->
     Pattern p ->
     Pattern  ( (a_App p (Rho Irrel) a) )
 | Pattern_Co : forall (p:tm) (g:co),
     lc_co g ->
     Pattern p ->
     Pattern  ( (a_CApp p g) ) .

(* defns JSubPat *)
Inductive SubPat : tm -> tm -> Prop :=    (* defn SubPat *)
 | SubPat_Refl : forall (p:tm),
     Pattern p ->
     SubPat p p
 | SubPat_Rel : forall (p' p:tm) (R:role) (x:tmvar),
     SubPat p' p ->
     SubPat p'  ( (a_App p (Role R) (a_Var_f x)) )
 | SubPat_Irrel : forall (p' p:tm),
     SubPat p' p ->
     SubPat p'  ( (a_App p (Rho Irrel) a_Bullet) )
 | SubPat_Co : forall (p' p:tm),
     SubPat p' p ->
     SubPat p'  ( (a_CApp p g_Triv) ) .

(* defns JTmPatternAgree *)
Inductive tm_pattern_agree : tm -> tm -> Prop :=    (* defn tm_pattern_agree *)
 | tm_pattern_agree_Const : forall (F:const),
     tm_pattern_agree (a_Fam F) (a_Fam F)
 | tm_pattern_agree_AppRelR : forall (a1:tm) (R:role) (a2 p1:tm) (x:tmvar),
     lc_tm a2 ->
     tm_pattern_agree a1 p1 ->
     tm_pattern_agree  ( (a_App a1 (Role R) a2) )   ( (a_App p1 (Role R) (a_Var_f x)) )
 | tm_pattern_agree_AppIrrel : forall (a1 a p1:tm),
     lc_tm a ->
     tm_pattern_agree a1 p1 ->
     tm_pattern_agree  ( (a_App a1 (Rho Irrel) a) )   ( (a_App p1 (Rho Irrel) a_Bullet) )
 | tm_pattern_agree_CApp : forall (a1 p1:tm),
     tm_pattern_agree a1 p1 ->
     tm_pattern_agree  ( (a_CApp a1 g_Triv) )   ( (a_CApp p1 g_Triv) ) .

(* defns JTmSubPatternAgree *)
Inductive tm_subpattern_agree : tm -> tm -> Prop :=    (* defn tm_subpattern_agree *)
 | tm_subpattern_agree_Base : forall (a p:tm),
     tm_pattern_agree a p ->
     tm_subpattern_agree a p
 | tm_subpattern_agree_AppRelR : forall (a p:tm) (R:role) (x:tmvar),
     tm_subpattern_agree a p ->
     tm_subpattern_agree a  ( (a_App p (Role R) (a_Var_f x)) )
 | tm_subpattern_agree_AppIrrel : forall (a p:tm),
     tm_subpattern_agree a p ->
     tm_subpattern_agree a  ( (a_App p (Rho Irrel) a_Bullet) )
 | tm_subpattern_agree_CAppp : forall (a p:tm),
     tm_subpattern_agree a p ->
     tm_subpattern_agree a  ( (a_CApp p g_Triv) ) .

(* defns JSubTmPatternAgree *)
Inductive subtm_pattern_agree : tm -> tm -> Prop :=    (* defn subtm_pattern_agree *)
 | subtm_pattern_agree_Base : forall (a p:tm),
     tm_pattern_agree a p ->
     subtm_pattern_agree a p
 | subtm_pattern_agree_App : forall (a:tm) (nu:appflag) (a2 p:tm),
     lc_tm a2 ->
     subtm_pattern_agree a p ->
     subtm_pattern_agree (a_App a nu a2) p
 | subtm_pattern_agree_CAppp : forall (a p:tm),
     subtm_pattern_agree a p ->
     subtm_pattern_agree (a_CApp a g_Triv) p.

(* defns JValuePath *)
Inductive ValuePath : tm -> const -> Prop :=    (* defn ValuePath *)
 | ValuePath_AbsConst : forall (F:const) (A:tm) (Rs:roles),
      binds  F  ( (Cs A Rs) )   toplevel   ->
     ValuePath (a_Fam F) F
 | ValuePath_Const : forall (F:const) (p a A:tm) (R1:role) (Rs:roles),
      binds  F  ( (Ax p a A R1 Rs) )   toplevel   ->
     ValuePath (a_Fam F) F
 | ValuePath_App : forall (a:tm) (nu:appflag) (b':tm) (F:const),
     lc_tm b' ->
     ValuePath a F ->
     ValuePath  ( (a_App a nu b') )  F
 | ValuePath_CApp : forall (a:tm) (F:const),
     ValuePath a F ->
     ValuePath  ( (a_CApp a g_Triv) )  F.

(* defns JCasePath *)
Inductive CasePath : role -> tm -> const -> Prop :=    (* defn CasePath *)
 | CasePath_AbsConst : forall (R:role) (a:tm) (F:const) (A:tm) (Rs:roles),
     ValuePath a F ->
      binds  F  ( (Cs A Rs) )   toplevel   ->
     CasePath R a F
 | CasePath_Const : forall (R:role) (a:tm) (F:const) (p b A:tm) (R1:role) (Rs:roles),
     ValuePath a F ->
      binds  F  ( (Ax p b A R1 Rs) )   toplevel   ->
      not (  ( SubRole R1 R )  )  ->
     CasePath R a F
 | CasePath_UnMatch : forall (R:role) (a:tm) (F:const) (p b A:tm) (R1:role) (Rs:roles),
     ValuePath a F ->
      binds  F  ( (Ax p b A R1 Rs) )   toplevel   ->
      not (  ( subtm_pattern_agree a p )  )  ->
     CasePath R a F.

(* defns JApplyArgs *)
Inductive ApplyArgs : tm -> tm -> tm -> Prop :=    (* defn ApplyArgs *)
 | ApplyArgs_Const : forall (F:const) (b:tm),
     lc_tm b ->
     ApplyArgs (a_Fam F) b b
 | ApplyArgs_AppRole : forall (a:tm) (R:role) (a' b b':tm),
     lc_tm a' ->
     ApplyArgs a b b' ->
     ApplyArgs  ( (a_App a (Role R) a') )  b  ( (a_App b' (Rho Rel) a') )
 | ApplyArgs_AppRho : forall (a:tm) (rho:relflag) (a' b b':tm),
     lc_tm a' ->
     ApplyArgs a b b' ->
     ApplyArgs  ( (a_App a (Rho rho) a') )  b  ( (a_App b' (Rho rho) a') )
 | ApplyArgs_CApp : forall (a b b':tm),
     ApplyArgs a b b' ->
     ApplyArgs (a_CApp a g_Triv) b (a_CApp b' g_Triv).

(* defns JValue *)
Inductive Value : role -> tm -> Prop :=    (* defn Value *)
 | Value_Star : forall (R:role),
     Value R a_Star
 | Value_Pi : forall (R:role) (rho:relflag) (A B:tm),
     lc_tm A ->
     lc_tm (a_Pi rho A B) ->
     Value R (a_Pi rho A B)
 | Value_CPi : forall (R:role) (phi:constraint) (B:tm),
     lc_constraint phi ->
     lc_tm (a_CPi phi B) ->
     Value R (a_CPi phi B)
 | Value_AbsRel : forall (R:role) (A a:tm),
     lc_tm A ->
     lc_tm (a_Abs Rel A a) ->
     Value R (a_Abs Rel A a)
 | Value_UAbsRel : forall (R:role) (a:tm),
     lc_tm (a_UAbs Rel a) ->
     Value R (a_UAbs Rel a)
 | Value_UAbsIrrel : forall (L:vars) (R:role) (a:tm),
      ( forall x , x \notin  L  -> Value R  ( open_tm_wrt_tm a (a_Var_f x) )  )  ->
     Value R (a_UAbs Irrel a)
 | Value_CAbs : forall (R:role) (phi:constraint) (a:tm),
     lc_constraint phi ->
     lc_tm (a_CAbs phi a) ->
     Value R (a_CAbs phi a)
 | Value_UCAbs : forall (R:role) (a:tm),
     lc_tm (a_UCAbs a) ->
     Value R (a_UCAbs a)
 | Value_Path : forall (R:role) (a:tm) (F:const),
     CasePath R a F ->
     Value R a.

(* defns JValueType *)
Inductive value_type : role -> tm -> Prop :=    (* defn value_type *)
 | value_type_Star : forall (R:role),
     value_type R a_Star
 | value_type_Pi : forall (R:role) (rho:relflag) (A B:tm),
     lc_tm A ->
     lc_tm (a_Pi rho A B) ->
     value_type R (a_Pi rho A B)
 | value_type_CPi : forall (R:role) (phi:constraint) (B:tm),
     lc_constraint phi ->
     lc_tm (a_CPi phi B) ->
     value_type R (a_CPi phi B)
 | value_type_ValuePath : forall (R:role) (a:tm) (F:const),
     CasePath R a F ->
     value_type R a.

(* defns Jconsistent *)
Inductive consistent : tm -> tm -> role -> Prop :=    (* defn consistent *)
 | consistent_a_Star : forall (R:role),
     consistent a_Star a_Star R
 | consistent_a_Pi : forall (rho:relflag) (A1 B1 A2 B2:tm) (R':role),
     lc_tm A1 ->
     lc_tm (a_Pi rho A1 B1) ->
     lc_tm A2 ->
     lc_tm (a_Pi rho A2 B2) ->
     consistent  ( (a_Pi rho A1 B1) )   ( (a_Pi rho A2 B2) )  R'
 | consistent_a_CPi : forall (phi1:constraint) (A1:tm) (phi2:constraint) (A2:tm) (R:role),
     lc_constraint phi1 ->
     lc_tm (a_CPi phi1 A1) ->
     lc_constraint phi2 ->
     lc_tm (a_CPi phi2 A2) ->
     consistent  ( (a_CPi phi1 A1) )   ( (a_CPi phi2 A2) )  R
 | consistent_a_CasePath : forall (a1 a2:tm) (R:role) (F:const),
     CasePath R a1 F ->
     CasePath R a2 F ->
     consistent a1 a2 R
 | consistent_a_Step_R : forall (a b:tm) (R:role),
     lc_tm a ->
      not ( value_type R b )  ->
     consistent a b R
 | consistent_a_Step_L : forall (a b:tm) (R:role),
     lc_tm b ->
      not ( value_type R a )  ->
     consistent a b R.

(* defns Jroleing *)
Inductive roleing : role_context -> tm -> role -> Prop :=    (* defn roleing *)
 | role_a_Bullet : forall (W:role_context) (R:role),
      uniq  W  ->
     roleing W a_Bullet R
 | role_a_Star : forall (W:role_context) (R:role),
      uniq  W  ->
     roleing W a_Star R
 | role_a_Var : forall (W:role_context) (x:tmvar) (R1 R:role),
      uniq  W  ->
      binds  x   R   W  ->
     SubRole R R1 ->
     roleing W (a_Var_f x) R1
 | role_a_Abs : forall (L:vars) (W:role_context) (rho:relflag) (a:tm) (R:role),
      ( forall x , x \notin  L  -> roleing  (( x  ~  Nom ) ++  W )   ( open_tm_wrt_tm a (a_Var_f x) )  R )  ->
     roleing W  ( (a_UAbs rho a) )  R
 | role_a_App : forall (W:role_context) (a:tm) (rho:relflag) (b:tm) (R:role),
     roleing W a R ->
     roleing W b Nom ->
     roleing W  ( (a_App a (Rho rho) b) )  R
 | role_a_TApp : forall (W:role_context) (a:tm) (R1:role) (b:tm) (R:role),
     roleing W a R ->
     roleing W b  (param R1   R )  ->
     roleing W (a_App a (Role R1) b) R
 | role_a_Pi : forall (L:vars) (W:role_context) (rho:relflag) (A B:tm) (R:role),
     roleing W A R ->
      ( forall x , x \notin  L  -> roleing  (( x  ~  Nom ) ++  W )   ( open_tm_wrt_tm B (a_Var_f x) )  R )  ->
     roleing W  ( (a_Pi rho A B) )  R
 | role_a_CPi : forall (L:vars) (W:role_context) (a b A:tm) (R1:role) (B:tm) (R:role),
     roleing W a R1 ->
     roleing W b R1 ->
     roleing W A Rep ->
      ( forall c , c \notin  L  -> roleing W  ( open_tm_wrt_co B (g_Var_f c) )  R )  ->
     roleing W  ( (a_CPi (Eq a b A R1) B) )  R
 | role_a_CAbs : forall (L:vars) (W:role_context) (b:tm) (R:role),
      ( forall c , c \notin  L  -> roleing W  ( open_tm_wrt_co b (g_Var_f c) )  R )  ->
     roleing W  ( (a_UCAbs b) )  R
 | role_a_CApp : forall (W:role_context) (a:tm) (R:role),
     roleing W a R ->
     roleing W  ( (a_CApp a g_Triv) )  R
 | role_a_Const : forall (W:role_context) (F:const) (R:role) (A:tm) (Rs:roles),
      uniq  W  ->
      binds  F  ( (Cs A Rs) )   toplevel   ->
     roleing W (a_Fam F) R
 | role_a_Fam : forall (W:role_context) (F:const) (R1:role) (p a A:tm) (R:role) (Rs:roles),
      uniq  W  ->
      binds  F  ( (Ax p a A R Rs) )   toplevel   ->
     roleing W (a_Fam F) R1
 | role_a_Pattern : forall (W:role_context) (a:tm) (F:const) (Apps5:Apps) (b1 b2:tm) (R1:role),
     roleing W a Nom ->
     roleing W b1 R1 ->
     roleing W b2 R1 ->
     roleing W (a_Pattern Nom a F Apps5 b1 b2) R1.

(* defns JChk *)
Inductive RhoCheck : relflag -> tmvar -> tm -> Prop :=    (* defn RhoCheck *)
 | Rho_Rel : forall (x:tmvar) (A:tm),
      True  ->
     RhoCheck Rel x A
 | Rho_IrrRel : forall (x:tmvar) (A:tm),
      ~ AtomSetImpl.In  x    (fv_tm_tm_tm  A )   ->
     RhoCheck Irrel x A.

(* defns Jpar *)
Inductive Par : role_context -> tm -> tm -> role -> Prop :=    (* defn Par *)
 | Par_Refl : forall (W:role_context) (a:tm) (R:role),
     roleing W a R ->
     Par W a a R
 | Par_Beta : forall (W:role_context) (a:tm) (rho:relflag) (b a' b':tm) (R:role),
     Par W a  ( (a_UAbs rho a') )  R ->
     Par W b b' Nom ->
     Par W (a_App a (Rho rho) b)  (open_tm_wrt_tm  a'   b' )  R
 | Par_App : forall (W:role_context) (a:tm) (nu:appflag) (b a' b':tm) (R:role),
     Par W a a' R ->
     Par W b b'  (  app_role  nu   R  )  ->
     Par W (a_App a nu b) (a_App a' nu b') R
 | Par_CBeta : forall (W:role_context) (a a':tm) (R:role),
     Par W a  ( (a_UCAbs a') )  R ->
     Par W (a_CApp a g_Triv)  (open_tm_wrt_co  a'   g_Triv )  R
 | Par_CApp : forall (W:role_context) (a a':tm) (R:role),
     Par W a a' R ->
     Par W (a_CApp a g_Triv) (a_CApp a' g_Triv) R
 | Par_Abs : forall (L:vars) (W:role_context) (rho:relflag) (a a':tm) (R:role),
      ( forall x , x \notin  L  -> Par  (( x  ~  Nom ) ++  W )   ( open_tm_wrt_tm a (a_Var_f x) )   ( open_tm_wrt_tm a' (a_Var_f x) )  R )  ->
     Par W (a_UAbs rho a) (a_UAbs rho a') R
 | Par_Pi : forall (L:vars) (W:role_context) (rho:relflag) (A B A' B':tm) (R:role),
     Par W A A' R ->
      ( forall x , x \notin  L  -> Par  (( x  ~  Nom ) ++  W )   ( open_tm_wrt_tm B (a_Var_f x) )   ( open_tm_wrt_tm B' (a_Var_f x) )  R )  ->
     Par W (a_Pi rho A B) (a_Pi rho A' B') R
 | Par_CAbs : forall (L:vars) (W:role_context) (a a':tm) (R:role),
      ( forall c , c \notin  L  -> Par W  ( open_tm_wrt_co a (g_Var_f c) )   ( open_tm_wrt_co a' (g_Var_f c) )  R )  ->
     Par W (a_UCAbs a) (a_UCAbs a') R
 | Par_CPi : forall (L:vars) (W:role_context) (a b A:tm) (R1:role) (B a' b' A' B':tm) (R:role),
     Par W A A' Rep ->
     Par W a a' R1 ->
     Par W b b' R1 ->
      ( forall c , c \notin  L  -> Par W  ( open_tm_wrt_co B (g_Var_f c) )   ( open_tm_wrt_co B' (g_Var_f c) )  R )  ->
     Par W (a_CPi (Eq a b A R1) B) (a_CPi (Eq a' b' A' R1) B') R
 | Par_AxiomBase : forall (W:role_context) (F:const) (b:tm) (R:role) (A:tm) (R1:role) (Rs:roles),
      binds  F  ( (Ax (a_Fam F) b A R1 Rs) )   toplevel   ->
     SubRole R1 R ->
      uniq  W  ->
     Par W (a_Fam F) b R
 | Par_AxiomApp : forall (W:role_context) (a:tm) (nu:appflag) (a1 a2:tm) (R:role) (F:const) (p b A:tm) (R1:role) (Rs:roles) (a' a1' p' b':tm) (D':available_props),
      binds  F  ( (Ax p b A R1 Rs) )   toplevel   ->
      tm_subpattern_agree a p  /\   not (  ( tm_pattern_agree a p )  )   ->
     Par W a a' R ->
     Par W a1 a1'  (  app_role  nu   R  )  ->
     Rename p b p' b'  (  (  (dom  W )   `union`   (fv_tm_tm_tm  p )  )  )  D' ->
     MatchSubst  ( (a_App a' nu a1') )  p' b' a2 ->
     SubRole R1 R ->
     Par W (a_App a nu a1) a2 R
 | Par_AxiomCApp : forall (W:role_context) (a a2:tm) (R:role) (F:const) (p b A:tm) (R1:role) (Rs:roles) (a' p' b':tm) (D':available_props),
      binds  F  ( (Ax p b A R1 Rs) )   toplevel   ->
      tm_subpattern_agree a p  /\   not (  ( tm_pattern_agree a p )  )   ->
     Par W a a' R ->
     Rename p b p' b'  (  (  (dom  W )   `union`   (fv_tm_tm_tm  p )  )  )  D' ->
     MatchSubst  ( (a_CApp a' g_Triv) )  p' b' a2 ->
     SubRole R1 R ->
     Par W (a_CApp a g_Triv) a2 R
 | Par_Pattern : forall (W:role_context) (a:tm) (F:const) (Apps5:Apps) (b1 b2 a' b1' b2':tm) (R0:role),
     Par W a a' Nom ->
     Par W b1 b1' R0 ->
     Par W b2 b2' R0 ->
     Par W  ( (a_Pattern Nom a F Apps5 b1 b2) )   ( (a_Pattern Nom a' F Apps5 b1' b2') )  R0
 | Par_PatternTrue : forall (W:role_context) (a:tm) (F:const) (Apps5:Apps) (b1 b2 b:tm) (R0:role) (a' b1' b2':tm) (Apps':Apps),
     Par W a a' Nom ->
     Par W b1 b1' R0 ->
     Par W b2 b2' R0 ->
     AppsPath Nom a' F Apps5 ->
     ApplyArgs a' b1' b ->
     SatApp F Apps' ->
     Par W  ( (a_Pattern Nom a F Apps5 b1 b2) )  (a_CApp b g_Triv) R0
 | Par_PatternFalse : forall (W:role_context) (a:tm) (F:const) (Apps5:Apps) (b1 b2 b2':tm) (R0:role) (a' b1':tm),
     Par W a a' Nom ->
     Par W b1 b1' R0 ->
     Par W b2 b2' R0 ->
     Value Nom a' ->
      not (  ( AppsPath Nom a' F Apps5 )  )  ->
     Par W  ( (a_Pattern Nom a F Apps5 b1 b2) )  b2' R0
with MultiPar : role_context -> tm -> tm -> role -> Prop :=    (* defn MultiPar *)
 | MP_Refl : forall (W:role_context) (a:tm) (R:role),
     lc_tm a ->
     MultiPar W a a R
 | MP_Step : forall (W:role_context) (a a':tm) (R:role) (b:tm),
     Par W a b R ->
     MultiPar W b a' R ->
     MultiPar W a a' R
with joins : role_context -> tm -> tm -> role -> Prop :=    (* defn joins *)
 | join : forall (W:role_context) (a1 a2:tm) (R:role) (b:tm),
     MultiPar W a1 b R ->
     MultiPar W a2 b R ->
     joins W a1 a2 R.

(* defns Jbeta *)
Inductive Beta : tm -> tm -> role -> Prop :=    (* defn Beta *)
 | Beta_AppAbs : forall (rho:relflag) (v b:tm) (R1:role),
     lc_tm b ->
     Value R1  ( (a_UAbs rho v) )  ->
     Beta (a_App  ( (a_UAbs rho v) )  (Rho rho) b)  (open_tm_wrt_tm  v   b )  R1
 | Beta_CAppCAbs : forall (a':tm) (R:role),
     lc_tm (a_UCAbs a') ->
     Beta (a_CApp  ( (a_UCAbs a') )  g_Triv)  (open_tm_wrt_co  a'   g_Triv )  R
 | Beta_Axiom : forall (a b':tm) (R:role) (F:const) (p b A:tm) (R1:role) (Rs:roles) (p1 b1:tm) (D':available_props),
      binds  F  ( (Ax p b A R1 Rs) )   toplevel   ->
     Rename p b p1 b1  (  (  (fv_tm_tm_tm  a )   `union`   (fv_tm_tm_tm  p )  )  )  D' ->
     MatchSubst a p1 b1 b' ->
     SubRole R1 R ->
     Beta a b' R
 | Beta_PatternTrue : forall (a:tm) (F:const) (Apps5:Apps) (b1 b2 b1':tm) (R0:role) (Apps':Apps),
     lc_tm b2 ->
     AppsPath Nom a F Apps5 ->
     ApplyArgs a b1 b1' ->
     SatApp F Apps' ->
     Beta (a_Pattern Nom a F Apps5 b1 b2) (a_CApp b1' g_Triv) R0
 | Beta_PatternFalse : forall (a:tm) (F:const) (Apps5:Apps) (b1 b2:tm) (R0:role),
     lc_tm b1 ->
     lc_tm b2 ->
     Value Nom a ->
      not (  ( AppsPath Nom a F Apps5 )  )  ->
     Beta (a_Pattern Nom a F Apps5 b1 b2) b2 R0
with reduction_in_one : tm -> tm -> role -> Prop :=    (* defn reduction_in_one *)
 | E_AbsTerm : forall (L:vars) (a a':tm) (R1:role),
      ( forall x , x \notin  L  -> reduction_in_one  ( open_tm_wrt_tm a (a_Var_f x) )   ( open_tm_wrt_tm a' (a_Var_f x) )  R1 )  ->
     reduction_in_one (a_UAbs Irrel a) (a_UAbs Irrel a') R1
 | E_AppLeft : forall (a:tm) (nu:appflag) (b a':tm) (R1:role),
     lc_tm b ->
     reduction_in_one a a' R1 ->
     reduction_in_one (a_App a nu b) (a_App a' nu b) R1
 | E_CAppLeft : forall (a a':tm) (R:role),
     reduction_in_one a a' R ->
     reduction_in_one (a_CApp a g_Triv) (a_CApp a' g_Triv) R
 | E_Pattern : forall (a:tm) (F:const) (Apps5:Apps) (b1 b2 a':tm) (R0:role),
     lc_tm b1 ->
     lc_tm b2 ->
     reduction_in_one a a' Nom ->
     reduction_in_one (a_Pattern Nom a F Apps5 b1 b2) (a_Pattern Nom a' F Apps5 b1 b2) R0
 | E_Prim : forall (a b:tm) (R:role),
     Beta a b R ->
     reduction_in_one a b R
with reduction : tm -> tm -> role -> Prop :=    (* defn reduction *)
 | Equal : forall (a:tm) (R:role),
     lc_tm a ->
     reduction a a R
 | Step : forall (a a':tm) (R:role) (b:tm),
     reduction_in_one a b R ->
     reduction b a' R ->
     reduction a a' R.

(* defns JBranchTyping *)
Inductive BranchTyping : context -> Apps -> role -> tm -> tm -> tm -> pattern_args -> tm -> tm -> tm -> Prop :=    (* defn BranchTyping *)
 | BranchTyping_Base : forall (G:context) (a A b:tm) (pattern_args5:pattern_args) (C1 C2:tm),
     lc_tm a ->
     lc_tm b ->
     lc_tm A ->
      uniq  G  ->
      (  (open_tm_wrt_co  C1   g_Triv )   =  C2 )  ->
     BranchTyping G A_nil Nom a A b pattern_args5 A (a_CPi  ( (Eq a  (apply_pattern_args  b   pattern_args5 )  A Nom) )  C1) C2
 | BranchTyping_PiRole : forall (L:vars) (G:context) (R:role) (Apps5:Apps) (a A1 b:tm) (pattern_args5:pattern_args) (A B C C':tm),
      ( forall x , x \notin  L  -> BranchTyping  (( x ~ Tm  A ) ++  G )  Apps5 Nom a A1 b  ( pattern_args5  ++ [  (p_Tm (Role R) (a_Var_f x))  ])   ( open_tm_wrt_tm B (a_Var_f x) )   ( open_tm_wrt_tm C (a_Var_f x) )  C' )  ->
     BranchTyping G  ( (A_cons (A_Tm (Role R)) Apps5) )  Nom a A1 b pattern_args5 (a_Pi Rel A B) (a_Pi Rel A C) C'
 | BranchTyping_PiRel : forall (L:vars) (G:context) (Apps5:Apps) (a A1 b:tm) (pattern_args5:pattern_args) (A B C C':tm),
      ( forall x , x \notin  L  -> BranchTyping  (( x ~ Tm  A ) ++  G )  Apps5 Nom a A1 b  ( pattern_args5  ++ [  (p_Tm (Rho Rel) (a_Var_f x))  ])   ( open_tm_wrt_tm B (a_Var_f x) )   ( open_tm_wrt_tm C (a_Var_f x) )  C' )  ->
     BranchTyping G  ( (A_cons (A_Tm (Rho Rel)) Apps5) )  Nom a A1 b pattern_args5 (a_Pi Rel A B) (a_Pi Rel A C) C'
 | BranchTyping_PiIrrel : forall (L:vars) (G:context) (Apps5:Apps) (a A1 b:tm) (pattern_args5:pattern_args) (A B C C':tm),
      ( forall x , x \notin  L  -> BranchTyping  (( x ~ Tm  A ) ++  G )  Apps5 Nom a A1 b  ( pattern_args5  ++ [  (p_Tm (Rho Irrel) a_Bullet)  ])   ( open_tm_wrt_tm B (a_Var_f x) )   ( open_tm_wrt_tm C (a_Var_f x) )  C' )  ->
     BranchTyping G  ( (A_cons (A_Tm (Rho Irrel)) Apps5) )  Nom a A1 b pattern_args5 (a_Pi Irrel A B) (a_Pi Irrel A C) C'
 | BranchTyping_CPi : forall (L:vars) (G:context) (Apps5:Apps) (a A b:tm) (pattern_args5:pattern_args) (phi:constraint) (B C C':tm),
      ( forall c , c \notin  L  -> BranchTyping  (( c ~ Co  phi ) ++  G )  Apps5 Nom a A b  ( pattern_args5  ++ [  (p_Co g_Triv)  ])   ( open_tm_wrt_co B (g_Var_f c) )   ( open_tm_wrt_co C (g_Var_f c) )  C' )  ->
     BranchTyping G  ( (A_cons A_Co Apps5) )  Nom a A b pattern_args5 (a_CPi phi B) (a_CPi phi C) C'.

(* defns Jett *)
Inductive PropWff : context -> constraint -> Prop :=    (* defn PropWff *)
 | E_Wff : forall (G:context) (a b A:tm) (R:role),
     Typing G a A ->
     Typing G b A ->
      ( Typing G A a_Star )  ->
     PropWff G (Eq a b A R)
with Typing : context -> tm -> tm -> Prop :=    (* defn Typing *)
 | E_Star : forall (G:context),
     Ctx G ->
     Typing G a_Star a_Star
 | E_Var : forall (G:context) (x:tmvar) (A:tm),
     Ctx G ->
      binds  x  (Tm  A )  G  ->
     Typing G (a_Var_f x) A
 | E_Pi : forall (L:vars) (G:context) (rho:relflag) (A B:tm),
      ( forall x , x \notin  L  -> Typing  (( x ~ Tm  A ) ++  G )   ( open_tm_wrt_tm B (a_Var_f x) )  a_Star )  ->
     Typing G A a_Star ->
     Typing G (a_Pi rho A B) a_Star
 | E_Abs : forall (L:vars) (G:context) (rho:relflag) (a A B:tm),
      ( forall x , x \notin  L  -> Typing  (( x ~ Tm  A ) ++  G )   ( open_tm_wrt_tm a (a_Var_f x) )   ( open_tm_wrt_tm B (a_Var_f x) )  )  ->
      ( Typing G A a_Star )  ->
      ( forall x , x \notin  L  -> RhoCheck rho x  ( open_tm_wrt_tm a (a_Var_f x) )  )  ->
     Typing G (a_UAbs rho a)  ( (a_Pi rho A B) )
 | E_App : forall (G:context) (b a B A:tm),
     Typing G b (a_Pi Rel A B) ->
     Typing G a A ->
     Typing G (a_App b (Rho Rel) a)  (open_tm_wrt_tm  B   a )
 | E_TApp : forall (G:context) (b:tm) (R:role) (a B A:tm) (Rs:roles),
     Typing G b (a_Pi Rel A B) ->
     Typing G a A ->
     RolePath b  ( R :: Rs )  ->
     Typing G (a_App b (Role R) a)  (open_tm_wrt_tm  B   a )
 | E_IApp : forall (G:context) (b B a A:tm),
     Typing G b (a_Pi Irrel A B) ->
     Typing G a A ->
     Typing G (a_App b (Rho Irrel) a_Bullet)  (open_tm_wrt_tm  B   a )
 | E_Conv : forall (G:context) (a B A:tm),
     Typing G a A ->
     DefEq G  (dom  G )  A B a_Star Rep ->
      ( Typing G B a_Star )  ->
     Typing G a B
 | E_CPi : forall (L:vars) (G:context) (phi:constraint) (B:tm),
      ( forall c , c \notin  L  -> Typing  (( c ~ Co  phi ) ++  G )   ( open_tm_wrt_co B (g_Var_f c) )  a_Star )  ->
      ( PropWff G phi )  ->
     Typing G (a_CPi phi B) a_Star
 | E_CAbs : forall (L:vars) (G:context) (a:tm) (phi:constraint) (B:tm),
      ( forall c , c \notin  L  -> 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)
 | E_CApp : forall (G:context) (a1 B1 a b A:tm) (R:role),
     Typing G a1 (a_CPi  ( (Eq a b A R) )  B1) ->
     DefEq G  (dom  G )  a b A R ->
     Typing G (a_CApp a1 g_Triv)  (open_tm_wrt_co  B1   g_Triv )
 | E_Const : forall (G:context) (F:const) (A:tm) (Rs:roles),
     Ctx G ->
      binds  F  ( (Cs A Rs) )   toplevel   ->
      ( Typing  nil  A a_Star )  ->
     Typing G (a_Fam F) A
 | E_Fam : forall (G:context) (F:const) (A p a:tm) (R1:role) (Rs:roles),
     Ctx G ->
      binds  F  ( (Ax p a A R1 Rs) )   toplevel   ->
      ( Typing  nil  A a_Star )  ->
     Typing G (a_Fam F) A
 | E_Case : forall (G:context) (a:tm) (F:const) (Apps5:Apps) (b1 b2 C A B A1:tm),
     Typing G a A ->
     Typing G b1 B ->
     Typing G b2 C ->
     BranchTyping G Apps5 Nom a A (a_Fam F)  nil  A1 B C ->
     Typing G (a_Fam F) A1 ->
     SatApp F Apps5 ->
     Typing G (a_Pattern Nom a F Apps5 b1 b2) C
with Iso : context -> available_props -> constraint -> constraint -> Prop :=    (* defn Iso *)
 | E_PropCong : forall (G:context) (D:available_props) (A1 B1 A:tm) (R:role) (A2 B2:tm),
     DefEq G D A1 A2 A R ->
     DefEq G D B1 B2 A R ->
     Iso G D (Eq A1 B1 A R) (Eq A2 B2 A R)
 | E_IsoConv : forall (G:context) (D:available_props) (A1 A2 A:tm) (R:role) (B:tm) (R0:role),
     DefEq G D A B a_Star R0 ->
     PropWff G (Eq A1 A2 A R) ->
     PropWff G (Eq A1 A2 B R) ->
     Iso G D (Eq A1 A2 A R) (Eq A1 A2 B R)
 | E_CPiFst : forall (G:context) (D:available_props) (a1 a2 A:tm) (R1:role) (b1 b2 B:tm) (R2:role) (B1 B2:tm) (R':role),
     DefEq G D (a_CPi  ( (Eq a1 a2 A R1) )  B1) (a_CPi  ( (Eq b1 b2 B R2) )  B2) a_Star R' ->
     Iso G D (Eq a1 a2 A R1) (Eq b1 b2 B R2)
with DefEq : context -> available_props -> tm -> tm -> tm -> role -> Prop :=    (* defn DefEq *)
 | E_Assn : forall (G:context) (D:available_props) (a b A:tm) (R:role) (c:covar),
     Ctx G ->
      binds  c  (Co   ( (Eq a b A R) )  )  G  ->
      AtomSetImpl.In  c   D  ->
     DefEq G D a b A R
 | E_Refl : forall (G:context) (D:available_props) (a A:tm) (R:role),
     Typing G a A ->
     DefEq G D a a A R
 | E_Sym : forall (G:context) (D:available_props) (a b A:tm) (R:role),
     DefEq G D b a A R ->
     DefEq G D a b A R
 | E_Trans : forall (G:context) (D:available_props) (a b A:tm) (R:role) (a1:tm),
     DefEq G D a a1 A R ->
     DefEq G D a1 b A R ->
     DefEq G D a b A R
 | E_Sub : forall (G:context) (D:available_props) (a b A:tm) (R2 R1:role),
     DefEq G D a b A R1 ->
     SubRole R1 R2 ->
     DefEq G D a b A R2
 | E_Beta : forall (G:context) (D:available_props) (a1 a2 B:tm) (R:role),
     Typing G a1 B ->
      ( Typing G a2 B )  ->
     Beta a1 a2 R ->
     DefEq G D a1 a2 B R
 | E_PiCong : forall (L:vars) (G:context) (D:available_props) (rho:relflag) (A1 B1 A2 B2:tm) (R':role),
     DefEq G D A1 A2 a_Star R' ->
      ( forall x , x \notin  L  -> DefEq  (( x ~ Tm  A1 ) ++  G )  D  ( open_tm_wrt_tm B1 (a_Var_f x) )   ( open_tm_wrt_tm B2 (a_Var_f x) )  a_Star R' )  ->
      ( Typing G A1 a_Star )  ->
      ( Typing G (a_Pi rho A1 B1) a_Star )  ->
      ( Typing G (a_Pi rho A2 B2) a_Star )  ->
     DefEq G D  ( (a_Pi rho A1 B1) )   ( (a_Pi rho A2 B2) )  a_Star R'
 | E_AbsCong : forall (L:vars) (G:context) (D:available_props) (rho:relflag) (b1 b2 A1 B:tm) (R':role),
      ( forall x , x \notin  L  -> DefEq  (( x ~ Tm  A1 ) ++  G )  D  ( open_tm_wrt_tm b1 (a_Var_f x) )   ( open_tm_wrt_tm b2 (a_Var_f x) )   ( open_tm_wrt_tm B (a_Var_f x) )  R' )  ->
      ( Typing G A1 a_Star )  ->
      ( forall x , x \notin  L  -> RhoCheck rho x  ( open_tm_wrt_tm b1 (a_Var_f x) )  )  ->
      ( forall x , x \notin  L  -> RhoCheck rho x  ( open_tm_wrt_tm b2 (a_Var_f x) )  )  ->
     DefEq G D  ( (a_UAbs rho b1) )   ( (a_UAbs rho b2) )   ( (a_Pi rho A1 B) )  R'
 | E_AppCong : forall (G:context) (D:available_props) (a1 a2 b1 b2 B:tm) (R':role) (A:tm),
     DefEq G D a1 b1  ( (a_Pi Rel A B) )  R' ->
     DefEq G D a2 b2 A Nom ->
     DefEq G D (a_App a1 (Rho Rel) a2) (a_App b1 (Rho Rel) b2)  (  (open_tm_wrt_tm  B   a2 )  )  R'
 | E_TAppCong : forall (G:context) (D:available_props) (a1:tm) (R:role) (a2 b1 b2 B:tm) (R':role) (A:tm) (Rs:roles),
     DefEq G D a1 b1  ( (a_Pi Rel A B) )  R' ->
     DefEq G D a2 b2 A  (param R   R' )  ->
     RolePath a1  ( R :: Rs )  ->
     RolePath b1  ( R :: Rs )  ->
     Typing G (a_App b1 (Role R) b2)  (open_tm_wrt_tm  B   a2 )  ->
     DefEq G D (a_App a1 (Role R) a2) (a_App b1 (Role R) b2)  (  (open_tm_wrt_tm  B   a2 )  )  R'
 | E_IAppCong : forall (G:context) (D:available_props) (a1 b1 B a:tm) (R':role) (A:tm),
     DefEq G D a1 b1  ( (a_Pi Irrel A B) )  R' ->
     Typing G a A ->
     DefEq G D (a_App a1 (Rho Irrel) a_Bullet) (a_App b1 (Rho Irrel) a_Bullet)  (  (open_tm_wrt_tm  B   a )  )  R'
 | E_PiFst : forall (G:context) (D:available_props) (A1 A2:tm) (R':role) (rho:relflag) (B1 B2:tm),
     DefEq G D (a_Pi rho A1 B1) (a_Pi rho A2 B2) a_Star R' ->
     DefEq G D A1 A2 a_Star R'
 | E_PiSnd : forall (G:context) (D:available_props) (B1 a1 B2 a2:tm) (R':role) (rho:relflag) (A1 A2:tm),
     DefEq G D (a_Pi rho A1 B1) (a_Pi rho A2 B2) a_Star R' ->
     DefEq G D a1 a2 A1 Nom ->
     DefEq G D  (open_tm_wrt_tm  B1   a1 )   (open_tm_wrt_tm  B2   a2 )  a_Star R'
 | E_CPiCong : forall (L:vars) (G:context) (D:available_props) (a1 b1 A1:tm) (R:role) (A a2 b2 A2 B:tm) (R':role),
     Iso G D (Eq a1 b1 A1 R) (Eq a2 b2 A2 R) ->
      ( forall c , c \notin  L  -> DefEq  (( c ~ Co  (Eq a1 b1 A1 R) ) ++  G )  D  ( open_tm_wrt_co A (g_Var_f c) )   ( open_tm_wrt_co B (g_Var_f c) )  a_Star R' )  ->
      ( PropWff G (Eq a1 b1 A1 R) )  ->
      ( Typing G (a_CPi (Eq a1 b1 A1 R) A) a_Star )  ->
      ( Typing G (a_CPi (Eq a2 b2 A2 R) B) a_Star )  ->
     DefEq G D (a_CPi (Eq a1 b1 A1 R) A) (a_CPi (Eq a2 b2 A2 R) B) a_Star R'
 | E_CAbsCong : forall (L:vars) (G:context) (D:available_props) (a b:tm) (phi1:constraint) (B:tm) (R:role),
      ( forall c , c \notin  L  -> DefEq  (( c ~ Co  phi1 ) ++  G )  D  ( open_tm_wrt_co a (g_Var_f c) )   ( open_tm_wrt_co b (g_Var_f c) )   ( open_tm_wrt_co B (g_Var_f c) )  R )  ->
      ( PropWff G phi1 )  ->
     DefEq G D  ( (a_UCAbs a) )   ( (a_UCAbs b) )  (a_CPi phi1 B) R
 | E_CAppCong : forall (G:context) (D:available_props) (a1 b1 B:tm) (R':role) (a b A:tm) (R:role),
     DefEq G D a1 b1  ( (a_CPi  ( (Eq a b A R) )  B) )  R' ->
     DefEq G  (dom  G )  a b A R ->
     DefEq G D (a_CApp a1 g_Triv) (a_CApp b1 g_Triv)  (  (open_tm_wrt_co  B   g_Triv )  )  R'
 | E_CPiSnd : forall (G:context) (D:available_props) (B1 B2:tm) (R0:role) (a1 a2 A:tm) (R:role) (a1' a2' A':tm) (R':role),
     DefEq G D (a_CPi  ( (Eq a1 a2 A R) )  B1) (a_CPi  ( (Eq a1' a2' A' R') )  B2) a_Star R0 ->
     DefEq G  (dom  G )  a1 a2 A R ->
     DefEq G  (dom  G )  a1' a2' A' R' ->
     DefEq G D  (open_tm_wrt_co  B1   g_Triv )   (open_tm_wrt_co  B2   g_Triv )  a_Star R0
 | E_Cast : forall (G:context) (D:available_props) (a' b' A':tm) (R':role) (a b A:tm) (R:role),
     DefEq G D a b A R ->
     Iso G D (Eq a b A R) (Eq a' b' A' R') ->
     DefEq G D a' b' A' R'
 | E_EqConv : forall (G:context) (D:available_props) (a b B:tm) (R:role) (A:tm),
     DefEq G D a b A R ->
     DefEq G  (dom  G )  A B a_Star Rep ->
      ( Typing G B a_Star )  ->
     DefEq G D a b B R
 | E_IsoSnd : forall (G:context) (D:available_props) (A A' a b:tm) (R1:role) (a' b':tm),
     Iso G D (Eq a b A R1) (Eq a' b' A' R1) ->
     DefEq G D A A' a_Star Rep
 | E_PatCong : forall (G:context) (D:available_props) (a:tm) (F:const) (Apps5:Apps) (b1 b2 a' b1' b2' C:tm) (R0:role) (A B A1 B':tm),
     DefEq G D a a' A Nom ->
     DefEq G D b1 b1' B R0 ->
     DefEq G D b2 b2' C R0 ->
     BranchTyping G Apps5 Nom a A (a_Fam F)  nil  A1 B C ->
     BranchTyping G Apps5 Nom a' A (a_Fam F)  nil  A1 B' C ->
     DefEq G D B B' a_Star Rep ->
     SatApp F Apps5 ->
     Typing G (a_Fam F) A1 ->
     DefEq G D (a_Pattern Nom a F Apps5 b1 b2) (a_Pattern Nom a' F Apps5 b1' b2') C R0
 | E_LeftRel : forall (G:context) (D:available_props) (a a' A B:tm) (R' R1:role) (b:tm) (F:const) (b':tm),
     CasePath R'  ( (a_App a (Role R1) b) )  F ->
     CasePath R'  ( (a_App a' (Role R1) b') )  F ->
     Typing G a (a_Pi Rel A B) ->
     Typing G b A ->
     Typing G a' (a_Pi Rel A B) ->
     Typing G b' A ->
     DefEq G D (a_App a (Role R1) b) (a_App a' (Role R1) b')  (open_tm_wrt_tm  B   b )  R' ->
     DefEq G  (dom  G )   (open_tm_wrt_tm  B   b )   (open_tm_wrt_tm  B   b' )  a_Star Rep ->
     DefEq G D a a' (a_Pi Rel A B) R'
 | E_LeftIrrel : forall (G:context) (D:available_props) (a a' A B:tm) (R':role) (F:const) (b b':tm),
     CasePath R'  ( (a_App a (Rho Irrel) a_Bullet) )  F ->
     CasePath R'  ( (a_App a' (Rho Irrel) a_Bullet) )  F ->
     Typing G a (a_Pi Irrel A B) ->
     Typing G b A ->
     Typing G a' (a_Pi Irrel A B) ->
     Typing G b' A ->
     DefEq G D (a_App a (Rho Irrel) a_Bullet) (a_App a' (Rho Irrel) a_Bullet)  (open_tm_wrt_tm  B   b )  R' ->
     DefEq G  (dom  G )   (open_tm_wrt_tm  B   b )   (open_tm_wrt_tm  B   b' )  a_Star Rep ->
     DefEq G D a a' (a_Pi Irrel A B) R'
 | E_Right : forall (G:context) (D:available_props) (b b' A:tm) (R1 R':role) (a:tm) (F:const) (a' B:tm),
     CasePath R'  ( (a_App a (Role R1) b) )  F ->
     CasePath R'  ( (a_App a' (Role R1) b') )  F ->
     Typing G a (a_Pi Rel A B) ->
     Typing G b A ->
     Typing G a' (a_Pi Rel A B) ->
     Typing G b' A ->
     DefEq G D (a_App a (Role R1) b) (a_App a' (Role R1) b')  (open_tm_wrt_tm  B   b )  R' ->
     DefEq G  (dom  G )   (open_tm_wrt_tm  B   b )   (open_tm_wrt_tm  B   b' )  a_Star Rep ->
     DefEq G D b b' A  (param R1   R' )
 | E_CLeft : forall (G:context) (D:available_props) (a a' a1 a2 A:tm) (R1:role) (B:tm) (R':role) (F:const),
     CasePath R'  ( (a_CApp a g_Triv) )  F ->
     CasePath R'  ( (a_CApp a' g_Triv) )  F ->
     Typing G a (a_CPi  ( (Eq a1 a2 A R1) )  B) ->
     Typing G a' (a_CPi  ( (Eq a1 a2 A R1) )  B) ->
     DefEq G  (dom  G )  a1 a2 A  (param R1   R' )  ->
     DefEq G D (a_CApp a g_Triv) (a_CApp a' g_Triv)  (open_tm_wrt_co  B   g_Triv )  R' ->
     DefEq G D a a' (a_CPi  ( (Eq a1 a2 A R1) )  B) R'
with Ctx : context -> Prop :=    (* defn Ctx *)
 | E_Empty :
     Ctx  nil
 | E_ConsTm : forall (G:context) (x:tmvar) (A:tm),
     Ctx G ->
     Typing G A a_Star ->
      ~ AtomSetImpl.In  x    (dom  G )   ->
     Ctx  (( x ~ Tm  A ) ++  G )
 | E_ConsCo : forall (G:context) (c:covar) (phi:constraint),
     Ctx G ->
     PropWff G phi ->
      ~ AtomSetImpl.In  c    (dom  G )   ->
     Ctx  (( c ~ Co  phi ) ++  G ) .

(* defns Jsig *)
Inductive Sig : sig -> Prop :=    (* defn Sig *)
 | Sig_Empty :
     Sig  nil
 | Sig_ConsConst : forall (S:sig) (F:const) (A:tm) (Rs:roles),
     Sig S ->
     Typing  nil  A a_Star ->
      ~ AtomSetImpl.In  F  (dom  S )  ->
     Sig  (( F ~ (Cs A Rs) )++ S )
 | Sig_ConsAx : forall (S:sig) (F:const) (p a A:tm) (R:role) (W:role_context) (G:context) (V:atom_list) (B:tm),
     Sig S ->
      ~ AtomSetImpl.In  F  (dom  S )  ->
     Typing  nil  A a_Star ->
     PatternContexts W G V F A p B ->
     Typing G a B ->
      (forall x, In x  V  -> x `notin`   (fv_tm_tm_tm  a )  )  ->
     roleing W a R ->
     Sig  (( F ~ (Ax p a A R  (range( W )) ) )++ S ) .

(* defns Jhiding *)
Inductive RoleWeaken : roles -> roles -> Prop :=    (* defn RoleWeaken *)
 | R_Nil :
     RoleWeaken  nil   nil
 | R_Cons : forall (R1:role) (Rs1:roles) (R2:role) (Rs2:roles),
     SubRole R2 R1 ->
     RoleWeaken Rs1 Rs2 ->
     RoleWeaken  ( R1 :: Rs1 )   ( R2 :: Rs2 )
with SigWeaken : sig -> sig -> Prop :=    (* defn SigWeaken *)
 | S_Forget : forall (S1 S2:sig) (F:const) (sig_sort5:sig_sort),
     lc_sig_sort sig_sort5 ->
     SigWeaken S1 S2 ->
     SigWeaken S1  (( F ~ sig_sort5 )++ S2 )
 | S_Hide : forall (S1:sig) (F:const) (A:tm) (Rs1:roles) (S2:sig) (p a:tm) (R:role) (Rs2:roles),
     lc_tm p ->
     lc_tm a ->
     lc_tm A ->
     SigWeaken S1 S2 ->
     RoleWeaken Rs1 Rs2 ->
     SigWeaken  (( F ~ (Cs A Rs1) )++ S1 )   (( F ~ (Ax p a A R Rs2) )++ S2 )
 | S_WeakenConst : forall (S1:sig) (F:const) (A:tm) (Rs1:roles) (S2:sig) (Rs2:roles),
     lc_tm A ->
     SigWeaken S1 S2 ->
     RoleWeaken Rs1 Rs2 ->
     SigWeaken  (( F ~ (Cs A Rs1) )++ S1 )   (( F ~ (Cs A Rs2) )++ S2 )
 | S_WeakenAxiom : forall (S1:sig) (F:const) (p' a A:tm) (R:role) (Rs1:roles) (S2:sig) (p:tm) (Rs2:roles),
     lc_tm p' ->
     lc_tm p ->
     lc_tm a ->
     lc_tm A ->
     SigWeaken S1 S2 ->
     RoleWeaken Rs1 Rs2 ->
     SigWeaken  (( F ~ (Ax p' a A R Rs1) )++ S1 )   (( F ~ (Ax p a A R Rs2) )++ S2 )
 | S_Empty :
     SigWeaken  nil   nil
 | S_Same : forall (S1:sig) (F:const) (sig_sort5:sig_sort) (S2:sig),
     lc_sig_sort sig_sort5 ->
     SigWeaken S1 S2 ->
     SigWeaken  (( F ~ sig_sort5 )++ S1 )   (( F ~ sig_sort5 )++ S2 ) .

(* defns JSrc *)
Inductive SrcTyping : context -> tm -> tm -> Prop :=    (* defn SrcTyping *)
 | S_Star : forall (G:context),
     Ctx G ->
     SrcTyping G a_Star a_Star
 | S_Var : forall (G:context) (x:tmvar) (A:tm),
     Ctx G ->
      binds  x  (Tm  A )  G  ->
     SrcTyping G (a_Var_f x) A
 | S_Pi : forall (L:vars) (G:context) (rho:relflag) (A B A':tm),
     SrcTyping G A a_Star ->
     SrcTrans G A A' a_Star ->
      ( forall x , x \notin  L  -> SrcTyping  (( x ~ Tm  A' ) ++  G )   ( open_tm_wrt_tm B (a_Var_f x) )  a_Star )  ->
     SrcTyping G  ( (a_Pi rho A B) )  a_Star
 | S_Abs : forall (L:vars) (G:context) (a A B:tm),
      ( forall x , x \notin  L  -> SrcTyping  (( x ~ Tm  A ) ++  G )  a  ( open_tm_wrt_tm B (a_Var_f x) )  )  ->
     SrcTyping G  (a_UAbs Rel  a )   ( (a_Pi Rel A B) )
 | S_IAbs : forall (L:vars) (G:context) (a A B:tm),
      ( forall x , x \notin  L  -> SrcTyping  (( x ~ Tm  A ) ++  G )  a  ( open_tm_wrt_tm B (a_Var_f x) )  )  ->
     SrcTyping G a  ( (a_Pi Irrel A B) )
 | S_Conv : forall (G:context) (a B A:tm),
     SrcTyping G a A ->
     DefEq G  (dom  G )  A B a_Star Nom ->
     SrcTyping G a B
 | S_Coerce : forall (G:context) (a B A:tm),
     SrcTyping G a A ->
     DefEq G  (dom  G )  A B a_Star Rep ->
     SrcTyping G (a_SrcApp a_Coerce a) B
 | S_App : forall (G:context) (b a B a' A:tm),
     SrcTyping G b (a_Pi Rel A B) ->
     SrcTrans G a a' A ->
     SrcTyping G (a_SrcApp b a)  (open_tm_wrt_tm  B   a' )
 | S_IApp : forall (G:context) (b B a' A:tm),
     SrcTyping G b (a_Pi Irrel A B) ->
     Typing G a' A ->
     SrcTyping G b  (open_tm_wrt_tm  B   a' )
 | S_CPi : forall (L:vars) (G:context) (phi:constraint) (B:tm) (phi':constraint),
     SrcPropWff G phi phi' ->
      ( forall c , c \notin  L  -> SrcTyping  (( c ~ Co  phi' ) ++  G )   ( open_tm_wrt_co B (g_Var_f c) )  a_Star )  ->
     SrcTyping G (a_CPi phi B) a_Star
 | S_CAbs : forall (L:vars) (G:context) (a:tm) (phi:constraint) (B:tm) (phi':constraint),
     lc_constraint phi ->
      ( forall c , c \notin  L  -> SrcTyping  (( c ~ Co  phi' ) ++  G )  a  ( open_tm_wrt_co B (g_Var_f c) )  )  ->
     SrcTyping G a (a_CPi phi B)
 | S_CApp : forall (G:context) (a1 B1 a b A:tm) (R:role),
     SrcTyping G a1 (a_CPi  ( (Eq a b A R) )  B1) ->
     DefEq G  (dom  G )  a b A R ->
     SrcTyping G a1  (open_tm_wrt_co  B1   g_Triv )
 | S_Const : forall (G:context) (F:const) (A:tm) (Rs:roles),
     Ctx G ->
      binds  F  ( (Cs A Rs) )   toplevel   ->
     SrcTyping G (a_Fam F) A
 | S_Fam : forall (G:context) (F:const) (A:tm),
     lc_tm A ->
     Ctx G ->
     SrcTyping G (a_Fam F) A
 | S_Case : forall (G:context) (a:tm) (F:const) (Apps5:Apps) (b1 b2 C A b1' B b2':tm),
     lc_tm b1 ->
     lc_tm b2 ->
     SrcTyping G a A ->
     SrcTyping G b1' B ->
     SrcTyping G b2' C ->
     SrcTyping G (a_Pattern Nom a F Apps5 b1 b2) C
with SrcTrans : context -> tm -> tm -> tm -> Prop :=    (* defn SrcTrans *)
 | ST_Star : forall (G:context),
     Ctx G ->
     SrcTrans G a_Star a_Star a_Star
 | ST_Var : forall (G:context) (x:tmvar) (A:tm),
     Ctx G ->
      binds  x  (Tm  A )  G  ->
     SrcTrans G (a_Var_f x) (a_Var_f x) A
 | ST_Pi : forall (L:vars) (G:context) (rho:relflag) (A B A' B':tm),
     SrcTrans G A A' a_Star ->
      ( forall x , x \notin  L  -> SrcTrans  (( x ~ Tm  A' ) ++  G )   ( open_tm_wrt_tm B (a_Var_f x) )   ( open_tm_wrt_tm B' (a_Var_f x) )  a_Star )  ->
     SrcTrans G  ( (a_Pi rho A B) )   ( (a_Pi rho A' B') )  a_Star
 | ST_Abs : forall (L:vars) (G:context) (a a' A B:tm),
      ( forall x , x \notin  L  -> SrcTrans  (( x ~ Tm  A ) ++  G )  a  ( open_tm_wrt_tm a' (a_Var_f x) )   ( open_tm_wrt_tm B (a_Var_f x) )  )  ->
     SrcTrans G  (a_UAbs Rel  a )  (a_UAbs Rel a')  ( (a_Pi Rel A B) )
 | ST_IAbs : forall (L:vars) (G:context) (a A B a':tm),
      ( forall x , x \notin  L  -> SrcTrans  (( x ~ Tm  A ) ++  G )   ( open_tm_wrt_tm a (a_Var_f x) )  a'  ( open_tm_wrt_tm B (a_Var_f x) )  )  ->
      ( forall x , x \notin  L  ->  ~ AtomSetImpl.In  x    (fv_tm_tm_tm   ( open_tm_wrt_tm a (a_Var_f x) )  )   )  ->
      ( forall x , x \notin  L  -> SrcTrans G  ( open_tm_wrt_tm a (a_Var_f x) )  (a_UAbs Irrel a)  ( (a_Pi Irrel A B) )  )
 | ST_App : forall (G:context) (b a b' a' B A:tm),
     SrcTrans G b b' (a_Pi Rel A B) ->
     SrcTrans G a a' A ->
     SrcTrans G (a_SrcApp b a) (a_App b' (Rho Rel) a')  (open_tm_wrt_tm  B   a' )
 | ST_TApp : forall (G:context) (b a b':tm) (R:role) (a' B A:tm) (Rs:roles),
     SrcTrans G b b' (a_Pi Rel A B) ->
     SrcTrans G a a' A ->
     RolePath b  ( R :: Rs )  ->
     SrcTrans G (a_SrcApp b a) (a_App b' (Role R) a')  (open_tm_wrt_tm  B   a )
 | ST_IApp : forall (G:context) (b b' B a A:tm),
     SrcTrans G b b' (a_Pi Irrel A B) ->
     Typing G a A ->
     SrcTrans G b (a_App b' (Rho Irrel) a_Bullet)  (open_tm_wrt_tm  B   a )
 | ST_Conv : forall (G:context) (a a' B A:tm),
     SrcTrans G a a' A ->
     DefEq G  (dom  G )  A B a_Star Nom ->
     SrcTrans G a a' B
 | ST_Coerce : forall (G:context) (a a' B A:tm),
     SrcTrans G a a' A ->
     DefEq G  (dom  G )  A B a_Star Rep ->
     SrcTrans G (a_SrcApp a_Coerce a) a' B
 | ST_CPi : forall (L:vars) (G:context) (phi:constraint) (B B':tm) (phi':constraint),
     SrcPropWff G phi phi' ->
      ( forall c , c \notin  L  -> SrcTrans  (( c ~ Co  phi' ) ++  G )   ( open_tm_wrt_co B (g_Var_f c) )   ( open_tm_wrt_co B' (g_Var_f c) )  a_Star )  ->
     SrcTrans G (a_CPi phi B) (a_CPi phi B') a_Star
 | ST_CAbs : forall (L:vars) (G:context) (a a':tm) (phi:constraint) (B:tm),
      ( forall c , c \notin  L  -> SrcTrans  (( c ~ Co  phi ) ++  G )  a  ( open_tm_wrt_co a' (g_Var_f c) )   ( open_tm_wrt_co B (g_Var_f c) )  )  ->
     SrcTrans G a (a_UCAbs a') (a_CPi phi B)
 | ST_CApp : forall (G:context) (a1 a1' B1 a b A:tm) (R:role),
     SrcTrans G a1 a1' (a_CPi  ( (Eq a b A R) )  B1) ->
     DefEq G  (dom  G )  a b A R ->
     SrcTrans G a1 (a_CApp a1' g_Triv)  (open_tm_wrt_co  B1   g_Triv )
 | ST_Const : forall (G:context) (F:const) (A:tm) (Rs:roles),
     Ctx G ->
      binds  F  ( (Cs A Rs) )   toplevel   ->
     SrcTrans G (a_Fam F) (a_Fam F) A
 | ST_Fam : forall (G:context) (F:const) (A:tm),
     lc_tm A ->
     Ctx G ->
     SrcTrans G (a_Fam F) (a_Fam F) A
 | ST_Case : forall (G:context) (a:tm) (F:const) (Apps5:Apps) (b1 b2 a' b1' b2' C A B:tm),
     SrcTrans G a a' A ->
     SrcTrans G b1 b1' B ->
     SrcTrans G b2 b2' C ->
     SrcTrans G (a_Pattern Nom a F Apps5 b1 b2) (a_Pattern Nom a' F Apps5 b1' b2') C
with SrcPropWff : context -> constraint -> constraint -> Prop :=    (* defn SrcPropWff *)
 | S_Wff : forall (G:context) (a b A a' b':tm),
     SrcTrans G a a' A ->
     SrcTrans G b b' A ->
     SrcPropWff G  ( (Eq a b A Nom) )   ( (Eq a' b' A Nom) ) .

(* defns Jann *)
Inductive AnnPropWff : context -> constraint -> Prop :=    (* defn AnnPropWff *)
with AnnTyping : context -> tm -> tm -> role -> Prop :=    (* defn AnnTyping *)
with AnnIso : context -> available_props -> co -> constraint -> constraint -> Prop :=    (* defn AnnIso *)
with AnnDefEq : context -> available_props -> co -> tm -> tm -> role -> Prop :=    (* defn AnnDefEq *)
with AnnCtx : context -> Prop :=    (* defn AnnCtx *).

(* defns Jred *)
Inductive head_reduction : context -> tm -> tm -> role -> Prop :=    (* defn head_reduction *).

(** infrastructure *)
Hint Constructors SubRole RolePath AppsPath AppRoles SatApp PatternContexts Rename MatchSubst Pattern SubPat tm_pattern_agree tm_subpattern_agree subtm_pattern_agree ValuePath CasePath ApplyArgs Value value_type consistent roleing RhoCheck Par MultiPar joins Beta reduction_in_one reduction BranchTyping PropWff Typing Iso DefEq Ctx Sig RoleWeaken SigWeaken SrcTyping SrcTrans SrcPropWff AnnPropWff AnnTyping AnnIso AnnDefEq AnnCtx head_reduction lc_co lc_brs lc_tm lc_constraint lc_sort lc_sig_sort lc_pattern_arg.


Require Import Coq.Lists.List.
Require Import Coq.Setoids.Setoid.
Require Import Coq.Lists.SetoidList.
Require Import Crypto.Util.Option.

Import ListNotations.

Lemma list_elementwise_eqlistA : forall {T R} (l1 l2 : list T),
  (forall i, option_eq R (nth_error l1 i) (nth_error l2 i)) -> eqlistA R l1 l2.
Proof.
  induction l1, l2; intros H; try solve [ constructor ];
    pose proof (H 0%nat) as Hfirst; cbn in Hfirst; try solve [ inversion Hfirst ].
  constructor; [ assumption | ].
  apply IHl1.
  intros i; specialize (H (S i)).
  assumption.
Qed.

Lemma nth_error_Proper_eqlistA {T R}
  : Proper (eqlistA R ==> eq ==> option_eq R) (@nth_error T).
Proof.
  intros ls1 ls2 Hls n n' ?; subst n'.
  revert ls1 ls2 Hls.
  induction n; intros ls1 ls2 Hls; destruct Hls; cbn; auto.
Qed.

Lemma eqlistA_eq_iff {A}
  : forall ls1 ls2, eqlistA (@eq A) ls1 ls2 <-> ls1 = ls2.
Proof.
  induction ls1 as [|x xs IHxs], ls2 as [|y ys].
  all: split; intro H; inversion_clear H; repeat constructor; subst; f_equal; try reflexivity.
  apply IHxs; assumption.
Qed.

Lemma InA_map A B (f : A -> B) (eqA eqB : relation _) a b l
      (f_Proper_a_b : forall v, eqA a v -> eqB b (f v))
  : InA eqA a l -> InA eqB b (List.map f l).
Proof.
  rewrite !InA_alt.
  intros [v H]; exists (f v); split; [ now apply f_Proper_a_b | now apply in_map ].
Qed.

Lemma InA_map_iff A B (f : A -> B) (eqA eqB : relation _) a b l
      (f_Proper_a_b : forall v, eqA a v <-> eqB b (f v))
  : InA eqB b (List.map f l) <-> InA eqA a l.
Proof.
  split; [ | solve [ apply InA_map, f_Proper_a_b ] ].
  rewrite !InA_alt; intros [v [H1 H2]].
  induction l as [|? ? IH]; cbn [List.map List.In] in *;
    [ easy | ].
  destruct H2; subst; firstorder eauto.
Qed.

Lemma NoDupA_map_inv A B (f : A -> B) (eqA eqB : relation _) (l : list A)
      {f_Proper : Proper (eqA ==> eqB) f}
  : NoDupA eqB (List.map f l) -> NoDupA eqA l.
Proof.
  induction l as [|? ? IH]; cbn [List.map]; intro H; inversion_clear H;
    [ constructor | ].
  specialize (IH ltac:(assumption)).
  constructor; [ | assumption ].
  let H := match goal with H : ~ InA _ _ _ |- _ => H end in
  intro H'; apply H; clear H.
  eapply InA_map; [ | eassumption ].
  intro; apply f_Proper.
Qed.

Global Instance InA_Proper_impl {A} {eqA : relation A}
       {eqA_Proper : Proper (eqA ==> eqA ==> Basics.impl) eqA}
  : Proper (eqA ==> eqlistA eqA ==> Basics.impl) (@InA A eqA) | 10.
Proof.
  cbv [Basics.impl] in *.
  intros a a' Ha l l' Hl.
  induction Hl as [|?????? IH].
  { intro H'; inversion H'. }
  { intro H'; inversion_clear H';
      try solve [ constructor; eapply eqA_Proper; eassumption
                | constructor; eauto ]. }
Qed.

Global Instance InA_Proper_flip_impl {A} {eqA : relation A}
       {eqA_Proper : Proper (eqA ==> eqA ==> Basics.flip Basics.impl) eqA}
  : Proper (eqA ==> eqlistA eqA ==> Basics.flip Basics.impl) (@InA A eqA) | 10.
Proof.
  cbv [Basics.impl] in *.
  intros a a' Ha l l' Hl.
  induction Hl as [|?????? IH].
  { intro H'; inversion H'. }
  { intro H'; inversion_clear H';
      try solve [ constructor; eapply eqA_Proper; eassumption
                | constructor; eauto ]. }
Qed.

(** We could just use [now typeclasses eauto with core] in Coq >= 8.10, but it doesn't work in 8.9 :-( *)
Local Ltac grepeat_eapply :=
  multimatch goal with
  | [ H : _ |- _ ] => eapply H; clear H
  end;
  solve [ grepeat_eapply ].

Global Instance InA_Proper_iff {A} {eqA : relation A}
       {eqA_Proper : Proper (eqA ==> eqA ==> iff) eqA}
  : Proper (eqA ==> eqlistA eqA ==> iff) (@InA A eqA) | 10.
Proof.
  unshelve (split; (eapply InA_Proper_impl + eapply InA_Proper_flip_impl); assumption).
  all: repeat intro; solve [ edestruct eqA_Proper; grepeat_eapply ].
Qed.

Global Instance NoDupA_Proper_eqlistA_impl {A eqA}
       {eqA_Proper : Proper (eqA ==> eqA ==> flip impl) eqA}
  : Proper (eqlistA eqA ==> impl) (@NoDupA A eqA) | 10.
Proof.
  cbv [flip impl].
  intros l1 l2 Hl.
  induction Hl as [|? ? ? ? ? ? IH].
  { constructor. }
  { intro H'; inversion_clear H'; constructor; eauto.
    all: match goal with
         | [ H : ~InA _ _ _ |- ~ InA _ _ _ ] => intro H'; apply H; clear H
         end.
    eapply InA_Proper_flip_impl; eassumption. }
Qed.

Global Instance NoDupA_Proper_eqlistA_flip_impl {A eqA}
       {eqA_Proper : Proper (eqA ==> eqA ==> impl) eqA}
  : Proper (eqlistA eqA ==> flip impl) (@NoDupA A eqA) | 10.
Proof.
  cbv [flip impl].
  intros l1 l2 Hl.
  induction Hl as [|? ? ? ? ? ? IH].
  { constructor. }
  { intro H'; inversion_clear H'; constructor; eauto.
    all: match goal with
         | [ H : ~InA _ _ _ |- ~ InA _ _ _ ] => intro H'; apply H; clear H
         end.
    eapply InA_Proper_impl; eassumption. }
Qed.

Global Instance NoDupA_Proper_eqlistA_iff {A eqA}
       {eqA_Proper : Proper (eqA ==> eqA ==> iff) eqA}
  : Proper (eqlistA eqA ==> iff) (@NoDupA A eqA) | 10.
Proof.
  unshelve (split; (eapply NoDupA_Proper_eqlistA_impl + eapply NoDupA_Proper_eqlistA_flip_impl); assumption).
  all: repeat intro; solve [ edestruct eqA_Proper; grepeat_eapply ].
Qed.


Require Import Undecidability.TM.SBTM Undecidability.TM.Enumerators.SBTM_HALT_enum.
Require Import Undecidability.Synthetic.Definitions.

(** ** SBTM_HALT is enumerable *)

Lemma SBTM_HALT_enum :
  enumerable (SBTM_HALT).
Proof.
  exists SBTM_HALT_enumerator.
  exact SBTM_HALT_enumerator_spec.
Qed.


(*
  Copyright 2022 ZhengPu Shi
  This file is part of CoqExt. It is distributed under the MIT
  "expat license". You should have recieved a LICENSE file with it.

  purpose   : Extension for tuples
  author    : ZhengPu Shi
  date      : 2022.06

  remark    :
  1. T2 : A * A
     T3 : A * A * A
     ...
  2. T_3x3 := T3 * T3 * T3.
*)

Open Scope type_scope.

(** * Short name for tuples type *)
Section TuplesType.

  Context {A : Type}.

  (* Definition T1 := A. *)
  Definition T2 := A * A.
  Definition T3 := T2 * A.
  Definition T4 := T3 * A.

  (* Definition T_1x1 := T1. *)
  Definition T_2x2 := T2 * T2.
  Definition T_3x3 := T3 * T3 * T3.

End TuplesType.