theory Strong_CRef
imports Main "CRef"
begin

coinductive "RGSimStrong"::"[('g\<times>'l,'p,'f,'e) body,('g,'l,'p,'f,'e) config_p, (('g,'l) c_state) rel1,
                           (('g,'l) c_state) rel1,
                     (('g,'l) c_state,('g1,'l1) c_state) rel,
                     (('g,'l) c_state,('g1,'l1) c_state) rel,
                     (('g,'l) c_state,('g1,'l1) c_state)  rel,
                     ('g1\<times>'l1,'p,'f,'e) body,('g1,'l1,'p,'f,'e) config_p, (('g1,'l1) c_state) rel1,
                            (('g1,'l1) c_state) rel1
                    ] \<Rightarrow> bool"
("'(_,_,_,_')/ \<succeq>\<^sub>s\<^sub>'(\<^sub>_\<^sub>;\<^sub>_\<^sub>;\<^sub>_\<^sub>')/ '(_,_,_,_')" [81,81,81,81,81,81,81,81,81,81,81] 100)
where
  srgsim: "\<lbrakk>(((\<sigma>g,\<sigma>l),\<sigma>ls),((\<Sigma>g, \<Sigma>l), \<Sigma>ls))\<in>\<alpha>;
           \<forall>c\<^sub>c' \<sigma>g' \<sigma>l'. \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>\<tau> (c\<^sub>c,(\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l'))  \<longrightarrow>
             (\<exists>c\<^sub>s' \<Sigma>g' \<Sigma>l'.  \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s, (\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (c\<^sub>s', (\<Sigma>g', \<Sigma>l'))) \<and>
             (\<forall>c\<^sub>s' \<Sigma>g' \<Sigma>l'.  \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s, (\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
                (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
                ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
                  (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
                (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)) ;
           \<forall>v c\<^sub>c' \<sigma>g' \<sigma>l' e. e=Some v \<and> \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>e (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l'))  \<longrightarrow>
             (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l'))) \<and>
             (\<forall> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
               (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
               (((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
                 (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> (G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
               (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)) ;
           \<forall>\<sigma>g' \<sigma>l' \<sigma>ls' \<Sigma>g' \<Sigma>l'  \<Sigma>ls'.
             ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls')),
               (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls'))) \<in> ((R\<^sub>c,R\<^sub>s\<^sup>*)\<^sub>\<alpha>)  \<longrightarrow>
             (\<Gamma>\<^sub>c,(c\<^sub>c, ((\<sigma>g',\<sigma>l'),\<sigma>ls')),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s, ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls')),R\<^sub>s,G\<^sub>s);
           c\<^sub>c = Skip \<longrightarrow>
             (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Skip, (\<Sigma>g', \<Sigma>l'))) \<and>
               (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Skip, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
             ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)),  (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
               (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<gamma>\<^sub>q \<and> \<gamma>\<^sub>q\<subseteq>\<alpha>);
           c\<^sub>c = Throw \<longrightarrow>
             (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Throw, (\<Sigma>g', \<Sigma>l'))) \<and>
             (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Throw, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
             ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
               (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<gamma>\<^sub>a \<and> \<gamma>\<^sub>a\<subseteq>\<alpha>);
           \<forall>f. c\<^sub>c = Fault f  \<longrightarrow>
             (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Fault f, (\<Sigma>g', \<Sigma>l'))) \<and>
               (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Fault f, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
             ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
               (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha>);
           c\<^sub>c = Stuck  \<longrightarrow>
             (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Stuck, (\<Sigma>g', \<Sigma>l'))) \<and>
               (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Stuck, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
             ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
               (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha>)
          \<rbrakk> \<Longrightarrow> (\<Gamma>\<^sub>c,(c\<^sub>c, ((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s, ((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"

inductive_cases s_sim_elim_cases:
  "(\<Gamma>\<^sub>c,(c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c',((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"

inductive_cases s_sim_elim_cases_c[split_format (complete)]:
  "(\<Gamma>\<^sub>c,(Skip,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c',((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"
  "(\<Gamma>\<^sub>c,(Throw, ((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c',((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"
  "(\<Gamma>\<^sub>c,(Fault f, ((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c',((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"
  "(\<Gamma>\<^sub>c,(Stuck, ((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c',((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"

lemma dest_s_sim_ev_step:
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
    \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>(Some v) (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l')) \<Longrightarrow>
    (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l'))) \<and>
    (\<forall> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
        (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
        ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
          (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
        (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s))"
  apply (erule s_sim_elim_cases)
  by auto

lemma dest_s_sim_ev_step':
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
    \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>(Some v) (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l')) \<Longrightarrow>
    (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<and>
        (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
        ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
          (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
        (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s))"
  using dest_s_sim_ev_step by fast

lemma dest_s_sim_ev_step1:
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
    \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>(Some v) (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l')) \<longrightarrow>
    (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l'))) \<and>
    (\<forall> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
        (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
        ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
          (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
        (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s))"
  by (erule s_sim_elim_cases, auto)

lemma dest_s_sim_ev_step1':
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
    \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>(Some v) (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l')) \<longrightarrow>
    (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c\<^sub>v (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sup>+  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<and>
        (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
        ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
          (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
        (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s))"
  using dest_s_sim_ev_step1 by fast

lemma dest_s_sim_tau_step:
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
    \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>\<tau> (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l')) \<Longrightarrow>
    (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>*  (c\<^sub>s', (\<Sigma>g', \<Sigma>l'))) \<and>
    (\<forall> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>*  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
        (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
        ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
          (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
        (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s))"
  by (erule s_sim_elim_cases, force)

lemma dest_s_sim_tau_step':
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
    \<Gamma>\<^sub>c\<turnstile>\<^sub>c\<^sub>\<tau> (c\<^sub>c, (\<sigma>g,\<sigma>l)) \<rightarrow> (c\<^sub>c', (\<sigma>g',\<sigma>l')) \<Longrightarrow>
    (\<exists> c\<^sub>s' \<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>*  (c\<^sub>s', (\<Sigma>g', \<Sigma>l')) \<and>
    (((\<sigma>g',\<sigma>l'),\<sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha> \<and>
    ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls)),
      (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
    (\<Gamma>\<^sub>c,(c\<^sub>c', ((\<sigma>g',\<sigma>l'),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s', ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls)),R\<^sub>s,G\<^sub>s))"
  using dest_s_sim_tau_step by fast

lemma dest_s_sim_env_step:
  "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
   ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g',\<sigma>l'),\<sigma>ls')),
          (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls'))) \<in> ((R\<^sub>c,R\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<Longrightarrow>
    (\<Gamma>\<^sub>c,(c\<^sub>c, ((\<sigma>g',\<sigma>l'),\<sigma>ls')),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s, ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls')),R\<^sub>s,G\<^sub>s)"
  by (erule s_sim_elim_cases, auto)

 lemma dest_s_sim_alpha:
 "(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
   (((\<sigma>g,\<sigma>l),\<sigma>ls),((\<Sigma>g, \<Sigma>l), \<Sigma>ls))  \<in> \<alpha>"
   by (erule s_sim_elim_cases,auto)

lemma dest_s_final_skip:
"(\<Gamma>\<^sub>c,(Skip,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Skip, (\<Sigma>g', \<Sigma>l'))) \<and>
  (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Skip, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)),  (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
   (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<gamma>\<^sub>q \<and> \<gamma>\<^sub>q\<subseteq>\<alpha>)"
  by (erule s_sim_elim_cases,auto)

lemma dest_s_final_skip':
"(\<Gamma>\<^sub>c,(Skip,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Skip, (\<Sigma>g', \<Sigma>l')) \<and>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)),  (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
   (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<gamma>\<^sub>q \<and> \<gamma>\<^sub>q\<subseteq>\<alpha>)"
  using dest_s_final_skip by fast

lemma dest_s_final_Throw:
"(\<Gamma>\<^sub>c,(Throw,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Throw, (\<Sigma>g', \<Sigma>l'))) \<and>
 (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Throw, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
 (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<gamma>\<^sub>a \<and> \<gamma>\<^sub>a\<subseteq>\<alpha>)"
  by (erule s_sim_elim_cases,auto)

lemma dest_s_final_Throw':
"(\<Gamma>\<^sub>c,(Throw,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Throw, (\<Sigma>g', \<Sigma>l')) \<and>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
 (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<gamma>\<^sub>a \<and> \<gamma>\<^sub>a\<subseteq>\<alpha>)"
  using dest_s_final_Throw by fast

lemma dest_s_final_Fault:
"(\<Gamma>\<^sub>c,(Fault f,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Fault f, (\<Sigma>g', \<Sigma>l'))) \<and>
               (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Fault f, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
             ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
               (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha>)"
  by (erule s_sim_elim_cases, auto)

lemma dest_s_final_Fault':
"(\<Gamma>\<^sub>c,(Fault f,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Fault f, (\<Sigma>g', \<Sigma>l')) \<and>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
   (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha>)"
  using dest_s_final_Fault by fast

lemma dest_s_final_Stuck:
"(\<Gamma>\<^sub>c,(Stuck,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Stuck, (\<Sigma>g', \<Sigma>l'))) \<and>
 (\<forall>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Stuck, (\<Sigma>g', \<Sigma>l')) \<longrightarrow>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
 (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha>)"
   by (erule s_sim_elim_cases, auto)

lemma dest_s_final_Stuck':
"(\<Gamma>\<^sub>c,(Stuck,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
 (\<exists>\<Sigma>g' \<Sigma>l'. \<Gamma>\<^sub>s\<turnstile>\<^sub>c (c\<^sub>s,(\<Sigma>g, \<Sigma>l)) \<rightarrow>\<^sub>\<tau>\<^sup>* (Stuck, (\<Sigma>g', \<Sigma>l')) \<and>
 ((((\<sigma>g,\<sigma>l),\<sigma>ls),((\<sigma>g,\<sigma>l),\<sigma>ls)), (((\<Sigma>g, \<Sigma>l), \<Sigma>ls),((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))) \<in> ((G\<^sub>c,G\<^sub>s\<^sup>*)\<^sub>\<alpha>) \<and>
 (((\<sigma>g,\<sigma>l),\<sigma>ls), ((\<Sigma>g', \<Sigma>l'), \<Sigma>ls))\<in>\<alpha>)"
  using dest_s_final_Stuck by fast

lemma sim_strong_weak:"(\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s) \<Longrightarrow>
       (\<Gamma>\<^sub>c,(c\<^sub>c,((\<sigma>g,\<sigma>l),\<sigma>ls)),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>q\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c\<^sub>s,((\<Sigma>g, \<Sigma>l), \<Sigma>ls)),R\<^sub>s,G\<^sub>s)"
  apply(coinduction arbitrary: \<sigma>g \<sigma>l \<sigma>ls \<Sigma>g \<Sigma>l \<Sigma>ls c\<^sub>c c\<^sub>s, clarsimp)
  apply (auto simp add: toSeq_def)
         apply (auto intro: dest_s_sim_alpha)[1]
        apply (fast dest: dest_s_sim_tau_step')
       apply (drule dest_s_sim_ev_step1', fast)
  by (fast dest: dest_s_sim_env_step dest_s_final_skip
                dest_s_final_Throw dest_s_final_Fault dest_s_final_Stuck)+

definition "SRGSim_pre"::
  "[('g\<times>'l,'p,'f,'e) body,('g \<times> 'l,'p,'f,'e)com,
    (('g,'l) c_state) rel1, (('g,'l) c_state) rel1,
     (('g,'l) c_state,('g1,'l1) c_state) rel, (('g,'l) c_state,('g1,'l1) c_state) rel,
      (('g,'l) c_state,('g1,'l1) c_state) rel,  (('g,'l) c_state,('g1,'l1) c_state) rel,
    ('g1\<times>'l1,'p,'f,'e) body,('g1 \<times> 'l1,'p,'f,'e) com,
     (('g1,'l1) c_state) rel1, (('g1,'l1) c_state) rel1] \<Rightarrow> bool "
  ("'(_,_,_,_')/ \<succeq>\<^sub>s\<^sub>'(\<^sub>_\<^sub>;\<^sub>_\<^sub>\<rhd>\<^sub>_\<^sub>;\<^sub>_\<^sub>')/ '(_,_,_,_')" [81,81,81,81,81,81,81,81,81,81,81,81] 100)
  where
" (\<Gamma>\<^sub>c,c,R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<xi>\<^sub>\<rhd>\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,c',R\<^sub>s,G\<^sub>s) \<equiv>
  \<forall>\<sigma> \<Sigma>. (\<sigma>,\<Sigma>)\<in>\<xi> \<longrightarrow> (\<Gamma>\<^sub>c,(c, \<sigma>),R\<^sub>c,G\<^sub>c) \<succeq>\<^sub>s\<^sub>(\<^sub>\<alpha>\<^sub>;\<^sub>\<gamma>\<^sub>n\<^sub>;\<^sub>\<gamma>\<^sub>a\<^sub>) (\<Gamma>\<^sub>s,(c', \<Sigma>),R\<^sub>s,G\<^sub>s)
"

end


(*  Title:      HOL/Auth/Guard/Proto.thy
    Author:     Frederic Blanqui, University of Cambridge Computer Laboratory
    Copyright   2002  University of Cambridge
*)

section\<open>Other Protocol-Independent Results\<close>

theory Proto imports Guard_Public begin

subsection\<open>protocols\<close>

type_synonym rule = "event set * event"

abbreviation
  msg' :: "rule => msg" where
  "msg' R == msg (snd R)"

type_synonym proto = "rule set"

definition wdef :: "proto => bool" where
"wdef p == ALL R k. R:p --> Number k:parts {msg' R}
--> Number k:parts (msg`(fst R))"

subsection\<open>substitutions\<close>

record subs =
  agent   :: "agent => agent"
  nonce :: "nat => nat"
  nb    :: "nat => msg"
  key   :: "key => key"

primrec apm :: "subs => msg => msg" where
  "apm s (Agent A) = Agent (agent s A)"
| "apm s (Nonce n) = Nonce (nonce s n)"
| "apm s (Number n) = nb s n"
| "apm s (Key K) = Key (key s K)"
| "apm s (Hash X) = Hash (apm s X)"
| "apm s (Crypt K X) = (
if (EX A. K = pubK A) then Crypt (pubK (agent s (agt K))) (apm s X)
else if (EX A. K = priK A) then Crypt (priK (agent s (agt K))) (apm s X)
else Crypt (key s K) (apm s X))"
| "apm s \<lbrace>X,Y\<rbrace> = \<lbrace>apm s X, apm s Y\<rbrace>"

lemma apm_parts: "X:parts {Y} ==> apm s X:parts {apm s Y}"
apply (erule parts.induct, simp_all, blast)
apply (erule parts.Fst)
apply (erule parts.Snd)
by (erule parts.Body)+

lemma Nonce_apm [rule_format]: "Nonce n:parts {apm s X} ==>
(ALL k. Number k:parts {X} --> Nonce n ~:parts {nb s k}) -->
(EX k. Nonce k:parts {X} & nonce s k = n)"
by (induct X, simp_all, blast)

lemma wdef_Nonce: "[| Nonce n:parts {apm s X}; R:p; msg' R = X; wdef p;
Nonce n ~:parts (apm s `(msg `(fst R))) |] ==>
(EX k. Nonce k:parts {X} & nonce s k = n)"
apply (erule Nonce_apm, unfold wdef_def)
apply (drule_tac x=R in spec, drule_tac x=k in spec, clarsimp)
apply (drule_tac x=x in bspec, simp)
apply (drule_tac Y="msg x" and s=s in apm_parts, simp)
by (blast dest: parts_parts)

primrec ap :: "subs => event => event" where
  "ap s (Says A B X) = Says (agent s A) (agent s B) (apm s X)"
| "ap s (Gets A X) = Gets (agent s A) (apm s X)"
| "ap s (Notes A X) = Notes (agent s A) (apm s X)"

abbreviation
  ap' :: "subs => rule => event" where
  "ap' s R == ap s (snd R)"

abbreviation
  apm' :: "subs => rule => msg" where
  "apm' s R == apm s (msg' R)"

abbreviation
  priK' :: "subs => agent => key" where
  "priK' s A == priK (agent s A)"

abbreviation
  pubK' :: "subs => agent => key" where
  "pubK' s A == pubK (agent s A)"

subsection\<open>nonces generated by a rule\<close>

definition newn :: "rule => nat set" where
"newn R == {n. Nonce n:parts {msg (snd R)} & Nonce n ~:parts (msg`(fst R))}"

lemma newn_parts: "n:newn R ==> Nonce (nonce s n):parts {apm' s R}"
by (auto simp: newn_def dest: apm_parts)

subsection\<open>traces generated by a protocol\<close>

definition ok :: "event list => rule => subs => bool" where
"ok evs R s == ((ALL x. x:fst R --> ap s x:set evs)
& (ALL n. n:newn R --> Nonce (nonce s n) ~:used evs))"

inductive_set
  tr :: "proto => event list set"
  for p :: proto
where

  Nil [intro]: "[]:tr p"

| Fake [intro]: "[| evsf:tr p; X:synth (analz (spies evsf)) |]
  ==> Says Spy B X # evsf:tr p"

| Proto [intro]: "[| evs:tr p; R:p; ok evs R s |] ==> ap' s R # evs:tr p"

subsection\<open>general properties\<close>

lemma one_step_tr [iff]: "one_step (tr p)"
apply (unfold one_step_def, clarify)
by (ind_cases "ev # evs:tr p" for ev evs, auto)

definition has_only_Says' :: "proto => bool" where
"has_only_Says' p == ALL R. R:p --> is_Says (snd R)"

lemma has_only_Says'D: "[| R:p; has_only_Says' p |]
==> (EX A B X. snd R = Says A B X)"
by (unfold has_only_Says'_def is_Says_def, blast)

lemma has_only_Says_tr [simp]: "has_only_Says' p ==> has_only_Says (tr p)"
apply (unfold has_only_Says_def)
apply (rule allI, rule allI, rule impI)
apply (erule tr.induct)
apply (auto simp: has_only_Says'_def ok_def)
by (drule_tac x=a in spec, auto simp: is_Says_def)

lemma has_only_Says'_in_trD: "[| has_only_Says' p; list @ ev # evs1 \<in> tr p |]
==> (EX A B X. ev = Says A B X)"
by (drule has_only_Says_tr, auto)

lemma ok_not_used: "[| Nonce n ~:used evs; ok evs R s;
ALL x. x:fst R --> is_Says x |] ==> Nonce n ~:parts (apm s `(msg `(fst R)))"
apply (unfold ok_def, clarsimp)
apply (drule_tac x=x in spec, drule_tac x=x in spec)
by (auto simp: is_Says_def dest: Says_imp_spies not_used_not_spied parts_parts)

lemma ok_is_Says: "[| evs' @ ev # evs:tr p; ok evs R s; has_only_Says' p;
R:p; x:fst R |] ==> is_Says x"
apply (unfold ok_def is_Says_def, clarify)
apply (drule_tac x=x in spec, simp)
apply (subgoal_tac "one_step (tr p)")
apply (drule trunc, simp, drule one_step_Cons, simp)
apply (drule has_only_SaysD, simp+)
by (clarify, case_tac x, auto)

subsection\<open>types\<close>

type_synonym keyfun = "rule => subs => nat => event list => key set"

type_synonym secfun = "rule => nat => subs => key set => msg"

subsection\<open>introduction of a fresh guarded nonce\<close>

definition fresh :: "proto => rule => subs => nat => key set => event list
=> bool" where
"fresh p R s n Ks evs == (EX evs1 evs2. evs = evs2 @ ap' s R # evs1
& Nonce n ~:used evs1 & R:p & ok evs1 R s & Nonce n:parts {apm' s R}
& apm' s R:guard n Ks)"

lemma freshD: "fresh p R s n Ks evs ==> (EX evs1 evs2.
evs = evs2 @ ap' s R # evs1 & Nonce n ~:used evs1 & R:p & ok evs1 R s
& Nonce n:parts {apm' s R} & apm' s R:guard n Ks)"
by (unfold fresh_def, blast)

lemma freshI [intro]: "[| Nonce n ~:used evs1; R:p; Nonce n:parts {apm' s R};
ok evs1 R s; apm' s R:guard n Ks |]
==> fresh p R s n Ks (list @ ap' s R # evs1)"
by (unfold fresh_def, blast)

lemma freshI': "[| Nonce n ~:used evs1; (l,r):p;
Nonce n:parts {apm s (msg r)}; ok evs1 (l,r) s; apm s (msg r):guard n Ks |]
==> fresh p (l,r) s n Ks (evs2 @ ap s r # evs1)"
by (drule freshI, simp+)

lemma fresh_used: "[| fresh p R' s' n Ks evs; has_only_Says' p |]
==> Nonce n:used evs"
apply (unfold fresh_def, clarify)
apply (drule has_only_Says'D)
by (auto intro: parts_used_app)

lemma fresh_newn: "[| evs' @ ap' s R # evs:tr p; wdef p; has_only_Says' p;
Nonce n ~:used evs; R:p; ok evs R s; Nonce n:parts {apm' s R} |]
==> EX k. k:newn R & nonce s k = n"
apply (drule wdef_Nonce, simp+)
apply (frule ok_not_used, simp+)
apply (clarify, erule ok_is_Says, simp+)
apply (clarify, rule_tac x=k in exI, simp add: newn_def)
apply (clarify, drule_tac Y="msg x" and s=s in apm_parts)
apply (drule ok_not_used, simp+)
by (clarify, erule ok_is_Says, simp_all)

lemma fresh_rule: "[| evs' @ ev # evs:tr p; wdef p; Nonce n ~:used evs;
Nonce n:parts {msg ev} |] ==> EX R s. R:p & ap' s R = ev"
apply (drule trunc, simp, ind_cases "ev # evs:tr p", simp)
by (drule_tac x=X in in_sub, drule parts_sub, simp, simp, blast+)

lemma fresh_ruleD: "[| fresh p R' s' n Ks evs; keys R' s' n evs <= Ks; wdef p;
has_only_Says' p; evs:tr p; ALL R k s. nonce s k = n --> Nonce n:used evs -->
R:p --> k:newn R --> Nonce n:parts {apm' s R} --> apm' s R:guard n Ks -->
apm' s R:parts (spies evs) --> keys R s n evs <= Ks --> P |] ==> P"
apply (frule fresh_used, simp)
apply (unfold fresh_def, clarify)
apply (drule_tac x=R' in spec)
apply (drule fresh_newn, simp+, clarify)
apply (drule_tac x=k in spec)
apply (drule_tac x=s' in spec)
apply (subgoal_tac "apm' s' R':parts (spies (evs2 @ ap' s' R' # evs1))")
apply (case_tac R', drule has_only_Says'D, simp, clarsimp)
apply (case_tac R', drule has_only_Says'D, simp, clarsimp)
apply (rule_tac Y="apm s' X" in parts_parts, blast)
by (rule parts.Inj, rule Says_imp_spies, simp, blast)

subsection\<open>safe keys\<close>

definition safe :: "key set => msg set => bool" where
"safe Ks G == ALL K. K:Ks --> Key K ~:analz G"

lemma safeD [dest]: "[| safe Ks G; K:Ks |] ==> Key K ~:analz G"
by (unfold safe_def, blast)

lemma safe_insert: "safe Ks (insert X G) ==> safe Ks G"
by (unfold safe_def, blast)

lemma Guard_safe: "[| Guard n Ks G; safe Ks G |] ==> Nonce n ~:analz G"
by (blast dest: Guard_invKey)

subsection\<open>guardedness preservation\<close>

definition preserv :: "proto => keyfun => nat => key set => bool" where
"preserv p keys n Ks == (ALL evs R' s' R s. evs:tr p -->
Guard n Ks (spies evs) --> safe Ks (spies evs) --> fresh p R' s' n Ks evs -->
keys R' s' n evs <= Ks --> R:p --> ok evs R s --> apm' s R:guard n Ks)"

lemma preservD: "[| preserv p keys n Ks; evs:tr p; Guard n Ks (spies evs);
safe Ks (spies evs); fresh p R' s' n Ks evs; R:p; ok evs R s;
keys R' s' n evs <= Ks |] ==> apm' s R:guard n Ks"
by (unfold preserv_def, blast)

lemma preservD': "[| preserv p keys n Ks; evs:tr p; Guard n Ks (spies evs);
safe Ks (spies evs); fresh p R' s' n Ks evs; (l,Says A B X):p;
ok evs (l,Says A B X) s; keys R' s' n evs <= Ks |] ==> apm s X:guard n Ks"
by (drule preservD, simp+)

subsection\<open>monotonic keyfun\<close>

definition monoton :: "proto => keyfun => bool" where
"monoton p keys == ALL R' s' n ev evs. ev # evs:tr p -->
keys R' s' n evs <= keys R' s' n (ev # evs)"

lemma monotonD [dest]: "[| keys R' s' n (ev # evs) <= Ks; monoton p keys;
ev # evs:tr p |] ==> keys R' s' n evs <= Ks"
by (unfold monoton_def, blast)

subsection\<open>guardedness theorem\<close>

lemma Guard_tr [rule_format]: "[| evs:tr p; has_only_Says' p;
preserv p keys n Ks; monoton p keys; Guard n Ks (initState Spy) |] ==>
safe Ks (spies evs) --> fresh p R' s' n Ks evs --> keys R' s' n evs <= Ks -->
Guard n Ks (spies evs)"
apply (erule tr.induct)
(* Nil *)
apply simp
(* Fake *)
apply (clarify, drule freshD, clarsimp)
apply (case_tac evs2)
(* evs2 = [] *)
apply (frule has_only_Says'D, simp)
apply (clarsimp, blast)
(* evs2 = aa # list *)
apply (clarsimp, rule conjI)
apply (blast dest: safe_insert)
(* X:guard n Ks *)
apply (rule in_synth_Guard, simp, rule Guard_analz)
apply (blast dest: safe_insert)
apply (drule safe_insert, simp add: safe_def)
(* Proto *)
apply (clarify, drule freshD, clarify)
apply (case_tac evs2)
(* evs2 = [] *)
apply (frule has_only_Says'D, simp)
apply (frule_tac R=R' in has_only_Says'D, simp)
apply (case_tac R', clarsimp, blast)
(* evs2 = ab # list *)
apply (frule has_only_Says'D, simp)
apply (clarsimp, rule conjI)
apply (drule Proto, simp+, blast dest: safe_insert)
(* apm s X:guard n Ks *)
apply (frule Proto, simp+)
apply (erule preservD', simp+)
apply (blast dest: safe_insert)
apply (blast dest: safe_insert)
by (blast, simp, simp, blast)

subsection\<open>useful properties for guardedness\<close>

lemma newn_neq_used: "[| Nonce n:used evs; ok evs R s; k:newn R |]
==> n ~= nonce s k"
by (auto simp: ok_def)

lemma ok_Guard: "[| ok evs R s; Guard n Ks (spies evs); x:fst R; is_Says x |]
==> apm s (msg x):parts (spies evs) & apm s (msg x):guard n Ks"
apply (unfold ok_def is_Says_def, clarify)
apply (drule_tac x="Says A B X" in spec, simp)
by (drule Says_imp_spies, auto intro: parts_parts)

lemma ok_parts_not_new: "[| Y:parts (spies evs); Nonce (nonce s n):parts {Y};
ok evs R s |] ==> n ~:newn R"
by (auto simp: ok_def dest: not_used_not_spied parts_parts)

subsection\<open>unicity\<close>

definition uniq :: "proto => secfun => bool" where
"uniq p secret == ALL evs R R' n n' Ks s s'. R:p --> R':p -->
n:newn R --> n':newn R' --> nonce s n = nonce s' n' -->
Nonce (nonce s n):parts {apm' s R} --> Nonce (nonce s n):parts {apm' s' R'} -->
apm' s R:guard (nonce s n) Ks --> apm' s' R':guard (nonce s n) Ks -->
evs:tr p --> Nonce (nonce s n) ~:analz (spies evs) -->
secret R n s Ks:parts (spies evs) --> secret R' n' s' Ks:parts (spies evs) -->
secret R n s Ks = secret R' n' s' Ks"

lemma uniqD: "[| uniq p secret; evs: tr p; R:p; R':p; n:newn R; n':newn R';
nonce s n = nonce s' n'; Nonce (nonce s n) ~:analz (spies evs);
Nonce (nonce s n):parts {apm' s R}; Nonce (nonce s n):parts {apm' s' R'};
secret R n s Ks:parts (spies evs); secret R' n' s' Ks:parts (spies evs);
apm' s R:guard (nonce s n) Ks; apm' s' R':guard (nonce s n) Ks |] ==>
secret R n s Ks = secret R' n' s' Ks"
by (unfold uniq_def, blast)

definition ord :: "proto => (rule => rule => bool) => bool" where
"ord p inff == ALL R R'. R:p --> R':p --> ~ inff R R' --> inff R' R"

lemma ordD: "[| ord p inff; ~ inff R R'; R:p; R':p |] ==> inff R' R"
by (unfold ord_def, blast)

definition uniq' :: "proto => (rule => rule => bool) => secfun => bool" where
"uniq' p inff secret == ALL evs R R' n n' Ks s s'. R:p --> R':p -->
inff R R' --> n:newn R --> n':newn R' --> nonce s n = nonce s' n' -->
Nonce (nonce s n):parts {apm' s R} --> Nonce (nonce s n):parts {apm' s' R'} -->
apm' s R:guard (nonce s n) Ks --> apm' s' R':guard (nonce s n) Ks -->
evs:tr p --> Nonce (nonce s n) ~:analz (spies evs) -->
secret R n s Ks:parts (spies evs) --> secret R' n' s' Ks:parts (spies evs) -->
secret R n s Ks = secret R' n' s' Ks"

lemma uniq'D: "[| uniq' p inff secret; evs: tr p; inff R R'; R:p; R':p; n:newn R;
n':newn R'; nonce s n = nonce s' n'; Nonce (nonce s n) ~:analz (spies evs);
Nonce (nonce s n):parts {apm' s R}; Nonce (nonce s n):parts {apm' s' R'};
secret R n s Ks:parts (spies evs); secret R' n' s' Ks:parts (spies evs);
apm' s R:guard (nonce s n) Ks; apm' s' R':guard (nonce s n) Ks |] ==>
secret R n s Ks = secret R' n' s' Ks"
by (unfold uniq'_def, blast)

lemma uniq'_imp_uniq: "[| uniq' p inff secret; ord p inff |] ==> uniq p secret"
apply (unfold uniq_def)
apply (rule allI)+
apply (case_tac "inff R R'")
apply (blast dest: uniq'D)
by (auto dest: ordD uniq'D intro: sym)

subsection\<open>Needham-Schroeder-Lowe\<close>

definition a :: agent where "a == Friend 0"
definition b :: agent where "b == Friend 1"
definition a' :: agent where "a' == Friend 2"
definition b' :: agent where "b' == Friend 3"
definition Na :: nat where "Na == 0"
definition Nb :: nat where "Nb == 1"

abbreviation
  ns1 :: rule where
  "ns1 == ({}, Says a b (Crypt (pubK b) \<lbrace>Nonce Na, Agent a\<rbrace>))"

abbreviation
  ns2 :: rule where
  "ns2 == ({Says a' b (Crypt (pubK b) \<lbrace>Nonce Na, Agent a\<rbrace>)},
    Says b a (Crypt (pubK a) \<lbrace>Nonce Na, Nonce Nb, Agent b\<rbrace>))"

abbreviation
  ns3 :: rule where
  "ns3 == ({Says a b (Crypt (pubK b) \<lbrace>Nonce Na, Agent a\<rbrace>),
    Says b' a (Crypt (pubK a) \<lbrace>Nonce Na, Nonce Nb, Agent b\<rbrace>)},
    Says a b (Crypt (pubK b) (Nonce Nb)))"

inductive_set ns :: proto where
  [iff]: "ns1:ns"
| [iff]: "ns2:ns"
| [iff]: "ns3:ns"

abbreviation (input)
  ns3a :: event where
  "ns3a == Says a b (Crypt (pubK b) \<lbrace>Nonce Na, Agent a\<rbrace>)"

abbreviation (input)
  ns3b :: event where
  "ns3b == Says b' a (Crypt (pubK a) \<lbrace>Nonce Na, Nonce Nb, Agent b\<rbrace>)"

definition keys :: "keyfun" where
"keys R' s' n evs == {priK' s' a, priK' s' b}"

lemma "monoton ns keys"
by (simp add: keys_def monoton_def)

definition secret :: "secfun" where
"secret R n s Ks ==
(if R=ns1 then apm s (Crypt (pubK b) \<lbrace>Nonce Na, Agent a\<rbrace>)
else if R=ns2 then apm s (Crypt (pubK a) \<lbrace>Nonce Na, Nonce Nb, Agent b\<rbrace>)
else Number 0)"

definition inf :: "rule => rule => bool" where
"inf R R' == (R=ns1 | (R=ns2 & R'~=ns1) | (R=ns3 & R'=ns3))"

lemma inf_is_ord [iff]: "ord ns inf"
apply (unfold ord_def inf_def)
apply (rule allI)+
apply (rule impI)
apply (simp add: split_paired_all)
by (rule impI, erule ns.cases, simp_all)+

subsection\<open>general properties\<close>

lemma ns_has_only_Says' [iff]: "has_only_Says' ns"
apply (unfold has_only_Says'_def)
apply (rule allI, rule impI)
apply (simp add: split_paired_all)
by (erule ns.cases, auto)

lemma newn_ns1 [iff]: "newn ns1 = {Na}"
by (simp add: newn_def)

lemma newn_ns2 [iff]: "newn ns2 = {Nb}"
by (auto simp: newn_def Na_def Nb_def)

lemma newn_ns3 [iff]: "newn ns3 = {}"
by (auto simp: newn_def)

lemma ns_wdef [iff]: "wdef ns"
by (auto simp: wdef_def elim: ns.cases)

subsection\<open>guardedness for NSL\<close>

lemma "uniq ns secret ==> preserv ns keys n Ks"
apply (unfold preserv_def)
apply (rule allI)+
apply (rule impI, rule impI, rule impI, rule impI, rule impI)
apply (erule fresh_ruleD, simp, simp, simp, simp)
apply (rule allI)+
apply (rule impI, rule impI, rule impI)
apply (simp add: split_paired_all)
apply (erule ns.cases)
(* fresh with NS1 *)
apply (rule impI, rule impI, rule impI, rule impI, rule impI, rule impI)
apply (erule ns.cases)
(* NS1 *)
apply clarsimp
apply (frule newn_neq_used, simp, simp)
apply (rule No_Nonce, simp)
(* NS2 *)
apply clarsimp
apply (frule newn_neq_used, simp, simp)
apply (case_tac "nonce sa Na = nonce s Na")
apply (frule Guard_safe, simp)
apply (frule Crypt_guard_invKey, simp)
apply (frule ok_Guard, simp, simp, simp, clarsimp)
apply (frule_tac K="pubK' s b" in Crypt_guard_invKey, simp)
apply (frule_tac R=ns1 and R'=ns1 and Ks=Ks and s=sa and s'=s in uniqD, simp+)
apply (simp add: secret_def, simp add: secret_def, force, force)
apply (simp add: secret_def keys_def, blast)
apply (rule No_Nonce, simp)
(* NS3 *)
apply clarsimp
apply (case_tac "nonce sa Na = nonce s Nb")
apply (frule Guard_safe, simp)
apply (frule Crypt_guard_invKey, simp)
apply (frule_tac x=ns3b in ok_Guard, simp, simp, simp, clarsimp)
apply (frule_tac K="pubK' s a" in Crypt_guard_invKey, simp)
apply (frule_tac R=ns1 and R'=ns2 and Ks=Ks and s=sa and s'=s in uniqD, simp+)
apply (simp add: secret_def, simp add: secret_def, force, force)
apply (simp add: secret_def, rule No_Nonce, simp)
(* fresh with NS2 *)
apply (rule impI, rule impI, rule impI, rule impI, rule impI, rule impI)
apply (erule ns.cases)
(* NS1 *)
apply clarsimp
apply (frule newn_neq_used, simp, simp)
apply (rule No_Nonce, simp)
(* NS2 *)
apply clarsimp
apply (frule newn_neq_used, simp, simp)
apply (case_tac "nonce sa Nb = nonce s Na")
apply (frule Guard_safe, simp)
apply (frule Crypt_guard_invKey, simp)
apply (frule ok_Guard, simp, simp, simp, clarsimp)
apply (frule_tac K="pubK' s b" in Crypt_guard_invKey, simp)
apply (frule_tac R=ns2 and R'=ns1 and Ks=Ks and s=sa and s'=s in uniqD, simp+)
apply (simp add: secret_def, simp add: secret_def, force, force)
apply (simp add: secret_def, rule No_Nonce, simp)
(* NS3 *)
apply clarsimp
apply (case_tac "nonce sa Nb = nonce s Nb")
apply (frule Guard_safe, simp)
apply (frule Crypt_guard_invKey, simp)
apply (frule_tac x=ns3b in ok_Guard, simp, simp, simp, clarsimp)
apply (frule_tac K="pubK' s a" in Crypt_guard_invKey, simp)
apply (frule_tac R=ns2 and R'=ns2 and Ks=Ks and s=sa and s'=s in uniqD, simp+)
apply (simp add: secret_def, simp add: secret_def, force, force)
apply (simp add: secret_def keys_def, blast)
apply (rule No_Nonce, simp)
(* fresh with NS3 *)
by simp

subsection\<open>unicity for NSL\<close>

lemma "uniq' ns inf secret"
apply (unfold uniq'_def)
apply (rule allI)+
apply (simp add: split_paired_all)
apply (rule impI, erule ns.cases)
(* R = ns1 *)
apply (rule impI, erule ns.cases)
(* R' = ns1 *)
apply (rule impI, rule impI, rule impI, rule impI)
apply (rule impI, rule impI, rule impI, rule impI)
apply (rule impI, erule tr.induct)
(* Nil *)
apply (simp add: secret_def)
(* Fake *)
apply (clarify, simp add: secret_def)
apply (drule notin_analz_insert)
apply (drule Crypt_insert_synth, simp, simp, simp)
apply (drule Crypt_insert_synth, simp, simp, simp, simp)
(* Proto *)
apply (erule_tac P="ok evsa R sa" in rev_mp)
apply (simp add: split_paired_all)
apply (erule ns.cases)
(* ns1 *)
apply (clarify, simp add: secret_def)
apply (erule disjE, erule disjE, clarsimp)
apply (drule ok_parts_not_new, simp, simp, simp)
apply (clarify, drule ok_parts_not_new, simp, simp, simp)
(* ns2 *)
apply (simp add: secret_def)
(* ns3 *)
apply (simp add: secret_def)
(* R' = ns2 *)
apply (rule impI, rule impI, rule impI, rule impI)
apply (rule impI, rule impI, rule impI, rule impI)
apply (rule impI, erule tr.induct)
(* Nil *)
apply (simp add: secret_def)
(* Fake *)
apply (clarify, simp add: secret_def)
apply (drule notin_analz_insert)
apply (drule Crypt_insert_synth, simp, simp, simp)
apply (drule_tac n="nonce s' Nb" in Crypt_insert_synth, simp, simp, simp, simp)
(* Proto *)
apply (erule_tac P="ok evsa R sa" in rev_mp)
apply (simp add: split_paired_all)
apply (erule ns.cases)
(* ns1 *)
apply (clarify, simp add: secret_def)
apply (drule_tac s=sa and n=Na in ok_parts_not_new, simp, simp, simp)
(* ns2 *)
apply (clarify, simp add: secret_def)
apply (drule_tac s=sa and n=Nb in ok_parts_not_new, simp, simp, simp)
(* ns3 *)
apply (simp add: secret_def)
(* R' = ns3 *)
apply simp
(* R = ns2 *)
apply (rule impI, erule ns.cases)
(* R' = ns1 *)
apply (simp only: inf_def, blast)
(* R' = ns2 *)
apply (rule impI, rule impI, rule impI, rule impI)
apply (rule impI, rule impI, rule impI, rule impI)
apply (rule impI, erule tr.induct)
(* Nil *)
apply (simp add: secret_def)
(* Fake *)
apply (clarify, simp add: secret_def)
apply (drule notin_analz_insert)
apply (drule_tac n="nonce s' Nb" in Crypt_insert_synth, simp, simp, simp)
apply (drule_tac n="nonce s' Nb" in Crypt_insert_synth, simp, simp, simp, simp)
(* Proto *)
apply (erule_tac P="ok evsa R sa" in rev_mp)
apply (simp add: split_paired_all)
apply (erule ns.cases)
(* ns1 *)
apply (simp add: secret_def)
(* ns2 *)
apply (clarify, simp add: secret_def)
apply (erule disjE, erule disjE, clarsimp, clarsimp)
apply (drule_tac s=sa and n=Nb in ok_parts_not_new, simp, simp, simp)
apply (erule disjE, clarsimp)
apply (drule_tac s=sa and n=Nb in ok_parts_not_new, simp, simp, simp)
by (simp_all add: secret_def)

end


theory flash9Bra  imports flash9Rev

  begin
lemma onInv9:

   assumes  a1:"iInv1 \<le> N" and

     b1:"r \<in> rules N" and b2:"invf=inv9  iInv1 "
   shows  "invHoldForRule' s invf r (invariants   N)"
   proof -
have c1:"ex1P N (% iRule1 .  r=NI_Local_GetX_PutX1 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_GetX  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Replace  iRule1 )\<or>ex0P N (  r=NI_ShWb N )\<or>ex0P N (  r=PI_Local_GetX_GetX2 )\<or>ex0P N (  r=NI_Local_PutXAcksDone )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX7 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak2  iRule1 )\<or>ex0P N (  r=NI_ReplaceHomeShrVld )\<or>ex1P N (% iRule1 .  r=NI_Remote_Put  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX5 N  iRule1 )\<or>ex0P N (  r=NI_Wb )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Get  iRule1 )\<or>ex0P N (  r=PI_Local_Replace )\<or>ex1P N (% iRule1 .  r=NI_ReplaceShrVld  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Local_GetX_PutX8 N  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_InvAck_2 N  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_Get_Nak2  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=PI_Remote_Replace  iRule1 )\<or>ex0P N (  r=NI_Nak_Home )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put2  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_InvAck_1  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX11 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX6 N  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_Get_Put2  iRule1  iRule2 )\<or>ex0P N (  r=PI_Local_Get_Put )\<or>ex0P N (  r=PI_Local_GetX_PutX1 N )\<or>ex1P N (% iRule1 .  r=NI_InvAck_1_Home  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_Get_Nak1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak2  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX10_home N  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_Get  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak3  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Local_GetX_PutX10 N  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX2 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_Get_Put1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_PutX  iRule1 )\<or>ex1P N (% iRule1 .  r=Store  iRule1 )\<or>ex0P N (  r=NI_FAck )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX3 N  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX3 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_GetX_PutX  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX8_home N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put1 N  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_GetX1 )\<or>ex0P N (  r=StoreHome )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_GetX_Nak  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Inv  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_PutX  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX4 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX4 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Nak  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX2 N )\<or>ex0P N (  r=NI_Local_Put )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak1  iRule1 )\<or>ex0P N (  r=NI_Nak_Clear )\<or>ex0P N (  r=PI_Local_PutX )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak3  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_GetX_Nak_Home  iRule1 )\<or>ex0P N (  r=PI_Local_Get_Get )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX9 N  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_GetX  iRule1 )\<or>ex0P N (  r=NI_ReplaceHome )\<or>ex1P N (% iRule1 .  r=NI_Remote_GetX_PutX_Home  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put3  iRule1 )"

        apply(cut_tac  b1)
        apply auto
        done      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX1 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX1 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_GetX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_GetX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_GetXVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Replace  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Replace  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_ReplaceVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ShWb N )
"

         from c1 have c2:" r= NI_ShWb N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ShWbVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_GetX2 )
"

         from c1 have c2:" r= PI_Local_GetX_GetX2 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= NI_Local_PutXAcksDone )
"

         from c1 have c2:" r= NI_Local_PutXAcksDone "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX7 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX7 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX7VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ReplaceHomeShrVld )
"

         from c1 have c2:" r= NI_ReplaceHomeShrVld "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Put  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Put  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_PutVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX5 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX5 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX5VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Wb )
"

         from c1 have c2:" r= NI_Wb "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Wb ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_WbVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Get  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Get  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_GetVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Replace )
"

         from c1 have c2:" r= PI_Local_Replace "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_ReplaceVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_ReplaceShrVld  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_ReplaceShrVld  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_ReplaceShrVldVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Local_GetX_PutX8 N  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Local_GetX_PutX8 N  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX8VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_InvAck_2 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_InvAck_2 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_Get_Nak2  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_Get_Nak2  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Nak2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_Replace  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_Replace  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_ReplaceVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Nak_Home )
"

         from c1 have c2:" r= NI_Nak_Home "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Nak_HomeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_InvAck_1  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_InvAck_1  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX11 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX11 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX11VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX6 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX6 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX6VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_Get_Put2  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_Get_Put2  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Put2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Get_Put )
"

         from c1 have c2:" r= PI_Local_Get_Put "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_Get_PutVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX1 N )
"

         from c1 have c2:" r= PI_Local_GetX_PutX1 N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_InvAck_1_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_InvAck_1_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_1_HomeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Get_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Get_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Nak1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX10_home N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX10_home N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX10_homeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_Get  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_Get  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_GetVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak3VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Local_GetX_PutX10 N  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Local_GetX_PutX10 N  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX10VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX2 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX2 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Get_Put1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Get_Put1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Put1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_PutX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_PutX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_PutXVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= Store  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= Store  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis StoreVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_FAck )
"

         from c1 have c2:" r= NI_FAck "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_FAck ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_FAckVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX3 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX3 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX3VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX3 )
"

         from c1 have c2:" r= PI_Local_GetX_PutX3 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_GetX_PutX  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_GetX_PutX  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_PutXVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX8_home N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX8_home N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX8_homeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put1 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put1 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_GetX1 )
"

         from c1 have c2:" r= PI_Local_GetX_GetX1 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= StoreHome )
"

         from c1 have c2:" r= StoreHome "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (StoreHome ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis StoreHomeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_GetX_Nak  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_GetX_Nak  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_NakVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Inv  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Inv  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_PutX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_PutX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_PutXVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX4 )
"

         from c1 have c2:" r= PI_Local_GetX_PutX4 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX4 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX4 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX4VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Nak  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Nak  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_NakVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX2 N )
"

         from c1 have c2:" r= PI_Local_GetX_PutX2 N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= NI_Local_Put )
"

         from c1 have c2:" r= NI_Local_Put "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Local_PutVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak1VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Nak_Clear )
"

         from c1 have c2:" r= NI_Nak_Clear "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Nak_ClearVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_PutX )
"

         from c1 have c2:" r= PI_Local_PutX "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_PutXVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak3VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_GetX_Nak_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_GetX_Nak_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_Nak_HomeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Get_Get )
"

         from c1 have c2:" r= PI_Local_Get_Get "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_Get_GetVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX9 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX9 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX9VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_GetX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_GetX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_GetXVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ReplaceHome )
"

         from c1 have c2:" r= NI_ReplaceHome "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ReplaceHomeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_GetX_PutX_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_GetX_PutX_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_PutX_HomeVsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv9  iInv1 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put3VsInv9 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }ultimately show "invHoldForRule' s invf r (invariants N) "
          by blast
     qed
end


(*  Title:      JinjaThreads/BV/BVSpec.thy
    Author:     Cornelia Pusch, Gerwin Klein, Andreas Lochbihler

    Based on the theory Jinja/BV/BVSpec
*)

header {* \isaheader{The Bytecode Verifier}\label{sec:BVSpec} *}

theory BVSpec
imports
  Effect
begin

text {*
  This theory contains a specification of the BV. The specification
  describes correct typings of method bodies; it corresponds
  to type \emph{checking}.
*}

-- "The method type only contains declared classes:"
definition check_types :: "'m prog \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> ty\<^sub>i' err list \<Rightarrow> bool"
where
  "check_types P mxs mxl \<tau>s \<equiv> set \<tau>s \<subseteq> states P mxs mxl"

-- "An instruction is welltyped if it is applicable and its effect"
-- "is compatible with the type at all successor instructions:"
definition wt_instr :: "['m prog,ty,nat,pc,ex_table,'addr instr,pc,ty\<^sub>m] \<Rightarrow> bool"
  ("_,_,_,_,_ \<turnstile> _,_ :: _" [60,0,0,0,0,0,0,61] 60)
where
  "P,T,mxs,mpc,xt \<turnstile> i,pc :: \<tau>s \<equiv>
  app i P mxs T pc mpc xt (\<tau>s!pc) \<and>
  (\<forall>(pc',\<tau>') \<in> set (eff i P pc xt (\<tau>s!pc)). P \<turnstile> \<tau>' \<le>' \<tau>s!pc')"

-- {* The type at @{text "pc=0"} conforms to the method calling convention: *}
definition wt_start :: "['m prog,cname,ty list,nat,ty\<^sub>m] \<Rightarrow> bool"
where
  "wt_start P C Ts mxl\<^sub>0 \<tau>s \<equiv>
  P \<turnstile> Some ([],OK (Class C)#map OK Ts@replicate mxl\<^sub>0 Err) \<le>' \<tau>s!0"

-- "A method is welltyped if the body is not empty,"
-- "if the method type covers all instructions and mentions"
-- "declared classes only, if the method calling convention is respected, and"
-- "if all instructions are welltyped."
definition wt_method :: "['m prog,cname,ty list,ty,nat,nat,'addr instr list, ex_table,ty\<^sub>m] \<Rightarrow> bool"
where
  "wt_method P C Ts T\<^sub>r mxs mxl\<^sub>0 is xt \<tau>s \<equiv>
  0 < size is \<and> size \<tau>s = size is \<and>
  check_types P mxs (1+size Ts+mxl\<^sub>0) (map OK \<tau>s) \<and>
  wt_start P C Ts mxl\<^sub>0 \<tau>s \<and>
  (\<forall>pc < size is. P,T\<^sub>r,mxs,size is,xt \<turnstile> is!pc,pc :: \<tau>s)"

-- "A program is welltyped if it is wellformed and all methods are welltyped"
definition wf_jvm_prog_phi :: "ty\<^sub>P \<Rightarrow> 'addr jvm_prog \<Rightarrow> bool" ("wf'_jvm'_prog\<^bsub>_\<^esub>")
where
  "wf_jvm_prog\<^bsub>\<Phi>\<^esub> \<equiv>
    wf_prog (\<lambda>P C (M,Ts,T\<^sub>r,(mxs,mxl\<^sub>0,is,xt)).
      wt_method P C Ts T\<^sub>r mxs mxl\<^sub>0 is xt (\<Phi> C M))"

definition wf_jvm_prog :: "'addr jvm_prog \<Rightarrow> bool"
where
  "wf_jvm_prog P \<equiv> \<exists>\<Phi>. wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"

lemma wt_jvm_progD:
  "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P \<Longrightarrow> \<exists>wt. wf_prog wt P"
(*<*) by (unfold wf_jvm_prog_phi_def, blast) (*>*)

lemma wt_jvm_prog_impl_wt_instr:
  "\<lbrakk> wf_jvm_prog\<^bsub>\<Phi>\<^esub> P;
      P \<turnstile> C sees M:Ts \<rightarrow> T = \<lfloor>(mxs,mxl\<^sub>0,ins,xt)\<rfloor> in C; pc < size ins \<rbrakk>
  \<Longrightarrow> P,T,mxs,size ins,xt \<turnstile> ins!pc,pc :: \<Phi> C M"
(*<*)
  apply (unfold wf_jvm_prog_phi_def)
  apply (drule (1) sees_wf_mdecl)
  apply (simp add: wf_mdecl_def wt_method_def)
  done
(*>*)

lemma wt_jvm_prog_impl_wt_start:
  "\<lbrakk> wf_jvm_prog\<^bsub>\<Phi>\<^esub> P;
     P \<turnstile> C sees M:Ts \<rightarrow> T = \<lfloor>(mxs,mxl\<^sub>0,ins,xt)\<rfloor> in C \<rbrakk> \<Longrightarrow>
  0 < size ins \<and> wt_start P C Ts mxl\<^sub>0 (\<Phi> C M)"
(*<*)
  apply (unfold wf_jvm_prog_phi_def)
  apply (drule (1) sees_wf_mdecl)
  apply (simp add: wf_mdecl_def wt_method_def)
  done
(*>*)

end