(*  Title:       X86 instruction semantics and basic block symbolic execution
    Authors:     Freek Verbeek, Abhijith Bharadwaj, Joshua Bockenek, Ian Roessle, Timmy Weerwag, Binoy Ravindran
    Year:        2020
    Maintainer:  Freek Verbeek (freek@vt.edu)
*)

section "Removing superfluous memory writes"

theory StateCleanUp
  imports State "HOL-Eisbach.Eisbach"
begin

definition "assumptions \<equiv> id"

text \<open>We are going to make schematic theorems of the form:
      \[
        @{term assumptions} ?A \implies \ldots
      \]
      The assumptions will be generated on-the-fly. The seemingly weird lemmas below achieves that.\<close>

lemma assumptions_impI:
assumes "assumptions (P \<and> A)"
  shows "P"
  using assms
  by (auto simp add: assumptions_def)

lemma assumptions_conjE:
  shows "assumptions (P \<and> A) \<longleftrightarrow> P \<and> assumptions A"
  by (auto simp add: assumptions_def)

lemma assumptionsI:
  shows "assumptions True"
  by (auto simp add: assumptions_def)

text \<open>Consider two consecutive memory updates. If they write to the same memory locations, only one of these
      need to be kept. We formulate an Eisbach method to that end. \<close>

text \<open>Returns true if two states are equal except for a specific memory region.\<close>
definition eq_except_for_mem :: "state \<Rightarrow> state \<Rightarrow> 64 word \<Rightarrow> nat \<Rightarrow> 256 word \<Rightarrow> bool \<Rightarrow> bool"
  where "eq_except_for_mem \<sigma> \<sigma>' a si v b \<equiv> \<sigma> with [\<lbrakk>a,si\<rbrakk> :=\<^sub>m v] = (if b then \<sigma>' else \<sigma>' with [\<lbrakk>a,si\<rbrakk> :=\<^sub>m v])"

lemma eefm_start:
  assumes "eq_except_for_mem (\<sigma> with updates) (\<sigma> with updates') a si v b"
  shows "(\<sigma> with ((\<lbrakk>a,si\<rbrakk> :=\<^sub>m v)#updates)) = (if b then \<sigma> with updates' else \<sigma> with ((\<lbrakk>a,si\<rbrakk> :=\<^sub>m v)#updates'))"
  using assms
  by (auto simp add: eq_except_for_mem_def region_addresses_def state_with_updates.simps(2) state_update.simps)

lemma eefm_clean_mem:
assumes "si' \<le> si"
    and "eq_except_for_mem (\<sigma> with updates) (\<sigma> with updates') a si v b"
  shows "eq_except_for_mem (\<sigma> with ((\<lbrakk>a,si'\<rbrakk> :=\<^sub>m v')#updates)) (\<sigma> with updates') a si v b"
  using assms
  apply (auto simp add: eq_except_for_mem_def state_with_updates.simps(2) state_update.simps)
  subgoal
    apply (cases "\<sigma> with updates";cases "\<sigma> with updates'";cases "\<sigma>")
    by (auto simp add: override_on_def region_addresses_iff)
  apply (cases "\<sigma> with updates";cases "\<sigma> with updates'")
  apply (auto simp add: override_on_def region_addresses_iff)
  apply (rule ext)
  apply (auto split: if_splits)
  by meson

method eefm_clean_mem = (rule eefm_clean_mem, (simp (no_asm);fail))

