(** NOTE: Auxiliary theorems are hidden in generated documentation.
    In general, there is a [_rec] version of every lemma involving
    [open] and [close]. *)


(* *********************************************************************** *)
(** * Induction principles for nonterminals *)

Scheme typ_ind' := Induction for typ Sort Prop.Definition typ_mutind :=
  fun H1 H2 H3 =>
  typ_ind' H1 H2 H3.Scheme typ_rec' := Induction for typ Sort Set.Definition typ_mutrec :=
  fun H1 H2 H3 =>
  typ_rec' H1 H2 H3.Scheme exp_ind' := Induction for exp Sort Prop.Definition exp_mutind :=
  fun H1 H2 H3 H4 H5 =>
  exp_ind' H1 H2 H3 H4 H5.Scheme exp_rec' := Induction for exp Sort Set.Definition exp_mutrec :=
  fun H1 H2 H3 H4 H5 =>
  exp_rec' H1 H2 H3 H4 H5.Definition close_exp_wrt_exp x1 e1 := close_exp_wrt_exp_rec 0 x1 e1.(* *********************************************************************** *)
(** * Size *)

Fixpoint size_typ (T1 : typ) {struct T1} : nat :=
  match T1 with
    | typ_base => 1
    | typ_arrow T2 T3 => 1 + (size_typ T2) + (size_typ T3)
  end.Fixpoint size_exp (e1 : exp) {struct e1} : nat :=
  match e1 with
    | var_f x1 => 1
    | var_b n1 => 1
    | abs e2 => 1 + (size_exp e2)
    | app e2 e3 => 1 + (size_exp e2) + (size_exp e3)
  end.(* *********************************************************************** *)
(** * Degree *)

(** These define only an upper bound, not a strict upper bound. *)

Inductive degree_exp_wrt_exp : nat -> exp -> Prop :=
  | degree_wrt_exp_var_f : forall n1 x1,
    degree_exp_wrt_exp n1 (var_f x1)
  | degree_wrt_exp_var_b : forall n1 n2,
    lt n2 n1 ->
    degree_exp_wrt_exp n1 (var_b n2)
  | degree_wrt_exp_abs : forall n1 e1,
    degree_exp_wrt_exp (S n1) e1 ->
    degree_exp_wrt_exp n1 (abs e1)
  | degree_wrt_exp_app : forall n1 e1 e2,
    degree_exp_wrt_exp n1 e1 ->
    degree_exp_wrt_exp n1 e2 ->
    degree_exp_wrt_exp n1 (app e1 e2).(* *********************************************************************** *)
(** * Degree *)

(** These define only an upper bound, not a strict upper bound. *)

Inductive degree_exp_wrt_exp : nat -> exp -> Prop :=
  | degree_wrt_exp_var_f : forall n1 x1,
    degree_exp_wrt_exp n1 (var_f x1)
  | degree_wrt_exp_var_b : forall n1 n2,
    lt n2 n1 ->
    degree_exp_wrt_exp n1 (var_b n2)
  | degree_wrt_exp_abs : forall n1 e1,
    degree_exp_wrt_exp (S n1) e1 ->
    degree_exp_wrt_exp n1 (abs e1)
  | degree_wrt_exp_app : forall n1 e1 e2,
    degree_exp_wrt_exp n1 e1 ->
    degree_exp_wrt_exp n1 e2 ->
    degree_exp_wrt_exp n1 (app e1 e2).(* *********************************************************************** *)
(** * Degree *)

(** These define only an upper bound, not a strict upper bound. *)

Inductive degree_exp_wrt_exp : nat -> exp -> Prop :=
  | degree_wrt_exp_var_f : forall n1 x1,
    degree_exp_wrt_exp n1 (var_f x1)
  | degree_wrt_exp_var_b : forall n1 n2,
    lt n2 n1 ->
    degree_exp_wrt_exp n1 (var_b n2)
  | degree_wrt_exp_abs : forall n1 e1,
    degree_exp_wrt_exp (S n1) e1 ->
    degree_exp_wrt_exp n1 (abs e1)
  | degree_wrt_exp_app : forall n1 e1 e2,
    degree_exp_wrt_exp n1 e1 ->
    degree_exp_wrt_exp n1 e2 ->
    degree_exp_wrt_exp n1 (app e1 e2).(* *********************************************************************** *)
