theory flash imports flashMainLemma
begin

lemma main:
  assumes   a1:"s \<in> reachableSet {andList (allIniSpecs   N)} (rules N)"  and a2:"0<N"

  shows "\<forall>invf. invf \<in>(invariants N)\<longrightarrow>formEval invf s"
proof(rule newconsistentLemma)
  show "newconsistent (invariants N) {andList (allIniSpecs   N)}(rules N)"
  proof(cut_tac a1, unfold newconsistent_def,rule conjI)
    show " \<forall>invf ini s. invf \<in>(invariants N)\<longrightarrow> ini \<in>{andList (allIniSpecs   N)}\<longrightarrow> formEval ini s\<longrightarrow> formEval invf s"
    proof((rule allI)+,(rule impI)+)
      fix invf ini s
      assume b1:"invf \<in>(invariants N) " and b2:"ini \<in> {andList (allIniSpecs   N)} " and b3:"formEval ini s"

      have b4:"formEval (andList (allIniSpecs   N)) s"
         by(cut_tac b2 b3,simp)

      show "formEval invf s"
      proof -

        have c1:" ex2P N (% iInv1  iInv2 .  invf= inv1  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv2  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv3  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv4  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv5  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv6  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv7  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv8  iInv1  iInv2 )  \<or> ex1P N (% iInv1 .  invf= inv9  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv10  iInv1 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv11  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv12 )  \<or> ex1P N (% iInv1 .  invf= inv13  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv14  iInv1 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv15  iInv1  iInv2  iInv3 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv16  iInv1  iInv2  iInv3 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv17  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv18  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv19  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv20  iInv1  iInv2 )  \<or> ex1P N (% iInv1 .  invf= inv21  iInv1 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv22  iInv1  iInv2  iInv3 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv23  iInv1  iInv2  iInv3 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv24  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv25  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv26  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv27  iInv1  iInv2 )  \<or> ex1P N (% iInv1 .  invf= inv28  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv29  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv30  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv31  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv32  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv33  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv34  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv35  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv36  iInv1 )  \<or> ex0P N  (  invf= inv37 )  \<or> ex0P N  (  invf= inv38 )  \<or> ex0P N  (  invf= inv39 )  \<or> ex1P N (% iInv1 .  invf= inv40  iInv1 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv41  iInv1  iInv2 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv42  iInv1  iInv2  iInv3 )  \<or> ex0P N  (  invf= inv43 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv44  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv45 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv46  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv47 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv48  iInv1  iInv2 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv49  iInv1  iInv2  iInv3 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv50  iInv1  iInv2 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv51  iInv1  iInv2  iInv3 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv52  iInv1  iInv2  iInv3 )  \<or> ex0P N  (  invf= inv53 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv54  iInv1  iInv2  iInv3 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv55  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv56  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv57  iInv1  iInv2 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv58  iInv1  iInv2  iInv3 )  \<or> ex3P N (% iInv1  iInv2  iInv3 .  invf= inv59  iInv1  iInv2  iInv3 )  \<or> ex1P N (% iInv1 .  invf= inv60  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv61  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv62  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv63  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv64  iInv1 )  \<or> ex1P N (% iInv1 .  invf= inv65  iInv1 )  \<or> ex0P N  (  invf= inv66 )  \<or> ex0P N  (  invf= inv67 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv68  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv69  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv70  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv71 )  \<or> ex0P N  (  invf= inv72 )  \<or> ex0P N  (  invf= inv73 )  \<or> ex0P N  (  invf= inv74 )  \<or> ex0P N  (  invf= inv75 )  \<or> ex0P N  (  invf= inv76 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv77  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv78 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv79  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv80 )  \<or> ex0P N  (  invf= inv81 )  \<or> ex1P N (% iInv1 .  invf= inv82  iInv1 )  \<or> ex0P N  (  invf= inv83 )  \<or> ex0P N  (  invf= inv84 )  \<or> ex0P N  (  invf= inv85 )  \<or> ex0P N  (  invf= inv86 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv87  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv88  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv89  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv90  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv91 )  \<or> ex0P N  (  invf= inv92 )  \<or> ex0P N  (  invf= inv93 )  \<or> ex0P N  (  invf= inv94 )  \<or> ex0P N  (  invf= inv95 )  \<or> ex0P N  (  invf= inv96 )  \<or> ex0P N  (  invf= inv97 )  \<or> ex0P N  (  invf= inv98 )  \<or> ex0P N  (  invf= inv99 )  \<or> ex0P N  (  invf= inv100 )  \<or> ex1P N (% iInv1 .  invf= inv101  iInv1 )  \<or> ex0P N  (  invf= inv102 )  \<or> ex0P N  (  invf= inv103 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv104  iInv1  iInv2 )  \<or> ex2P N (% iInv1  iInv2 .  invf= inv105  iInv1  iInv2 )  \<or> ex0P N  (  invf= inv106 )  \<or> ex0P N  (  invf= inv107 )  \<or> ex0P N  (  invf= inv108 )  \<or> ex0P N  (  invf= inv109 )  \<or> ex0P N  (  invf= inv110 )  \<or> ex0P N  (  invf= inv111 )  \<or> ex0P N  (  invf= inv112 )  \<or> ex0P N  (  invf= inv113 )   "
          by (cut_tac b1, simp )       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv1  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv1.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv2  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv2.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv3  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv3.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv4  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv4.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv5  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv5.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv6  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv6.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv7  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv7.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv8  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv8.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv9  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv9.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv10  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv10.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv11  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv11.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv12 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv12.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv13  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv13.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv14  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv14.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv15  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv15.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv16  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv16.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv17  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv17.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv18  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv18.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv19  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv19.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv20  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv20.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv21  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv21.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv22  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv22.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv23  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv23.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv24  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv24.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv25  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv25.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv26  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv26.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv27  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv27.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv28  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv28.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv29  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv29.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv30  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv30.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv31  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv31.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv32  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv32.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv33  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv33.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv34  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv34.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv35  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv35.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv36  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv36.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv37 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv37.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv38 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv38.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv39 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv39.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv40  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv40.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv41  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv41.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv42  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv42.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv43 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv43.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv44  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv44.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv45 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv45.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv46  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv46.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv47 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv47.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv48  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv48.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv49  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv49.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv50  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv50.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv51  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv51.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv52  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv52.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv53 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv53.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv54  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv54.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv55  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv55.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv56  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv56.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv57  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv57.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv58  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv58.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex3P N (% iInv1  iInv2  iInv3 .  invf= inv59  iInv1  iInv2  iInv3 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv59.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv60  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv60.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv61  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv61.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv62  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv62.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv63  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv63.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv64  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv64.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv65  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv65.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv66 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv66.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv67 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv67.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv68  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv68.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv69  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv69.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv70  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv70.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv71 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv71.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv72 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv72.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv73 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv73.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv74 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv74.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv75 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv75.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv76 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv76.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv77  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv77.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv78 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv78.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv79  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv79.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv80 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv80.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv81 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv81.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv82  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv82.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv83 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv83.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv84 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv84.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv85 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv85.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv86 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv86.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv87  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv87.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv88  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv88.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv89  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv89.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv90  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv90.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv91 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv91.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv92 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv92.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv93 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv93.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv94 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv94.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv95 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv95.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv96 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv96.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv97 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv97.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv98 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv98.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv99 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv99.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv100 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv100.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex1P N (% iInv1 .  invf= inv101  iInv1 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv101.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv102 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv102.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv103 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv103.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv104  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv104.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex2P N (% iInv1  iInv2 .  invf= inv105  iInv1  iInv2 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv105.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv106 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv106.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv107 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv107.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv108 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv108.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv109 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv109.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv110 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv110.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv111 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv111.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv112 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv112.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }
       moreover
        {assume d1: " ex0P N  (  invf= inv113 )  "

          have "formEval invf s"

            by(metis b4 d1 iniImply_inv113.iniImplyInv)
           (* apply(cut_tac d1,assumption)
           by (cut_tac  b4,simp)*)
        }

      ultimately show "formEval invf s"
      by blast
      qed
    qed
next
   show  "\<forall>invf r s. invf \<in> invariants N\<longrightarrow> r \<in>rules N\<longrightarrow> invHoldForRule' s invf r (invariants N) "

   proof((rule allI)+,(rule impI)+)
      fix invf r s
      assume b1:"invf \<in> invariants N" and b2:"r \<in> rules N"
      show "invHoldForRule' s invf r (invariants N) "
          by (metis mainLemma b1 b2)
     qed
qed
next
  show "s \<in> reachableSet {andList (allIniSpecs   N)}  (rules N)"
by (metis a1)

qed
end


section \<open>Operation Identification Phase\<close>
theory Sepref_Id_Op
imports
  Main
  Automatic_Refinement.Refine_Lib
  Automatic_Refinement.Autoref_Tagging
  Refine_Imperative_HOL.Named_Theorems_Rev
begin

text \<open>
  The operation identification phase is adapted from the Autoref tool.
  The basic idea is to have a type system, which works on so called
  interface types (also called conceptual types). Each conceptual type
  denotes an abstract data type, e.g., set, map, priority queue.

  Each abstract operation, which must be a constant applied to its arguments,
  is assigned a conceptual type. Additionally, there is a set of
  {\emph pattern rewrite rules},
  which are applied to subterms before type inference takes place, and
  which may be backtracked over.
  This way, encodings of abstract operations in Isabelle/HOL, like
  @{term [source] "\<lambda>_. None"} for the empty map,
  or @{term [source] "fun_upd m k (Some v)"} for map update, can be rewritten
  to abstract operations, and get properly typed.
\<close>

subsection "Proper Protection of Term"
text \<open> The following constants are meant to encode abstraction and
  application as proper HOL-constants, and thus avoid strange effects with
  HOL's higher-order unification heuristics and automatic
  beta and eta-contraction.

  The first step of operation identification is to protect the term
  by replacing all function applications and abstractions be
  the constants defined below.
\<close>

definition [simp]: "PROTECT2 x (y::prop) \<equiv> x"
consts DUMMY :: "prop"

abbreviation PROTECT2_syn ("'(#_#')") where "PROTECT2_syn t \<equiv> PROTECT2 t DUMMY"

abbreviation (input)ABS2 :: "('a\<Rightarrow>'b)\<Rightarrow>'a\<Rightarrow>'b" (binder "\<lambda>\<^sub>2" 10)
  where "ABS2 f \<equiv> (\<lambda>x. PROTECT2 (f x) DUMMY)"

lemma beta: "(\<lambda>\<^sub>2x. f x)$x \<equiv> f x" by simp

text \<open>
  Another version of @{const "APP"}. Treated like @{const APP} by our tool.
  Required to avoid infinite pattern rewriting in some cases, e.g., map-lookup.
\<close>

definition APP' (infixl "$''" 900) where [simp, autoref_tag_defs]: "f$'a \<equiv> f a"

text \<open>
  Sometimes, whole terms should be protected from being processed by our tool.
  For example, our tool should not look into numerals. For this reason,
  the \<open>PR_CONST\<close> tag indicates terms that our tool shall handle as
  atomic constants, an never look into them.

  The special form \<open>UNPROTECT\<close> can be used inside pattern rewrite rules.
  It has the effect to revert the protection from its argument, and then wrap
  it into a \<open>PR_CONST\<close>.
\<close>
definition [simp, autoref_tag_defs]: "PR_CONST x \<equiv> x" \<comment> \<open>Tag to protect constant\<close>
definition [simp, autoref_tag_defs]: "UNPROTECT x \<equiv> x" \<comment> \<open>Gets
  converted to @{term PR_CONST}, after unprotecting its content\<close>

subsection \<open>Operation Identification\<close>

text \<open> Indicator predicate for conceptual typing of a constant \<close>
definition intf_type :: "'a \<Rightarrow> 'b itself \<Rightarrow> bool" (infix "::\<^sub>i" 10) where
  [simp]: "c::\<^sub>iI \<equiv> True"

lemma itypeI: "c::\<^sub>iI" by simp
lemma itypeI': "intf_type c TYPE('T)" by (rule itypeI)

lemma itype_self: "(c::'a) ::\<^sub>i TYPE('a)" by simp

definition CTYPE_ANNOT :: "'b \<Rightarrow> 'a itself \<Rightarrow> 'b" (infix ":::\<^sub>i" 10) where
  [simp]: "c:::\<^sub>iI \<equiv> c"

text \<open> Wrapper predicate for an conceptual type inference \<close>
definition ID :: "'a \<Rightarrow> 'a \<Rightarrow> 'c itself \<Rightarrow> bool"
  where [simp]: "ID t t' T \<equiv> t=t'"

subsubsection \<open>Conceptual Typing Rules\<close>

lemma ID_unfold_vars: "ID x y T \<Longrightarrow> x\<equiv>y" by simp
lemma ID_PR_CONST_trigger: "ID (PR_CONST x) y T \<Longrightarrow> ID (PR_CONST x) y T" .

lemma pat_rule:
  "\<lbrakk> p\<equiv>p'; ID p' t' T \<rbrakk> \<Longrightarrow> ID p t' T" by simp

lemma app_rule:
  "\<lbrakk> ID f f' TYPE('a\<Rightarrow>'b); ID x x' TYPE('a)\<rbrakk> \<Longrightarrow> ID (f$x) (f'$x') TYPE('b)"
  by simp

lemma app'_rule:
  "\<lbrakk> ID f f' TYPE('a\<Rightarrow>'b); ID x x' TYPE('a)\<rbrakk> \<Longrightarrow> ID (f$'x) (f'$x') TYPE('b)"
  by simp

lemma abs_rule:
  "\<lbrakk> \<And>x x'. ID x x' TYPE('a) \<Longrightarrow> ID (t x) (t' x x') TYPE('b) \<rbrakk> \<Longrightarrow>
    ID (\<lambda>\<^sub>2x. t x) (\<lambda>\<^sub>2x'. t' x' x') TYPE('a\<Rightarrow>'b)"
  by simp

lemma id_rule: "c::\<^sub>iI \<Longrightarrow> ID c c I" by simp

lemma annot_rule: "ID t t' I \<Longrightarrow> ID (t:::\<^sub>iI) t' I"
  by simp

lemma fallback_rule:
  "ID (c::'a) c TYPE('c)"
  by simp

lemma unprotect_rl1: "ID (PR_CONST x) t T \<Longrightarrow> ID (UNPROTECT x) t T"
  by simp

subsection \<open> ML-Level code \<close>
ML \<open>
infix 0 THEN_ELSE_COMB'

signature ID_OP_TACTICAL = sig
  val SOLVE_FWD: tactic' -> tactic'
  val DF_SOLVE_FWD: bool -> tactic' -> tactic'
end

structure Id_Op_Tactical :ID_OP_TACTICAL = struct

  fun SOLVE_FWD tac i st = SOLVED' (
    tac
    THEN_ALL_NEW_FWD (SOLVE_FWD tac)) i st

  (* Search for solution with DFS-strategy. If dbg-flag is given,
    return sequence of stuck states if no solution is found.
  *)
  fun DF_SOLVE_FWD dbg tac = let
    val stuck_list_ref = Unsynchronized.ref []

    fun stuck_tac _ st = if dbg then (
      stuck_list_ref := st :: !stuck_list_ref;
      Seq.empty
    ) else Seq.empty

    fun rec_tac i st = (
        (tac THEN_ALL_NEW_FWD (SOLVED' rec_tac))
        ORELSE' stuck_tac
      ) i st

    fun fail_tac _ _ = if dbg then
      Seq.of_list (rev (!stuck_list_ref))
    else Seq.empty
  in
    rec_tac ORELSE' fail_tac
  end

end
\<close>

named_theorems_rev id_rules "Operation identification rules"
named_theorems_rev pat_rules "Operation pattern rules"
named_theorems_rev def_pat_rules "Definite operation pattern rules (not backtracked over)"

ML \<open>

  structure Id_Op = struct

    fun id_a_conv cnv ct = case Thm.term_of ct of
      @{mpat "ID _ _ _"} => Conv.fun_conv (Conv.fun_conv (Conv.arg_conv cnv)) ct
    | _ => raise CTERM("id_a_conv",[ct])

    fun
      protect env (@{mpat "?t:::\<^sub>i?I"}) = let
        val t = protect env t
      in
        @{mk_term env: "?t:::\<^sub>i?I"}
      end
    | protect _ (t as @{mpat "PR_CONST _"}) = t
    | protect env (t1$t2) = let
        val t1 = protect env t1
        val t2 = protect env t2
      in
        @{mk_term env: "?t1.0 $ ?t2.0"}
      end
    | protect env (Abs (x,T,t)) = let
        val t = protect (T::env) t
      in
        @{mk_term env: "\<lambda>v_x::?'v_T. PROTECT2 ?t DUMMY"}
      end
    | protect _ t = t

    fun protect_conv ctxt = Refine_Util.f_tac_conv ctxt
      (protect [])
      (simp_tac
        (put_simpset HOL_basic_ss ctxt addsimps @{thms PROTECT2_def APP_def}) 1)

    fun unprotect_conv ctxt
      = Simplifier.rewrite (put_simpset HOL_basic_ss ctxt
        addsimps @{thms PROTECT2_def APP_def})

    fun do_unprotect_tac ctxt =
      resolve_tac ctxt @{thms unprotect_rl1} THEN'
      CONVERSION (Refine_Util.HOL_concl_conv (fn ctxt => id_a_conv (unprotect_conv ctxt)) ctxt)

    val cfg_id_debug =
      Attrib.setup_config_bool @{binding id_debug} (K false)

    val cfg_id_trace_fallback =
      Attrib.setup_config_bool @{binding id_trace_fallback} (K false)

    fun dest_id_rl thm = case Thm.concl_of thm of
      @{mpat (typs) "Trueprop (?c::\<^sub>iTYPE(?'v_T))"} => (c,T)
    | _ => raise THM("dest_id_rl",~1,[thm])

    val add_id_rule = snd oo Thm.proof_attributes [Named_Theorems_Rev.add @{named_theorems_rev id_rules}]

    datatype id_tac_mode = Init | Step | Normal | Solve

    fun id_tac ss ctxt = let
      open Id_Op_Tactical
      val certT = Thm.ctyp_of ctxt
      val cert = Thm.cterm_of ctxt

      val thy = Proof_Context.theory_of ctxt

      val id_rules = Named_Theorems_Rev.get ctxt @{named_theorems_rev id_rules}
      val pat_rules = Named_Theorems_Rev.get ctxt @{named_theorems_rev pat_rules}
      val def_pat_rules = Named_Theorems_Rev.get ctxt @{named_theorems_rev def_pat_rules}

      val rl_net = Tactic.build_net (
        (pat_rules |> map (fn thm => thm RS @{thm pat_rule}))
        @ @{thms annot_rule app_rule app'_rule abs_rule}
        @ (id_rules |> map (fn thm => thm RS @{thm id_rule}))
      )

      val def_rl_net = Tactic.build_net (
        (def_pat_rules |> map (fn thm => thm RS @{thm pat_rule}))
      )

      val id_pr_const_rename_tac =
          resolve_tac ctxt @{thms ID_PR_CONST_trigger} THEN'
          Subgoal.FOCUS (fn { context=ctxt, prems, ... } =>
            let
              fun is_ID @{mpat "Trueprop (ID _ _ _)"} = true | is_ID _ = false
              val prems = filter (Thm.prop_of #> is_ID) prems
              val eqs = map (fn thm => thm RS @{thm ID_unfold_vars}) prems
              val conv = Conv.rewrs_conv eqs
              val conv = fn ctxt => (Conv.top_sweep_conv (K conv) ctxt)
              val conv = fn ctxt => Conv.fun2_conv (Conv.arg_conv (conv ctxt))
              val conv = Refine_Util.HOL_concl_conv conv ctxt
            in CONVERSION conv 1 end
          ) ctxt THEN'
          resolve_tac ctxt @{thms id_rule} THEN'
          resolve_tac ctxt id_rules

      val ityping = id_rules
        |> map dest_id_rl
        |> filter (is_Const o #1)
        |> map (apfst (#1 o dest_Const))
        |> Symtab.make_list

      val has_type = Symtab.defined ityping

      fun mk_fallback name cT =
        case try (Sign.the_const_constraint thy) name of
          SOME T => try (Thm.instantiate'
                          [SOME (certT cT), SOME (certT T)] [SOME (cert (Const (name,cT)))])
                        @{thm fallback_rule}
        | NONE => NONE

      fun trace_fallback thm =
        Config.get ctxt cfg_id_trace_fallback
        andalso let
          open Pretty
          val p = block [str "ID_OP: Applying fallback rule: ", Thm.pretty_thm ctxt thm]
        in
          string_of p |> tracing;
          false
        end

      val fallback_tac = CONVERSION Thm.eta_conversion THEN' IF_EXGOAL (fn i => fn st =>
        case Logic.concl_of_goal (Thm.prop_of st) i of
          @{mpat "Trueprop (ID (mpaq_STRUCT (mpaq_Const ?name ?cT)) _ _)"} => (
            if not (has_type name) then
              case mk_fallback name cT of
                SOME thm => (trace_fallback thm; resolve_tac ctxt [thm] i st)
              | NONE => Seq.empty
            else Seq.empty
          )
        | _ => Seq.empty)

      val init_tac = CONVERSION (
        Refine_Util.HOL_concl_conv (fn ctxt => (id_a_conv (protect_conv ctxt)))
          ctxt
      )

      val step_tac = (FIRST' [
        assume_tac ctxt,
        eresolve_tac ctxt @{thms id_rule},
        resolve_from_net_tac ctxt def_rl_net,
        resolve_from_net_tac ctxt rl_net,
        id_pr_const_rename_tac,
        do_unprotect_tac ctxt,
        fallback_tac])

      val solve_tac = DF_SOLVE_FWD (Config.get ctxt cfg_id_debug) step_tac

    in
      case ss of
        Init => init_tac
      | Step => step_tac
      | Normal => init_tac THEN' solve_tac
      | Solve => solve_tac

    end

  end

\<close>

subsection \<open>Default Setup\<close>

subsubsection \<open>Numerals\<close>
lemma pat_numeral[def_pat_rules]: "numeral$x \<equiv> UNPROTECT (numeral$x)" by simp

lemma id_nat_const[id_rules]: "(PR_CONST (a::nat)) ::\<^sub>i TYPE(nat)" by simp
lemma id_int_const[id_rules]: "(PR_CONST (a::int)) ::\<^sub>i TYPE(int)" by simp

(*subsection \<open>Example\<close>
schematic_lemma
  "ID (\<lambda>a b. (b(1::int\<mapsto>2::nat) |`(-{3})) a, Map.empty, \<lambda>a. case a of None \<Rightarrow> Some a | Some _ \<Rightarrow> None) (?c) (?T::?'d itself)"
  (*"TERM (?c,?T)"*)
  using [[id_debug]]
  apply (tactic {* Id_Op.id_tac Id_Op.Normal @{context} 1  *})
  done
*)

end


           (*-------------------------------------------*
            |        CSP-Prover on Isabelle2004         |
            |               November 2004               |
            |                   July 2005  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2005         |
            |                October 2005  (modified)   |
            |                  April 2006  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2009         |
            |                   June 2009  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2016         |
            |                    May 2016  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory Trace_par
imports Prefix
begin

(*  The following simplification rules are deleted in this theory file *)
(*  because they unexpectly rewrite (notick | t = <>)                  *)
(*                                                                     *)
(*                  disj_not1: (~ P | Q) = (P --> Q)                   *)

declare disj_not1 [simp del]

(*****************************************************************

         1. s |[X]|list t  : lists  --> list set
         2. s |[X]|tr t   : traces --> trace set
         3.
         4.

 *****************************************************************)

(* Isabelle 2005
consts
  parx :: "'a set => ('a trace * 'a trace * 'a trace) set"

inductive "parx X"
intros
parx_nil_nil:
  "(<>, <>, <>) : parx X"

parx_Tick_Tick:
  "(<Tick>, <Tick>, <Tick>) : parx X"

parx_Ev_nil:
  "[| (u, s, <>) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, <Ev a> ^^^ s, <>) : parx X"

parx_nil_Ev:
  "[| (u, <>, t) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, <>, <Ev a> ^^^ t) : parx X"

parx_Ev_sync:
  "[| (u, s, t) : parx X ; a : X |]
   ==> (<Ev a> ^^^ u, <Ev a> ^^^ s, <Ev a> ^^^ t) : parx X"

parx_Ev_left:
  "[| (u, s, t) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, <Ev a> ^^^ s, t) : parx X"

parx_Ev_right:
  "[| (u, s, t) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, s, <Ev a> ^^^ t) : parx X"
*)

inductive_set
  parx :: "'a set => ('a trace * 'a trace * 'a trace) set"
  for X :: "'a set"

where
parx_nil_nil:
  "(<>, <>, <>) : parx X" |

parx_Tick_Tick:
  "(<Tick>, <Tick>, <Tick>) : parx X" |

parx_Ev_nil:
  "[| (u, s, <>) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, <Ev a> ^^^ s, <>) : parx X" |

parx_nil_Ev:
  "[| (u, <>, t) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, <>, <Ev a> ^^^ t) : parx X" |

parx_Ev_sync:
  "[| (u, s, t) : parx X ; a : X |]
   ==> (<Ev a> ^^^ u, <Ev a> ^^^ s, <Ev a> ^^^ t) : parx X" |

parx_Ev_left:
  "[| (u, s, t) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, <Ev a> ^^^ s, t) : parx X" |

parx_Ev_right:
  "[| (u, s, t) : parx X ; a ~: X |]
   ==> (<Ev a> ^^^ u, s, <Ev a> ^^^ t) : parx X"

definition
  par_tr :: "'a trace => 'a set => 'a trace => 'a trace set"
                                        ("(_ |[_]|tr _)" [76,0,77] 76)
 where
  par_tr_def : "s |[X]|tr t == {u. (u, s, t) : parx X}"

lemma par_tr_defE: "[| u : s |[X]|tr t ; (u, s, t) : parx X ==> R |] ==> R"
by (simp add: par_tr_def)

(*************************************************************
                 par_tr intros and elims
 *************************************************************)

(*-------------------*
 |      intros       |
 *-------------------*)

lemma par_tr_nil_nil:
  "<> : <> |[X]|tr <>"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

lemma par_tr_Tick_Tick:
  "<Tick> : <Tick> |[X]|tr <Tick>"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

lemma par_tr_Ev_nil:
  "[| u : s |[X]|tr <> ; a ~: X |]
   ==> <Ev a> ^^^ u : (<Ev a> ^^^ s) |[X]|tr <>"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

lemma par_tr_nil_Ev:
  "[| u : <> |[X]|tr t ; a ~: X |]
   ==> <Ev a> ^^^ u : <> |[X]|tr (<Ev a> ^^^ t)"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

lemma par_tr_Ev_sync:
  "[| u : s |[X]|tr t ; a : X |]
   ==> <Ev a> ^^^ u : (<Ev a> ^^^ s) |[X]|tr (<Ev a> ^^^ t)"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

lemma par_tr_Ev_left:
  "[| u : s |[X]|tr t ; a ~: X |]
   ==> <Ev a> ^^^ u : (<Ev a> ^^^ s) |[X]|tr t"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

lemma par_tr_Ev_right:
  "[| u : s |[X]|tr t ; a ~: X |]
   ==> <Ev a> ^^^ u : s |[X]|tr (<Ev a> ^^^ t)"
apply (simp add: par_tr_def)
by (simp add: parx.intros)

(*** intro rule ***)

lemmas par_tr_intros =
       par_tr_nil_nil
       par_tr_Tick_Tick
       par_tr_Ev_nil
       par_tr_nil_Ev
       par_tr_Ev_sync
       par_tr_Ev_left
       par_tr_Ev_right

(*-------------------*
 |       elims       |
 *-------------------*)

lemma par_tr_elims_lm:
 "[| u : s |[X]|tr t ;
     (u = <> & s = <> & t = <>) --> P ;
     (u = <Tick> & s = <Tick> & t = <Tick>) --> P ;
     ALL a s' u'.
        (u = <Ev a> ^^^ u' & s = <Ev a> ^^^ s' & t = <> &
           u' : s' |[X]|tr <> & a ~: X)
        --> P;
     ALL a t' u'.
        (u = <Ev a> ^^^ u' & s = <> & t = <Ev a> ^^^ t' &
           u' : <> |[X]|tr t' & a ~: X)
        --> P;
     ALL a s' t' u'.
        (u = <Ev a> ^^^ u' & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t' &
           u' : s' |[X]|tr t' & a : X)
        --> P;
     ALL a s' u'.
        (u = <Ev a> ^^^ u' & s = <Ev a> ^^^ s' &
           u' : s' |[X]|tr t & a ~: X)
        --> P;
     ALL a t' u'.
        (u = <Ev a> ^^^ u' & t = <Ev a> ^^^ t' &
           u' : s |[X]|tr t' & a ~: X)
        --> P |]
  ==> P"
apply (simp add: par_tr_def)
apply (erule parx.cases)      (* .elims --> .cases *)
apply (simp_all)
done

(*** elim rule ***)

lemma par_tr_elims:
 "[| u : s |[X]|tr t ;
     [| u = <>; s = <>; t = <> |] ==> P ;
     [| u = <Tick>; s = <Tick>; t = <Tick> |] ==> P ;
     !!a s' u'.
        [| u = <Ev a> ^^^ u'; s = <Ev a> ^^^ s'; t = <> ;
           u' : s' |[X]|tr <>; a ~: X |]
        ==> P;
     !!a t' u'.
        [| u = <Ev a> ^^^ u' ; s = <> ; t = <Ev a> ^^^ t' ;
           u' : <> |[X]|tr t'; a ~: X |]
        ==> P;
     !!a s' t' u'.
        [| u = <Ev a> ^^^ u' ; s = <Ev a> ^^^ s' ; t = <Ev a> ^^^ t' ;
           u' : s' |[X]|tr t'; a : X |]
        ==> P;
     !!a s' u'.
        [| u = <Ev a> ^^^ u' ; s = <Ev a> ^^^ s' ;
           u' : s' |[X]|tr t; a ~: X |]
        ==> P;
     !!a t' u'.
        [| u = <Ev a> ^^^ u' ; t = <Ev a> ^^^ t' ;
           u' : s |[X]|tr t'; a ~: X |]
        ==> P |]
  ==> P"
apply (rule par_tr_elims_lm[of u s X t])
apply (simp_all)
(* for Isabelle 2013
apply (fast)
apply (fast)
apply (fast)    (* this takes 1 min *)
apply (fast)    (* this takes 1 min *)
apply (fast)    (* this takes 1 min *)
*)
done

(*************************************************************
                 par_tr decomposition
 *************************************************************)

(*-------------------*
 |     par nil       |
 *-------------------*)

(*** par_tr ***)

lemma par_tr_nil_only_if:
  "<> : s |[X]|tr t ==> s = <> & t = <>"
apply (erule par_tr_elims)
by (simp_all)

(*** iff ***)

lemma par_tr_nil1[simp]:
  "(<> : s |[X]|tr t) = (s = <> & t = <>)"
apply (rule iffI)
apply (simp add: par_tr_nil_only_if)
by (simp add: par_tr_intros)

lemma par_tr_nil2[simp]:
  "(u : <> |[X]|tr <>) = (u = <>)"
apply (rule iffI)
apply (erule par_tr_elims)
by (simp_all)

(*-------------------*
 |     par Tick      |
 *-------------------*)

(*** only if ***)

lemma par_tr_Tick_only_if:
  "<Tick> : s |[X]|tr t ==> s = <Tick> & t = <Tick>"
apply (erule par_tr_elims)
by (simp_all)

(*** iff ***)

lemma par_tr_Tick1[simp]:
  "<Tick> : s |[X]|tr t = (s = <Tick> & t = <Tick>)"
apply (rule iffI)
apply (simp add: par_tr_Tick_only_if)
by (simp add: par_tr_intros)

lemma par_tr_Tick2[simp]:
  "(u : <Tick> |[X]|tr <Tick>) = (u = <Tick>)"
apply (rule iffI)
apply (erule par_tr_elims)
by (simp_all)

(*-----------------*
 |     par Ev      |
 *-----------------*)

(*** only if ***)

lemma par_tr_Ev_only_if:
 "<Ev a> : s |[X]|tr t
   ==> ((a  : X & s = <Ev a> & t = <Ev a>) |
        (a ~: X & s = <Ev a> & t = <>) |
        (a ~: X & s = <>     & t = <Ev a> ))"
apply (erule par_tr_elims)
by (simp_all)

(*** if ***)

lemma par_tr_Ev_if:
 "((a  : X & s = <Ev a> & t = <Ev a>) |
   (a ~: X & s = <Ev a> & t = <>) |
   (a ~: X & s = <>     & t = <Ev a> ))
   ==> <Ev a> : s |[X]|tr t"
apply (erule disjE)
apply (insert par_tr_Ev_sync[of "<>" "<>" X "<>" a], simp)
apply (erule disjE)
apply (insert par_tr_Ev_left[of "<>" "<>" X "<>" a], simp)
apply (insert par_tr_Ev_right[of "<>" "<>" X "<>" a], simp)
done

lemma par_tr_Ev:
 "<Ev a> : s |[X]|tr t
   = ((a  : X & s = <Ev a> & t = <Ev a>) |
      (a ~: X & s = <Ev a> & t = <>) |
      (a ~: X & s = <>     & t = <Ev a> ))"
apply (rule iffI)
apply (simp add: par_tr_Ev_only_if)
apply (simp add: par_tr_Ev_if)
done

(*--------------------------------------------*
 |                 par one                    |
 *--------------------------------------------*)

lemma par_tr_one:
 "<e> : s |[X]|tr t
   = ((e = Tick & s = <Tick> & t = <Tick>) |
     (EX a. e = Ev a &
       ((a  : X & s = <Ev a> & t = <Ev a>) |
        (a ~: X & s = <Ev a> & t = <>) |
        (a ~: X & s = <>     & t = <Ev a> ))))"
apply (insert event_Tick_or_Ev)
apply (drule_tac x="e" in spec)
apply (erule disjE)
apply (simp)

apply (erule exE)
apply (simp add: par_tr_Ev)
done

(*--------------------------------------------*
 |                par head                    |
 *--------------------------------------------*)

(*** only if ***)

lemma par_tr_head_only_if:
 "<Ev a> ^^^ u : s |[X]|tr t
   ==> (a  : X & (EX s' t'. u : s' |[X]|tr t'
               & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
       (a ~: X & (EX s'.    u : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
       (a ~: X & (EX t'.    u : s |[X]|tr t' & t = <Ev a> ^^^ t'))"
apply (erule par_tr_elims)
by (simp_all)

(*** if ***)

lemma par_tr_head_if:
 "(a  : X & (EX s' t'. u : s' |[X]|tr t'
               & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
       (a ~: X & (EX s'.    u : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
       (a ~: X & (EX t'.    u : s |[X]|tr t' & t = <Ev a> ^^^ t'))
  ==> <Ev a> ^^^ u : s |[X]|tr t"

 (*** sync ***)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (simp add: par_tr_intros)

 (*** left ***)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (simp add: par_tr_intros)

 (*** right ***)
 apply (elim conjE exE)
 apply (simp add: par_tr_intros)
done

(*** iff ***)

lemma par_tr_head:
 "<Ev a> ^^^ u : s |[X]|tr t
   = ((a  : X & (EX s' t'. u : s' |[X]|tr t'
              & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
      (a ~: X & (EX s'.    u : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
      (a ~: X & (EX t'.    u : s |[X]|tr t' & t = <Ev a> ^^^ t')))"
apply (rule iffI)
apply (simp add: par_tr_head_only_if)
apply (simp add: par_tr_head_if)
done

(* erule *)

lemma par_tr_head_ifE:
 "[| <Ev a> ^^^ u : s |[X]|tr t ;
     [| (a  : X & (EX s' t'. u : s' |[X]|tr t'
                & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
        (a ~: X & (EX s'.    u : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
        (a ~: X & (EX t'.    u : s |[X]|tr t' & t = <Ev a> ^^^ t')) |] ==> R
  |] ==> R"
by (simp add: par_tr_head)

(* head Ev Ev *)

lemma par_tr_head_Ev_Ev:
   "(u : (<Ev a> ^^^ s) |[X]|tr (<Ev b> ^^^ t))
    = (EX c v. u = <Ev c> ^^^ v &
               (c : X & v : s |[X]|tr t & a = c & b = c |
                c ~: X & v : s |[X]|tr (<Ev b> ^^^ t) & a = c |
                c ~: X & v : (<Ev a> ^^^ s) |[X]|tr t & b = c))"
apply (rule iffI)

 (* => *)
 apply (insert trace_nil_or_Tick_or_Ev)
 apply (drule_tac x="u" in spec)
 apply (elim disjE conjE exE)
 apply (simp_all)
 apply (simp add: par_tr_head)

 (* => *)
 apply (elim conjE exE)
 apply (simp add: par_tr_head)
done

(* step *)

lemma par_tr_step:
   "(u : s |[X]|tr t)
    = ((u = <> & s = <> & t = <>) |
       (u = <Tick> & s = <Tick> & t = <Tick>) |
       (EX a v. u = <Ev a> ^^^ v &
        ((a  : X & (EX s' t'. v : s' |[X]|tr t'
              & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
         (a ~: X & (EX s'.    v : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
         (a ~: X & (EX t'.    v : s |[X]|tr t' & t = <Ev a> ^^^ t')))))"
apply (insert trace_nil_or_Tick_or_Ev)
apply (drule_tac x="u" in spec)
apply (elim disjE)
apply (simp_all)
apply (elim exE)
apply (simp add: par_tr_head)
done

lemma par_tr_stepI:
   "((u = <> & s = <> & t = <>) |
       (u = <Tick> & s = <Tick> & t = <Tick>) |
       (EX a v. u = <Ev a> ^^^ v &
        ((a  : X & (EX s' t'. v : s' |[X]|tr t'
              & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
         (a ~: X & (EX s'.    v : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
         (a ~: X & (EX t'.    v : s |[X]|tr t' & t = <Ev a> ^^^ t')))))
     ==> (u : s |[X]|tr t)"
by (simp add: par_tr_step[THEN sym])

lemma par_tr_stepE:
   "[| u : s |[X]|tr t ;
      ((u = <> & s = <> & t = <>) |
       (u = <Tick> & s = <Tick> & t = <Tick>) |
       (EX a v. u = <Ev a> ^^^ v &
        ((a  : X & (EX s' t'. v : s' |[X]|tr t'
              & s = <Ev a> ^^^ s' & t = <Ev a> ^^^ t')) |
         (a ~: X & (EX s'.    v : s' |[X]|tr t & s = <Ev a> ^^^ s')) |
         (a ~: X & (EX t'.    v : s |[X]|tr t' & t = <Ev a> ^^^ t')))))
     ==> R |] ==> R"
by (simp add: par_tr_step[THEN sym])

(*--------------------------------------------*
 |                par last                    |
 *--------------------------------------------*)

(*** only if ***)

lemma par_tr_last_only_if_lm:
 "ALL X u s t e.
    (u ^^^ <e> : s |[X]|tr t & noTick u)
   --> (((e  : Ev ` X | e = Tick) &
            (EX s' t'. u : s' |[X]|tr t' & s = s' ^^^ <e> & t = t' ^^^ <e>
                       & noTick s' & noTick t')) |
        (e ~: Ev ` X & e ~= Tick &
            (EX s'.    u : s' |[X]|tr t & s = s' ^^^ <e> & noTick s' & noTick t)) |
        (e ~: Ev ` X & e ~= Tick &
            (EX t'.    u : s |[X]|tr t' & t = t' ^^^ <e> & noTick s & noTick t')))"
apply (rule allI)
apply (rule allI)
apply (induct_tac u rule: induct_trace)

(* base *)
 (* <> *)
 apply (intro allI impI)
 apply (simp add: par_tr_one)
 apply (erule disjE, simp)
 apply (erule exE, force)

 (* <Tick> *)
 apply (simp)

 (* <Ev a> ^^^ ua *)
 apply (intro allI impI)
 apply (elim conjE)
 apply (simp add: appt_assoc)
 apply (simp add: par_tr_head)
 apply (elim disjE conjE exE)

  (* head sync *)
  apply (drule_tac x="s'" in spec)
  apply (drule_tac x="t'" in spec)
  apply (drule_tac x="e" in spec)
  apply (simp)

   (* last sync *)
   apply (erule disjE, simp)
   apply (elim conjE exE)
   apply (rule disjI1)
   apply (rule_tac x="<Ev a> ^^^ s'a" in exI)
   apply (rule_tac x="<Ev a> ^^^ t'a" in exI)
   apply (simp add: appt_assoc)

   (* last left *)
   apply (erule disjE, simp)
   apply (elim conjE exE)
   apply (rule disjI1)
   apply (rule_tac x="<Ev a> ^^^ s'a" in exI, simp)
   apply (simp add: appt_assoc)

   (* last right *)
   apply (simp)
   apply (elim conjE exE)
   apply (rule disjI2)
   apply (rule_tac x="<Ev a> ^^^ t'a" in exI, simp)
   apply (simp add: appt_assoc)

  (* head left *)
  apply (drule_tac x="s'" in spec)
  apply (drule_tac x="t" in spec)
  apply (drule_tac x="e" in spec)
  apply (simp)

   (* last sync *)
   apply (erule disjE, simp)
   apply (elim conjE exE)
   apply (rule disjI1)
   apply (rule_tac x="<Ev a> ^^^ s'a" in exI)
   apply (rule_tac x="t'" in exI)
   apply (simp add: appt_assoc)

   (* last left *)
   apply (erule disjE, simp)
   apply (elim conjE exE)
   apply (rule disjI1)
   apply (rule_tac x="<Ev a> ^^^ s'a" in exI, simp)
   apply (simp add: appt_assoc)

   (* last right *)
   apply (simp)
   apply (elim conjE exE)
   apply (rule disjI2)
   apply (rule_tac x="t'" in exI, simp)

  (* head right *)
  apply (drule_tac x="sa" in spec)
  apply (drule_tac x="t'" in spec)
  apply (drule_tac x="e" in spec)
  apply (simp)

   (* last sync *)
   apply (erule disjE, simp)
   apply (elim conjE exE)
   apply (rule disjI1)
   apply (rule_tac x="s'" in exI)
   apply (rule_tac x="<Ev a> ^^^ t'a" in exI)
   apply (simp add: appt_assoc)

   (* last left *)
   apply (erule disjE, simp)
   apply (elim conjE exE)
   apply (rule disjI1)
   apply (rule_tac x="s'" in exI, simp)

   (* last right *)
   apply (simp)
   apply (elim conjE exE)
   apply (rule disjI2)
   apply (rule_tac x="<Ev a> ^^^ t'a" in exI)
   apply (simp add: appt_assoc)
done

(*** rule ***)

lemma par_tr_last_only_if:
 "[| u ^^^ <e> : s |[X]|tr t ; noTick u |]
   ==> (((e  : Ev ` X | e = Tick) &
            (EX s' t'. u : s' |[X]|tr t' & s = s' ^^^ <e> & t = t' ^^^ <e>
                       & noTick s' & noTick t')) |
        (e ~: Ev ` X & e ~= Tick &
            (EX s'.    u : s' |[X]|tr t & s = s' ^^^ <e> & noTick s' & noTick t)) |
        (e ~: Ev ` X & e ~= Tick &
            (EX t'.    u : s |[X]|tr t' & t = t' ^^^ <e> & noTick s & noTick t')))"
by (simp add: par_tr_last_only_if_lm)

(*** if ***)

lemma par_tr_last_if_lm:
 "ALL X u s t e. (noTick u &
   (((e  : Ev ` X | e = Tick) &
            (EX s' t'. u : s' |[X]|tr t' & s = s' ^^^ <e> & t = t' ^^^ <e>
                       & noTick s' & noTick t')) |
        (e ~: Ev ` X & e ~= Tick &
            (EX s'.    u : s' |[X]|tr t & s = s' ^^^ <e> & noTick s' & noTick t)) |
        (e ~: Ev ` X & e ~= Tick &
            (EX t'.    u : s |[X]|tr t' & t = t' ^^^ <e>  & noTick s & noTick t'))))
   --> u ^^^ <e> : s |[X]|tr t"
apply (rule allI)
apply (rule allI)
apply (induct_tac u rule: induct_trace)

(* base *)
 (* <> *)
 apply (intro allI impI)
 apply (simp add: par_tr_one)
 apply (elim conjE disjE)
 apply (force)
 apply (simp)
 apply (simp add: not_Tick_to_Ev, fast)
 apply (simp add: not_Tick_to_Ev, fast)

 (* <Tick> *)
 apply (simp)

 (* s ^^^ <e> *)
 apply (intro allI impI)
 apply (simp add: par_tr_head)
 apply (simp add: appt_assoc)
 apply (elim conjE)
 apply (elim disjE)

  (* last sync *)
  apply (elim conjE exE)

   (* sync *)
   apply (rotate_tac 3)
   apply (erule disjE)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s'a ^^^ <e>" in spec)
   apply (drule_tac x="t'a ^^^ <e>" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

   (* left *)
   apply (rotate_tac -1)
   apply (erule disjE)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s'a ^^^ <e>" in spec)
   apply (drule_tac x="t' ^^^ <e>" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

   (* right *)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s' ^^^ <e>" in spec)
   apply (drule_tac x="t'a ^^^ <e>" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

  (* last left *)
  apply (elim conjE exE)

   (* sync *)
   apply (rotate_tac 4)
   apply (erule disjE)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s'a ^^^ <e>" in spec)
   apply (drule_tac x="t'" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

   (* left *)
   apply (rotate_tac -1)
   apply (erule disjE)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s'a ^^^ <e>" in spec)
   apply (drule_tac x="t" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

   (* right *)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s' ^^^ <e>" in spec)
   apply (drule_tac x="t'" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

  (* last right *)
  apply (elim conjE exE)

   (* sync *)
   apply (rotate_tac 4)
   apply (erule disjE)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s'" in spec)
   apply (drule_tac x="t'a ^^^ <e>" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

   (* left *)
   apply (rotate_tac -1)
   apply (erule disjE)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="s'" in spec)
   apply (drule_tac x="t' ^^^ <e>" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)

   (* right *)
   apply (elim conjE exE)
   apply (simp add: appt_assoc)
   apply (simp add: par_tr_head)
   apply (drule_tac x="sa" in spec)
   apply (drule_tac x="t'a ^^^ <e>" in spec)
   apply (drule_tac x="e" in spec)
   apply (simp)
   apply (fast)
done

(*** rule ***)

lemma par_tr_last_if:
 "[| noTick u;
    ((e  : Ev ` X | e = Tick) &
          (EX s' t'. u : s' |[X]|tr t' & s = s' ^^^ <e> & t = t' ^^^ <e>
                      & noTick s' & noTick t')) |
     (e ~: Ev ` X & e ~= Tick &
          (EX s'.    u : s' |[X]|tr t & s = s' ^^^ <e> & noTick s' & noTick t)) |
     (e ~: Ev ` X & e ~= Tick &
          (EX t'.    u : s |[X]|tr t' & t = t' ^^^ <e> & noTick s & noTick t')) |]
   ==> u ^^^ <e> : s |[X]|tr t"
apply (insert par_tr_last_if_lm)
apply (drule_tac x="X" in spec)
apply (drule_tac x="u" in spec)
apply (drule_tac x="s" in spec)
apply (drule_tac x="t" in spec)
apply (drule_tac x="e" in spec)
by (simp)

(*** iff ***)

lemma par_tr_last:
 "noTick u ==>
   u ^^^ <e> : s |[X]|tr t
   = (((e  : Ev ` X | e = Tick) &
            (EX s' t'. u : s' |[X]|tr t' & s = s' ^^^ <e> & t = t' ^^^ <e>
                       & noTick s' & noTick t')) |
      (e ~: Ev ` X & e ~= Tick &
            (EX s'.    u : s' |[X]|tr t & s = s' ^^^ <e> & noTick s' & noTick t)) |
      (e ~: Ev ` X & e ~= Tick &
            (EX t'.    u : s |[X]|tr t' & t = t' ^^^ <e> & noTick s & noTick t')))"
apply (rule iffI)
apply (simp add: par_tr_last_only_if)
apply (simp add: par_tr_last_if)
done

(*************************************************************
                     symmetricity
 *************************************************************)

lemma par_tr_sym_only_if_lm:
  "ALL u s t. u : (s |[X]|tr t) --> u : (t |[X]|tr s)"
apply (rule allI)
apply (induct_tac u rule: induct_trace)
apply (simp_all)

apply (intro allI impI)
apply (erule par_tr_elims)

 (* <> *)
 apply (simp)

 (* <Tick> *)
 apply (simp)

 (* Ev_nil *)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="<>" in spec)
 apply (simp add: par_tr_intros)

 (* nil_Ev *)
 apply (drule_tac x="<>" in spec)
 apply (drule_tac x="t'" in spec)
 apply (simp add: par_tr_intros)

 (* sync *)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t'" in spec)
 apply (simp add: par_tr_intros)

 (* left *)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t" in spec)
 apply (simp add: par_tr_intros)

 (* right *)
 apply (drule_tac x="sa" in spec)
 apply (drule_tac x="t'" in spec)
 apply (simp add: par_tr_intros)
done

lemma par_tr_sym_only_if:
  "u : (s |[X]|tr t) ==> u : (t |[X]|tr s)"
apply (insert par_tr_sym_only_if_lm[of X])
apply (drule_tac x="u" in spec)
apply (drule_tac x="s" in spec)
apply (drule_tac x="t" in spec)
apply (simp)
done

lemma par_tr_sym: "s |[X]|tr t = t |[X]|tr s"
apply (auto)
apply (rule par_tr_sym_only_if, simp_all)
apply (rule par_tr_sym_only_if, simp_all)
done

(*************************************************************
                     prefix_closed
 *************************************************************)

lemma par_tr_prefix_lm:
 "ALL X v u s t. prefix v u & u : s |[X]|tr t
     --> (EX s' t'. v : s' |[X]|tr t' &
                    prefix s' s & prefix t' t)"
apply (rule allI)
apply (rule allI)
apply (induct_tac v rule: induct_trace)
apply (simp_all add: disj_not1)
apply (simp add: prefix_Tick)

apply (intro allI impI)
apply (elim conjE exE)
apply (simp add: par_tr_head)

 (* sync *)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (drule_tac x="u'" in spec)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t'" in spec)
 apply (force)

 (* left *)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (drule_tac x="u'" in spec)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t" in spec)
 apply (force)

 (* right *)
 apply (elim conjE exE)
 apply (drule_tac x="u'" in spec)
 apply (drule_tac x="sa" in spec)
 apply (drule_tac x="t'" in spec)
 apply (force)
done

(*** rule ***)

lemma par_tr_prefix:
 "[| prefix v u ; u : s |[X]|tr t |]
  ==> (EX s' t'. v : s' |[X]|tr t' & prefix s' s & prefix t' t)"
apply (insert par_tr_prefix_lm)
apply (drule_tac x="X" in spec)
apply (drule_tac x="v" in spec)
apply (drule_tac x="u" in spec)
apply (drule_tac x="s" in spec)
apply (drule_tac x="t" in spec)
by (simp)

lemma par_tr_prefixE:
 "[| prefix v u ; u : s |[X]|tr t ;
     !! s' t'. [| v : s' |[X]|tr t' ; prefix s' s ; prefix t' t |] ==> R
  |] ==> R"
apply (insert par_tr_prefix[of v u s X t])
by (auto)

(*************************************************************
                  parallel lemmas etc.
 *************************************************************)

(*******************************
          par_tr lenght
 *******************************)

lemma par_tr_lengtht_lm:
 "ALL X u s t. u : s |[X]|tr t
         --> lengtht s <= lengtht u & lengtht t <= lengtht u"
apply (rule allI)
apply (rule allI)
apply (induct_tac u rule: induct_trace)
apply (simp_all)

apply (intro allI impI)
apply (simp add: par_tr_head)

 (* sync *)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t'" in spec)
 apply (simp)

 (* left *)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t" in spec)
 apply (force)

 (* right *)
 apply (elim conjE exE)
 apply (drule_tac x="sa" in spec)
 apply (drule_tac x="t'" in spec)
 apply (force)
done

(*** rule ***)

lemma par_tr_lengtht:
 "u : s |[X]|tr t ==> lengtht s <= lengtht u & lengtht t <= lengtht u"
by (simp add: par_tr_lengtht_lm)

(*** ruleE ***)

lemma par_tr_lengthtE:
 "[| u : s |[X]|tr t ;
     [| lengtht s <= lengtht u ; lengtht t <= lengtht u|] ==> R |] ==> R"
by (simp add: par_tr_lengtht)

(**************************************************
                    para
 **************************************************)

lemma par_tr_nil_Ev_rev:
  "u : <> |[X]|tr (<Ev a> ^^^ t)
   ==> a ~: X & (EX v. u = <Ev a> ^^^ v & v : <> |[X]|tr t)"
apply (erule par_tr_elims)
by (simp_all add: par_tr_intros)

lemma par_tr_Tick_Ev_rev:
  "u : <Tick> |[X]|tr (<Ev a> ^^^ t)
   ==> a ~: X & (EX v. u = <Ev a> ^^^ v & v : <Tick> |[X]|tr t)"
apply (erule par_tr_elims)
by (simp_all add: par_tr_intros)

(**************************************************
                    noTick
 **************************************************)

(*-----------------*
 |   par noTick    |
 *-----------------*)

(*** only if ***)

lemma par_tr_noTick_only_if_lm:
 "ALL s t. ( u : s |[X]|tr t & noTick s & noTick t ) --> noTick u"
apply (induct_tac u rule: induct_trace)
apply (simp)
apply (intro allI)
apply (case_tac "s ~= <Tick>", simp)
apply (case_tac "t ~= <Tick>", simp)
apply (simp)

apply (intro allI impI)
apply (elim conjE)
apply (simp add: par_tr_head)
apply (elim disjE conjE exE)
apply (auto)
done

lemma par_tr_noTick_only_if:
 "[| u : s |[X]|tr t ; noTick s ; noTick t |] ==> noTick u"
apply (insert par_tr_noTick_only_if_lm[of u X])
apply (drule_tac x="s" in spec)
apply (drule_tac x="t" in spec)
by (simp)

(*** if ***)

lemma par_tr_noTick_if_lm:
 "ALL s t. ( u : s |[X]|tr t & noTick u ) --> ( noTick s & noTick t )"
apply (induct_tac u rule: induct_trace)
apply (simp)
apply (simp)

apply (intro allI impI)
apply (elim conjE)
apply (erule par_tr_head_ifE)
apply (elim conjE exE disjE)

apply (drule_tac x="s'" in spec)
apply (drule_tac x="t'" in spec)
apply (simp)

apply (drule_tac x="s'" in spec)
apply (drule_tac x="t" in spec)
apply (simp)

apply (drule_tac x="sa" in spec)
apply (drule_tac x="t'" in spec)
apply (simp)
done

lemma par_tr_noTick_if:
 "[| u : s |[X]|tr t ; noTick u |] ==> ( noTick s & noTick t )"
apply (insert par_tr_noTick_if_lm[of u X])
apply (drule_tac x="s" in spec)
apply (drule_tac x="t" in spec)
by (simp)

(*** iff ***)

lemma par_tr_noTick:
 "u : s |[X]|tr t ==> (noTick s & noTick t) = noTick u"
apply (rule iffI)
apply (simp add: par_tr_noTick_only_if)
apply (simp add: par_tr_noTick_if)
done

lemmas par_tr_noTick_compo = par_tr_noTick_only_if
lemmas par_tr_noTick_decompo = par_tr_noTick_if

(****** used in Alpha_parallel ******)

(*** nil-Tick ***)

lemma par_tr_nil_Tick[simp]:
  "(u : <> |[X]|tr <Tick>) = False"
apply (induct_tac u rule: induct_trace)
by (simp_all add: par_tr_head)

lemma par_tr_Tick_nil[simp]:
  "(u : <Tick> |[X]|tr <>) = False"
apply (induct_tac u rule: induct_trace)
by (simp_all add: par_tr_head)

(*** nil-Ev ***)

lemma par_tr_nil_Ev_iff:
  "u : <> |[X]|tr (<Ev a> ^^^ t)
   = (a ~: X & (EX v. u = <Ev a> ^^^ v & v : <> |[X]|tr t))"
apply (rule iffI)
apply (rule par_tr_nil_Ev_rev)
apply (simp)

apply (elim conjE exE, simp)
apply (simp add: par_tr_nil_Ev)
done

(*** Tcik-Ev ***)

lemma par_tr_Tick_Ev_iff:
  "u : <Tick> |[X]|tr (<Ev a> ^^^ t)
   = (a ~: X & (EX v. u = <Ev a> ^^^ v & v : <Tick> |[X]|tr t))"
apply (rule iffI)
apply (rule par_tr_Tick_Ev_rev)
apply (simp)

apply (elim conjE exE, simp)
apply (simp add: par_tr_Ev_right)
done

(****** nil ******)

lemma par_tr_nil_left_only_if_imp:
 "ALL u. (u : <> |[X]|tr s)
   --> (u = s & Tick ~: sett u & sett u Int Ev ` X = {})"
apply (induct_tac s rule: induct_trace)
apply (simp_all)

apply (intro allI impI)
apply (simp add: par_tr_nil_Ev_iff)
apply (elim conjE exE)
apply (drule_tac x="v" in spec)
apply (auto)
done

lemma par_tr_nil_left_only_if:
 "(u : <> |[X]|tr s)
   ==> u = s & Tick ~: sett u & sett u Int Ev ` X = {}"
apply (insert par_tr_nil_left_only_if_imp[of X s])
apply (drule_tac x="u" in spec)
apply (auto)
done

lemma par_tr_nil_left_if_imp:
 "(Tick ~: sett u & sett u Int Ev ` X = {})
  --> (u : <> |[X]|tr u)"
apply (induct_tac u rule: induct_trace)
by (auto simp add: par_tr_head)

lemma par_tr_nil_left_if:
 "[| Tick ~: sett u ; sett u Int Ev ` X = {} |]
  ==> (u : <> |[X]|tr u)"
by (simp add: par_tr_nil_left_if_imp)

(*** nil left ***)

lemma par_tr_nil_left:
 "(u : <> |[X]|tr s) = (u = s & Tick ~: sett u & sett u Int Ev ` X = {})"
apply (rule iffI)
apply (simp add: par_tr_nil_left_only_if)
apply (auto simp add: par_tr_nil_left_if)
done

(*** nil right ***)

lemma par_tr_nil_right:
 "(u : s |[X]|tr <>) = (u = s & Tick ~: sett u & sett u Int Ev ` X = {})"
apply (simp add: par_tr_sym)
apply (simp add: par_tr_nil_left)
done

lemmas par_tr_nil = par_tr_nil_left par_tr_nil_right

(****** Tick ******)

lemma par_tr_Tick_left_only_if_imp:
 "ALL u. u : <Tick> |[X]|tr s
   --> (u = s & Tick : sett u & sett u Int Ev ` X = {})"
apply (induct_tac s rule: induct_trace)
apply (simp_all)
apply (simp add: image_def)

apply (intro allI impI)
apply (simp add: par_tr_Tick_Ev_iff)
apply (elim conjE exE)
apply (drule_tac x="v" in spec)
apply (auto)
done

lemma par_tr_Tick_left_only_if:
 "(u : <Tick> |[X]|tr s)
   ==> u = s & Tick : sett u & sett u Int Ev ` X = {}"
apply (insert par_tr_Tick_left_only_if_imp[of X s])
apply (drule_tac x="u" in spec)
apply (auto)
done

lemma par_tr_Tick_left_if_imp:
 "(Tick : sett u & sett u Int Ev ` X = {})
  --> (u : <Tick> |[X]|tr u)"
apply (induct_tac u rule: induct_trace)
by (auto simp add: par_tr_head)

lemma par_tr_Tick_left_if:
 "[| Tick : sett u ; sett u Int Ev ` X = {} |]
  ==> (u : <Tick> |[X]|tr u)"
by (simp add: par_tr_Tick_left_if_imp)

(*** Tick left ***)

lemma par_tr_Tick_left:
 "(u : <Tick> |[X]|tr s)
= (u = s & Tick : sett u & sett u Int Ev ` X = {})"
apply (rule iffI)
apply (simp add: par_tr_Tick_left_only_if)
apply (auto simp add: par_tr_Tick_left_if)
done

(*** Tick right ***)

lemma par_tr_Tick_right:
 "(u : s |[X]|tr <Tick>)
= (u = s & Tick : sett u & sett u Int Ev ` X = {})"
apply (simp add: par_tr_sym[of _ _ "<Tick>"])
apply (simp add: par_tr_Tick_left)
done

lemmas par_tr_Tick = par_tr_Tick_left par_tr_Tick_right

(*** par sett ***)

lemma par_tr_sett: "ALL s t. u : s |[X]|tr t --> sett u <= sett s Un sett t"
apply (induct_tac u rule: induct_trace)
apply (simp_all)
apply (intro allI impI)
apply (simp add: par_tr_head)
apply (erule disjE)

(* sync *)
 apply (elim conjE exE)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t'" in spec)
 apply (force)

(* left *)
 apply (erule disjE)
 apply (elim conjE exE)
 apply (drule_tac x="s'" in spec)
 apply (drule_tac x="t" in spec)
 apply (force)

(* right *)
 apply (elim conjE exE)
 apply (drule_tac x="sa" in spec)
 apply (drule_tac x="t'" in spec)
 apply (force)
done

(* =================================================== *
 |             addition for CSP-Prover 5               |
 * =================================================== *)

lemma interleave_appt_left_lm:
  "ALL u s t.
   (u : s |[{}]|tr t & (noTick v))
     --> v ^^^ u : (v ^^^ s) |[{}]|tr t"
apply (induct_tac v rule: induct_trace)
apply (simp_all)
apply (intro allI impI)
apply (simp)
apply (drule_tac x="u" in spec)
apply (drule_tac x="sa" in spec)
apply (drule_tac x="t" in spec)
apply (erule conjE)
apply (simp add: appt_assoc)
apply (simp add: par_tr_head)
done

lemma interleave_appt_left_step:
  "[| u : s |[{}]|tr t ; noTick v |] ==> v ^^^ u : (v ^^^ s) |[{}]|tr t"
by (simp add: interleave_appt_left_lm)

lemma interleave_appt_right_step:
  "[| u : t |[{}]|tr s ; noTick v |] ==> v ^^^ u : t |[{}]|tr (v ^^^ s)"
apply (simp add: par_tr_sym)
apply (insert interleave_appt_left_step[of u s t v])
apply (simp add: par_tr_sym)
done

lemma interleave_appt_left_nil:
  "[| u : <> |[{}]|tr t ; noTick v |] ==> v ^^^ u : v |[{}]|tr t"
apply (insert interleave_appt_left_step[of u <> t v])
by (simp)

lemma interleave_appt_right_nil:
  "[| u : t |[{}]|tr <> ; noTick v |] ==> v ^^^ u : t |[{}]|tr v"
apply (insert interleave_appt_right_step[of u t <> v])
by (simp)

lemma interleave_appt_left_nil_nil:
  "noTick t ==> t : t |[{}]|tr <>"
apply (insert interleave_appt_left_step[of <> <> <> t])
by (simp)

lemma interleave_appt_right_nil_nil:
  "noTick t ==> t : <> |[{}]|tr t"
apply (insert interleave_appt_right_step[of <> <> <> t])
by (simp)

lemmas interleave_appt_left =
       interleave_appt_left_step
       interleave_appt_left_nil
       interleave_appt_left_nil_nil

lemmas interleave_appt_right =
       interleave_appt_right_step
       interleave_appt_right_nil
       interleave_appt_right_nil_nil

(*  par decompo *)

lemma par_tr_app_right[rule_format]:
  "ALL u v s t.
   (noTick u & sett u Int (Ev ` X) = {} & v : (s |[X]|tr t))
     --> u ^^^ v : (s |[X]|tr (u ^^^ t))"
apply (rule)
apply (induct_tac u rule: induct_trace)
apply (simp_all)
apply (intro allI impI)
apply (elim exE conjE)
apply (drule_tac x="v" in spec)
apply (drule_tac x="sa" in spec)
apply (drule_tac x="t" in spec)
apply (simp)
apply (simp add: appt_assoc)
apply (simp add: par_tr_head)
apply (auto)
done

(****************** to add it again ******************)

declare disj_not1   [simp]

end