G4iSLt.G4iSLT_dec

Require Import List.
Export ListNotations.

Require Import general_export.

Require Import G4iSLT_calc.
Require Import G4iSLT_list_lems.
Require Import G4iSLT_remove_list.

Set Implicit Arguments.

(* In this file we show that the applicability of the rules in G4iSLT is decidable. *)

Lemma dec_is_atomicT : (A : MPropF), (is_atomicT A) + ((is_atomicT A) False).
Proof.
induction A.
- left. left. exists n. reflexivity.
- left. right. reflexivity.
- right. intro. inversion X. inversion H. inversion . inversion H.
- right. intro. inversion X. inversion H. inversion . inversion H.
- right. intro. inversion X. inversion H. inversion . inversion H.
- right. intro. inversion X. inversion H. inversion . inversion H.
Qed.


Lemma dec_prop_var_in0 : l, ( P, In (# P) l) +
                                      (( P, In (# P) l) False).
Proof.
intro. induction l.
- right. intro. destruct H. destruct i.
- destruct IHl.
  * destruct s. left. exists x. apply in_cons ; auto.
  * destruct (dec_is_atomicT a).
    + inversion i. left. destruct H. exists x. simpl. auto. right. intro. destruct .
        inversion . subst. inversion . apply f. exists x. auto.
    + right. intro. simpl in H. destruct H. destruct o. subst.
      { subst. apply . left. exists x. reflexivity. }
      { apply f. firstorder. }
Qed.


Lemma dec_prop_var_in : s, ( P, (In (# P) (fst s)) (# P = snd s)) +
                                      (( P, (In (# P) (fst s)) (# P = snd s)) False).
Proof.
intro. destruct s.
induction l.
- right. intro. destruct H. destruct a. simpl in H. inversion H.
- destruct IHl.
  * destruct s. simpl in . destruct . left. exists x. simpl. split. auto. assumption.
  * destruct (dec_is_atomicT a).
    + destruct (eq_dec_form m a).
      { inversion i. left. subst. destruct H. exists x. simpl. split. auto. subst. auto.
        subst. right. simpl. intro. destruct H. destruct a. destruct H. inversion H. apply f.
        exists x. auto. }
      { right. simpl. intro. destruct H. destruct . destruct H.
        - subst. apply n. subst. auto.
        - apply f. simpl. exists x. firstorder. }
    + right. intro. simpl in H. destruct H. destruct . destruct H.
      { subst. apply . left. exists x. reflexivity. }
      { apply f. firstorder. }
Qed.


Lemma dec_is_boxedT : (A : MPropF), (is_boxedT A) + ((is_boxedT A) False).
Proof.
induction A.
- right. intro. inversion X. inversion H.
- right. intro. inversion X. inversion H.
- right. intro. inversion X. inversion H.
- right. intro. inversion X. inversion H.
- right. intro. inversion X. inversion H.
- left. exists A. reflexivity.
Qed.


Lemma dec_is_box : (A : MPropF), ( B, A = Box B) + (( B, A = Box B ) False).
Proof.
destruct A.
- right. intro. destruct H. inversion e.
- right. intro. destruct H. inversion e.
- right. intro. destruct H. inversion e.
- right. intro. destruct H. inversion e.
- right. intro. destruct H. inversion e.
- left. exists A. reflexivity.
Qed.


Lemma dec_box_in : s, ( (A : MPropF), (In (Box A) (fst s)) (Box A = snd s)) +
                             (( (A : MPropF), (In (Box A) (fst s)) (Box A = snd s)) False).
Proof.
intro. destruct s.
induction l.
- right. intro. destruct H. destruct a. simpl in H. inversion H.
- destruct IHl.
  * destruct s. simpl in . destruct . left. exists x. simpl. split. auto. assumption.
  * destruct (dec_is_box a).
    + destruct (eq_dec_form m a).
      { left. destruct s. subst. simpl. exists x. auto. }
      { right. simpl. intro. destruct H. destruct . destruct H.
        - subst. apply n. auto.
        - apply f. simpl. exists x. firstorder. }
    + right. intro. simpl in H. destruct H. destruct . destruct H.
      { subst. apply . exists x. reflexivity. }
      { apply f. firstorder. }
Qed.


(* Initial rules *)

Lemma dec_G4iSLT_init_rules : (s : Seq) ,
          ((IdPRule [] s) + (BotLRule [] s)) +
          (((IdPRule [] s) + (BotLRule [] s)) False).
Proof.
intro s. destruct s. destruct (dec_prop_var_in (pair l m)).
- destruct s. destruct a. left. left. simpl in H. simpl in .
  apply in_splitT in H. destruct H. destruct s. subst. apply IdPRule_I.
- destruct (In_dec l ()).
  + left. apply in_splitT in i. destruct i. destruct s. subst. right. apply BotLRule_I.
  + right. intro. destruct H.
    * inversion i. subst. simpl in f. apply f. exists P. split. 2: auto. apply in_or_app. right. apply in_eq.
    * inversion b. subst. apply . apply in_or_app. right. apply in_eq.
Qed.


Lemma dec_IdP_rule : (s : Seq),
          (IdPRule [] s) +
          ((IdPRule [] s) False).
Proof.
intro s. destruct s. destruct (dec_prop_var_in (pair l m)).
- destruct s. destruct a. left. simpl in H. simpl in .
  apply in_splitT in H. destruct H. destruct s. subst. apply IdPRule_I.
- right. intro. destruct H. apply f. exists P. split ; auto ; apply in_or_app ; right ; apply in_eq.
Qed.


Lemma dec_BotL_rule : (s : Seq),
          (BotLRule [] s) +
          ((BotLRule [] s) False).
Proof.
intro s. destruct s. destruct (In_dec l ()).
- left. apply in_splitT in i. destruct i. destruct s. subst. apply BotLRule_I.
- right. intro. inversion H. apply f. subst. apply in_or_app. right. apply in_eq.
Qed.


(* Conjunction rules *)

Lemma dec_is_and : (A : MPropF), ( B C, A = And B C) + (( B C, A = And B C) False).
Proof.
destruct A.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- left. exists . exists . reflexivity.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
Qed.


Lemma dec_and_in : (l : list MPropF), ( A B, In (And A B) l) + (( A B, In (And A B) l) False).
Proof.
induction l.
- right. intro. destruct H. destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . apply in_cons. assumption.
  * destruct (dec_is_and a).
    + repeat destruct s. subst. left. exists x. exists . apply in_eq.
    + right. intro. destruct H. destruct s. inversion i.
      { subst. apply . exists x. exists . reflexivity. }
      { apply f. exists x. exists . assumption. }
Qed.


Lemma dec_AndR_rule : (concl : Seq),
          ( prem1 prem2, AndRRule [;] concl) + (( prem1 prem2, AndRRule [ ; ] concl) False).
Proof.
intros concl. destruct concl. destruct (dec_is_and m).
- left. repeat destruct s. subst. exists (l, x). exists (l, ). apply AndRRule_I.
- right. intro. destruct H. destruct s. inversion a. subst. apply f. exists A. exists B. auto.
Qed.


Lemma dec_AndL_rule : (concl : Seq),
          ( prem, AndLRule [prem] concl) + (( prem, AndLRule [prem] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_and_in l).
- left. repeat destruct s. apply in_splitT in i. destruct i. destruct s. subst.
  exists ( x :: :: , m). apply AndLRule_I.
- right. intro. destruct H. inversion a. subst. apply f. exists A. exists B.
  apply in_or_app. right. apply in_eq.
Qed.


(* Disjunction rules *)

Lemma dec_is_or : (A : MPropF), ( B C, A = Or B C) + (( B C, A = Or B C) False).
Proof.
destruct A.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- left. exists . exists . reflexivity.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
Qed.


Lemma dec_or_in : (l : list MPropF), ( A B, In (Or A B) l) + (( A B, In (Or A B) l) False).
Proof.
induction l.
- right. intro. destruct H. destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . apply in_cons. assumption.
  * destruct (dec_is_or a).
    + repeat destruct s. subst. left. exists x. exists . apply in_eq.
    + right. intro. destruct H. destruct s. inversion i.
      { subst. apply . exists x. exists . reflexivity. }
      { apply f. exists x. exists . assumption. }
Qed.


Lemma dec_OrR1_rule : (concl : Seq),
          ( prem, OrR1Rule [prem] concl) + (( prem, OrR1Rule [prem] concl) False).
Proof.
intros concl. destruct concl. destruct (dec_is_or m).
- left. subst. destruct s. destruct s. subst.
  exists (l, x). apply OrR1Rule_I.
- right. intro. destruct H. inversion o. subst. apply f. exists A. exists B. auto.
Qed.


Lemma dec_OrR2_rule : (concl : Seq),
          ( prem, OrR2Rule [prem] concl) + (( prem, OrR2Rule [prem] concl) False).
Proof.
intros concl. destruct concl. destruct (dec_is_or m).
- left. subst. destruct s. destruct s. subst.
  exists (l, ). apply OrR2Rule_I.
- right. intro. destruct H. inversion o. subst. apply f. exists A. exists B. auto.
Qed.


Lemma dec_OrL_rule : (concl : Seq),
          ( prem1 prem2, OrLRule [ ; ] concl) + (( prem1 prem2, OrLRule [ ; ] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_or_in l).
- left. repeat destruct s. apply in_splitT in i. destruct i. destruct s. subst.
  exists ( x :: , m). exists ( :: , m). apply OrLRule_I.
- right. intro. destruct H. destruct s. inversion o. subst. apply f. exists A. exists B.
  apply in_or_app. right. apply in_eq.
Qed.


(* Implication rules *)

Lemma dec_is_imp : (A : MPropF), ( B C, A = Imp B C) + (( B C, A = Imp B C) False).
Proof.
destruct A.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- right. intro. destruct H. destruct s. inversion e.
- left. exists . exists . reflexivity.
- right. intro. destruct H. destruct s. inversion e.
Qed.


Lemma dec_imp_in : (l : list MPropF), ( A B, In (Imp A B) l) + (( A B, In (Imp A B) l) False).
Proof.
induction l.
- right. intro. destruct H. destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . apply in_cons. assumption.
  * destruct (dec_is_imp a).
    + repeat destruct s. subst. left. exists x. exists . apply in_eq.
    + right. intro. destruct H. destruct s. inversion i.
      { subst. apply . exists x. exists . reflexivity. }
      { apply f. exists x. exists . assumption. }
Qed.


Lemma dec_ImpR_rule : (concl : Seq),
          ( prem, ImpRRule [prem] concl) + (( prem, ImpRRule [prem] concl) False).
Proof.
intros concl. destruct concl. destruct (dec_is_imp m).
- left. repeat destruct s. subst. exists ([] x :: l, ). apply ImpRRule_I.
- right. intro. destruct H. inversion i. subst. apply f. exists A. exists B. auto.
Qed.


Lemma dec_is_atomimp : (A : MPropF), ( P C, A = Imp # P C) + (( P C, A = Imp # P C) False).
Proof.
intro A. destruct (dec_is_imp A).
- destruct s. destruct s. subst. destruct (dec_is_atomicT x).
  + destruct i. destruct s. subst. left. exists . exists . auto. right. subst. intro. destruct H. destruct s. inversion e.
  + right. intro. destruct H. destruct s. inversion e. apply f. subst. left. exists . auto.
- right. intro. firstorder.
Qed.


Lemma dec_atomimp_in : (l : list MPropF) P, ( B, In (Imp # P B) l) + (( B, In (Imp # P B) l) False).
Proof.
induction l.
- right. intro. destruct H. inversion i.
- intro. destruct (IHl P).
  * repeat destruct s. left. exists x. apply in_cons. assumption.
  * destruct (dec_is_atomimp a).
    + repeat destruct s. subst. destruct (eq_dec_form (# P) (# x)). left. exists . rewrite e. apply in_eq.
       right. intro. destruct H. inversion i. inversion H ; auto. subst. apply f. exists . auto.
    + right. intro. destruct H. inversion i.
      { subst. apply . exists P. exists x. reflexivity. }
      { apply f. exists x. assumption. }
Qed.


Lemma dec_atom_atomimp1_in : (l : list MPropF), ( P B l0 l1, (In (# P) ) * (In (Imp # P B) ) * (l = )) +
                  (( P B l0 l1, (In (# P) ) * (In (Imp # P B) ) * (l = )) False).
Proof.
induction l.
- right. intro. destruct H. destruct s. destruct s. destruct s. destruct p. destruct p. assert ( = []). symmetry in e. apply app_eq_nil in e.
  destruct e. auto. subst. inversion i.
- destruct IHl.
  * repeat destruct s. repeat destruct p. subst. left. exists x. exists . exists (a :: ). exists . repeat split ; auto. apply in_cons. assumption.
  * destruct (dec_is_atomicT a).
    + destruct i.
      { destruct s. subst. destruct (dec_atomimp_in l x).
         - destruct s. left. exists x. exists . exists [# x]. exists l. repeat split ; auto. apply in_eq.
         - right. intro. destruct H. repeat destruct s. repeat destruct p. subst. destruct . simpl in e. subst. inversion i. inversion e.
           subst. inversion i. rewrite H in . apply . exists . apply in_or_app. auto. apply f. exists . exists . exists . exists .
           repeat split ; auto. }
      { subst. right. intro. destruct H. apply f. repeat destruct s. repeat destruct p. destruct . simpl in e. inversion i.
        inversion e. subst. exists x. exists . exists . exists . repeat split ; auto. inversion i ; auto. inversion H. }
    + right. intro. destruct H. repeat destruct s. repeat destruct p. apply f. exists x. exists . destruct . inversion i. inversion e. subst.
       exists . exists . repeat split ; auto. inversion i ; auto. subst. exfalso. apply . left. exists x. auto.
Qed.


Lemma dec_AtomImpL1_rule : (concl : Seq),
          ( prem, AtomImpL1Rule [prem] concl) + (( prem, AtomImpL1Rule [prem] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_atom_atomimp1_in l).
- repeat destruct s. repeat destruct p. subst. apply in_splitT in i. destruct i. destruct s. subst.
  apply in_splitT in . destruct . destruct s. subst. repeat rewrite app_assoc. simpl. left.
  exists ( # x :: ( ) :: , m).
  assert (( # x :: (Imp (# x) ) :: , m) = ( # x :: ( ) Imp # x :: , m)).
  repeat rewrite app_assoc. auto. rewrite H. apply AtomImpL1Rule_I.
- right. intro. destruct H. inversion a. subst. apply f. exists P. exists A. exists (Γ0 # P :: Γ1).
  exists (Imp # P A :: Γ2). repeat split. apply in_or_app. right. apply in_eq. apply in_eq. repeat rewrite app_assoc. auto.
Qed.


Lemma dec_atom_atomimp2_in : (l : list MPropF), ( P B l0 l1, (In (# P) ) * (In (Imp # P B) ) * (l = )) +
                  (( P B l0 l1, (In (# P) ) * (In (Imp # P B) ) * (l = )) False).
Proof.
induction l.
- right. intro. destruct H. destruct s. destruct s. destruct s. destruct p. destruct p. assert ( = []). symmetry in e. apply app_eq_nil in e.
  destruct e. auto. subst. inversion .
- destruct IHl.
  * repeat destruct s. repeat destruct p. subst. left. exists x. exists . exists (a :: ). exists . repeat split ; auto. apply in_cons. assumption.
  * destruct (dec_is_atomimp a).
    + destruct s. destruct s. subst. destruct (In_dec l (# x)).
       { left. exists x. exists . exists [# x ]. exists l. repeat split ; auto. apply in_eq. }
       { right. intro. destruct H. repeat destruct s. repeat destruct p. subst. destruct . simpl in e. subst. inversion . inversion e.
         subst. inversion . inversion H. subst. apply . apply in_or_app ; auto. apply f. exists . exists . exists . exists .
         repeat split ; auto. }
    + right. intro. destruct H. repeat destruct s. repeat destruct p. apply f. exists x. exists . destruct . inversion . inversion e. subst.
       exists . exists . repeat split ; auto. inversion ; auto. subst. exfalso. apply . exists x. exists . auto.
Qed.


Lemma dec_AtomImpL2_rule : (concl : Seq),
          ( prem, AtomImpL2Rule [prem] concl) + (( prem, AtomImpL2Rule [prem] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_atom_atomimp2_in l).
- repeat destruct s. repeat destruct p. subst. apply in_splitT in i. destruct i. destruct s. subst.
  apply in_splitT in . destruct . destruct s. subst. repeat rewrite app_assoc. simpl. left.
  exists ( :: ( ) # x :: , m).
  assert ( # x :: # x :: = # x :: ( ) # x :: ).
  repeat rewrite app_assoc. auto. rewrite H. apply AtomImpL2Rule_I.
- right. intro. destruct H. inversion a. subst. apply f. exists P. exists A. exists (Γ0 # P A :: Γ1).
  exists (# P :: Γ2). repeat split. apply in_eq. apply in_or_app. right. apply in_eq. repeat rewrite app_assoc. auto.
Qed.


Lemma dec_is_andimp : (A : MPropF), ( B C D, A = Imp (And B C) D) + (( B C D, A = Imp (And B C) D) False).
Proof.
intro A. destruct (dec_is_imp A).
- destruct s. destruct s. subst. destruct (dec_is_and x).
  + repeat destruct s. subst. left. exists . exists . exists . auto.
  + right. intro. destruct H. repeat destruct s. inversion e. apply f. subst. exists . exists . auto.
- right. intro. firstorder.
Qed.


Lemma dec_andimp_in : (l : list MPropF), ( A B C, In (Imp (And A B) C) l) + (( A B C, In (Imp (And A B) C) l) False).
Proof.
induction l.
- right. intro. destruct H. repeat destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . exists . apply in_cons. assumption.
  * destruct (dec_is_andimp a).
    + repeat destruct s. subst. left. exists x. exists . exists . apply in_eq.
    + right. intro. destruct H. repeat destruct s. inversion i.
      { subst. apply . exists x. exists . exists . reflexivity. }
      { apply f. exists x. exists . exists . assumption. }
Qed.


Lemma dec_AndImpL_rule : (concl : Seq),
          ( prem, AndImpLRule [prem] concl) + (( prem, AndImpLRule [prem] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_andimp_in l).
- left. repeat destruct s. apply in_splitT in i. destruct i. destruct s. subst.
  exists ( Imp x (Imp ) :: , m). apply AndImpLRule_I.
- right. intro. destruct H. inversion a. subst. apply f. exists A. exists B. exists C.
  apply in_or_app. right. apply in_eq.
Qed.


Lemma dec_is_orimp : (A : MPropF), ( B C D, A = Imp (Or B C) D) + (( B C D, A = Imp (Or B C) D) False).
Proof.
intro A. destruct (dec_is_imp A).
- destruct s. destruct s. subst. destruct (dec_is_or x).
  + repeat destruct s. subst. left. exists . exists . exists . auto.
  + right. intro. destruct H. repeat destruct s. inversion e. apply f. subst. exists . exists . auto.
- right. intro. firstorder.
Qed.


Lemma dec_orimp_in : (l : list MPropF), ( A B C, In (Imp (Or A B) C) l) + (( A B C, In (Imp (Or A B) C) l) False).
Proof.
induction l.
- right. intro. destruct H. repeat destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . exists . apply in_cons. assumption.
  * destruct (dec_is_orimp a).
    + repeat destruct s. subst. left. exists x. exists . exists . apply in_eq.
    + right. intro. destruct H. repeat destruct s. inversion i.
      { subst. apply . exists x. exists . exists . reflexivity. }
      { apply f. exists x. exists . exists . assumption. }
Qed.


Lemma dec_OrImpL_rule : (concl : Seq),
          ( prem, OrImpLRule [prem] concl) + (( prem, OrImpLRule [prem] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_orimp_in l).
- left. repeat destruct s. apply in_splitT in i. destruct i. destruct s. subst.
  exists ( (Imp x ) :: [] Imp :: , m). apply OrImpLRule_I.
- right. intro. destruct H. inversion o. subst. apply f. exists A. exists B. exists C.
  apply in_or_app. right. apply in_eq.
Qed.


Lemma dec_is_impimp : (A : MPropF), ( B C D, A = Imp (Imp B C) D) + (( B C D, A = Imp (Imp B C) D) False).
Proof.
intro A. destruct (dec_is_imp A).
- destruct s. destruct s. subst. destruct (dec_is_imp x).
  + repeat destruct s. subst. left. exists . exists . exists . auto.
  + right. intro. destruct H. repeat destruct s. inversion e. apply f. subst. exists . exists . auto.
- right. intro. firstorder.
Qed.


Lemma dec_impimp_in : (l : list MPropF), ( A B C, In (Imp (Imp A B) C) l) + (( A B C, In (Imp (Imp A B) C) l) False).
Proof.
induction l.
- right. intro. destruct H. repeat destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . exists . apply in_cons. assumption.
  * destruct (dec_is_impimp a).
    + repeat destruct s. subst. left. exists x. exists . exists . apply in_eq.
    + right. intro. destruct H. repeat destruct s. inversion i.
      { subst. apply . exists x. exists . exists . reflexivity. }
      { apply f. exists x. exists . exists . assumption. }
Qed.


Lemma dec_ImpImpL_rule : (concl : Seq),
          ( prem1 prem2, ImpImpLRule [ ; ] concl) + (( prem1 prem2, ImpImpLRule [ ; ] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_impimp_in l).
- left. repeat destruct s. apply in_splitT in i. destruct i. destruct s. subst.
  exists ( Imp :: , Imp x ). exists ( :: , m). apply ImpImpLRule_I.
- right. intro. destruct H. destruct s. inversion i. subst. apply f. exists A. exists B. exists C.
  apply in_or_app. right. apply in_eq.
Qed.


Lemma dec_is_boximp : (A : MPropF), ( B C, A = Imp (Box B) C) + (( B C, A = Imp (Box B)C) False).
Proof.
intro A. destruct (dec_is_imp A).
- destruct s. destruct s. subst. destruct (dec_is_box x).
  + repeat destruct s. subst. left. exists . exists . auto.
  + right. intro. destruct H. repeat destruct s. inversion e. apply f. subst. exists . auto.
- right. intro. firstorder.
Qed.


Lemma dec_boximp_in : (l : list MPropF), ( A B, In (Imp (Box A) B) l) + (( A B, In (Imp (Box A) B) l) False).
Proof.
induction l.
- right. intro. destruct H. repeat destruct s. inversion i.
- destruct IHl.
  * repeat destruct s. left. exists x. exists . apply in_cons. assumption.
  * destruct (dec_is_boximp a).
    + repeat destruct s. subst. left. exists x. exists . apply in_eq.
    + right. intro. destruct H. repeat destruct s. inversion i.
      { subst. apply . exists x. exists . reflexivity. }
      { apply f. exists x. exists . assumption. }
Qed.


Lemma dec_BoxImpL_rule : (concl : Seq),
          ( prem1 prem2, BoxImpLRule [ ; ] concl) + (( prem1 prem2, BoxImpLRule [ ; ] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_boximp_in l).
- left. repeat destruct s. apply in_splitT in i. destruct i. destruct s. subst.
  exists (pair (unBoxed_list :: unBoxed_list [Box x]) x). exists (( :: ), m). apply BoxImpLRule_I.
- right. intro. destruct H. destruct s. inversion b. subst. apply f. exists A. exists B.
  apply in_or_app. right. apply in_eq.
Qed.


Lemma dec_box_in_list : l, ( (A : MPropF), In (Box A) l) +
                             (( (A : MPropF), In (Box A) l) False).
Proof.
induction l.
- simpl. right. intro. destruct H. assumption.
- destruct (dec_is_box a).
  * destruct s. subst. left. exists x. apply in_eq.
  * destruct IHl.
    + left. destruct s. exists x. apply in_cons. assumption.
    + right. intro. destruct H. inversion i. subst. apply f. exists x. reflexivity. apply .
      exists x. assumption.
Qed.


Lemma dec_SLR_rule : (concl : Seq),
          ( prem, SLRRule [prem] concl) + (( prem, SLRRule [prem] concl) False).
Proof.
intro concl. destruct concl. destruct (dec_is_box m).
- left. destruct s. subst. exists (unBoxed_list l [Box x], x).
  apply SLRRule_I.
- right. intro. destruct H. inversion s. subst. apply f. exists A. auto.
Qed.


Lemma dec_G4iSLT_rules : (concl : Seq),
          (( prems, G4iSLT_rules prems concl) False) + ( prems, G4iSLT_rules prems concl).
Proof.
intro concl. destruct (dec_G4iSLT_init_rules concl).
- right. repeat destruct s.
  * exists nil. apply IdP. assumption.
  * exists nil. apply BotL. assumption.
- destruct (dec_ImpR_rule concl).
  * right. destruct s. exists [x]. apply ImpR. assumption.
  * destruct (dec_AtomImpL1_rule concl).
    + right. repeat destruct s. exists [x]. apply AtomImpL1. assumption.
    + destruct (dec_SLR_rule concl).
      { right. destruct s. exists [x]. apply SLR. assumption. }
      { destruct (dec_AndImpL_rule concl).
        - right. repeat destruct s. exists [x]. apply AndImpL. assumption.
        - destruct (dec_OrImpL_rule concl).
          + right. repeat destruct s. exists [x]. apply OrImpL. assumption.
          + destruct (dec_ImpImpL_rule concl).
            * right. repeat destruct s. exists [x;]. apply ImpImpL. assumption.
            * destruct (dec_BoxImpL_rule concl).
              { right. repeat destruct s. exists [x;]. apply BoxImpL. assumption. }
              { destruct (dec_AndR_rule concl).
                - right. repeat destruct s. exists [x; ]. apply AndR. assumption.
                - destruct (dec_AndL_rule concl).
                  + right. repeat destruct s. exists [x]. apply AndL. assumption.
                  + destruct (dec_OrR1_rule concl).
                    * right. repeat destruct s. exists [x]. apply OrR1. assumption.
                    * destruct (dec_OrR2_rule concl).
                      { right. repeat destruct s. exists [x]. apply OrR2. assumption. }
                      { destruct (dec_OrL_rule concl).
                        - right. repeat destruct s. exists [x;]. apply OrL. assumption.
                        - destruct (dec_AtomImpL2_rule concl).
                            + right. repeat destruct s. exists [x]. apply AtomImpL2. assumption.
                            + left. intro. destruct H. inversion g.
                              * inversion H. subst. apply f. auto.
                              * inversion H. subst. apply f. auto.
                              * inversion H. subst. apply . exists (Γ,A). exists (Γ, B). assumption.
                              * inversion H. subst. apply . exists (Γ0 A :: B :: Γ1, C). assumption.
                              * inversion H. subst. apply . exists (Γ, A). assumption.
                              * inversion H. subst. apply . exists (Γ, B). assumption.
                              * inversion H. subst. apply . exists (Γ0 A :: Γ1, C). exists (Γ0 B :: Γ1, C). assumption.
                              * inversion H. subst. apply . exists (Γ0 A :: Γ1, B). assumption.
                              * inversion H. subst. apply . exists (Γ0 # P :: Γ1 A :: Γ2, C). assumption.
                              * inversion H. subst. apply . exists (Γ0 A :: Γ1 # P :: Γ2, C). assumption.
                              * inversion H. subst. apply . exists (Γ0 Imp A (Imp B C) :: Γ1, D). assumption.
                              * inversion H. subst. apply . exists (Γ0 Imp A C :: Γ1 Imp B C :: Γ2, D). assumption.
                              * inversion H. subst. apply . exists (Γ0 Imp B C :: Γ1, Imp A B). exists (Γ0 C :: Γ1, D). assumption.
                              * inversion H. subst. apply . exists (unBoxed_list Γ0 B :: unBoxed_list Γ1 [Box A], A). exists (Γ0 B :: Γ1, C). assumption.
                              * inversion H. subst. apply . exists (unBoxed_list Γ [Box A], A). assumption. } } }
Qed.