(** * Degree *)

(** These define only an upper bound, not a strict upper bound. *)

Inductive degree_exp_wrt_exp : nat -> exp -> Prop :=
  | degree_wrt_exp_var_f : forall n1 x1,
    degree_exp_wrt_exp n1 (var_f x1)
  | degree_wrt_exp_var_b : forall n1 n2,
    lt n2 n1 ->
    degree_exp_wrt_exp n1 (var_b n2)
  | degree_wrt_exp_abs : forall n1 e1,
    degree_exp_wrt_exp (S n1) e1 ->
    degree_exp_wrt_exp n1 (abs e1)
  | degree_wrt_exp_app : forall n1 e1 e2,
    degree_exp_wrt_exp n1 e1 ->
    degree_exp_wrt_exp n1 e2 ->
    degree_exp_wrt_exp n1 (app e1 e2).(* *********************************************************************** *)
(** * Degree *)

(** These define only an upper bound, not a strict upper bound. *)

Inductive degree_exp_wrt_exp : nat -> exp -> Prop :=
  | degree_wrt_exp_var_f : forall n1 x1,
    degree_exp_wrt_exp n1 (var_f x1)
  | degree_wrt_exp_var_b : forall n1 n2,
    lt n2 n1 ->
    degree_exp_wrt_exp n1 (var_b n2)
  | degree_wrt_exp_abs : forall n1 e1,
    degree_exp_wrt_exp (S n1) e1 ->
    degree_exp_wrt_exp n1 (abs e1)
  | degree_wrt_exp_app : forall n1 e1 e2,
    degree_exp_wrt_exp n1 e1 ->
    degree_exp_wrt_exp n1 e2 ->
    degree_exp_wrt_exp n1 (app e1 e2).Scheme degree_exp_wrt_exp_ind' := Induction for degree_exp_wrt_exp Sort Prop.Definition degree_exp_wrt_exp_mutind :=
  fun H1 H2 H3 H4 H5 =>
  degree_exp_wrt_exp_ind' H1 H2 H3 H4 H5.(* *********************************************************************** *)
(** * Local closure (version in [Set], induction principles) *)

Inductive lc_set_exp : exp -> Set :=
  | lc_set_var_f : forall x1,
    lc_set_exp (var_f x1)
  | lc_set_abs : forall e1,
    (forall x1 : var, lc_set_exp (open_exp_wrt_exp e1 (var_f x1))) ->
    lc_set_exp (abs e1)
  | lc_set_app : forall e1 e2,
    lc_set_exp e1 ->
    lc_set_exp e2 ->
    lc_set_exp (app e1 e2).(* *********************************************************************** *)
(** * Local closure (version in [Set], induction principles) *)

Inductive lc_set_exp : exp -> Set :=
  | lc_set_var_f : forall x1,
    lc_set_exp (var_f x1)
  | lc_set_abs : forall e1,
    (forall x1 : var, lc_set_exp (open_exp_wrt_exp e1 (var_f x1))) ->
    lc_set_exp (abs e1)
  | lc_set_app : forall e1 e2,
    lc_set_exp e1 ->
    lc_set_exp e2 ->
    lc_set_exp (app e1 e2).(* *********************************************************************** *)
(** * Local closure (version in [Set], induction principles) *)

Inductive lc_set_exp : exp -> Set :=
  | lc_set_var_f : forall x1,
    lc_set_exp (var_f x1)
  | lc_set_abs : forall e1,
    (forall x1 : var, lc_set_exp (open_exp_wrt_exp e1 (var_f x1))) ->
    lc_set_exp (abs e1)
  | lc_set_app : forall e1 e2,
    lc_set_exp e1 ->
    lc_set_exp e2 ->
    lc_set_exp (app e1 e2).(* *********************************************************************** *)
(** * Local closure (version in [Set], induction principles) *)

