(*************************************************)
(* Parallel beta reduction with residual tracing *)
(*************************************************)

(* (residuals U V W) means W are residuals of redexes U by step V *)

Inductive residuals : redexes -> redexes -> redexes -> Prop :=
  | Res_Var : forall n : nat, residuals (Var n) (Var n) (Var n)
  | Res_Fun :
      forall U V W : redexes,
      residuals U V W -> residuals (Fun U) (Fun V) (Fun W)
  | Res_Ap :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool, residuals (Ap b U1 U2) (Ap false V1 V2) (Ap b W1 W2)
  | Res_redex :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool,
      residuals (Ap b (Fun U1) U2) (Ap true (Fun V1) V2) (subst_r W2 W1).(*************************************************)
(* Parallel beta reduction with residual tracing *)
(*************************************************)

(* (residuals U V W) means W are residuals of redexes U by step V *)

Inductive residuals : redexes -> redexes -> redexes -> Prop :=
  | Res_Var : forall n : nat, residuals (Var n) (Var n) (Var n)
  | Res_Fun :
      forall U V W : redexes,
      residuals U V W -> residuals (Fun U) (Fun V) (Fun W)
  | Res_Ap :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool, residuals (Ap b U1 U2) (Ap false V1 V2) (Ap b W1 W2)
  | Res_redex :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool,
      residuals (Ap b (Fun U1) U2) (Ap true (Fun V1) V2) (subst_r W2 W1).(*************************************************)
(* Parallel beta reduction with residual tracing *)
(*************************************************)

(* (residuals U V W) means W are residuals of redexes U by step V *)

Inductive residuals : redexes -> redexes -> redexes -> Prop :=
  | Res_Var : forall n : nat, residuals (Var n) (Var n) (Var n)
  | Res_Fun :
      forall U V W : redexes,
      residuals U V W -> residuals (Fun U) (Fun V) (Fun W)
  | Res_Ap :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool, residuals (Ap b U1 U2) (Ap false V1 V2) (Ap b W1 W2)
  | Res_redex :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool,
      residuals (Ap b (Fun U1) U2) (Ap true (Fun V1) V2) (subst_r W2 W1).(*************************************************)
(* Parallel beta reduction with residual tracing *)
(*************************************************)

(* (residuals U V W) means W are residuals of redexes U by step V *)

Inductive residuals : redexes -> redexes -> redexes -> Prop :=
  | Res_Var : forall n : nat, residuals (Var n) (Var n) (Var n)
  | Res_Fun :
      forall U V W : redexes,
      residuals U V W -> residuals (Fun U) (Fun V) (Fun W)
  | Res_Ap :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool, residuals (Ap b U1 U2) (Ap false V1 V2) (Ap b W1 W2)
  | Res_redex :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool,
      residuals (Ap b (Fun U1) U2) (Ap true (Fun V1) V2) (subst_r W2 W1).(*************************************************)
(* Parallel beta reduction with residual tracing *)
(*************************************************)

(* (residuals U V W) means W are residuals of redexes U by step V *)

Inductive residuals : redexes -> redexes -> redexes -> Prop :=
  | Res_Var : forall n : nat, residuals (Var n) (Var n) (Var n)
  | Res_Fun :
      forall U V W : redexes,
      residuals U V W -> residuals (Fun U) (Fun V) (Fun W)
  | Res_Ap :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool, residuals (Ap b U1 U2) (Ap false V1 V2) (Ap b W1 W2)
  | Res_redex :
      forall U1 V1 W1 : redexes,
      residuals U1 V1 W1 ->
      forall U2 V2 W2 : redexes,
      residuals U2 V2 W2 ->
      forall b : bool,
      residuals (Ap b (Fun U1) U2) (Ap true (Fun V1) V2) (subst_r W2 W1).

(* Specifications: *)
Lemma residuals_function : forall U V W : redexes, residuals U V W -> forall (W' : redexes) (R : residuals U V W'), W' = W.
Lemma residuals_lift_rec : forall U1 U2 U3 : redexes, residuals U1 U2 U3 -> forall k n : nat, residuals (lift_rec_r U1 n k) (lift_rec_r U2 n k) (lift_rec_r U3 n k).
Lemma residuals_lift : forall U1 U2 U3 : redexes, residuals U1 U2 U3 -> forall k : nat, residuals (lift_r k U1) (lift_r k U2) (lift_r k U3).
Lemma residuals_subst_rec : forall U1 U2 U3 V1 V2 V3 : redexes, residuals U1 U2 U3 -> residuals V1 V2 V3 -> forall k : nat, residuals (subst_rec_r U1 V1 k) (subst_rec_r U2 V2 k) (subst_rec_r U3 V3 k).
Theorem commutation : forall U1 U2 U3 V1 V2 V3 : redexes, residuals U1 U2 U3 -> residuals V1 V2 V3 -> residuals (subst_r V1 U1) (subst_r V2 U2) (subst_r V3 U3).
Lemma residuals_comp : forall U V W : redexes, residuals U V W -> comp U V.
Lemma preservation1 : forall U V UV : redexes, residuals U V UV -> forall (T : redexes) (UVT : union U V T), residuals T V UV.
Lemma preservation : forall U V W UV : redexes, union U V W -> residuals U V UV -> residuals W V UV.
Lemma mutual_residuals_comp : forall (W U UW : redexes) (RU : residuals U W UW) (V VW : redexes) (RV : residuals V W VW), comp UW VW.
Lemma residuals_regular : forall U V W : redexes, residuals U V W -> regular V.
Lemma residuals_intro : forall U V : redexes, comp U V -> regular V -> exists W : redexes, residuals U V W.
Lemma residuals_preserve_regular : forall U V W : redexes, residuals U V W -> regular U -> regular W.