(* Invertion principles for transitions and location invariants *)

Derive Inversion_clear cl_TRT_APPROACH with
 (forall st1 st2 : S_Ck ST, TrT st1 Approach st2) Sort Prop.Derive Inversion_clear cl_TRT_IN with
 (forall st1 st2 : S_Ck ST, TrT st1 In st2) Sort Prop.Derive Inversion_clear cl_TRT_EXIT with
 (forall st1 st2 : S_Ck ST, TrT st1 Exit st2) Sort Prop.Derive Inversion_clear cl_TRT_INC_TIME with
 (forall st1 st2 : S_Ck ST, TrT st1 Tick st2) Sort Prop.Derive Inversion_clear cl_TRC_APPROACH with
 (forall sc1 sc2 : S_Ck SC, TrC sc1 Approach sc2) Sort Prop.Derive Inversion_clear cl_TRC_LOWER with
 (forall sc1 sc2 : S_Ck SC, TrC sc1 Lower sc2) Sort Prop.Derive Inversion_clear cl_TRC_EXIT with
 (forall sc1 sc2 : S_Ck SC, TrC sc1 Exit sc2) Sort Prop.Derive Inversion_clear cl_TRC_RAISE with
 (forall sc1 sc2 : S_Ck SC, TrC sc1 Raise sc2) Sort Prop.Derive Inversion_clear cl_TRC_INC_TIME with
 (forall sc1 sc2 : S_Ck SC, TrC sc1 Tick sc2) Sort Prop.Derive Inversion_clear cl_TRG_LOWER with
 (forall sg1 sg2 : S_Ck SG, TrG sg1 Lower sg2) Sort Prop.Derive Inversion_clear cl_TRG_DOWN with
 (forall sg1 sg2 : S_Ck SG, TrG sg1 Down sg2) Sort Prop.Derive Inversion_clear cl_TRG_RAISE with
 (forall sg1 sg2 : S_Ck SG, TrG sg1 Raise sg2) Sort Prop.Derive Inversion_clear cl_TRG_UP with
 (forall sg1 sg2 : S_Ck SG, TrG sg1 Up sg2) Sort Prop.Derive Inversion_clear cl_TRG_INC_TIME with
 (forall sg1 sg2 : S_Ck SG, TrG sg1 Tick sg2) Sort Prop.Derive Inversion_clear cl_Ifar with (forall x : Clock, InvT (Far, x)) Sort
 Prop.Derive Inversion_clear cl_Inear with (forall x : Clock, InvT (Near, x)) Sort
 Prop.Derive Inversion_clear cl_Iinside with (forall x : Clock, InvT (Inside, x))
 Sort Prop.Derive Inversion_clear cl_Isc1 with (forall y : Clock, InvC (Sc1, y)) Sort
 Prop.Derive Inversion_clear cl_Isc2 with (forall y : Clock, InvC (Sc2, y)) Sort
 Prop.Derive Inversion_clear cl_Isc3 with (forall y : Clock, InvC (Sc3, y)) Sort
 Prop.Derive Inversion_clear cl_Isc4 with (forall y : Clock, InvC (Sc4, y)) Sort
 Prop.Derive Inversion_clear cl_Iopen with (forall z : Clock, InvG (Open, z)) Sort
 Prop.Derive Inversion_clear cl_Ilowering with
 (forall z : Clock, InvG (Lowering, z)) Sort Prop.Derive Inversion_clear cl_Iclosed with (forall z : Clock, InvG (Closed, z))
 Sort Prop.Derive Inversion_clear cl_Iraising with (forall z : Clock, InvG (Raising, z))
 Sort Prop.(* Some tactics *)

Ltac Easy := try discriminate; auto with *.Ltac Easy2 := intros; try discriminate; auto with *.Ltac Simpl_or eq := elim eq; intro; Easy.Ltac Simpl_and eq := elim eq; intros; Easy.Ltac Generalize_Easy eq := generalize eq; intro; Easy.Ltac Split3_Trivial := split; [ auto with * | split; auto with * ].Ltac BeginForAll :=
  unfold ForAll in |- *; simple induction 1;
   [ simpl in |- *; intros; Easy | idtac ].Ltac SplitTrans :=
  intros s1 s2 l rs_s1 p_s1 tr_gl; generalize rs_s1; clear rs_s1;
   generalize p_s1; clear p_s1; elim tr_gl.Ltac SplitTrans_Simpl :=
  SplitTrans;
   [ Simpl_In
   | Simpl_Down
   | Simpl_Up
   | Simpl_Approach
   | Simpl_Exit
   | Simpl_Lower
   | Simpl_Raise
   | Simpl_Tick ]
 with Simpl_In :=
  intros st1 st2 trt_In; inversion trt_In using cl_TRT_IN;
   intros x gt_x_kt1 lt_x_kt2 sc sg; elim sc; elim sg; 
   simpl in |- *; intros; Easy
 with Simpl_Down :=
  intros sg1 sg2 trg_Down; inversion trg_Down using cl_TRG_DOWN;
   intros z lt_z_kg1 st sc; elim st; elim sc; simpl in |- *; 
   intros; Easy
 with Simpl_Up :=
  intros sg1 sg2 trg_Up; inversion trg_Up using cl_TRG_UP;
   intros z ge_z_kg2 lt_z_kg3 st sc; elim st; elim sc; 
   simpl in |- *; intros; Easy
 with Simpl_Approach :=
  intros st1 st2 sc1 sc2 trt_Approach trc_Approach;
   inversion trt_Approach using cl_TRT_APPROACH;
   inversion trc_Approach using cl_TRC_APPROACH; intros y x sg; 
   elim sg; simpl in |- *; intros; Easy
 with Simpl_Exit :=
  intros st1 st2 sc1 sc2 trt_Exit trc_Exit;
   inversion trt_Exit using cl_TRT_EXIT; inversion trc_Exit using cl_TRC_EXIT;
   intros y x lt_x_kt2 sg; elim sg; simpl in |- *; 
   intros; Easy
 with Simpl_Lower :=
  intros sc1 sc2 sg1 sg2 trc_Lower trg_Lower;
   inversion trc_Lower using cl_TRC_LOWER;
   inversion trg_Lower using cl_TRG_LOWER; intros z y eq_y_kc1 st; 
   elim st; simpl in |- *; intros; Easy
 with Simpl_Raise :=
  intros sc1 sc2 sg1 sg2 trc_Raise trg_Raise;
   inversion trc_Raise using cl_TRC_RAISE;
   inversion trg_Raise using cl_TRG_RAISE; intros z y lt_y_kc2 st; 
   elim st; simpl in |- *; intros; Easy
 with Simpl_Tick :=
  intros st1 st2 sc1 sc2 sg1 sg2 trt_Tick trc_Tick trg_Tick;
   inversion trt_Tick using cl_TRT_INC_TIME;
   inversion trc_Tick using cl_TRC_INC_TIME;
   inversion trg_Tick using cl_TRG_INC_TIME; simpl in |- *; 
   intros; Easy.Notation InvTCG :=
  (fun s : StGlobal =>
   match s with
   | (st_x, (sc_y, sg_z)) => InvT st_x /\ InvC sc_y /\ InvG sg_z
   end) (only parsing).Notation ForAll_TCG := (ForAll TrGlobal) (only parsing).Notation Exists_TCG := (Exists TrGlobal) (only parsing).

Lemma Inv_SiniTCG : (fun s : StGlobal => match s with | (st_x, (sc_y, sg_z)) => InvT st_x /\ InvC sc_y /\ InvG sg_z end) SiniTCG.