Inductive lc_set_exp : exp -> Set :=
  | lc_set_var_f : forall x1,
    lc_set_exp (var_f x1)
  | lc_set_abs : forall e1,
    (forall x1 : var, lc_set_exp (open_exp_wrt_exp e1 (var_f x1))) ->
    lc_set_exp (abs e1)
  | lc_set_app : forall e1 e2,
    lc_set_exp e1 ->
    lc_set_exp e2 ->
    lc_set_exp (app e1 e2).Scheme lc_exp_ind' := Induction for lc_exp Sort Prop.Definition lc_exp_mutind :=
  fun H1 H2 H3 H4 =>
  lc_exp_ind' H1 H2 H3 H4.Scheme lc_set_exp_ind' := Induction for lc_set_exp Sort Prop.Definition lc_set_exp_mutind :=
  fun H1 H2 H3 H4 =>
  lc_set_exp_ind' H1 H2 H3 H4.Scheme lc_set_exp_rec' := Induction for lc_set_exp Sort Set.Definition lc_set_exp_mutrec :=
  fun H1 H2 H3 H4 =>
  lc_set_exp_rec' H1 H2 H3 H4.(* *********************************************************************** *)
(** * Body *)

Definition body_exp_wrt_exp e1 := forall x1, lc_exp (open_exp_wrt_exp e1 (var_f x1)).

