G4iSLt.G4iSLT_exch_prelims1

Require Import List.
Export ListNotations.
Require Import PeanoNat.
Require Import Lia.

Require Import general_export.

Require Import G4iSLT_calc.
Require Import G4iSLT_list_lems.

(* First, as we want to mimick sequents based on multisets of formulae we need to
obtain exchange. *)


(* Definition of exchange with lists of formulae directly. It is more general and should
make the proofs about exchange easier to handle. *)


Inductive list_exch_L : relationT Seq :=
  | list_exch_LI Γ0 Γ1 Γ2 Γ3 Γ4 A : list_exch_L
      (Γ0 Γ1 Γ2 Γ3 Γ4, A) (Γ0 Γ3 Γ2 Γ1 Γ4, A).

(* Some lemmas about In and exchange. *)

Lemma InT_list_exch_L : A l1 l2,
            (@list_exch_L (,A) (,A))
            ( x, (InT x InT x ) * (InT x InT x )).
Proof.
intros A exch. inversion exch.
intro x. split ; intro ; apply InT_exch_list ; auto.
Qed.


(* Some useful lemmas about list exchange. *)

Lemma list_exch_L_id : s, (@list_exch_L s s).
Proof.
intros s. destruct s. pose (list_exch_LI l [] [] [] [] m). simpl in .
rewrite app_nil_end in ; auto.
Qed.


Lemma list_exch_L_same_R : s se,
    (@list_exch_L s se)
    ( Γ Γe A0 A1, (s = (Γ , ))
    (se = (Γe , ))
    ( = )).
Proof.
intros s se exch. induction exch. intros Γ Γe .
inversion . inversion . rewrite in . assumption.
Qed.


Lemma list_exch_L_permL : s se,
    (@list_exch_L s se)
      ( Γ0 Γ1 A C, s = ((Γ0 C :: Γ1), A)
      ( eΓ0 eΓ1, se = ((eΓ0 C :: eΓ1), A))).
Proof.
intros s se exch. inversion exch ; subst. intros.
inversion H ; subst. apply partition_1_element in . destruct ; repeat destruct s ; subst.
+ exists x. exists ( Γ3 Γ2 Γ1 Γ4). repeat rewrite app_assoc ; auto.
+ exists (Γ0 Γ3 Γ2 x). exists ( Γ4). repeat rewrite app_assoc ; auto.
+ exists (Γ0 Γ3 x). exists ( Γ1 Γ4). repeat rewrite app_assoc ; auto.
+ exists (Γ0 x). exists ( Γ2 Γ1 Γ4). repeat rewrite app_assoc ; auto.
+ exists (Γ0 Γ3 Γ2 Γ1 x). exists . repeat rewrite app_assoc ; auto.
Qed.


(* Interactions between exchange and rules. *)

Lemma AndR_app_list_exchL : s se ps1 ps2,
  (@list_exch_L s se)
  (AndRRule [;] s)
  ( pse1 pse2,
    (AndRRule [;] se) *
    (@list_exch_L ) *
    (@list_exch_L )).
Proof.
intros s se exch RA. inversion RA. subst. inversion exch. subst. exists (Γ0 Γ3 Γ2 Γ1 Γ4, A).
exists (Γ0 Γ3 Γ2 Γ1 Γ4, B). repeat split.
Qed.


Lemma AndL_app_list_exchL : s se ps,
  (@list_exch_L s se)
  (AndLRule [ps] s)
  ( pse,
    (AndLRule [pse] se) *
    (@list_exch_L ps pse)).
