(****************************)
(*  Substitution of redexes *)
(****************************)

(* Similar to lift_rec of Terms *)



Fixpoint lift_rec_r (L : redexes) : nat -> nat -> redexes :=
  fun k n : nat =>
  match L with
  | Var i => Var (relocate i k n)
  | Fun M => Fun (lift_rec_r M (S k) n)
  | Ap b M N => Ap b (lift_rec_r M k n) (lift_rec_r N k n)
  end.Definition lift_r (n : nat) (N : redexes) := lift_rec_r N 0 n.Definition insert_Var (N : redexes) (i k : nat) :=
  match compare k i with
  
      (* k<i *) | inleft (left _) => Var (pred i)
   (* k=i *) | inleft _ => lift_r k N
   (* k>i *) | _ => Var i
  end.(* Similar to subst_rec of Terms *)

Fixpoint subst_rec_r (L : redexes) : redexes -> nat -> redexes :=
  fun (N : redexes) (k : nat) =>
  match L with
  | Var i => insert_Var N i k
  | Fun M => Fun (subst_rec_r M N (S k))
  | Ap b M M' => Ap b (subst_rec_r M N k) (subst_rec_r M' N k)
  end.Definition subst_r (N M : redexes) := subst_rec_r M N 0.

(* Specifications: *)
Lemma lift_le : forall n i k : nat, k <= i -> lift_rec_r (Var i) k n = Var (n + i).
Lemma lift_gt : forall n i k : nat, k > i -> lift_rec_r (Var i) k n = Var i.
Lemma lift1 : forall (U : redexes) (j i k : nat), lift_rec_r (lift_rec_r U i j) (j + i) k = lift_rec_r U i (j + k).
Lemma lift_lift_rec : forall (U : redexes) (k p n i : nat), i <= n -> lift_rec_r (lift_rec_r U i p) (p + n) k = lift_rec_r (lift_rec_r U n k) i p.
Lemma lift_lift : forall (U : redexes) (k p n : nat), lift_rec_r (lift_r p U) (p + n) k = lift_r p (lift_rec_r U n k).
Lemma liftrecO : forall (U : redexes) (n : nat), lift_rec_r U n 0 = U.
Lemma liftO : forall U : redexes, lift_r 0 U = U.
Lemma lift_rec_lift_rec : forall (U : redexes) (n p k i : nat), k <= i + n -> i <= k -> lift_rec_r (lift_rec_r U i n) k p = lift_rec_r U i (p + n).
Lemma lift_rec_lift : forall (U : redexes) (n p k i : nat), k <= n -> lift_rec_r (lift_r n U) k p = lift_r (p + n) U.
Lemma subst_eq : forall (U : redexes) (n : nat), subst_rec_r (Var n) U n = lift_r n U.
Lemma subst_gt : forall (U : redexes) (n p : nat), n > p -> subst_rec_r (Var n) U p = Var (pred n).
Lemma subst_lt : forall (U : redexes) (n p : nat), p > n -> subst_rec_r (Var n) U p = Var n.
Lemma lift_rec_subst_rec : forall (U V : redexes) (k p n : nat), lift_rec_r (subst_rec_r V U p) (p + n) k = subst_rec_r (lift_rec_r V (S (p + n)) k) (lift_rec_r U n k) p.
Lemma lift_subst : forall (U V : redexes) (k n : nat), lift_rec_r (subst_r U V) n k = subst_r (lift_rec_r U n k) (lift_rec_r V (S n) k).
Lemma subst_rec_lift_rec1 : forall (U V : redexes) (n p k : nat), k <= n -> subst_rec_r (lift_rec_r U k p) V (p + n) = lift_rec_r (subst_rec_r U V n) k p.
Lemma subst_rec_lift1 : forall (U V : redexes) (n p : nat), subst_rec_r (lift_r p U) V (p + n) = lift_r p (subst_rec_r U V n).
Lemma subst_rec_lift_rec : forall (U V : redexes) (p q n : nat), q <= p + n -> n <= q -> subst_rec_r (lift_rec_r U n (S p)) V q = lift_rec_r U n p.
Lemma subst_rec_lift : forall (U V : redexes) (p q : nat), q <= p -> subst_rec_r (lift_r (S p) U) V q = lift_r p U.
Lemma subst_rec_subst_rec : forall (U V W : redexes) (n p : nat), subst_rec_r (subst_rec_r V U p) W (p + n) = subst_rec_r (subst_rec_r V W (S (p + n))) (subst_rec_r U W n) p.
Lemma subst_rec_subst_0 : forall (U V W : redexes) (n : nat), subst_rec_r (subst_rec_r V U 0) W n = subst_rec_r (subst_rec_r V W (S n)) (subst_rec_r U W n) 0.
Lemma substitution : forall (U V W : redexes) (n : nat), subst_rec_r (subst_r U V) W n = subst_r (subst_rec_r U W n) (subst_rec_r V W (S n)).
Lemma lift_rec_preserve_comp : forall U1 V1 : redexes, comp U1 V1 -> forall n m : nat, comp (lift_rec_r U1 m n) (lift_rec_r V1 m n).
Lemma subst_rec_preserve_comp : forall U1 V1 U2 V2 : redexes, comp U1 V1 -> comp U2 V2 -> forall n : nat, comp (subst_rec_r U1 U2 n) (subst_rec_r V1 V2 n).
Lemma subst_preserve_comp : forall U1 V1 U2 V2 : redexes, comp U1 V1 -> comp U2 V2 -> comp (subst_r U2 U1) (subst_r V2 V1).
Lemma lift_rec_preserve_regular : forall U : redexes, regular U -> forall n m : nat, regular (lift_rec_r U m n).
Lemma subst_rec_preserve_regular : forall U V : redexes, regular U -> regular V -> forall n : nat, regular (subst_rec_r U V n).
Lemma subst_preserve_regular : forall U V : redexes, regular U -> regular V -> regular (subst_r U V).