(* Specifications: *)
Lemma size_typ_min_mutual : (forall T1, 1 <= size_typ T1).
Lemma size_typ_min : forall T1, 1 <= size_typ T1.
Lemma size_exp_min_mutual : (forall e1, 1 <= size_exp e1).
Lemma size_exp_min : forall e1, 1 <= size_exp e1.
Lemma size_exp_close_exp_wrt_exp_rec_mutual : (forall e1 x1 n1, size_exp (close_exp_wrt_exp_rec n1 x1 e1) = size_exp e1).
Lemma size_exp_close_exp_wrt_exp_rec : forall e1 x1 n1, size_exp (close_exp_wrt_exp_rec n1 x1 e1) = size_exp e1.
Lemma size_exp_close_exp_wrt_exp : forall e1 x1, size_exp (close_exp_wrt_exp x1 e1) = size_exp e1.
Lemma size_exp_open_exp_wrt_exp_rec_mutual : (forall e1 e2 n1, size_exp e1 <= size_exp (open_exp_wrt_exp_rec n1 e2 e1)).
Lemma size_exp_open_exp_wrt_exp_rec : forall e1 e2 n1, size_exp e1 <= size_exp (open_exp_wrt_exp_rec n1 e2 e1).
Lemma size_exp_open_exp_wrt_exp : forall e1 e2, size_exp e1 <= size_exp (open_exp_wrt_exp e1 e2).
Lemma size_exp_open_exp_wrt_exp_rec_var_mutual : (forall e1 x1 n1, size_exp (open_exp_wrt_exp_rec n1 (var_f x1) e1) = size_exp e1).
Lemma size_exp_open_exp_wrt_exp_rec_var : forall e1 x1 n1, size_exp (open_exp_wrt_exp_rec n1 (var_f x1) e1) = size_exp e1.
Lemma size_exp_open_exp_wrt_exp_var : forall e1 x1, size_exp (open_exp_wrt_exp e1 (var_f x1)) = size_exp e1.
Lemma degree_exp_wrt_exp_S_mutual : (forall n1 e1, degree_exp_wrt_exp n1 e1 -> degree_exp_wrt_exp (S n1) e1).
Lemma degree_exp_wrt_exp_S : forall n1 e1, degree_exp_wrt_exp n1 e1 -> degree_exp_wrt_exp (S n1) e1.
Lemma degree_exp_wrt_exp_O : forall n1 e1, degree_exp_wrt_exp O e1 -> degree_exp_wrt_exp n1 e1.
Lemma degree_exp_wrt_exp_close_exp_wrt_exp_rec_mutual : (forall e1 x1 n1, degree_exp_wrt_exp n1 e1 -> degree_exp_wrt_exp (S n1) (close_exp_wrt_exp_rec n1 x1 e1)).
Lemma degree_exp_wrt_exp_close_exp_wrt_exp_rec : forall e1 x1 n1, degree_exp_wrt_exp n1 e1 -> degree_exp_wrt_exp (S n1) (close_exp_wrt_exp_rec n1 x1 e1).
Lemma degree_exp_wrt_exp_close_exp_wrt_exp : forall e1 x1, degree_exp_wrt_exp 0 e1 -> degree_exp_wrt_exp 1 (close_exp_wrt_exp x1 e1).
Lemma degree_exp_wrt_exp_close_exp_wrt_exp_rec_inv_mutual : (forall e1 x1 n1, degree_exp_wrt_exp (S n1) (close_exp_wrt_exp_rec n1 x1 e1) -> degree_exp_wrt_exp n1 e1).
Lemma degree_exp_wrt_exp_close_exp_wrt_exp_rec_inv : forall e1 x1 n1, degree_exp_wrt_exp (S n1) (close_exp_wrt_exp_rec n1 x1 e1) -> degree_exp_wrt_exp n1 e1.
Lemma degree_exp_wrt_exp_close_exp_wrt_exp_inv : forall e1 x1, degree_exp_wrt_exp 1 (close_exp_wrt_exp x1 e1) -> degree_exp_wrt_exp 0 e1.
Lemma degree_exp_wrt_exp_open_exp_wrt_exp_rec_mutual : (forall e1 e2 n1, degree_exp_wrt_exp (S n1) e1 -> degree_exp_wrt_exp n1 e2 -> degree_exp_wrt_exp n1 (open_exp_wrt_exp_rec n1 e2 e1)).
Lemma degree_exp_wrt_exp_open_exp_wrt_exp_rec : forall e1 e2 n1, degree_exp_wrt_exp (S n1) e1 -> degree_exp_wrt_exp n1 e2 -> degree_exp_wrt_exp n1 (open_exp_wrt_exp_rec n1 e2 e1).
Lemma degree_exp_wrt_exp_open_exp_wrt_exp : forall e1 e2, degree_exp_wrt_exp 1 e1 -> degree_exp_wrt_exp 0 e2 -> degree_exp_wrt_exp 0 (open_exp_wrt_exp e1 e2).
Lemma degree_exp_wrt_exp_open_exp_wrt_exp_rec_inv_mutual : (forall e1 e2 n1, degree_exp_wrt_exp n1 (open_exp_wrt_exp_rec n1 e2 e1) -> degree_exp_wrt_exp (S n1) e1).
Lemma degree_exp_wrt_exp_open_exp_wrt_exp_rec_inv : forall e1 e2 n1, degree_exp_wrt_exp n1 (open_exp_wrt_exp_rec n1 e2 e1) -> degree_exp_wrt_exp (S n1) e1.
Lemma degree_exp_wrt_exp_open_exp_wrt_exp_inv : forall e1 e2, degree_exp_wrt_exp 0 (open_exp_wrt_exp e1 e2) -> degree_exp_wrt_exp 1 e1.
Lemma close_exp_wrt_exp_rec_inj_mutual : (forall e1 e2 x1 n1, close_exp_wrt_exp_rec n1 x1 e1 = close_exp_wrt_exp_rec n1 x1 e2 -> e1 = e2).
Lemma close_exp_wrt_exp_rec_inj : forall e1 e2 x1 n1, close_exp_wrt_exp_rec n1 x1 e1 = close_exp_wrt_exp_rec n1 x1 e2 -> e1 = e2.
Lemma close_exp_wrt_exp_inj : forall e1 e2 x1, close_exp_wrt_exp x1 e1 = close_exp_wrt_exp x1 e2 -> e1 = e2.
Lemma open_exp_wrt_exp_rec_close_exp_wrt_exp_rec_mutual : (forall e1 x1 n1, open_exp_wrt_exp_rec n1 (var_f x1) (close_exp_wrt_exp_rec n1 x1 e1) = e1).
Lemma open_exp_wrt_exp_rec_close_exp_wrt_exp_rec : forall e1 x1 n1, open_exp_wrt_exp_rec n1 (var_f x1) (close_exp_wrt_exp_rec n1 x1 e1) = e1.
Lemma open_exp_wrt_exp_close_exp_wrt_exp : forall e1 x1, open_exp_wrt_exp (close_exp_wrt_exp x1 e1) (var_f x1) = e1.
Lemma degree_exp_wrt_exp_of_lc_exp_mutual : (forall e1, lc_exp e1 -> degree_exp_wrt_exp 0 e1).
Lemma degree_exp_wrt_exp_of_lc_exp : forall e1, lc_exp e1 -> degree_exp_wrt_exp 0 e1.
Lemma lc_exp_of_degree_size_mutual : forall i1, (forall e1, size_exp e1 = i1 -> degree_exp_wrt_exp 0 e1 -> lc_exp e1).
Lemma lc_exp_of_degree : forall e1, degree_exp_wrt_exp 0 e1 -> lc_exp e1.