Proof.
intros s se ps exch RA. inversion RA. subst. inversion exch. subst. symmetry in .
apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
- destruct Γ3.
  + simpl in . subst. simpl. destruct Γ4.
      * simpl in . simpl. destruct Γ5.
        { simpl in . subst. simpl. exists (Γ0 A :: B :: Γ1, C). repeat split. apply list_exch_L_id. }
        { simpl in . inversion . subst. simpl. exists (Γ0 A :: B :: Γ5 Γ6, C). repeat split. apply list_exch_L_id. }
      * simpl in . inversion . subst. exists (Γ0 Γ5 A :: B :: Γ4 Γ6, C). repeat split.
        pose (AndLRule_I A B C (Γ0 Γ5) (Γ4 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
        pose (list_exch_LI Γ0 [] (A :: B :: Γ4) Γ5 Γ6 C). simpl in l ; auto.
  + simpl in . inversion . subst. exists (Γ0 Γ5 Γ4 A :: B :: Γ3 Γ6, C). repeat split.
      pose (AndLRule_I A B C (Γ0 Γ5 Γ4) (Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
      pose (list_exch_LI Γ0 (A :: B :: Γ3) Γ4 Γ5 Γ6 C). simpl in l ; auto.
- destruct x.
  + simpl in . subst. simpl. destruct Γ3.
      * simpl in . simpl. destruct Γ4.
        { simpl in . subst. simpl. rewrite . exists ((Γ0 []) A :: B :: Γ1, C). repeat split. rewrite app_assoc. apply list_exch_L_id. }
        { simpl in . inversion . subst. simpl. rewrite app_assoc ; simpl. exists (Γ0 Γ5 A :: B :: Γ4 Γ6, C). repeat split.
          pose (AndLRule_I A B C (Γ0 Γ5) (Γ4 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
          pose (list_exch_LI Γ0 [] (A :: B :: Γ4) Γ5 Γ6 C). simpl in l ; auto. }
      * simpl in . inversion . subst. rewrite app_assoc ; simpl. exists (Γ0 Γ5 Γ4 A :: B :: Γ3 Γ6, C). repeat split.
        pose (AndLRule_I A B C (Γ0 Γ5 Γ4) (Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
        pose (list_exch_LI Γ0 (A :: B :: Γ3) Γ4 Γ5 Γ6 C). simpl in l ; auto.
  + simpl in . inversion . subst. exists (Γ0 A :: B :: x Γ5 Γ4 Γ3 Γ6, C). repeat rewrite app_assoc. repeat split.
      pose (list_exch_LI (Γ0 A :: B :: x) Γ3 Γ4 Γ5 Γ6 C). repeat rewrite app_assoc in l ; simpl in l ; auto.
- apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
  + simpl in . subst. simpl. destruct Γ4.
      * simpl in . simpl. destruct Γ5.
        { simpl in . subst. simpl. exists ((Γ2 Γ3) A :: B :: Γ1, C). repeat split. 2: apply list_exch_L_id. rewrite app_assoc.
           apply AndLRule_I. }
        { simpl in . inversion . subst. simpl. exists (Γ2 A :: B :: Γ5 Γ3 Γ6, C). repeat split.
           pose (list_exch_LI Γ2 Γ3 [] (A :: B :: Γ5) Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
      * simpl in . inversion . subst. exists ((Γ2 Γ5) A :: B :: Γ4 Γ3 Γ6, C). repeat split.
        pose (AndLRule_I A B C (Γ2 Γ5) (Γ4 Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
        pose (list_exch_LI Γ2 Γ3 (A :: B :: Γ4) Γ5 Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto.
  + apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
      * simpl in . simpl. destruct Γ5.
        { simpl in . subst. simpl. exists ((Γ2 Γ4 Γ3) A :: B :: Γ1, C). repeat split.
           pose (AndLRule_I A B C (Γ2 Γ4 Γ3) Γ1). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
           pose (list_exch_LI Γ2 Γ3 Γ4 [] (A :: B :: Γ1) C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
        { simpl in . inversion . subst. simpl. exists (Γ2 A :: B :: Γ5 Γ4 Γ3 Γ6, C). repeat split.
           pose (list_exch_LI Γ2 Γ3 Γ4 (A :: B :: Γ5) Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
      * apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
        { repeat rewrite app_assoc. exists (Γ2 Γ5 Γ4 Γ3 A :: B :: Γ1, C). repeat split. repeat rewrite app_assoc. apply AndLRule_I. }
        { repeat rewrite app_assoc. exists (Γ2 Γ5 Γ4 Γ3 A :: B :: Γ1, C). repeat split. repeat rewrite app_assoc. apply AndLRule_I. }
        { destruct .
            - simpl in . subst. repeat rewrite app_assoc. simpl. exists (Γ2 x Γ4 Γ3 A :: B :: Γ1, C). repeat split.
              repeat rewrite app_assoc. apply AndLRule_I.
            - simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists ((Γ2 x) A :: B :: Γ4 Γ3 Γ6, C). repeat split.
              pose (AndLRule_I A B C (Γ2 x) ( Γ4 Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
              pose (list_exch_LI Γ2 Γ3 Γ4 (x A :: B :: ) Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
      * destruct x.
        { simpl in . destruct Γ5.
            - simpl in . subst. repeat rewrite app_assoc. simpl. exists (Γ2 Γ3 A :: B :: Γ1, C). repeat split.
              repeat rewrite app_assoc. apply AndLRule_I.
              pose (list_exch_LI Γ2 Γ3 [] (A :: B :: Γ1) C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto.
            - simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists (Γ2 A :: B :: Γ5 Γ3 Γ6, C). repeat split.
              pose (list_exch_LI Γ2 Γ3 (A :: B :: Γ5) Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
        { simpl in . inversion . subst. exists ((Γ2 Γ5 ) A :: B :: x Γ3 Γ6, C). split.
           pose (AndLRule_I A B C (Γ2 Γ5 ) (x Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
           pose (list_exch_LI Γ2 Γ3 ( A :: B :: x) Γ5 Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
  + destruct .
      * simpl in . simpl. destruct Γ4.
        { simpl in . destruct Γ5.
            - simpl in . subst. repeat rewrite app_assoc. simpl. exists (Γ2 x A :: B :: Γ1, C). repeat split.
              repeat rewrite app_assoc. apply AndLRule_I. apply list_exch_L_id.
            - simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists (Γ2 A :: B :: Γ5 x Γ6, C). repeat split.
              pose (list_exch_LI Γ2 x [] (A :: B :: Γ5) Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
        { simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists ((Γ2 Γ5) A :: B :: Γ4 x Γ6, C). repeat split.
          pose (AndLRule_I A B C (Γ2 Γ5) (Γ4 x Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
          pose (list_exch_LI Γ2 x (A :: B :: Γ4) Γ5 Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto. }
      * simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists ((Γ2 Γ5 Γ4 x) A :: B :: Γ6, C). repeat split.
         pose (AndLRule_I A B C (Γ2 Γ5 Γ4 x) ( Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in a ; simpl in a ; auto.
         pose (list_exch_LI Γ2 (x A :: B :: ) Γ4 Γ5 Γ6 C). repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; auto.
Qed.


Lemma OrR1_app_list_exchL : s se ps,
  (@list_exch_L s se)
  (OrR1Rule [ps] s)
  ( pse,
    (OrR1Rule [pse] se) *
    (@list_exch_L ps pse)).
Proof.
intros s se ps exch RA. inversion RA. subst. inversion exch. subst. exists (Γ0 Γ3 Γ2 Γ1 Γ4, A).
split ; auto. apply OrR1Rule_I. apply list_exch_LI.
Qed.


Lemma OrR2_app_list_exchL : s se ps,
  (@list_exch_L s se)
  (OrR2Rule [ps] s)
  ( pse,
    (OrR2Rule [pse] se) *
    (@list_exch_L ps pse)).
Proof.
intros s se ps exch RA. inversion RA. subst. inversion exch. subst. exists (Γ0 Γ3 Γ2 Γ1 Γ4, B).
split ; auto. apply OrR2Rule_I. apply list_exch_LI.
Qed.


Lemma OrL_app_list_exchL : s se ps1 ps2,
  (@list_exch_L s se)
  (OrLRule [;] s)
  ( pse1 pse2,
    (OrLRule [;] se) *
    (@list_exch_L ) *
    (@list_exch_L )).
Proof.
intros s se exch RA. inversion RA. subst. inversion exch. subst. symmetry in .
apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
- destruct Γ3.
  + simpl in . subst. simpl. destruct Γ4.
      * simpl in . simpl. destruct Γ5.
        { simpl in . subst. simpl. exists (Γ0 A :: Γ1, C). exists (Γ0 B :: Γ1, C). repeat split ; try apply list_exch_L_id. }
        { simpl in . inversion . subst. simpl. exists (Γ0 A :: Γ5 Γ6, C). exists (Γ0 B :: Γ5 Γ6, C). repeat split ; try apply list_exch_L_id. }
      * simpl in . inversion . subst. exists (Γ0 Γ5 A :: Γ4 Γ6, C). exists (Γ0 Γ5 B :: Γ4 Γ6, C). repeat split.
        pose (OrLRule_I A B C (Γ0 Γ5) (Γ4 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
        1-2: epose (list_exch_LI Γ0 [] (_ :: Γ4) Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
  + simpl in . inversion . subst. exists (Γ0 Γ5 Γ4 A :: Γ3 Γ6, C). exists (Γ0 Γ5 Γ4 B :: Γ3 Γ6, C). repeat split.
      pose (OrLRule_I A B C (Γ0 Γ5 Γ4) (Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
      1-2: epose (list_exch_LI Γ0 (_ :: Γ3) Γ4 Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
- destruct x.
  + simpl in . subst. simpl. destruct Γ3.
      * simpl in . simpl. destruct Γ4.
        { simpl in . subst. simpl. rewrite . exists ((Γ0 []) A :: Γ1, C). exists ((Γ0 []) B :: Γ1, C). repeat split ; rewrite app_assoc ; simpl ; try apply list_exch_L_id. }
        { simpl in . inversion . subst. simpl. rewrite app_assoc ; simpl. exists (Γ0 Γ5 A :: Γ4 Γ6, C). exists (Γ0 Γ5 B :: Γ4 Γ6, C). repeat split.
          pose (OrLRule_I A B C (Γ0 Γ5) (Γ4 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
          1-2: epose (list_exch_LI Γ0 (_ :: Γ4) [] Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
      * simpl in . inversion . subst. rewrite app_assoc ; simpl. exists (Γ0 Γ5 Γ4 A :: Γ3 Γ6, C). exists (Γ0 Γ5 Γ4 B :: Γ3 Γ6, C). repeat split.
        pose (OrLRule_I A B C (Γ0 Γ5 Γ4) (Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
        1-2: epose (list_exch_LI Γ0 (_ :: Γ3) Γ4 Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
  + simpl in . inversion . subst. exists (Γ0 A :: x Γ5 Γ4 Γ3 Γ6, C). exists (Γ0 B :: x Γ5 Γ4 Γ3 Γ6, C). repeat rewrite app_assoc. repeat split.
      1-2: epose (list_exch_LI (Γ0 _ :: x) Γ3 Γ4 Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
- apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
  + simpl in . subst. simpl. destruct Γ4.
      * simpl in . simpl. destruct Γ5.
        { simpl in . subst. simpl. exists ((Γ2 Γ3) A :: Γ1, C). exists ((Γ2 Γ3) B :: Γ1, C). repeat split ; try apply list_exch_L_id. rewrite app_assoc.
           apply OrLRule_I. }
        { simpl in . inversion . subst. simpl. exists (Γ2 A :: Γ5 Γ3 Γ6, C). exists (Γ2 B :: Γ5 Γ3 Γ6, C). repeat split.
          1-2: epose (list_exch_LI Γ2 Γ3 [] (_ :: Γ5) Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
      * simpl in . inversion . subst. exists ((Γ2 Γ5) A :: Γ4 Γ3 Γ6, C). exists ((Γ2 Γ5) B :: Γ4 Γ3 Γ6, C). repeat split.
        pose (OrLRule_I A B C (Γ2 Γ5) (Γ4 Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
        1-2 : epose (list_exch_LI Γ2 Γ3 (_ :: Γ4) Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
  + apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
      * simpl in . simpl. destruct Γ5.
        { simpl in . subst. simpl. exists ((Γ2 Γ4 Γ3) A :: Γ1, C). exists ((Γ2 Γ4 Γ3) B :: Γ1, C). repeat split.
           pose (OrLRule_I A B C (Γ2 Γ4 Γ3) Γ1). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
           1-2 : epose (list_exch_LI Γ2 Γ3 [] Γ4 (_ :: Γ1) C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
        { simpl in . inversion . subst. simpl. exists (Γ2 A :: Γ5 Γ4 Γ3 Γ6, C). exists (Γ2 B :: Γ5 Γ4 Γ3 Γ6, C). repeat split.
           1-2 : epose (list_exch_LI Γ2 Γ3 Γ4 (_ :: Γ5) Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
      * apply app2_find_hole in . destruct . repeat destruct s ; destruct p ; subst.
        { repeat rewrite app_assoc. exists (Γ2 Γ5 Γ4 Γ3 A :: Γ1, C). exists (Γ2 Γ5 Γ4 Γ3 B :: Γ1, C). repeat split. repeat rewrite app_assoc. apply OrLRule_I. }
        { repeat rewrite app_assoc. exists (Γ2 Γ5 Γ4 Γ3 A :: Γ1, C). exists (Γ2 Γ5 Γ4 Γ3 B :: Γ1, C). repeat split. repeat rewrite app_assoc. apply OrLRule_I. }
        { destruct .
            - simpl in . subst. repeat rewrite app_assoc. simpl. exists (Γ2 x Γ4 Γ3 A :: Γ1, C). exists (Γ2 x Γ4 Γ3 B :: Γ1, C). repeat split.
              repeat rewrite app_assoc. apply OrLRule_I.
            - simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists ((Γ2 x) A :: Γ4 Γ3 Γ6, C). exists ((Γ2 x) B :: Γ4 Γ3 Γ6, C). repeat split.
              pose (OrLRule_I A B C (Γ2 x) ( Γ4 Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
              1-2 : epose (list_exch_LI Γ2 Γ3 Γ4 (x _ :: ) Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
      * destruct x.
        { simpl in . destruct Γ5.
            - simpl in . subst. repeat rewrite app_assoc. simpl. exists (Γ2 Γ3 A :: Γ1, C). exists (Γ2 Γ3 B :: Γ1, C). repeat split.
              repeat rewrite app_assoc. apply OrLRule_I.
              1-2 : epose (list_exch_LI Γ2 Γ3 [] (_ :: Γ1) C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
            - simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists (Γ2 A :: Γ5 Γ3 Γ6, C). exists (Γ2 B :: Γ5 Γ3 Γ6, C). repeat split.
              1-2 : epose (list_exch_LI Γ2 Γ3 (_ :: Γ5) Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
        { simpl in . inversion . subst. exists ((Γ2 Γ5 ) A :: x Γ3 Γ6, C). exists ((Γ2 Γ5 ) B :: x Γ3 Γ6, C). repeat split.
          pose (OrLRule_I A B C (Γ2 Γ5 ) (x Γ3 Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
          1-2 : epose (list_exch_LI Γ2 Γ3 ( _ :: x) Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
  + destruct .
      * simpl in . simpl. destruct Γ4.
        { simpl in . destruct Γ5.
            - simpl in . subst. repeat rewrite app_assoc. simpl. exists (Γ2 x A :: Γ1, C). exists (Γ2 x B :: Γ1, C). repeat split.
              repeat rewrite app_assoc. apply OrLRule_I. apply list_exch_L_id. apply list_exch_L_id.
            - simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists (Γ2 A :: Γ5 x Γ6, C). exists (Γ2 B :: Γ5 x Γ6, C). repeat split.
              1-2 : epose (list_exch_LI Γ2 x [] (_ :: Γ5) Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
        { simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists ((Γ2 Γ5) A :: Γ4 x Γ6, C). exists ((Γ2 Γ5) B :: Γ4 x Γ6, C). repeat split.
          pose (OrLRule_I A B C (Γ2 Γ5) (Γ4 x Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
          1-2 : epose (list_exch_LI Γ2 x (_ :: Γ4) Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l. }
      * simpl in . inversion . subst. repeat rewrite app_assoc. simpl. exists ((Γ2 Γ5 Γ4 x) A :: Γ6, C). exists ((Γ2 Γ5 Γ4 x) B :: Γ6, C). repeat split.
        pose (OrLRule_I A B C (Γ2 Γ5 Γ4 x) ( Γ6)). repeat rewrite app_assoc ; repeat rewrite app_assoc in o ; simpl in o ; auto.
        1-2 : epose (list_exch_LI Γ2 (x _ :: ) Γ4 Γ5 Γ6 C) ; repeat rewrite app_assoc ; simpl ; repeat rewrite app_assoc in l ; simpl in l ; apply l.
Qed.