lemma eefm_clean_mem_enclosed:
  assumes "si < 32" (* due to 256 words being written to memory *)
      and "enclosed a' si' a si"
      and "eq_except_for_mem (\<sigma> with updates) (\<sigma> with updates') a' si' v' b"
  shows "eq_except_for_mem (\<sigma> with ((\<lbrakk>a,si\<rbrakk> :=\<^sub>m v)#updates))
                           (\<sigma> with ((\<lbrakk>a,si\<rbrakk> :=\<^sub>m overwrite (8 * unat (a' - a)) (8 * unat (a' - a) + 8*si') v (v' << unat (a'-a)*8))#updates'))
                           a' si' v' True"
proof(cases b)
  case True
  thus ?thesis
    using assms(3)
    apply (auto simp add: eq_except_for_mem_def state_with_updates.simps(2) state_update.simps)
    apply (cases "\<sigma> with updates";cases "\<sigma> with updates'")
    apply (auto simp add: override_on_def)
    apply (rule ext)
    apply (auto)

    apply (rule word_eqI)
    subgoal premises prems for _ _ _ _ x n
    proof-
      have 1: "unat (x - a) - unat (a' - a) = unat(x - a')"
        using address_in_enclosed_region_as_linarith[OF assms(2),of x]
              address_of_enclosed_region_ge[OF assms(2)]
              word_le_nat_alt prems(4-5)
        by (auto simp add: unat_sub_if_size word_size)
      thus ?thesis
        using prems address_in_enclosed_region[of a' si' a si x,OF assms(2)] assms(1)
        by (auto simp add: word_size take_byte_shiftlr_256 nth_take_byte_overwrite)
    qed

    apply (rule word_eqI)
    subgoal for _ _ _ _ x n
      using notin_region_addresses_sub[of x a' si' a]
      by (auto simp add: word_size nth_take_byte_overwrite)
    done
next
  case False
  thus ?thesis
    using assms(3)
    apply (auto simp add: eq_except_for_mem_def state_with_updates.simps(2) state_update.simps)
    apply (cases "\<sigma> with updates";cases "\<sigma> with updates'")
    apply (auto simp add: override_on_def)
    apply (rule ext)
    using enclosed_spec[OF assms(2)]
    apply (auto)

    subgoal premises prems for _ _ _ _ _ x
    proof-
      have 1: "unat (x - a) - unat (a' - a) = unat(x - a')"
        using address_in_enclosed_region_as_linarith[OF assms(2),of x]
              address_of_enclosed_region_ge[OF assms(2)]
              word_le_nat_alt prems(6)
        by (auto simp add: unat_sub_if_size word_size)
      show ?thesis
        apply (rule word_eqI)
        using 1 prems address_in_enclosed_region[of a' si' a si x,OF assms(2)] assms(1)
        by (auto simp add: word_size take_byte_shiftlr_256 nth_take_byte_overwrite)
    qed

     subgoal for _ _ _ _ _ x
       apply (rule word_eqI)
       using notin_region_addresses_sub[of x a' si' a]
       by (auto simp add: word_size nth_take_byte_overwrite)
     by meson
qed

lemmas eefm_clean_mem_enclosed_plus  = eefm_clean_mem_enclosed[OF _ enclosed_plus, simplified]
lemmas eefm_clean_mem_enclosed_minus_numeral = eefm_clean_mem_enclosed[OF _ enclosed_minus_minus, of _ "numeral n" "numeral m"] for n m

method eefm_clean_mem_enclosed_plus =
        (rule eefm_clean_mem_enclosed_plus, (
            (simp (no_asm);fail), (simp (no_asm);fail),
            (
             (simp (no_asm_simp);fail) |
             (rule assumptions_impI[of "_ + _ < 18446744073709551616"],simp (no_asm_simp),subst (asm) assumptions_conjE))
            )
        )

method eefm_clean_mem_enclosed_minus_numeral =
        (rule eefm_clean_mem_enclosed_minus_numeral, (
            (simp (no_asm);fail), (simp (no_asm);fail), (simp (no_asm);fail), (simp (no_asm);fail), (simp (no_asm);fail),
            (
             (simp (no_asm_simp);fail) |
             (rule assumptions_impI[of "_ \<le> _"],simp (no_asm_simp),subst (asm) assumptions_conjE))
            )
        )

lemma eefm_next_mem:
assumes "separate a si a' si'"
   and "eq_except_for_mem (\<sigma> with updates) (\<sigma> with updates') a si v b"
 shows "eq_except_for_mem (\<sigma> with ((\<lbrakk>a',si'\<rbrakk> :=\<^sub>m v')#updates)) (\<sigma> with ((\<lbrakk>a',si'\<rbrakk> :=\<^sub>m v')#updates')) a si v b"
  using assms
  apply (auto simp add: eq_except_for_mem_def override_on_def separate_def state_with_updates.simps(2) state_update.simps)
  apply (cases "\<sigma> with updates";cases "\<sigma> with updates'")
  apply (auto simp add: override_on_def)
  apply (rule ext)
   apply (auto)
  apply (cases "\<sigma> with updates";cases "\<sigma> with updates'")
  apply (auto simp add: override_on_def)
  apply (rule ext)
  apply (auto)
  by (metis select_convs(2))

method eefm_next_mem =
        (rule eefm_next_mem,
            (  (simp (no_asm_simp) add: separate_simps state_simps; fail) |
               (rule assumptions_impI[of "separate _ _ _ _ "],simp (no_asm_simp),subst (asm) assumptions_conjE))
        )

lemma eefm_end:
  shows "eq_except_for_mem (\<sigma> with updates) (\<sigma> with updates) a si v False"
  by (auto simp add: eq_except_for_mem_def)

text \<open>We need a tactic exactly like ``subst'' but that applies to the outer most term.\<close>

ML_file \<open>MySubst.ML\<close>

text \<open>The following method takes a goal with state with symbolic state updates.
      It first applies @{thm eefm_start}, considering the outer-most memory update to some region $\llbracket a, si \rrbracket$.
      A list @{term updates'} is generated that produces a similar state except for region $\llbracket a, si \rrbracket$.
      The list thus can have fewer updates since any update to a region that is enclosed in region $\llbracket a, si \rrbracket$ can be removed.
      Consecutively, this method applies rules to determine whether a state update can be kept, merged or removed.
      It may add assumptions to the goal, that assume no overflow.
\<close>

method clean_up_mem = (
    mysubst eefm_start,
    ( eefm_clean_mem | eefm_clean_mem_enclosed_plus | eefm_clean_mem_enclosed_minus_numeral | eefm_next_mem)+,
    rule eefm_end,
    simp (no_asm),
    ((match premises in A[thin]: "assumptions (?A \<and> ?B)" \<Rightarrow> \<open>cut_tac A;subst (asm) assumptions_conjE, erule conjE \<close>)+)?
  )

text \<open>The method above applies to one state update. This method can be repeated as long as modifies
      the goal, as it always makes the goal smaller. The method below repeats a given method until
      the goal is unchanged. In deterministic fashion (a la the REPEAT\_DETERM tactic).\<close>

method_setup repeat_until_unchanged = \<open>
  Method.text_closure >>
    (fn text => fn ctxt => fn using =>
          \<comment> \<open>parse the method supplied as parameter\<close>
      let val ctxt_tac = Method.evaluate_runtime text ctxt using
          fun repeat_until_unchanged (ctxt,st) =
            case Seq.pull (ctxt_tac (ctxt,st)) of
                SOME (Seq.Result (ctxt',st'), _) =>
                  if Thm.eq_thm (st, st') then
                    Seq.make_results (Seq.succeed (ctxt',st'))
                  else
                    repeat_until_unchanged (ctxt',st')
              | _ => Seq.make_results (Seq.succeed (ctxt,st))
      in
        repeat_until_unchanged
      end)
\<close>

method clean_up = repeat_until_unchanged clean_up_mem

end


theory KVS_WAL_ordered_disk
imports Main Option String
begin

(* We model the disk as list of strings. In this preliminary version, we assume a string can be contained in disk slot (ie., a block) *)
type_synonym disk = "string list"

(* Convenience type which models a list of disk states that could result as an operation on the disk*)
type_synonym disk_states = "disk list"

(* Usually, the log is a dedicated portion in the disk. In our model, we model it as a separate disk. This pair of data and log portions
make up the actual disk*)
record diskpair = data :: disk
                  log :: disk

(* Convenience type which models a list of diskpairs *)
type_synonym diskpairlist = "diskpair list"

(* Helper to enumerate disk lists *)
fun enumdisks :: "disk list list  => disk list"
where
  "enumdisks [] = []"
| "enumdisks (x#d1) = (x) @ enumdisks d1"

(* Helper to enumerate diskpair lists *)
fun enumdiskpairs :: "diskpair list list  => diskpair list"
where
  "enumdiskpairs [] = []"
| "enumdiskpairs (x#d1) = (x) @ enumdiskpairs d1"

(* Helper to check if a given element in present in a list *)
fun list_contains :: "'a \<Rightarrow> 'a list \<Rightarrow> bool"
where
"list_contains item [] = False" |
"list_contains item (first # others) = ((item = first) \<or> (list_contains item others))"

(* Log update : This function models how a key value pair is updated on the log *)
(* Param1: key :: string *)
(* Param2: value :: string *)
(* returns: all possible log states :: disk_states *)
(* There are 3 slots in the log. The first slot contains information about the log itself
   It can either contain 'N' which means there is a log update currently happening or 'C'
   which means the log update completed and it is safe to apply the update. Note: We assume
   the log is cleaned properly (without failures) after applying an update from the log.
*)
fun log_update :: "string \<Rightarrow> string \<Rightarrow> disk_states"
where
"log_update key value  = [
                          [[],[],[]][0:=''N''],
                          [[],[],[]][0:=''N'',(Suc 0):=key],
                          [[],[],[]][0:=''N'',(Suc 0):=key,(Suc (Suc 0)):=value],
                          [[],[],[]][0:=''C'',(Suc 0):=key,(Suc (Suc 0)):=value]
                         ]"

(* Log recovery : This function models how the log is recovered. *)
(* Param1: index_to_apply :: nat *)
(* Param2: data_portion :: disk *)
(* Param3: log_portion :: disk *)
(* returns: data_portion :: disk*)
(* Checks if the first slot in the log is 'C' which means the log update has completed properly.
   In that case, it applies the update to index_to_apply in the data portion. Note: Recovery itself
   can crash. This is modelled by function recover_crash *)
fun recover :: "nat \<Rightarrow> disk \<Rightarrow> disk \<Rightarrow> disk"
where
"recover idx data_disk log_disk  = (if(log_disk!0 = ''C'')
                 then data_disk[idx := log_disk!1, (Suc idx) := log_disk!2] else data_disk)"

(* Log recovery(crashing version) : This function models how the log is recovered. *)
(* Param1: index_to_apply :: nat *)
(* Param2: data_portion :: disk *)
(* Param3: log_portion :: disk *)
(* returns nothing *)
(* Checks if the first slot in the log is 'C' which means the log update has completed properly.
   In that case, it applies the update to index_to_apply in the data portion and marks the first slot as 'D'.
   Otherwise does nothing *)
(* returns: all possible disk pairs that would result if the recovery crashes :: diskpairlist *)
fun recover_crash :: "nat \<Rightarrow> disk \<Rightarrow> disk \<Rightarrow> diskpairlist"
where
"recover_crash idx data_disk log_disk  =
                 (if(log_disk!0 = ''C'')
                 then
                 [
                  (| data = data_disk, log = log_disk |),
                  (| data = data_disk[idx := log_disk!1],
                                   log = log_disk |),
                  (| data = data_disk[idx := log_disk!1, (Suc idx) := log_disk!2],
                                   log = log_disk |),
                  (| data = data_disk[idx := log_disk!1, (Suc idx) := log_disk!2],
                                   log = log_disk[0 := ''D''] |)
                 ]
                 else
                 [
                  (| data = data_disk, log = log_disk |)
                 ]
                 )"

(* Log checkpointing : This function models how the log is checkpointed. *)
(* Param1: index_to_apply :: nat *)
(* Param2: data_portion :: disk *)
(* Param3: log_portion :: disk *)
(* returns nothing *)
(* Same as recovery but called during normal operation and not after failures *)
(* returns: data_portion :: disk*)
fun checkpoint :: "nat \<Rightarrow> disk \<Rightarrow> disk \<Rightarrow> disk"
where
"checkpoint idx data_disk log_disk  =(if(log_disk!0 = ''C'')
                 then data_disk[idx := log_disk!1, (Suc idx) := log_disk!2] else data_disk)"

(* KV_Put : This function models how our toy key-value store PUT operation works. *)
(* Param1: key :: string *)
(* Param1: value :: string *)
(* Param1: data_portion :: disk *)
(* Param2: index_to_apply: nat *)
(* returns all possible disk states that could result on doing this PUT operation :: disk_states *)
fun kv_put :: "string \<Rightarrow> string \<Rightarrow> disk \<Rightarrow> nat \<Rightarrow> disk_states"
where
"kv_put k v current_disk idx= map (checkpoint idx current_disk) (log_update k v)"

(*Test code*)
value "log_update ''a'' ''b''"
value "enumdisks [ [[''1'',''2''],[''3'',''4''],[''5'',''6'']],  [[''7'',''8''],[''9'',''10''],[''11'',''12'']] ]"
value "enumdiskpairs (map (recover_crash 1 [''x'',''y'',''z'']) (log_update ''a'' ''b''))"
value "map (recover 1 [''x'',''y'',''z'']) (log_update ''a'' ''b'')"
value "map (recover 5 [''1'',''2'',''3'',''4'',''5'',''6'',''7'']) (log_update ''a'' ''b'')"
value "enumdiskpairs (map (recover_crash 5 [''1'',''2'',''3'',''4'',''5'',''6'',''7'']) (log_update ''a'' ''b''))"
(*End of test code*)

(* Assuming no crashes during recovery, prove that the logging mechanism can atomically update a key value pair
   on disk *)
theorem atomic_recovery_no_crash_theorem:
shows   "length d \<ge> 2 \<and> (Suc idx) < length d \<and> (list_contains after (map (recover idx d) (log_update s1 s2))) \<and> s1\<noteq>[] \<and> s2 \<noteq>[]
         \<Longrightarrow>
         after!idx=d!idx \<and> after!(Suc idx)=d!(Suc idx)
         \<or>
         after!idx=s1 \<and> after!(Suc idx)=s2"
apply(auto)
done

(* Assuming crashes during recovery, prove that the logging mechanism can atomically update a key value pair
   on disk *)
theorem atomic_recovery_crash_theorem:
shows   "length d \<ge> 2 \<and> (Suc idx) < length d  \<and> ( list_contains after (enumdiskpairs (map (recover_crash idx d) (log_update s1 s2) ) ) )  \<and> s1\<noteq>[] \<and> s2 \<noteq>[]
         \<Longrightarrow>
         (log after)!0=''D'' \<Longrightarrow> (data after)!idx=s1 \<and> (data after)!(Suc idx)=s2
         \<and>
         (log after)!0=''N'' \<Longrightarrow> (data after)!idx=d!idx \<and> (data after)!(Suc idx)=d!(Suc idx)"
apply(auto)
done

(* Atomic KV puts *)
theorem kv_put_atomic_theorem:
shows   "length d \<ge> 2 \<and> (Suc idx) < length d  \<and> (list_contains after (kv_put s1 s2 d idx)) \<and> s1\<noteq>[] \<and> s2 \<noteq>[]
         \<Longrightarrow>
         after!idx=d!idx \<and> after!(Suc idx)=d!(Suc idx)
         \<or>
         after!idx=s1 \<and> after!(Suc idx)=s2"
apply(auto)
done


section \<open>Dynamic Backward Slice\<close>

theory DynSlice imports DependentLiveVariables BitVector "../Basic/SemanticsCFG" begin

subsection \<open>Backward slice of paths\<close>

context DynPDG begin

fun slice_path :: "'edge list \<Rightarrow> bit_vector"
  where "slice_path [] = []"
  | "slice_path (a#as) = (let n' = last(targetnodes (a#as)) in
                           (sourcenode a -a#as\<rightarrow>\<^sub>d* n')#slice_path as)"

(*<*)declare Let_def [simp](*>*)

lemma slice_path_length:
  "length(slice_path as) = length as"
by(induct as) auto

lemma slice_path_right_Cons:
  assumes slice:"slice_path as = x#xs"
  obtains a' as' where "as = a'#as'" and "slice_path as' = xs"
proof(atomize_elim)
  from slice show "\<exists>a' as'. as = a'#as' \<and> slice_path as' = xs"
    by(induct as) auto
qed

subsection \<open>The proof of the fundamental property of (dynamic) slicing\<close>

fun select_edge_kinds :: "'edge list \<Rightarrow> bit_vector \<Rightarrow> 'state edge_kind list"
where "select_edge_kinds [] [] = []"
  | "select_edge_kinds (a#as) (b#bs) = (if b then kind a
      else (case kind a of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>))#select_edge_kinds as bs"

definition slice_kinds :: "'edge list \<Rightarrow> 'state edge_kind list"
  where "slice_kinds as = select_edge_kinds as (slice_path as)"

lemma select_edge_kinds_max_bv:
  "select_edge_kinds as (replicate (length as) True) = kinds as"
by(induct as,auto simp:kinds_def)

lemma slice_path_leqs_information_same_Uses:
  "\<lbrakk>n -as\<rightarrow>* n'; bs \<preceq>\<^sub>b bs'; slice_path as = bs;
    select_edge_kinds as bs = es; select_edge_kinds as bs' = es';
    \<forall>V xs. (V,xs,as) \<in> dependent_live_vars n' \<longrightarrow> state_val s V = state_val s' V;
    preds es' s'\<rbrakk>
  \<Longrightarrow> (\<forall>V \<in> Use n'. state_val (transfers es s) V =
      state_val (transfers es' s') V) \<and> preds es s"
proof(induct bs bs' arbitrary:as es es' n s s' rule:bv_leqs.induct)
  case 1
  from \<open>slice_path as = []\<close> have "as = []" by(cases as) auto
  with \<open>select_edge_kinds as [] = es\<close> \<open>select_edge_kinds as [] = es'\<close>
  have "es = []" and "es' = []" by simp_all
  { fix V assume "V \<in> Use n'"
    hence "(V,[],[]) \<in> dependent_live_vars n'" by(rule dep_vars_Use)
    with \<open>\<forall>V xs. (V,xs,as) \<in> dependent_live_vars n' \<longrightarrow>
                  state_val s V = state_val s' V\<close> \<open>V \<in> Use n'\<close> \<open>as = []\<close>
    have "state_val s V = state_val s' V" by blast }
  with \<open>es = []\<close> \<open>es' = []\<close> show ?case by simp
next
  case (2 x xs y ys)
  note all = \<open>\<forall>V xs. (V,xs,as) \<in> dependent_live_vars n' \<longrightarrow>
                     state_val s V = state_val s' V\<close>
  note IH = \<open>\<And>as es es' n s s'. \<lbrakk>n -as\<rightarrow>* n'; xs \<preceq>\<^sub>b ys; slice_path as = xs;
                        select_edge_kinds as xs = es; select_edge_kinds as ys = es';
                        \<forall>V xs. (V,xs,as) \<in> dependent_live_vars n' \<longrightarrow>
                                   state_val s V = state_val s' V;
                           preds es' s'\<rbrakk>
            \<Longrightarrow> (\<forall>V \<in> Use n'. state_val (transfers es s) V =
                state_val (transfers es' s') V) \<and> preds es s\<close>
  from \<open>x#xs \<preceq>\<^sub>b y#ys\<close> have "x \<longrightarrow> y" and "xs \<preceq>\<^sub>b ys" by simp_all
  from \<open>slice_path as = x#xs\<close> obtain a' as' where "as = a'#as'"
    and "slice_path as' = xs" by(erule slice_path_right_Cons)
  from \<open>as = a'#as'\<close> \<open>select_edge_kinds as (x#xs) = es\<close>
  obtain ex esx where "es = ex#esx"
    and ex:"ex = (if x then kind a'
                    else (case kind a' of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>))"
    and "select_edge_kinds as' xs = esx" by auto
  from \<open>as = a'#as'\<close> \<open>select_edge_kinds as (y#ys) = es'\<close> obtain ex' esx'
    where "es' = ex'#esx'"
    and ex':"ex' = (if y then kind a'
                    else (case kind a' of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>))"
    and "select_edge_kinds as' ys = esx'" by auto
  from \<open>n -as\<rightarrow>* n'\<close> \<open>as = a'#as'\<close> have [simp]:"n = sourcenode a'"
    and "valid_edge a'" and "targetnode a' -as'\<rightarrow>* n'"
    by(auto elim:path_split_Cons)
  from \<open>n -as\<rightarrow>* n'\<close> \<open>as = a'#as'\<close> have "last(targetnodes as) = n'"
    by(fastforce intro:path_targetnode)
  from \<open>preds es' s'\<close> \<open>es' = ex'#esx'\<close> have "pred ex' s'"
    and "preds esx' (transfer ex' s')" by simp_all
  show ?case
  proof(cases "as' = []")
    case True
    hence [simp]:"as' = []" by simp
    with \<open>slice_path as' = xs\<close> \<open>xs \<preceq>\<^sub>b ys\<close>
    have [simp]:"xs = [] \<and> ys = []" by auto(cases ys,auto)+
    with \<open>select_edge_kinds as' xs = esx\<close> \<open>select_edge_kinds as' ys = esx'\<close>
    have [simp]:"esx = []" and [simp]:"esx' = []" by simp_all
    from True \<open>targetnode a' -as'\<rightarrow>* n'\<close>
    have [simp]:"n' = targetnode a'" by(auto elim:path.cases)
    show ?thesis
    proof(cases x)
      case True
      with \<open>x \<longrightarrow> y\<close> ex ex' have [simp]:"ex = kind a' \<and> ex' = kind a'" by simp
      have "pred ex s"
      proof(cases ex)
        case (Predicate Q)
        with ex ex' True \<open>x \<longrightarrow> y\<close> have [simp]:"transfer ex s = s"
          and [simp]:"transfer ex' s' = s'"
          by(cases "kind a'",auto)+
        show ?thesis
        proof(cases "n -[a']\<rightarrow>\<^sub>c\<^sub>d n'")
          case True
          { fix V' assume "V' \<in> Use n"
            with True \<open>valid_edge a'\<close>
            have "(V',[],a'#[]@[]) \<in> dependent_live_vars n'"
              by(fastforce intro:dep_vars_Cons_cdep DynPDG_path_Nil
                          simp:targetnodes_def)
            with all \<open>as = a'#as'\<close> have "state_val s V' = state_val s' V'"
              by fastforce }
          with \<open>pred ex' s'\<close> \<open>valid_edge a'\<close>
          show ?thesis by(fastforce elim:CFG_edge_Uses_pred_equal)
        next
          case False
          from ex True Predicate have "kind a' = (Q)\<^sub>\<surd>" by(auto split:if_split_asm)
          from True \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close> have "n -[a']\<rightarrow>\<^sub>d* n'"
            by(auto simp:targetnodes_def)
          thus ?thesis
          proof(induct rule:DynPDG_path.cases)
            case (DynPDG_path_Nil nx)
            hence False by simp
            thus ?case by simp
          next
            case (DynPDG_path_Append_cdep nx asx n'' asx' nx')
            from \<open>[a'] = asx@asx'\<close>
            have "(asx = [a'] \<and> asx' = []) \<or> (asx = [] \<and> asx' = [a'])"
              by (cases asx) auto
            hence False
            proof
              assume "asx = [a'] \<and> asx' = []"
              with \<open>n'' -asx'\<rightarrow>\<^sub>c\<^sub>d nx'\<close> show False
                by(fastforce elim:DynPDG_edge.cases dest:dyn_control_dependence_path)
            next
              assume "asx = [] \<and> asx' = [a']"
              with \<open>nx -asx\<rightarrow>\<^sub>d* n''\<close> have "nx = n''" and "asx' = [a']"
                by(auto intro:DynPDG_empty_path_eq_nodes)
              with \<open>n = nx\<close> \<open>n' = nx'\<close> \<open>n'' -asx'\<rightarrow>\<^sub>c\<^sub>d nx'\<close> False
              show False by simp
            qed
            thus ?thesis by simp
          next
            case (DynPDG_path_Append_ddep nx asx n'' V asx' nx')
            from \<open>[a'] = asx@asx'\<close>
            have "(asx = [a'] \<and> asx' = []) \<or> (asx = [] \<and> asx' = [a'])"
              by (cases asx) auto
            thus ?case
            proof
              assume "asx = [a'] \<and> asx' = []"
              with \<open>n'' -{V}asx'\<rightarrow>\<^sub>d\<^sub>d nx'\<close> have False
                by(fastforce elim:DynPDG_edge.cases simp:dyn_data_dependence_def)
              thus ?thesis by simp
            next
              assume "asx = [] \<and> asx' = [a']"
              with \<open>nx -asx\<rightarrow>\<^sub>d* n''\<close> have "nx = n''"
                by(simp add:DynPDG_empty_path_eq_nodes)
              { fix V' assume "V' \<in> Use n"
                from \<open>n'' -{V}asx'\<rightarrow>\<^sub>d\<^sub>d nx'\<close> \<open>asx = [] \<and> asx' = [a']\<close> \<open>n' = nx'\<close>
                have "(V,[],[]) \<in> dependent_live_vars n'"
                  by(fastforce intro:dep_vars_Use elim:DynPDG_edge.cases
                    simp:dyn_data_dependence_def)
                with \<open>V' \<in> Use n\<close> \<open>n'' -{V}asx'\<rightarrow>\<^sub>d\<^sub>d nx'\<close> \<open>asx = [] \<and> asx' = [a']\<close>
                  \<open>n = nx\<close> \<open>nx = n''\<close> \<open>n' = nx'\<close>
                have "(V',[],[a']) \<in> dependent_live_vars n'"
                  by(auto elim:dep_vars_Cons_ddep simp:targetnodes_def)
                with all \<open>as = a'#as'\<close> have "state_val s V' = state_val s' V'"
                  by fastforce }
              with \<open>pred ex' s'\<close> \<open>valid_edge a'\<close> ex ex' True \<open>x \<longrightarrow> y\<close> show ?thesis
                by(fastforce elim:CFG_edge_Uses_pred_equal)
            qed
          qed
        qed
      qed simp
      { fix V assume "V \<in> Use n'"
        from \<open>V \<in> Use n'\<close> have "(V,[],[]) \<in> dependent_live_vars n'"
          by(rule dep_vars_Use)
        have "state_val (transfer ex s) V = state_val (transfer ex' s') V"
        proof(cases "n -{V}[a']\<rightarrow>\<^sub>d\<^sub>d n'")
          case True
          hence "V \<in> Def n"
            by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)
          have "\<And>V. V \<in> Use n \<Longrightarrow> state_val s V = state_val s' V"
          proof -
            fix V' assume "V' \<in> Use n"
            with \<open>(V,[],[]) \<in> dependent_live_vars n'\<close> True
            have "(V',[],[a']) \<in> dependent_live_vars n'"
              by(fastforce intro:dep_vars_Cons_ddep simp:targetnodes_def)
            with all \<open>as = a'#as'\<close> show "state_val s V' = state_val s' V'" by auto
          qed
          with \<open>valid_edge a'\<close> \<open>pred ex' s'\<close> \<open>pred ex s\<close>
          have "\<forall>V \<in> Def n. state_val (transfer (kind a') s) V =
                              state_val (transfer (kind a') s') V"
            by simp(rule CFG_edge_transfer_uses_only_Use,auto)
          with \<open>V \<in> Def n\<close> have "state_val (transfer (kind a') s) V =
                         state_val (transfer (kind a') s') V"
            by simp
          thus ?thesis by fastforce
        next
          case False
          with \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
            \<open>(V,[],[]) \<in> dependent_live_vars n'\<close>
          have "(V,[a'],[a']) \<in> dependent_live_vars n'"
            by(fastforce intro:dep_vars_Cons_keep)
          from \<open>(V,[a'],[a']) \<in> dependent_live_vars n'\<close> all \<open>as = a'#as'\<close>
          have states_eq:"state_val s V = state_val s' V"
            by auto
          from \<open>valid_edge a'\<close> \<open>V \<in> Use n'\<close> False \<open>pred ex s\<close>
          have "state_val (transfers (kinds [a']) s) V = state_val s V"
            apply(auto intro!:no_ddep_same_state path_edge simp:targetnodes_def)
            apply(simp add:kinds_def)
            by(case_tac as',auto)
          moreover
          from \<open>valid_edge a'\<close> \<open>V \<in> Use n'\<close> False \<open>pred ex' s'\<close>
          have "state_val (transfers (kinds [a']) s') V = state_val s' V"
            apply(auto intro!:no_ddep_same_state path_edge simp:targetnodes_def)
            apply(simp add:kinds_def)
            by(case_tac as',auto)
          ultimately show ?thesis using states_eq by(auto simp:kinds_def)
        qed }
      hence "\<forall>V \<in> Use n'. state_val (transfer ex s) V =
                                state_val (transfer ex' s') V" by simp
      with \<open>pred ex s\<close> \<open>es = ex#esx\<close> \<open>es' = ex'#esx'\<close> show ?thesis by simp
    next
      case False
      with ex have cases_x:"ex = (case kind a' of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>)"
        by simp
      from cases_x have "pred ex s" by(cases "kind a'",auto)
      show ?thesis
      proof(cases y)
        case True
        with ex' have [simp]:"ex' = kind a'" by simp
        { fix V assume "V \<in> Use n'"
          from \<open>V \<in> Use n'\<close> have "(V,[],[]) \<in> dependent_live_vars n'"
            by(rule dep_vars_Use)
          from \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close> \<open>\<not> x\<close>
          have "\<not> n -[a']\<rightarrow>\<^sub>d* n'" by(simp add:targetnodes_def)
          hence "\<not> n -{V}[a']\<rightarrow>\<^sub>d\<^sub>d n'" by(fastforce dest:DynPDG_path_ddep)
          with \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
            \<open>(V,[],[]) \<in> dependent_live_vars n'\<close>
          have "(V,[a'],[a']) \<in> dependent_live_vars n'"
            by(fastforce intro:dep_vars_Cons_keep)
          with all \<open>as = a'#as'\<close> have "state_val s V = state_val s' V" by auto
          from \<open>valid_edge a'\<close> \<open>V \<in> Use n'\<close> \<open>pred ex' s'\<close>
            \<open>\<not> n -{V}[a']\<rightarrow>\<^sub>d\<^sub>d n'\<close> \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
          have "state_val (transfers (kinds [a']) s') V = state_val s' V"
            apply(auto intro!:no_ddep_same_state path_edge)
            apply(simp add:kinds_def)
            by(case_tac as',auto)
          with \<open>state_val s V = state_val s' V\<close> cases_x
          have "state_val (transfer ex s) V =
                state_val (transfer ex' s') V"
            by(cases "kind a'",simp_all add:kinds_def) }
        hence "\<forall>V \<in> Use n'. state_val (transfer ex s) V =
                           state_val (transfer ex' s') V" by simp
        with \<open>as = a'#as'\<close> \<open>es = ex#esx\<close> \<open>es' = ex'#esx'\<close> \<open>pred ex s\<close>
        show ?thesis by simp
      next
        case False
        with ex' have cases_y:"ex' = (case kind a' of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>)"
          by simp
        with cases_x have [simp]:"ex = ex'" by(cases "kind a'") auto
        { fix V assume "V \<in> Use n'"
          from \<open>V \<in> Use n'\<close> have "(V,[],[]) \<in> dependent_live_vars n'"
            by(rule dep_vars_Use)
          from \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close> \<open>\<not> x\<close>
          have "\<not> n -[a']\<rightarrow>\<^sub>d* n'" by(simp add:targetnodes_def)
          hence no_dep:"\<not> n -{V}[a']\<rightarrow>\<^sub>d\<^sub>d n'" by(fastforce dest:DynPDG_path_ddep)
          with \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
            \<open>(V,[],[]) \<in> dependent_live_vars n'\<close>
          have "(V,[a'],[a']) \<in> dependent_live_vars n'"
            by(fastforce intro:dep_vars_Cons_keep)
          with all \<open>as = a'#as'\<close> have "state_val s V = state_val s' V" by auto }
        with \<open>as = a'#as'\<close> cases_x \<open>es = ex#esx\<close> \<open>es' = ex'#esx'\<close> \<open>pred ex s\<close>
        show ?thesis by(cases "kind a'",auto)
      qed
    qed
  next
    case False
    show ?thesis
    proof(cases "\<forall>V xs. (V,xs,as') \<in> dependent_live_vars n' \<longrightarrow>
                        state_val (transfer ex s) V = state_val (transfer ex' s') V")
      case True
      hence imp':"\<forall>V xs. (V,xs,as') \<in> dependent_live_vars n' \<longrightarrow>
                       state_val (transfer ex s) V = state_val (transfer ex' s') V" .
      from IH[OF \<open>targetnode a' -as'\<rightarrow>* n'\<close> \<open>xs \<preceq>\<^sub>b ys\<close> \<open>slice_path as' = xs\<close>
        \<open>select_edge_kinds as' xs = esx\<close> \<open>select_edge_kinds as' ys = esx'\<close>
        this \<open>preds esx' (transfer ex' s')\<close>]
      have all':"\<forall>V\<in>Use n'. state_val (transfers esx (transfer ex s)) V =
                             state_val (transfers esx' (transfer ex' s')) V"
        and "preds esx (transfer ex s)" by simp_all
      have "pred ex s"
      proof(cases ex)
        case (Predicate Q)
        with \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close> \<open>last(targetnodes as) = n'\<close> ex
        have "ex = (\<lambda>s. True)\<^sub>\<surd> \<or> n -a'#as'\<rightarrow>\<^sub>d* n'"
          by(cases "kind a'",auto split:if_split_asm)
        thus ?thesis
        proof
          assume "ex = (\<lambda>s. True)\<^sub>\<surd>" thus ?thesis by simp
        next
          assume "n -a'#as'\<rightarrow>\<^sub>d* n'"
          with \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close> \<open>last(targetnodes as) = n'\<close> ex
          have [simp]:"ex = kind a'" by clarsimp
          with \<open>x \<longrightarrow> y\<close> ex ex' have [simp]:"ex' = ex" by(cases x) auto
          from \<open>n -a'#as'\<rightarrow>\<^sub>d* n'\<close> show ?thesis
          proof(induct rule:DynPDG_path_rev_cases)
            case DynPDG_path_Nil
            hence False by simp
            thus ?thesis by simp
          next
            case (DynPDG_path_cdep_Append n'' asx asx')
            from \<open>n -asx\<rightarrow>\<^sub>c\<^sub>d n''\<close>have "asx \<noteq> []"
              by(auto elim:DynPDG_edge.cases dest:dyn_control_dependence_path)
            with \<open>n -asx\<rightarrow>\<^sub>c\<^sub>d n''\<close> \<open>n'' -asx'\<rightarrow>\<^sub>d* n'\<close> \<open>a'#as' = asx@asx'\<close>
            have cdep:"\<exists>as1 as2 n''. n -a'#as1\<rightarrow>\<^sub>c\<^sub>d n'' \<and>
                                     n'' -as2\<rightarrow>\<^sub>d* n' \<and> as' = as1@as2"
              by(cases asx) auto
            { fix V assume "V \<in> Use n"
              with cdep \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
              have "(V,[],as) \<in> dependent_live_vars n'"
                by(fastforce intro:dep_vars_Cons_cdep)
              with all have "state_val s V = state_val s' V" by blast }
            with \<open>valid_edge a'\<close> \<open>pred ex' s'\<close>
            show ?thesis by(fastforce elim:CFG_edge_Uses_pred_equal)
          next
            case (DynPDG_path_ddep_Append V n'' asx asx')
            from \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> obtain ai ais where "asx = ai#ais"
              by(cases asx)(auto dest:DynPDG_ddep_edge_CFG_path)
            with \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> have "sourcenode ai = n"
              by(fastforce dest:DynPDG_ddep_edge_CFG_path elim:path.cases)
            from \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> \<open>asx = ai#ais\<close>
            have "last(targetnodes asx) = n''"
              by(fastforce intro:path_targetnode dest:DynPDG_ddep_edge_CFG_path)
            { fix V' assume "V' \<in> Use n"
              from \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> have "(V,[],[]) \<in> dependent_live_vars n''"
                by(fastforce elim:DynPDG_edge.cases dep_vars_Use
                            simp:dyn_data_dependence_def)
              with \<open>n'' -asx'\<rightarrow>\<^sub>d* n'\<close> have "(V,[],[]@asx') \<in> dependent_live_vars n'"
                by(rule dependent_live_vars_dep_dependent_live_vars)
              have "(V',[],as) \<in> dependent_live_vars n'"
              proof(cases "asx' = []")
                case True
                with \<open>n'' -asx'\<rightarrow>\<^sub>d* n'\<close> have "n'' = n'"
                  by(fastforce intro:DynPDG_empty_path_eq_nodes)
                with \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> \<open>V' \<in> Use n\<close> True \<open>as = a'#as'\<close>
                  \<open>a'#as' = asx@asx'\<close>
                show ?thesis by(fastforce intro:dependent_live_vars_ddep_empty_fst)
              next
                case False
                with \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> \<open>asx = ai#ais\<close>
                  \<open>(V,[],[]@asx') \<in> dependent_live_vars n'\<close>
                have "(V,ais@[],ais@asx') \<in> dependent_live_vars n'"
                  by(fastforce intro:ddep_dependent_live_vars_keep_notempty)
                from \<open>n'' -asx'\<rightarrow>\<^sub>d* n'\<close> False have "last(targetnodes asx') = n'"
                  by -(rule path_targetnode,rule DynPDG_path_CFG_path)
                with \<open>(V,ais@[],ais@asx') \<in> dependent_live_vars n'\<close>
                  \<open>V' \<in> Use n\<close> \<open>n -{V}asx\<rightarrow>\<^sub>d\<^sub>d n''\<close> \<open>asx = ai#ais\<close>
                  \<open>sourcenode ai = n\<close> \<open>last(targetnodes asx) = n''\<close> False
                have "(V',[],ai#ais@asx') \<in> dependent_live_vars n'"
                  by(fastforce intro:dep_vars_Cons_ddep simp:targetnodes_def)
                with \<open>asx = ai#ais\<close> \<open>a'#as' = asx@asx'\<close> \<open>as = a'#as'\<close>
                show ?thesis by simp
              qed
              with all have "state_val s V' = state_val s' V'" by blast }
            with \<open>pred ex' s'\<close> \<open>valid_edge a'\<close>
            show ?thesis by(fastforce elim:CFG_edge_Uses_pred_equal)
          qed
        qed
      qed simp
      with all' \<open>preds esx (transfer ex s)\<close> \<open>es = ex#esx\<close> \<open>es' = ex'#esx'\<close>
      show ?thesis by simp
    next
      case False
      then obtain V' xs' where "(V',xs',as') \<in> dependent_live_vars n'"
        and "state_val (transfer ex s) V' \<noteq> state_val (transfer ex' s') V'"
        by auto
      show ?thesis
      proof(cases "n -a'#as'\<rightarrow>\<^sub>d* n'")
        case True
        with \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close> \<open>last(targetnodes as) = n'\<close> ex
        have [simp]:"ex = kind a'" by clarsimp
        with \<open>x \<longrightarrow> y\<close> ex ex' have [simp]:"ex' = ex" by(cases x) auto
        { fix V assume "V \<in> Use (sourcenode a')"
          hence "(V,[],[]) \<in> dependent_live_vars (sourcenode a')"
            by(rule dep_vars_Use)
          with \<open>n -a'#as'\<rightarrow>\<^sub>d* n'\<close> have "(V,[],[]@a'#as') \<in> dependent_live_vars n'"
            by(fastforce intro:dependent_live_vars_dep_dependent_live_vars)
          with all \<open>as = a'#as'\<close> have "state_val s V = state_val s' V"
            by fastforce }
        with \<open>pred ex' s'\<close> \<open>valid_edge a'\<close> have "pred ex s"
          by(fastforce intro:CFG_edge_Uses_pred_equal)
        show ?thesis
        proof(cases "V' \<in> Def n")
          case True
          with \<open>state_val (transfer ex s) V' \<noteq> state_val (transfer ex' s') V'\<close>
            \<open>valid_edge a'\<close> \<open>pred ex' s'\<close> \<open>pred ex s\<close>
            CFG_edge_transfer_uses_only_Use[of a' s s']
          obtain V'' where "V'' \<in> Use n"
            and "state_val s V'' \<noteq> state_val s' V''"
            by auto
          from True \<open>(V',xs',as') \<in> dependent_live_vars n'\<close>
            \<open>targetnode a' -as'\<rightarrow>* n'\<close> \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
            \<open>valid_edge a'\<close> \<open>n = sourcenode a'\<close>[THEN sym]
          have "n -{V'}a'#xs'\<rightarrow>\<^sub>d\<^sub>d last(targetnodes (a'#xs'))"
            by -(drule dependent_live_vars_dependent_edge,
              auto dest!: dependent_live_vars_dependent_edge
                   dest:DynPDG_ddep_edge_CFG_path path_targetnode
                   simp del:\<open>n = sourcenode a'\<close>)
          with \<open>(V',xs',as') \<in> dependent_live_vars n'\<close> \<open>V'' \<in> Use n\<close>
            \<open>last(targetnodes as) = n'\<close> \<open>as = a'#as'\<close>
          have "(V'',[],as) \<in> dependent_live_vars n'"
            by(fastforce intro:dep_vars_Cons_ddep)
          with all have "state_val s V'' = state_val s' V''" by blast
          with \<open>state_val s V'' \<noteq> state_val s' V''\<close> have False by simp
          thus ?thesis by simp
        next
          case False
          with \<open>valid_edge a'\<close> \<open>pred ex s\<close>
          have "state_val (transfer (kind a') s) V' = state_val s V'"
            by(fastforce intro:CFG_edge_no_Def_equal)
          moreover
          from False \<open>valid_edge a'\<close> \<open>pred ex' s'\<close>
          have "state_val (transfer (kind a') s') V' = state_val s' V'"
            by(fastforce intro:CFG_edge_no_Def_equal)
          ultimately have "state_val s V' \<noteq> state_val s' V'"
            using \<open>state_val (transfer ex s) V' \<noteq> state_val (transfer ex' s') V'\<close>
            by simp
          from False have "\<not> n -{V'}a'#xs'\<rightarrow>\<^sub>d\<^sub>d
                           last(targetnodes (a'#xs'))"
            by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)
          with \<open>(V',xs',as') \<in> dependent_live_vars n'\<close> \<open>last(targetnodes as) = n'\<close>
            \<open>as = a'#as'\<close>
          have "(V',a'#xs',a'#as') \<in> dependent_live_vars n'"
            by(fastforce intro:dep_vars_Cons_keep)
          with \<open>as = a'#as'\<close> all have "state_val s V' = state_val s' V'" by auto
          with \<open>state_val s V' \<noteq> state_val s' V'\<close> have False by simp
          thus ?thesis by simp
        qed
      next
        case False
        { assume "V' \<in> Def n"
          with \<open>(V',xs',as') \<in> dependent_live_vars n'\<close> \<open>targetnode a' -as'\<rightarrow>* n'\<close>
            \<open>valid_edge a'\<close>
          have "n -a'#as'\<rightarrow>\<^sub>d* n'"
            by -(drule dependent_live_vars_dependent_edge,
              auto dest:DynPDG_path_ddep DynPDG_path_Append)
          with False have "False" by simp }
        hence "V' \<notin> Def (sourcenode a')" by fastforce
        from False \<open>slice_path as = x#xs\<close> \<open>as = a'#as'\<close>
          \<open>last(targetnodes as) = n'\<close> \<open>as' \<noteq> []\<close>
        have "\<not> x" by(auto simp:targetnodes_def)
        with ex have cases:"ex = (case kind a' of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>)"
          by simp
        have "state_val s V' \<noteq> state_val s' V'"
        proof(cases y)
          case True
          with ex' have [simp]:"ex' = kind a'" by simp
          from \<open>V' \<notin> Def (sourcenode a')\<close> \<open>valid_edge a'\<close> \<open>pred ex' s'\<close>
          have states_eq:"state_val (transfer (kind a') s') V' = state_val s' V'"
            by(fastforce intro:CFG_edge_no_Def_equal)
          from cases have "state_val s V' = state_val (transfer ex s) V'"
            by(cases "kind a'") auto
          with states_eq
            \<open>state_val (transfer ex s) V' \<noteq> state_val (transfer ex' s') V'\<close>
          show ?thesis by simp
        next
          case False
          with ex' have "ex' = (case kind a' of \<Up>f \<Rightarrow> \<Up>id | (Q)\<^sub>\<surd> \<Rightarrow> (\<lambda>s. True)\<^sub>\<surd>)"
            by simp
          with cases have "state_val s V' = state_val (transfer ex s) V'"
            and "state_val s' V' = state_val (transfer ex' s') V'"
            by(cases "kind a'",auto)+
          with \<open>state_val (transfer ex s) V' \<noteq> state_val (transfer ex' s') V'\<close>
          show ?thesis by simp
        qed
        from \<open>V' \<notin> Def (sourcenode a')\<close>
        have "\<not> n -{V'}a'#xs'\<rightarrow>\<^sub>d\<^sub>d last(targetnodes (a'#xs'))"
          by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)
        with \<open>(V',xs',as') \<in> dependent_live_vars n'\<close> \<open>last(targetnodes as) = n'\<close>
          \<open>as = a'#as'\<close>
        have "(V',a'#xs',a'#as') \<in> dependent_live_vars n'"
          by(fastforce intro:dep_vars_Cons_keep)
        with \<open>as = a'#as'\<close> all have "state_val s V' = state_val s' V'" by auto
        with \<open>state_val s V' \<noteq> state_val s' V'\<close> have False by simp
        thus ?thesis by simp
      qed
    qed
  qed
qed simp_all

theorem fundamental_property_of_path_slicing:
  assumes "n -as\<rightarrow>* n'" and "preds (kinds as) s"
  shows "(\<forall>V \<in> Use n'. state_val (transfers (slice_kinds as) s) V =
                         state_val (transfers (kinds as) s) V)"
  and "preds (slice_kinds as) s"
proof -
  have "length as = length (slice_path as)" by(simp add:slice_path_length)
  hence "slice_path as \<preceq>\<^sub>b replicate (length as) True"
    by(simp add:maximal_element)
  have "select_edge_kinds as (replicate (length as) True) = kinds as"
    by(rule select_edge_kinds_max_bv)
  with \<open>n -as\<rightarrow>* n'\<close> \<open>slice_path as \<preceq>\<^sub>b replicate (length as) True\<close>
    \<open>preds (kinds as) s\<close>
  have "(\<forall>V\<in>Use n'. state_val (transfers (slice_kinds as) s) V =
       state_val (transfers (kinds as) s) V) \<and> preds (slice_kinds as) s"
    by -(rule slice_path_leqs_information_same_Uses,simp_all add:slice_kinds_def)
  thus "\<forall>V\<in>Use n'. state_val (transfers (slice_kinds as) s) V =
    state_val (transfers (kinds as) s) V" and "preds (slice_kinds as) s"
    by simp_all
qed

end

subsection \<open>The fundamental property of (dynamic) slicing related to the semantics\<close>

locale BackwardPathSlice_wf =
  DynPDG sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
    dyn_control_dependence +
  CFG_semantics_wf sourcenode targetnode kind valid_edge Entry sem identifies
  for sourcenode :: "'edge \<Rightarrow> 'node" and targetnode :: "'edge \<Rightarrow> 'node"
  and kind :: "'edge \<Rightarrow> 'state edge_kind" and valid_edge :: "'edge \<Rightarrow> bool"
  and Entry :: "'node" ("'('_Entry'_')") and Def :: "'node \<Rightarrow> 'var set"
  and Use :: "'node \<Rightarrow> 'var set" and state_val :: "'state \<Rightarrow> 'var \<Rightarrow> 'val"
  and dyn_control_dependence :: "'node \<Rightarrow> 'node \<Rightarrow> 'edge list \<Rightarrow> bool"
    ("_ controls _ via _" [51, 0, 0] 1000)
  and Exit :: "'node" ("'('_Exit'_')")
  and sem :: "'com \<Rightarrow> 'state \<Rightarrow> 'com \<Rightarrow> 'state \<Rightarrow> bool"
    ("((1\<langle>_,/_\<rangle>) \<Rightarrow>/ (1\<langle>_,/_\<rangle>))" [0,0,0,0] 81)
  and identifies :: "'node \<Rightarrow> 'com \<Rightarrow> bool" ("_ \<triangleq> _" [51, 0] 80)

begin

theorem fundamental_property_of_path_slicing_semantically:
  assumes "n \<triangleq> c" and "\<langle>c,s\<rangle> \<Rightarrow> \<langle>c',s'\<rangle>"
  obtains n' as where "n -as\<rightarrow>* n'" and "preds (slice_kinds as) s"
  and "n' \<triangleq> c'"
  and "\<forall>V \<in> Use n'. state_val (transfers (slice_kinds as) s) V =
                     state_val s' V"
proof(atomize_elim)
  from \<open>n \<triangleq> c\<close> \<open>\<langle>c,s\<rangle> \<Rightarrow> \<langle>c',s'\<rangle>\<close> obtain n' as where "n -as\<rightarrow>* n'"
    and "transfers (kinds as) s = s'"
    and "preds (kinds as) s"
    and "n' \<triangleq> c'"
    by(fastforce dest:fundamental_property)
  with \<open>n -as\<rightarrow>* n'\<close> \<open>preds (kinds as) s\<close>
  have "\<forall>V \<in> Use n'. state_val (transfers (slice_kinds as) s) V =
    state_val (transfers (kinds as) s) V" and "preds (slice_kinds as) s"
    by -(rule fundamental_property_of_path_slicing,simp_all)+
  with \<open>transfers (kinds as) s = s'\<close> have "\<forall>V \<in> Use n'.
    state_val (transfers (slice_kinds as) s) V =
    state_val s' V" by simp
  with \<open>n -as\<rightarrow>* n'\<close> \<open>preds (slice_kinds as) s\<close> \<open>n' \<triangleq> c'\<close>
  show "\<exists>as n'. n -as\<rightarrow>* n' \<and> preds (slice_kinds as) s \<and> n' \<triangleq> c' \<and>
       (\<forall>V\<in>Use n'. state_val (transfers (slice_kinds as) s) V = state_val s' V)"
    by blast
qed

end

end


theory flash14Rev imports flashPub
begin
section{*Main defintions*}
lemma NI_FAckVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_FAck ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_InvVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Inv  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_InvAck_1VsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by(cut_tac a1 a2 a3 a4, auto)
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_1_HomeVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_InvAck_1_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_InvAck_2VsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_InvAck_2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_Local_GetX_GetXVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Para ''UniMsg_Cmd'' iInv1) )  ( Const UNI_GetX ))    ( eqn ( IVar ( Para ''CacheState'' iInv1) )  ( Const CACHE_E ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_Nak1VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_Nak2VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_Nak3VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX1VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX2VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX3VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX4VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX5VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX6VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX7VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX8VsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))   \<or>((iRule1~=iInv1 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX8_homeVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX9VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX10VsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))   \<or>((iRule1~=iInv1 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX10_homeVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX11VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_GetVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_Local_Get_Nak1VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_Nak2VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_Nak3VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_Put1VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_Put2VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Put2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_Put3VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Get_Put3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_PutVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_Local_PutXAcksDoneVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Local_PutXAcksDone ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_NakVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Nak  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Nak_ClearVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Nak_Clear ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_Nak_HomeVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Nak_Home ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_Remote_GetX_NakVsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))   \<or>((iRule1~=iInv1 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_GetX_Nak_HomeVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_Remote_GetX_PutXVsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))   \<or>((iRule1~=iInv1 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>iRule2=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_GetX_PutX_HomeVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_Get_Nak1VsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_Remote_Get_Nak2VsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))   \<or>((iRule1~=iInv1 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_Get_Put1VsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Put1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_Get_Put2VsInv14:
    (*Rule2VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))   \<or>((iRule1~=iInv1 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>iRule2=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 )\<and>(iRule2~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_PutVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_Put  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

                     have allCases:"formEval  ( eqn ( IVar ( Para ''InvMarked'' iInv1) )  ( Const true ))  s  \<or>formEval   (neg ( eqn ( IVar ( Para ''InvMarked'' iInv1) )  ( Const true )) )  s  "
	                      by auto

    moreover
                       {assume c1:"formEval ( eqn ( IVar ( Para ''InvMarked'' iInv1) )  ( Const true ))  s"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1  c1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume c1:"formEval  (neg ( eqn ( IVar ( Para ''InvMarked'' iInv1) )  ( Const true )) )  s"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1  c1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }
   ultimately have "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_PutXVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_ReplaceVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_ReplaceHomeVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_ReplaceHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_ReplaceHomeShrVldVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_ReplaceHomeShrVld ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_ReplaceShrVldVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_ReplaceShrVld  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma NI_ShWbVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_ShWb N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma NI_WbVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (NI_Wb ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_GetX_GetX1VsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_GetX1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_GetX_GetX2VsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_GetX2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_GetX_PutX1VsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX1 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_GetX_PutX2VsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX2 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_GetX_PutX3VsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX3 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_GetX_PutX4VsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_GetX_PutX4 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_Get_GetVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_Get_Get ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_Get_PutVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_Get_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_PutXVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_PutX ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Local_ReplaceVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Local_Replace ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 lemma PI_Remote_GetVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma PI_Remote_GetXVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Para ''CacheState'' iInv1) )  ( Const CACHE_E ))    ( eqn ( IVar ( Para ''CacheState'' iInv1) )  ( Const CACHE_I ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma PI_Remote_PutXVsInv14:
  (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>((iRule1~=iInv1 ))   "
	                      by( cut_tac  a1  a2  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma PI_Remote_ReplaceVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (PI_Remote_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma StoreVsInv14:
    (*Rule1VsPInv1*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (Store  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by  (cut_tac  a1  a2 , auto)
 lemma StoreHomeVsInv14:
    (*Rule0VsPInv1*)
  assumes   a1:"iInv1 \<le> N"

  shows  "invHoldForRule' s (inv14  iInv1 ) (StoreHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1 , auto)
 end