(*  Title:      HOL/Auth/flash_data_cub_lemma_on_inv__40.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

header{*The flash_data_cub Protocol Case Study*}

theory flash_data_cub_lemma_on_inv__40 imports flash_data_cub_base
begin
section{*All lemmas on causal relation between inv__40 and some rule r*}
lemma n_PI_Local_Get_GetVsinv__40:
assumes a1: "(r=n_PI_Local_Get_Get  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_Get_PutVsinv__40:
assumes a1: "(r=n_PI_Local_Get_Put  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
have "((formEval (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true)) s))\<or>((formEval (neg (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true))) s))" by auto
  moreover {
    assume c1: "((formEval (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true)) s))"
    have "?P1 s"
    proof(cut_tac a1 a2  c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (neg (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2  c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_PI_Local_GetX_GetX__part__0Vsinv__40:
assumes a1: "(r=n_PI_Local_GetX_GetX__part__0  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_GetX__part__1Vsinv__40:
assumes a1: "(r=n_PI_Local_GetX_GetX__part__1  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_PutX_HeadVld__part__0Vsinv__40:
assumes a1: "(r=n_PI_Local_GetX_PutX_HeadVld__part__0 N )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P3 s"
  apply (cut_tac a1 a2 , simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeUniMsg'') ''Cmd'')) (Const UNI_Get)) (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const false))))" in exI, auto) done
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_PutX_HeadVld__part__1Vsinv__40:
assumes a1: "(r=n_PI_Local_GetX_PutX_HeadVld__part__1 N )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P3 s"
  apply (cut_tac a1 a2 , simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeUniMsg'') ''Cmd'')) (Const UNI_Get)) (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const false))))" in exI, auto) done
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_PutX__part__0Vsinv__40:
assumes a1: "(r=n_PI_Local_GetX_PutX__part__0  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P3 s"
  apply (cut_tac a1 a2 , simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeUniMsg'') ''Cmd'')) (Const UNI_Get)) (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const false))))" in exI, auto) done
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_GetX_PutX__part__1Vsinv__40:
assumes a1: "(r=n_PI_Local_GetX_PutX__part__1  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P3 s"
  apply (cut_tac a1 a2 , simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeUniMsg'') ''Cmd'')) (Const UNI_Get)) (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const false))))" in exI, auto) done
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_PI_Local_PutXVsinv__40:
assumes a1: "(r=n_PI_Local_PutX  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
have "((formEval (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const true)) s))\<or>((formEval (neg (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const true))) s))" by auto
  moreover {
    assume c1: "((formEval (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const true)) s))"
    have "?P1 s"
    proof(cut_tac a1 a2  c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (neg (eqn (IVar (Field (Field (Ident ''Sta'') ''Dir'') ''Pending'')) (Const true))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2  c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_PI_Local_ReplaceVsinv__40:
assumes a1: "(r=n_PI_Local_Replace  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Nak_HomeVsinv__40:
assumes a1: "(r=n_NI_Nak_Home  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_Get_Put_DirtyVsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Put_Dirty  src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_Get_Put_Dirty  src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_Get_Nak_HomeVsinv__40:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_Get_Nak_Home  dst)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_Get_Nak_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_Get_Put_HomeVsinv__40:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_Get_Put_Home  dst)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_Get_Put_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_1Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_1 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_1 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_2Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_2 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_2 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_3Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_3 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_3 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_4Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_4 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_4 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_5Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_5 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_5 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_6Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_6 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_6 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_7__part__0Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7__part__0 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_7__part__0 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_7__part__1Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7__part__1 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_7__part__1 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_7_NODE_Get__part__0Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7_NODE_Get__part__0 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_7_NODE_Get__part__0 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_7_NODE_Get__part__1Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_7_NODE_Get__part__1 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_7_NODE_Get__part__1 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_8_HomeVsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_8_Home N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_8_Home N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_8_Home_NODE_GetVsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_8_Home_NODE_Get N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_8_Home_NODE_Get N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_8Vsinv__40:
assumes a1: "(\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_8 N src pp)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src pp where a1:"src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_8 N src pp" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_8_NODE_GetVsinv__40:
assumes a1: "(\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_8_NODE_Get N src pp)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src pp where a1:"src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_8_NODE_Get N src pp" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_GetX_PutX_11Vsinv__40:
assumes a1: "(\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_11 N src)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain src where a1:"src\<le>N\<and>r=n_NI_Local_GetX_PutX_11 N src" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_GetX_Nak_HomeVsinv__40:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_GetX_Nak_Home  dst)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_GetX_Nak_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Remote_GetX_PutX_HomeVsinv__40:
assumes a1: "(\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_GetX_PutX_Home  dst)" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain dst where a1:"dst\<le>N\<and>r=n_NI_Remote_GetX_PutX_Home  dst" apply fastforce done
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_PutVsinv__40:
assumes a1: "(r=n_NI_Local_Put  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
have "((formEval (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true)) s))\<or>((formEval (neg (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true))) s))" by auto
  moreover {
    assume c1: "((formEval (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true)) s))"
    have "?P1 s"
    proof(cut_tac a1 a2  c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
  moreover {
    assume c1: "((formEval (neg (eqn (IVar (Field (Field (Ident ''Sta'') ''HomeProc'') ''InvMarked'')) (Const true))) s))"
    have "?P1 s"
    proof(cut_tac a1 a2  c1, auto) qed
    then have "invHoldForRule s f r (invariants N)" by auto
  }
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_NI_Local_PutXAcksDoneVsinv__40:
assumes a1: "(r=n_NI_Local_PutXAcksDone  )" and
a2: "(f=inv__40  )"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
  have "?P1 s"
  proof(cut_tac a1 a2 , auto) qed
  then show "invHoldForRule s f r (invariants N)" by auto
qed

lemma n_NI_Local_Get_Get__part__1Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Get__part__1  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_GetVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_PI_Remote_Get  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_9__part__0Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_9__part__0 N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_WbVsinv__40:
  assumes a1: "r=n_NI_Wb  " and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_StoreVsinv__40:
  assumes a1: "\<exists> src data. src\<le>N\<and>data\<le>N\<and>r=n_Store  src data" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_GetX__part__1Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_GetX__part__1  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_3Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_3 N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_1Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_1 N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_ReplaceVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_PI_Remote_Replace  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_Store_HomeVsinv__40:
  assumes a1: "\<exists> data. data\<le>N\<and>r=n_Store_Home  data" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_Nak__part__1Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_Nak__part__1  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Nak__part__1Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Nak__part__1  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Get__part__0Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Get__part__0  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_existsVsinv__40:
  assumes a1: "\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_InvAck_exists  src pp" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_Nak__part__2Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_Nak__part__2  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_PutXVsinv__40:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_PI_Remote_PutX  dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Put_HeadVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Put_Head N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvVsinv__40:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Inv  dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Nak__part__2Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Nak__part__2  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_GetX__part__0Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_GetX__part__0  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_ShWbVsinv__40:
  assumes a1: "r=n_NI_ShWb N " and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_ReplaceVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Replace  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_GetX_NakVsinv__40:
  assumes a1: "\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_GetX_Nak  src dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_NakVsinv__40:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Nak  dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_9__part__1Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_9__part__1 N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_PI_Remote_GetXVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_PI_Remote_GetX  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_PutXVsinv__40:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_PutX  dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_PutVsinv__40:
  assumes a1: "\<exists> dst. dst\<le>N\<and>r=n_NI_Remote_Put  dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_10Vsinv__40:
  assumes a1: "\<exists> src pp. src\<le>N\<and>pp\<le>N\<and>src~=pp\<and>r=n_NI_Local_GetX_PutX_10 N src pp" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_PutVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Put  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_Nak__part__0Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_Nak__part__0  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_exists_HomeVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_exists_Home  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Replace_HomeVsinv__40:
  assumes a1: "r=n_NI_Replace_Home  " and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_GetX_PutXVsinv__40:
  assumes a1: "\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_GetX_PutX  src dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_Get_NakVsinv__40:
  assumes a1: "\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_Get_Nak  src dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Nak_ClearVsinv__40:
  assumes a1: "r=n_NI_Nak_Clear  " and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_Get_Nak__part__0Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_Get_Nak__part__0  src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Remote_Get_PutVsinv__40:
  assumes a1: "\<exists> src dst. src\<le>N\<and>dst\<le>N\<and>src~=dst\<and>r=n_NI_Remote_Get_Put  src dst" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_Local_GetX_PutX_10_HomeVsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_Local_GetX_PutX_10_Home N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_InvAck_2Vsinv__40:
  assumes a1: "\<exists> src. src\<le>N\<and>r=n_NI_InvAck_2 N src" and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_NI_FAckVsinv__40:
  assumes a1: "r=n_NI_FAck  " and
  a2: "(f=inv__40  )"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

end


(*  Title:      HOL/Auth/n_german_lemma_on_inv__24.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

(*header{*The n_german Protocol Case Study*}*)

theory n_german_lemma_on_inv__24 imports n_german_base
begin
section{*All lemmas on causal relation between inv__24 and some rule r*}
lemma n_SendInv__part__0Vsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_SendInv__part__0  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_SendInv__part__1Vsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_SendInv__part__1  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_SendInvAckVsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_SendInvAck  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_RecvInvAckVsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_RecvInvAck  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Para (Ident ''Chan3'') p__Inv2) ''Cmd'')) (Const InvAck)) (eqn (IVar (Field (Para (Ident ''Chan2'') p__Inv2) ''Cmd'')) (Const GntS))))" in exI, auto) done
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_SendGntSVsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendGntS  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_SendGntS  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_SendGntEVsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendGntE N i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_SendGntE N i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_RecvGntSVsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_RecvGntS  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_RecvGntEVsinv__24:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)" and
a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
shows "invHoldForRule s f r (invariants N)" (is "?P1 s \<or> ?P2 s \<or> ?P3 s")
proof -
from a1 obtain i where a1:"i\<le>N\<and>r=n_RecvGntE  i" apply fastforce done
from a2 obtain p__Inv2 where a2:"p__Inv2\<le>N\<and>f=inv__24  p__Inv2" apply fastforce done
have "(i=p__Inv2)\<or>(i~=p__Inv2)\<or>(i~=p__Inv2)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv2)"
  have "?P1 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv2)"
  have "?P2 s"
  proof(cut_tac a1 a2 b1, auto) qed
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_SendReqE__part__1Vsinv__24:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i" and
  a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_StoreVsinv__24:
  assumes a1: "\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d" and
  a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_RecvReqEVsinv__24:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_RecvReqE N i" and
  a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendReqE__part__0Vsinv__24:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i" and
  a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendReqSVsinv__24:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendReqS  i" and
  a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_RecvReqSVsinv__24:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_RecvReqS N i" and
  a2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

end


theory HoareTripleForInstructions2

imports Main "./HoareTripleForInstructions"
"./HoareTripleForStorage"

begin

lemma memory_range_elms_in_minus_action [simp] :
  "memory_range_elms data_start data
       \<subseteq> X - {ContractActionElm a} =
   (memory_range_elms data_start data \<subseteq> X)"
 by (auto dest: stateelm_dest)

lemma stack_topmost_in_minus_code [simp] :
  "stack_topmost_elms h lst
       \<subseteq> X - {CodeElm p} =
  (stack_topmost_elms h lst \<subseteq> X)"
 by (auto dest: stateelm_dest)

lemma stack_topmost_in_minus_action [simp] :
  "stack_topmost_elms h lst
       \<subseteq> X - {ContractActionElm a} =
  (stack_topmost_elms h lst \<subseteq> X)"
 by (auto dest: stateelm_dest)

(* not correct anymore, new memory usage is calculated
lemma return_gas_triple:
  "triple {OutOfGas}
          (\<langle> h \<le> 1022 \<and> length data = unat data_size \<rangle> **
           memory_range data_start data **
           gas_pred g **
           stack_topmost h [data_size, data_start] **  program_counter k **
           continuing)
          {(k, Misc RETURN)}
          ( memory_range data_start data ** stack_topmost h [data_size, data_start] **
            program_counter k ** not_continuing ** action (ContractReturn data) ** gas_any)"
apply(simp add: triple_def)
apply(clarify)
apply(rule_tac x = "1" in exI)
apply(clarify)
apply(case_tac presult; auto simp add: ret_def not_continuing_def action_def
      instruction_result_as_set_def stack_as_set_def ext_program_as_set_def sep_memory_range
      sep_memory_range_sep vctx_returned_bytes_def)
 apply(rename_tac elm)
 apply(case_tac elm; simp)
  apply(rule leibniz)
   apply blast
  apply(rule  Set.equalityI; clarify)
   apply(rename_tac elm)
   apply(case_tac elm; simp)
  apply(rename_tac elm)
  apply(case_tac elm; simp)
 apply(rule leibniz)
  apply blast
 apply(rule Set.equalityI; clarify)
  apply(rename_tac elm)
  apply(case_tac elm; simp)
 apply(rename_tac elm)
 apply(case_tac elm; simp)
apply(split if_splits; auto)
done
*)

lemma pos_length_head_exists [simp] :
  "n < length lst \<Longrightarrow>
   index lst 0 = Some (lst ! 0)"
apply(case_tac lst; auto)
done

lemma rev_lookup :
  "k < length lst \<Longrightarrow>
   rev lst ! (length lst - Suc k) = lst ! k"
apply(simp add: List.rev_nth)
done

lemma list_swap_usage :
  "n < length lst \<Longrightarrow>
   rev lst ! (length lst - Suc 0) = w \<Longrightarrow>
   rev lst ! (length lst - Suc n) = v \<Longrightarrow>
   list_swap n lst = Some ([v] @ take (n - 1) (drop 1 lst) @ [w] @ (drop (n + 1) lst))"
apply(subgoal_tac "0 < length lst")
 apply(simp add: rev_lookup list_swap_def)
apply auto
  done

lemma triv_if_eq:
  "(if (w::w256) = 0 then word_of_int 1 else word_of_int 0) = (if w = 0 then 1 else 0)"
 by simp

lemma vctx_pc_stack_oblivious:
  "vctx_pc (x1\<lparr>vctx_stack := s\<rparr>) = vctx_pc x1"
by simp

lemma advance_pc_stack_oblivious:
  "vctx_pc (vctx_advance_pc co_ctx (x1\<lparr>vctx_stack := s\<rparr>)) =
   vctx_pc (vctx_advance_pc co_ctx x1)
  "
using vctx_advance_pc_def vctx_next_instruction_def vctx_pc_stack_oblivious apply auto
by(case_tac "program_content (cctx_program co_ctx) (vctx_pc x1)"; auto)

lemma iszero_gas_triple :
  notes if_split[split del]
  shows
   "triple net {OutOfGas} (\<langle> h \<le> 1023 \<rangle> **
                       stack_height (Suc h) **
                       stack h w **
                       program_counter k **
                       gas_pred g **
                       continuing
                      )

                      {(k, Arith ISZERO)}
                      (stack_height (Suc h) **
                       stack h (if w = 0 then 1 else 0) **
                       program_counter (k + 1) **
                       gas_pred (g - Gverylow) **
                       continuing
                      )"
  apply (auto simp add: triple_def)
  apply(rule_tac x = 1 in exI)
  apply(simp add: program_sem.simps)
  apply(case_tac presult;  (solves \<open>(hoare_sep sep: evm_sep simp:   stateelm_means_simps dest: stateelm_dest)\<close>)?)
  apply clarsimp
  apply(hoare_sep sep: evm_sep
                   simp: instruction_result_as_set_def  sstore_def
                         vctx_update_storage_def hoare_simps set_diff_eq
                   dest: advance_pc_inc_but_stack
                  split:if_split_asm)
  apply (drule advance_pc_inc_but_stack)
    apply (simp add: image_def)
  apply (simp add: triv_if_eq advance_pc_stack_oblivious)
  apply(erule_tac P=rest in back_subst)
  apply simp
  apply(rename_tac presult t)
  apply(rule  Set.equalityI; clarify)
   apply(simp)
   apply(rename_tac elm)
   apply(case_tac elm; simp add: hoare_simps split:if_splits prod.splits)
    apply(rename_tac p)
    apply(case_tac p; fastforce)
   apply(rename_tac p)
  apply(simp)
  apply(rename_tac elm)
  apply(case_tac elm; simp add: hoare_simps advance_pc_stack_oblivious split:if_splits)
  apply auto
 done

lemma tmp001:
"length lst = h \<Longrightarrow>
Suc (unat n) < h \<Longrightarrow>
unat n \<le> length (drop 1 lst)"
apply auto
done

lemma tmp000: "
a \<noteq> h - Suc 0 \<Longrightarrow> \<not> a < h - Suc (Suc (unat n)) \<Longrightarrow> a \<noteq> h - Suc (Suc (unat n)) \<Longrightarrow>
a < h \<Longrightarrow> (Suc (a + unat n) - h) < unat n
"
apply auto
done

lemma tmp002:
 "a \<noteq> h - Suc 0 \<Longrightarrow> a < h
   \<Longrightarrow> Suc (h - Suc (Suc a)) = h - Suc a"
apply auto
done

lemma take_drop_nth [simp] :
  "length (vctx_stack x1) = h \<Longrightarrow>
   Suc (unat n) < h \<Longrightarrow>
   a \<noteq> h - Suc 0 \<Longrightarrow> \<not> a < h - Suc (Suc (unat n)) \<Longrightarrow> a \<noteq> h - Suc (Suc (unat n)) \<Longrightarrow>
   a < h \<Longrightarrow>
   rev (take (unat n) (drop (Suc 0) (vctx_stack x1))) ! (Suc (a + unat n) - h) = rev (vctx_stack x1) ! a"
  apply(simp add: tmp000 tmp001 tmp002 List.rev_nth min_absorb2)
  done

context
  includes hoare_bundle hoare_inst_bundle
           simp_for_triples_bundle sep_crunch_bundle
begin

lemma swap_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1024 \<and> Suc (unat n) < h \<rangle> **
                       stack_height h **
                       stack (h - 1) w **
                       stack (h - (unat n) - 2) v **
                       program_counter k **
                       gas_pred g **
                       continuing
                      )

                      {(k, Swap n)}
                      (stack_height h **
                       stack (h - 1) v **
                       stack (h - (unat n) - 2) w **
                       program_counter (k + 1) **
                       gas_pred (g - Gverylow) **
                       continuing
                      )"
  apply(simp add: triple_def set_diff_eq)
apply clarify
apply(rule_tac x = 1 in exI)
apply(case_tac presult)
   defer
   apply(simp add: instruction_result_as_set_def)
  apply(simp add: instruction_result_as_set_def)
apply(simp add: swap_def list_swap_usage swap_inst_numbers_def)
apply(rule impI)
apply(erule_tac P=rest in back_subst)
apply(rule  Set.equalityI)
 apply(simp add: Set.subset_iff)
 apply(rule allI)
 apply(rename_tac elm)
 apply(case_tac elm; simp add: instruction_result_as_set_def)

 apply(rename_tac pair)
 apply(case_tac pair; simp)
 apply(case_tac "a = h - Suc 0"; simp)
  apply blast
 apply(case_tac "a < h - Suc (Suc (unat n))"; simp)

 apply(case_tac "a = h - Suc (Suc (unat n))"; simp)
  apply blast
    apply auto[1]
  apply(simp add: as_set_simps)
apply(simp add: Set.subset_iff)
apply(rule allI)
apply(rename_tac elm)
apply(case_tac elm; simp add: instruction_result_as_set_def)
 apply(rename_tac pair; case_tac pair)
 apply simp
 apply(case_tac "a = h - Suc 0"; simp)
  using rev_nth tmp002 apply auto[1]
 apply(case_tac "a < h - Suc 0"; simp)
  apply(case_tac "a = h - Suc (Suc (unat n))"; simp)
   apply blast
  apply(case_tac "a < h - Suc (Suc (unat n))"; simp)
  apply(simp add: tmp000 tmp001 tmp002 List.rev_nth)
   apply linarith
  apply(simp add: as_set_simps)
done

(* lemma imp_neq_sym:
  "(P \<longrightarrow> A \<noteq> B) \<Longrightarrow> (P \<longrightarrow> B \<noteq> A)"
  by blast

lemma swap_gas_triple1 :
shows
   "triple net {OutOfGas} (\<langle> h \<le> 1024 \<and> Suc (unat n) < h \<rangle> **
                       stack_height h **
                       stack (h - 1) w **
                       stack (h - (unat n) - 2) v **
                       program_counter k **
                       gas_pred g **
                       continuing
                      )

                      {(k, Swap n)}
                      (stack_height h **
                       stack (h - 1) v **
                       stack (h - (unat n) - 2) w **
                       program_counter (k + 1) **
                       gas_pred (g - Gverylow) **
                       continuing
                      )"
  apply(simp add: triple_def)
  apply clarify
  apply(rule_tac x = 1 in exI)
  apply clarsimp
  apply(case_tac presult)
    defer
    apply (hoare_sep sep: evm_sep)
  apply (hoare_sep sep: evm_sep)
 apply (hoare_sep sep: evm_sep)

  apply (simp add: program_sem.simps instruction_result_as_set_def next_state_def
                   vctx_next_instruction_def stateelm_means_simps stateelm_equiv_simps
                   instruction_sem_def check_resources_def inst_numbers_simps new_memory_consumption.simps)
  apply (simp add: swap_def list_swap_usage swap_inst_numbers_def meter_gas_def
        HoareTripleForInstructions_legacy_simps(4) gas_value_simps advance_pc_no_gas_change
        subtract_gas.simps stateelm_means_simps stateelm_equiv_simps new_memory_consumption.simps
      )
  apply (clarsimp split:if_split_asm)
  apply (clarsimp simp: next_state_def instruction_sem_simps
            gas_value_simps advance_pc_no_gas_change
      inst_numbers_simps split_def
      )
  apply (rule conjI)

  (* here *)
  apply (erule_tac P=rest in back_subst)
  apply(rule  Set.equalityI)
  apply (simp add: set_diff_eq)
  apply clarsimp
  apply(rename_tac elm)
  apply (case_tac elm; simp add: hoare_simps rev_nth_simps suc_minus_two  min_absorb2 saying_zero split:if_splits)
 apply(rename_tac pair)
   apply (case_tac pair; simp add: hoare_simps rev_nth_simps suc_minus_two  min_absorb2 saying_zero split:if_splits)
   apply (clarsimp)
   apply (rule conjI)+
  apply (clarsimp simp add: hoare_simps rev_nth_simps suc_minus_two  min_absorb2 saying_zero)

 apply(case_tac "aa = h - Suc 0"; simp add: Hoare_legacy_simps HoareTripleForInstructions_legacy_simps)
  apply
 apply(case_tac "aa < h - Suc (Suc (unat n))";  simp add: Hoare_legacy_simps HoareTripleForInstructions_legacy_simps)
find_theorems rev length nth
 apply(case_tac "aa = h - Suc (Suc (unat n))";  simp add: Hoare_legacy_simps HoareTripleForInstructions_legacy_simps)
  apply blast
apply auto[1]
apply(simp add: Set.subset_iff)
apply(rule allI)
apply(rename_tac elm)
apply(case_tac elm; simp add: instruction_result_as_set_def)
 apply(rename_tac pair; case_tac pair)
 apply simp
 apply(case_tac "a = h - Suc 0"; simp)
  using rev_nth tmp002 apply auto[1]
 apply(case_tac "a < h - Suc 0"; simp)
  apply(case_tac "a = h - Suc (Suc (unat n))"; simp)
   apply blast
  apply(case_tac "a < h - Suc (Suc (unat n))"; simp)
  apply(simp add: tmp000 tmp001 tmp002 List.rev_nth)
  apply linarith
done *)

lemma reverse_lookup[simp] :
  "n < length lst \<Longrightarrow>
   rev lst ! (length lst - Suc n) = lst ! n
  "
  using nth_rev_alt by fastforce

lemma deep_lookup [simp] :
  "w = rev (vctx_stack x1) ! (length (vctx_stack x1) - Suc (unat n)) \<Longrightarrow>
   unat n < length (vctx_stack x1) \<Longrightarrow>
   index (vctx_stack x1) (unat n) = Some w"
apply(simp)
done

lemma dup_advance [simp] :
"      program_content (cctx_program co_ctx) (vctx_pc x1) = Some (Dup n) \<Longrightarrow>
       k = vctx_pc x1 \<Longrightarrow>
       vctx_pc (vctx_advance_pc co_ctx x1) = vctx_pc x1 + 1
"
apply(simp add: vctx_advance_pc_def inst_size_def inst_code.simps)
done

lemma dup_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1023 \<and> unat n < h \<rangle> **
                       stack_height h **
                       stack (h - (unat n) - 1) w **
                       program_counter k **
                       gas_pred g **
                       account_existence c existence **
                       continuing
                      )
                      {(k, Dup n)}
                      (stack_height (h + 1) **
                       stack (h - (unat n) - 1) w **
                       stack h w **
                       program_counter (k + 1) **
                       gas_pred (g - Gverylow) **
                       account_existence c existence **
                       continuing
                      )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(case_tac presult; simp)
apply(clarsimp simp add:instruction_result_as_set_def )
apply(rule conjI, fastforce)+
apply(erule_tac P=rest in back_subst)
apply(rule Set.equalityI)
 apply(clarify)
 apply(simp)
   apply(rename_tac elm; case_tac elm; simp)
    apply clarsimp+
  apply(simp add: as_set_simps)
apply(rename_tac elm; case_tac elm; simp)
apply(auto simp add: as_set_simps)
done

lemma address_gas_triple :
  "triple net {OutOfGas}
          (\<langle> h \<le> 1023 \<rangle> ** stack_height h ** program_counter k ** this_account t ** gas_pred g ** account_existence c existence **continuing)
          {(k, Info ADDRESS)}
          (stack_height (h + 1) ** stack h (ucast t)
           ** program_counter (k + 1) ** this_account t ** gas_pred (g - Gbase) ** account_existence c existence **continuing )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
  apply(case_tac presult; simp add: instruction_result_as_set_def)
apply clarsimp
apply(erule_tac P=rest in back_subst)
apply(rule Set.equalityI)
 apply(clarify)
 apply(simp)
 apply(rename_tac elm; case_tac elm; simp)
    apply(clarsimp)+
  apply(simp add: as_set_simps)
apply(rename_tac elm; case_tac elm; simp)
apply(auto simp add: as_set_simps)
done

lemma push_advance [simp] :
"      vctx_pc x1 = k \<Longrightarrow>
       lst \<noteq> [] \<Longrightarrow>
       length lst \<le> 32 \<Longrightarrow>
       program_content (cctx_program co_ctx) k = Some (Stack (PUSH_N lst)) \<Longrightarrow>
       vctx_pc (vctx_advance_pc co_ctx x1) = k + 1 + (int (length lst))"
apply(simp add: vctx_advance_pc_def inst_size_def inst_code.simps stack_inst_code.simps)
done

lemma push_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1023 \<and> length lst > 0 \<and> 32 \<ge> length lst\<rangle> **
                       stack_height h **
                       program_counter k **
                       gas_pred g **
                       account_existence c existence **
                       continuing
                      )
                      {(k, Stack (PUSH_N lst))}
                      (stack_height (h + 1) **
                       stack h (word_rcat lst) **
                       program_counter (k + 1 + (int (length lst))) **
                       gas_pred (g - Gverylow) **
                       account_existence c existence **
                       continuing
                      )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(case_tac presult; simp add: instruction_result_as_set_def constant_mark_def)
apply clarify
apply(erule_tac P=rest in back_subst)
apply(rule Set.equalityI)
 apply(clarsimp)+
apply(rename_tac elm; case_tac elm; simp)
    apply(clarsimp)+
  apply(simp add: as_set_simps)
apply(rename_tac elm; case_tac elm; simp)
apply(auto simp add: as_set_simps)
done

lemma jumpi_size [simp] :
  "inst_size (Pc JUMPI) = 1"
apply(simp add: inst_size_def inst_code.simps)
done

lemma jumpi_false_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1022 \<rangle> **
                       stack_height (h + 2) **
                       stack (h + 1) d **
                       stack h 0 **
                       program_counter k **
                       gas_pred g **
                       account_existence c existence **
                       continuing
                      )
                      {(k, Pc JUMPI)}
                      (stack_height h **
                       program_counter (k + 1) **
                       gas_pred (g - Ghigh) **
                       account_existence c existence **
                       continuing)"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(simp add: instruction_result_as_set_def)
apply(case_tac presult; simp)
apply(clarsimp simp add: insert_minus_set vctx_advance_pc_def)
apply(erule_tac P=rest in back_subst)
apply(auto simp add: stack_as_set_def)
done

lemma jumpi_true_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1022 \<and> cond \<noteq> 0 \<rangle> **
                       stack_height (h + 2) **
                       stack (h + 1) d **
                       stack h cond **
                       program_counter k **
                       gas_pred g **
                       account_existence c existence **
                       continuing
                      )
                      {(k, Pc JUMPI), ((uint d), Pc JUMPDEST)}
                      (stack_height h **
                       program_counter (uint d) **
                       gas_pred (g - Ghigh) **
                       account_existence c existence **
                       continuing
                      )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(case_tac presult; simp )
apply(clarsimp simp add:  instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
apply(auto simp add: stack_as_set_def)
done

lemma jump_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1023 \<rangle> **
                       stack_height (h + 1) **
                       stack h d **
                       program_counter k **
                       gas_pred g **
                       continuing
                      )
                      {(k, Pc JUMP), ((uint d), Pc JUMPDEST)}
                      (stack_height h **
                       program_counter (uint d) **
                       gas_pred (g - Gmid) **
                       continuing
                      )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(case_tac presult; simp )
apply(auto simp add: instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
apply(auto simp add: stack_as_set_def)
done

declare jump_def [simp del]

lemma invalid_jump [simp] :
      "program_content (cctx_program co_ctx) (uint d) = Some i \<Longrightarrow>
       i \<noteq> Pc JUMPDEST \<Longrightarrow>
       g = vctx_gas v \<Longrightarrow>
       vctx_stack v = d # t \<Longrightarrow>
       jump v co_ctx = instruction_failure_result v [InvalidJumpDestination]"
apply(simp add: jump_def)
apply(case_tac i; simp)
apply(rename_tac j; case_tac j; simp)
done

lemma invalid_jump2 [simp] :
      "program_content (cctx_program co_ctx) (uint d) = None \<Longrightarrow>
       g = vctx_gas v \<Longrightarrow>
       vctx_stack v = d # t \<Longrightarrow>
       jump v co_ctx = instruction_failure_result v [InvalidJumpDestination]"
apply(simp add: jump_def)
done

lemma notin_diff [simp] :
  "x \<notin> A - B =
   (x \<notin> A \<or> x \<in> B)"
  by blast

lemma stack_elm_append [dest] :
  "x = StackElm (idx, lst ! idx) \<Longrightarrow>
   x \<in> contexts_as_set x1 co_ctx \<Longrightarrow>
   (idx < length (vctx_stack x1) \<and> rev (vctx_stack x1) ! idx = lst ! idx)"
apply(simp add: contexts_as_set_def)
done

lemma not_appended [dest] :
  "(rev ta @ [cond, d]) ! aa \<noteq> cond \<Longrightarrow>
   aa \<noteq> length ta
  "
apply(auto)
done

lemma not_first [simp] :
  "((cond # lst) ! n \<noteq> cond) = ((n \<noteq> 0) \<and> lst ! (n - 1) \<noteq> cond)"
apply(case_tac n; auto)
done

lemma invalid_jumpi_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1022 \<and> cond \<noteq> 0 \<and> i \<noteq> Pc JUMPDEST \<rangle> **
                       stack_height (h + 2) **
                       stack (h + 1) d **
                       stack h cond **
                       program_counter k **
                       gas_pred g **
                       continuing
                      )
                      {(k, Pc JUMPI), ((uint d), i)}
                      (stack_height (h + 1) **
                       stack h d **
                       program_counter k **
                       gas_pred (g - Ghigh) **
                       not_continuing **
                       action (ContractFail [InvalidJumpDestination])
                      )"
apply(auto simp add: triple_def set_diff_eq)
  apply(rule_tac x = 1 in exI)
 apply(case_tac presult; simp )
apply (auto simp add:  instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
 apply(auto simp add: stack_as_set_def)[1]
apply(erule_tac P=rest in back_subst)
apply(rule Set.equalityI)
 apply(clarify)
 apply(simp)
 apply(rename_tac elm; case_tac elm; simp)
 apply(rename_tac pair; case_tac pair; simp)
 apply(auto simp add: stack_as_set_def)
done

lemma invalid_jump_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1023 \<and> i \<noteq> Pc JUMPDEST\<rangle> **
                       stack_height (h + 1) **
                       stack h d **
                       program_counter k **
                       gas_pred g **
                       continuing
                      )
                      {(k, Pc JUMP), ((uint d), i)}
                      (stack_height (h + 1) **
                       stack h d **
                       program_counter k **
                       gas_pred (g - Gmid) **
                       not_continuing **
                       action (ContractFail [InvalidJumpDestination])
                      )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
  apply(case_tac presult; simp)
 apply (auto simp add: instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
 apply(auto)
apply(erule_tac P=rest in back_subst)
apply auto
done

lemma jumpdest_advance [simp] :
  "k = vctx_pc x1 \<Longrightarrow>
   program_content (cctx_program co_ctx) (vctx_pc x1) = Some (Pc JUMPDEST) \<Longrightarrow>
   vctx_pc (vctx_advance_pc co_ctx x1) = vctx_pc x1 + 1"
apply(simp add: vctx_advance_pc_def inst_size_def inst_code.simps)
done

lemma storage_continue [simp] :
  "StorageElm x3
       \<in> instruction_result_as_set co_ctx (InstructionContinue x1) =
   (StorageElm x3 \<in> variable_ctx_as_set x1)"
apply(simp add: instruction_result_as_set_def)
done

lemma memory_continue [simp] :
  "MemoryElm x4
       \<in> instruction_result_as_set co_ctx (InstructionContinue x1) =
   (MemoryElm x4 \<in> variable_ctx_as_set x1)"
apply(simp only: instruction_result_as_set_def)
apply(simp)
done

lemma union_cong :
  "a = b \<Longrightarrow> c = d \<Longrightarrow> a \<union> c = b \<union> d"
apply(simp)
done

lemma jumpdest_gas_triple :
   "triple net {OutOfGas} (\<langle> h \<le> 1024 \<rangle> **
                       stack_height h **
                       program_counter k **
                       gas_pred g **
                       account_existence c existence **
                       continuing
                      )
                      {(k, Pc JUMPDEST)}
                      (stack_height h **
                       program_counter (k + 1) **
                       gas_pred (g - Gjumpdest) **
                       account_existence c existence **
                       continuing
                      )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(case_tac presult; simp add: instruction_result_as_set_def)

apply(clarify)
apply(erule_tac P=rest in back_subst)
apply(simp add: instruction_result_as_set_def contexts_as_set_def)
apply(rule Set.equalityI)
 apply(clarsimp)+
  apply(rename_tac elm; case_tac elm; simp)
 apply clarsimp+
apply(rename_tac elm; case_tac elm; clarsimp)
done

lemma pop_gas_triple : "triple net {OutOfGas} (\<langle> h \<le> 1024 \<rangle> **
                            stack_height (h + 1) **
                            stack h v **
                            program_counter k **
                            gas_pred g **
                            continuing
                           )
                           {(k, Stack POP)}
                           (stack_height h **
                            program_counter (k + 1) **
                            gas_pred (g - Gbase) **
                            continuing
                            )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(case_tac presult; simp)
  apply(case_tac "vctx_stack x1"; simp)
  apply clarify
  apply(erule_tac P=rest in back_subst)
  apply(auto simp add: instruction_result_as_set_def)
  apply(auto simp add: vctx_advance_pc_def contexts_as_set_def
          variable_ctx_as_set_def ext_program_as_set_def balance_as_set_def)
done

lemma balance_gas_triple :
  "triple net {OutOfGas}
          (\<langle> h \<le> 1023 \<and> unat bn \<ge> 2463000 \<and> at_least_eip150 net\<rangle>
           ** block_number_pred bn ** stack_height (h + 1) ** stack h a
           ** program_counter k ** balance (ucast a) b ** gas_pred g ** account_existence c existence **continuing)
          {(k, Info BALANCE)}
          (block_number_pred bn ** stack_height (h + 1) ** stack h b
           ** program_counter (k + 1) ** balance (ucast a) b ** gas_pred (g - 400) ** account_existence c existence **continuing )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
apply(simp)
apply(case_tac presult; simp)
apply(case_tac "vctx_stack x1"; simp)
  apply clarify
apply (rule conjI, fastforce simp: instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
apply(simp add: instruction_result_as_set_def)
apply(rule Set.equalityI)
 apply(clarsimp)
 apply(rename_tac elm; case_tac elm; simp)
 apply(case_tac x2; simp)
 apply(case_tac "aa = length list"; simp)
apply(clarsimp)+
   apply(rename_tac elm; case_tac elm; simp)
    apply(auto simp add: as_set_simps)
done

(*
lemma eq0 [simp]: "
       vctx_stack x1 = v # w # ta \<Longrightarrow>
program_content (cctx_program co_ctx) (vctx_pc x1) = Some (Arith inst_EQ) \<Longrightarrow>
 (insert (GasElm (vctx_gas x1 - Gverylow))
              (insert (ContinuingElm True)
                (contexts_as_set (vctx_advance_pc co_ctx x1) co_ctx - stack_as_set (v # w # ta) \<union> stack_as_set (r # ta) -
                 {GasElm (vctx_gas x1)})) -
             {StackHeightElm (Suc (length ta))} -
             {StackElm (length ta, r)} -
             {PcElm (vctx_pc x1 + 1)} -
             {GasElm (vctx_gas x1 - Gverylow)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Arith inst_EQ)}) =
 (insert (ContinuingElm True) (contexts_as_set x1 co_ctx) - {StackHeightElm (Suc (Suc (length ta)))} -
             {StackElm (Suc (length ta), v)} -
             {StackElm (length ta, w)} -
             {PcElm (vctx_pc x1)} -
             {GasElm (vctx_gas x1)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Arith inst_EQ)})
"
apply(auto)
  apply(rename_tac elm; case_tac elm; auto)
 apply(rename_tac elm; case_tac elm; auto)
apply(rename_tac elm; case_tac elm; auto)
done
*)

lemma eq_gas_triple :
  "triple net {OutOfGas}  ( \<langle> h \<le> 1023 \<rangle> **
                        stack_height (h + 2) **
                        stack (h + 1) v **
                        stack h w **
                        program_counter k **
                        gas_pred g **
                        account_existence c existence **
                        continuing
                      )
                      {(k, Arith inst_EQ)}
                      ( stack_height (h + 1) **
                        stack h (if v = w then((word_of_int 1) ::  256 word) else((word_of_int 0) ::  256 word)) **
                        program_counter (k + 1) **
                        gas_pred (g - Gverylow) **
                        account_existence c existence **
                        continuing )"
apply(auto simp add: triple_def set_diff_eq)
 apply(rule_tac x = 1 in exI)
 apply(simp add: instruction_result_as_set_def)
  apply(case_tac presult; simp)
  apply (clarsimp simp add: failed_for_reasons_def
       instruction_result_as_set_def)
  apply(erule_tac P=rest in back_subst)
  apply(rule Set.equalityI)
  apply(clarsimp)
  apply(rename_tac elm; case_tac elm; simp)
  apply(case_tac "fst x2 < length ta"; simp)
   apply (case_tac x2; clarsimp)
  apply (metis (no_types, hide_lams) HoareTripleForInstructions.pair_snd_eq One_nat_def diff_diff_left diff_is_0_eq' length_Cons less_SucE less_Suc_eq_le list.size(4) nth_Cons_0 nth_non_equal_first_eq)
 apply(clarsimp)
    apply(rename_tac elm; case_tac elm; simp)
     apply(simp add: as_set_simps)
    apply(simp add: as_set_simps)
  apply(auto simp add: as_set_simps)[1]
apply(rule_tac x = 1 in exI)
  apply(case_tac presult; simp)
  apply (clarsimp simp add: failed_for_reasons_def
      instruction_result_as_set_def)
  apply(erule_tac P=rest in back_subst)
  apply(rule Set.equalityI)
 apply(clarsimp)
 apply(rename_tac elm; case_tac elm; simp)
  apply(case_tac "fst x2 < length ta"; simp)
  apply (case_tac x2; clarsimp)
  apply (metis (no_types, hide_lams) HoareTripleForInstructions.pair_snd_eq One_nat_def diff_diff_left diff_is_0_eq le_neq_implies_less length_Cons less_SucE list.size(4) not_less nth_Cons')

apply(clarsimp)
apply(rename_tac elm; case_tac elm; simp)
apply (auto simp add: as_set_simps)
done
(*
lemma tmp1 [simp]:
  "program_content (cctx_program co_ctx) (vctx_pc x1) = Some (Arith ADD) \<Longrightarrow>
   vctx_stack x1 = v # w # ta \<Longrightarrow>
   (insert (GasElm (vctx_gas x1 - Gverylow))
              (insert (ContinuingElm True)
                (contexts_as_set (vctx_advance_pc co_ctx x1) co_ctx - stack_as_set (v # w # ta) \<union> stack_as_set ((v + w) # ta) -
                 {GasElm (vctx_gas x1)})) -
             {StackHeightElm (Suc (length ta))} -
             {StackElm (length ta, v + w)} -
             {PcElm (vctx_pc x1 + 1)} -
             {GasElm (vctx_gas x1 - Gverylow)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Arith ADD)}) =
  (insert (ContinuingElm True) (contexts_as_set x1 co_ctx) - {StackHeightElm (Suc (Suc (length ta)))} -
             {StackElm (Suc (length ta), v)} -
             {StackElm (length ta, w)} -
             {PcElm (vctx_pc x1)} -
             {GasElm (vctx_gas x1)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Arith ADD)})"
apply(auto)
  apply(rename_tac elm; case_tac elm; auto)
 apply(rename_tac elm; case_tac elm; auto)
apply(rename_tac elm; case_tac elm; auto)
done
*)
lemma add_triple :
   "triple net {}
           (\<langle> h \<le> 1023 \<and> g \<ge> Gverylow \<rangle> **
            stack_height (h + 2) **
            stack (h + 1) v **
            stack h w **
            program_counter k **
            gas_pred g **
            continuing
           )
           {(k, Arith ADD)}
           (stack_height (h + 1) **
            stack h (v + w) **
            program_counter (k + 1) **
            gas_pred (g - Gverylow) **
            continuing
           )"
apply(simp add: triple_def set_diff_eq)
apply(clarify)
apply(rule_tac x = "1" in exI)
  apply(case_tac presult; simp)
 apply (auto simp add: instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
apply(rule Set.equalityI)
 apply(clarsimp)
 apply(rename_tac elm; case_tac elm; simp)
 apply(case_tac "fst x2 < length ta"; simp)
 apply(case_tac "fst x2 = length ta"; simp)
 apply(case_tac "fst x2 = Suc (length ta)"; simp)
apply(clarsimp)
  apply(rename_tac elm; case_tac elm; clarsimp)
  apply (auto simp: as_set_simps)
done

lemma add_gas_triple :
   "triple net {OutOfGas}
      (\<langle> h \<le> 1023\<rangle> **
       stack_height (h + 2) **
       stack (h + 1) v **
       stack h w **
       program_counter k **
       gas_pred g **
       continuing
      )

      {(k, Arith ADD)}

      (stack_height (h + 1) **
       stack h (v + w) **
       program_counter (k + 1) **
       gas_pred (g - Gverylow) **
       continuing
      )"
apply(simp add: triple_def set_diff_eq)
apply(clarify)
apply(rule_tac x = "1" in exI)
apply(case_tac presult; auto simp add: instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
apply(rule Set.equalityI)
 apply(clarsimp)
 apply(rename_tac elm; case_tac elm; simp)
 apply(case_tac "fst x2 < length ta"; simp)
 apply(case_tac "fst x2 = length ta"; simp)
 apply(case_tac "fst x2 = Suc (length ta)"; simp)
apply(clarsimp)+
apply(rename_tac elm; case_tac elm; simp)
  apply(auto simp add: as_set_simps)
done

lemma add_instance : "triple net {} (\<langle> (h + 1) \<le> 1023 \<and> g \<ge> Gverylow \<rangle> **
                            stack_height ((h + 1) + 2) **
                            stack ((h + 1) + 1) x **
                            stack (h + 1) v **
                            program_counter k **
                            gas_pred g **
                            continuing
                           )
                           ({(k, Arith ADD)})
                           (stack_height ((h + 1) + 1) **
                            stack (h + 1) (x + v) **
                            program_counter (k + 1) **
                            gas_pred (g - Gverylow) **
                            continuing
                            )"
apply(rule add_triple)
done

lemma add_extended : "triple net {} ((\<langle> (h + 1) \<le> 1023 \<and> g \<ge> Gverylow \<rangle> **
                            stack_height ((h + 1) + 2) **
                            stack ((h + 1) + 1) x **
                            stack (h + 1) v **
                            program_counter k **
                            gas_pred g **
                            continuing)
                            ** stack h w
                           )
                           ({(k, Arith ADD)})
                           ((stack_height ((h + 1) + 1) **
                            stack (h + 1) (x + v) **
                            program_counter (k + 1) **
                            gas_pred (g - Gverylow) **
                            continuing)
                            ** stack h w
                            )"
apply(rule frame)
apply(rule add_instance)
done

(*
lemma addadd_triple :
  "triple {} (\<langle> h \<le> 1022 \<and> g \<ge> 2 * Gverylow \<rangle> **
              stack_height (Suc (Suc (Suc h))) **
              stack (h + 2) x **
              stack (h + 1) v **
              stack h w **
              program_counter k **
              gas_pred g **
              continuing
             )
             ({(k, Arith ADD)} \<union> {(k + 1, Arith ADD)})
             (stack_height (h + 1) **
              stack h (x + v + w) **
              program_counter (2 + k) **
              gas_pred (g - 2 * Gverylow) **
              continuing
             )"
(* here the pure condition should be moved out *)
apply(auto)
apply(rule_tac cL = "{(k, Arith ADD)}" and cR = "{(k + 1, Arith ADD)}" in composition)
  apply(simp)
 defer
 apply(rule weaken_post)
 apply(rule_tac h = h and v = "x + v" and w = w and k = "k + 1" and g = "g - Gverylow" in add_triple)
 apply(auto)
apply(rule weaken_post)
 apply(rule strengthen_pre)
oops
*)

lemma pop1 [simp] :
"
vctx_stack x1 = v # t \<Longrightarrow>
(insert (GasElm (vctx_gas x1 - Gbase))
              (insert (ContinuingElm True)
                (insert (StackHeightElm (length t))
                  (insert (PcElm (vctx_pc x1 + 1)) (contexts_as_set x1 co_ctx) - {PcElm (vctx_pc x1)} -
                   insert (StackHeightElm (Suc (length t))) {StackElm (idx, (rev t @ [v]) ! idx) |idx. idx < Suc (length t)} \<union>
                   {StackElm (idx, rev t ! idx) |idx. idx < length t}) -
                 {GasElm (vctx_gas x1)})) -
             {StackHeightElm (length t)} -
             {PcElm (vctx_pc x1 + 1)} -
             {GasElm (vctx_gas x1 - Gbase)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Stack POP)}) =
 (insert (ContinuingElm True) (contexts_as_set x1 co_ctx) - {StackHeightElm (Suc (length t))} -
             {StackElm (length t, v)} -
             {PcElm (vctx_pc x1)} -
             {GasElm (vctx_gas x1)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Stack POP)})
"
apply(auto)
done

lemma pop_triple : "triple net {} (\<langle> h \<le> 1024 \<and> g \<ge> Gbase \<rangle> **
                            stack_height (h + 1) **
                            stack h v **
                            program_counter k **
                            gas_pred g **
                            continuing
                           )
                           {(k, Stack POP)}
                           (stack_height h **
                            program_counter (k + 1) **
                            gas_pred (g - Gbase) **
                            continuing
                            )"
apply(simp add: triple_def set_diff_eq)
apply(clarify)
apply(rule_tac x = "1" in exI)
apply(case_tac presult; simp)
apply(auto simp add: instruction_result_as_set_def)
apply(erule_tac P=rest in back_subst)
  apply(auto)
apply(auto simp add:
      vctx_advance_pc_def contexts_as_set_def variable_ctx_as_set_def
      ext_program_as_set_def balance_as_set_def)
done

declare misc_inst_numbers.simps [simp]
Gzero_def [simp]

lemma stop_gas_triple:
  "triple net {OutOfGas}
          (\<langle> h \<le> 1024 \<rangle> ** stack_height h ** program_counter k ** account_existence c existence **  continuing)
          {(k, Misc STOP)}
          (stack_height h ** program_counter k **  account_existence c existence ** not_continuing ** action (ContractReturn []))"
apply(simp add: triple_def set_diff_eq)
apply(clarify)
apply(rule_tac x = "1" in exI)
apply(clarify)
  apply(case_tac presult; simp)
  apply (auto simp add: stop_def not_continuing_def action_def
      instruction_result_as_set_def stack_as_set_def ext_program_as_set_def)
apply((erule_tac P=rest in back_subst)?, auto split: if_splits)+
done

lemma caller0 [simp] :
" program_content (cctx_program co_ctx) (vctx_pc x1) = Some (Info CALLER) \<Longrightarrow>
  (insert (GasElm (vctx_gas x1 - Gbase))
              (insert (ContinuingElm True)
                (contexts_as_set (vctx_advance_pc co_ctx x1) co_ctx - stack_as_set (vctx_stack x1) \<union>
                 stack_as_set (ucast (vctx_caller x1) # vctx_stack x1) -
                 {GasElm (vctx_gas x1)})) -
             {StackHeightElm (Suc (length (vctx_stack x1)))} -
             {StackElm (length (vctx_stack x1), ucast (vctx_caller x1))} -
             {PcElm (vctx_pc x1 + 1)} -
             {CallerElm (vctx_caller x1)} -
             {GasElm (vctx_gas x1 - Gbase)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Info CALLER)}) =
 (insert (ContinuingElm True) (contexts_as_set x1 co_ctx) - {StackHeightElm (length (vctx_stack x1))} -
             {PcElm (vctx_pc x1)} -
             {CallerElm (vctx_caller x1)} -
             {GasElm (vctx_gas x1)} -
             {ContinuingElm True} -
             {CodeElm (vctx_pc x1, Info CALLER)})
"
apply(auto)
  apply(rename_tac elm; case_tac elm; auto simp add: stack_as_set_def)
 apply(rename_tac elm; case_tac elm; auto simp add: stack_as_set_def)
apply(rename_tac elm; case_tac elm; auto simp add: stack_as_set_def)
done

lemma caller_gas_triple :
  "triple net {OutOfGas}
          (\<langle> h \<le> 1023 \<rangle> ** stack_height h ** program_counter k ** caller c ** gas_pred g **
account_existence c existence ** continuing)
          {(k, Info CALLER)}
          (stack_height (h + 1) ** stack h (ucast c)
           ** program_counter (k + 1) ** caller c ** gas_pred (g - Gbase) **
           account_existence c existence ** continuing )"
apply(auto simp add: triple_def set_diff_eq)
apply(rule_tac x = 1 in exI)
  apply(case_tac presult; simp)
  apply (clarsimp simp add: instruction_result_as_set_def set_diff_eq)
 apply(erule_tac P=rest in back_subst)
  apply(clarsimp)
  apply(rename_tac elm; case_tac elm; auto simp add: as_set_simps)
done

end

end


(*  Title:      JinjaThreads/Execute/JVM_Execute2.thy
    Author:     Andreas Lochbihler
*)

theory JVM_Execute2
imports
  SC_Schedulers
  JVMExec_Execute2
  "../BV/BVProgressThreaded"
begin

abbreviation sc_heap_read_cset :: "heap \<Rightarrow> addr \<Rightarrow> addr_loc \<Rightarrow> addr val set"
where "sc_heap_read_cset h ad al \<equiv> set_of_pred (sc_heap_read_i_i_i_o h ad al)"

abbreviation sc_heap_write_cset :: "heap \<Rightarrow> addr \<Rightarrow> addr_loc \<Rightarrow> addr val \<Rightarrow> heap set"
where "sc_heap_write_cset h ad al v \<equiv> set_of_pred (sc_heap_write_i_i_i_i_o h ad al v)"

interpretation sc!:
  JVM_heap_execute
    "addr2thread_id"
    "thread_id2addr"
    "sc_spurious_wakeups"
    "sc_empty"
    "sc_allocate P"
    "sc_typeof_addr"
    "sc_heap_read_cset"
    "sc_heap_write_cset"
  for P
  where "\<And>h ad al v. v \<in> sc_heap_read_cset h ad al \<equiv> sc_heap_read h ad al v"
  and "\<And>h ad al v h'. h' \<in> sc_heap_write_cset h ad al v \<equiv> sc_heap_write h ad al v h'"
apply(simp_all add: eval_sc_heap_read_i_i_i_o eval_sc_heap_write_i_i_i_i_o)
done

interpretation sc!:
  JVM_heap_execute_conf_read
    "addr2thread_id"
    "thread_id2addr"
    "sc_spurious_wakeups"
    "sc_empty"
    "sc_allocate P"
    "sc_typeof_addr"
    "sc_heap_read_cset"
    "sc_heap_write_cset"
    "sc_hconf P"
    "P"
  for P
  where "\<And>h ad al v. v \<in> sc_heap_read_cset h ad al \<equiv> sc_heap_read h ad al v"
  and "\<And>h ad al v h'. h' \<in> sc_heap_write_cset h ad al v \<equiv> sc_heap_write h ad al v h'"
proof -
  show unfolds: "\<And>h ad al v. v \<in> sc_heap_read_cset h ad al \<equiv> sc_heap_read h ad al v"
    "\<And>h ad al v h'. h' \<in> sc_heap_write_cset h ad al v \<equiv> sc_heap_write h ad al v h'"
    by(simp_all add: eval_sc_heap_read_i_i_i_o eval_sc_heap_write_i_i_i_i_o)
  show "JVM_heap_execute_conf_read
    addr2thread_id thread_id2addr
    sc_empty (sc_allocate P)
    sc_typeof_addr sc_heap_read_cset sc_heap_write_cset
    (sc_hconf P) P"
    apply(rule JVM_heap_execute_conf_read.intro)
    apply(unfold unfolds)
    apply(unfold_locales)
    done
qed

abbreviation sc_JVM_start_state :: "addr jvm_prog \<Rightarrow> cname \<Rightarrow> mname \<Rightarrow> addr val list \<Rightarrow> (addr,thread_id,addr jvm_thread_state,heap,addr) state"
where "sc_JVM_start_state P \<equiv> sc.execute.JVM_start_state TYPE(addr jvm_method) P P"

abbreviation sc_exec :: "addr jvm_prog \<Rightarrow> thread_id \<Rightarrow> (addr, heap) jvm_state' \<Rightarrow> (addr, thread_id, heap) jvm_ta_state' set"
where "sc_exec P \<equiv> sc.exec TYPE(addr jvm_method) P P"

abbreviation sc_execute_mexec :: "addr jvm_prog \<Rightarrow> thread_id \<Rightarrow> (addr jvm_thread_state \<times> heap)
  \<Rightarrow> (addr, thread_id, heap) jvm_thread_action \<Rightarrow> (addr jvm_thread_state \<times> heap) \<Rightarrow> bool"
where "sc_execute_mexec P \<equiv> sc.execute.mexec TYPE(addr jvm_method) P P"

fun sc_mexec ::
  "addr jvm_prog \<Rightarrow> thread_id \<Rightarrow> (addr jvm_thread_state' \<times> heap)
  \<Rightarrow> ((addr, thread_id, heap) jvm_thread_action' \<times> addr jvm_thread_state' \<times> heap) Predicate.pred"
where
  "sc_mexec P t ((xcp, frs), h) =
   sc.exec_1 (TYPE(addr jvm_method)) P P t (xcp, h, frs) \<guillemotright>= (\<lambda>(ta, xcp, h, frs). Predicate.single (ta, (xcp, frs), h))"

abbreviation sc_jvm_start_state_refine ::
  "addr jvm_prog \<Rightarrow> cname \<Rightarrow> mname \<Rightarrow> addr val list \<Rightarrow>
  (addr, thread_id, heap, (thread_id, (addr jvm_thread_state') \<times> addr released_locks) rbt, (thread_id, addr wait_set_status) rbt, thread_id rs) state_refine"
where
  "sc_jvm_start_state_refine \<equiv>
   sc_start_state_refine (rm_empty ()) rm_update (rm_empty ()) (rs_empty ()) (\<lambda>C M Ts T (mxs, mxl0, ins, xt) vs. (None, [((ins, ins, xt), [], Null # vs @ replicate mxl0 undefined_value, C, M, 0)]))"

fun jvm_mstate_of_jvm_mstate' ::
  "(addr,thread_id,addr jvm_thread_state',heap,addr) state \<Rightarrow> (addr,thread_id,addr jvm_thread_state,heap,addr) state"
where
  "jvm_mstate_of_jvm_mstate' (ls, (ts, m), ws) = (ls, (\<lambda>t. map_option (map_prod jvm_thread_state_of_jvm_thread_state' id) (ts t), m), ws)"

definition sc_jvm_state_invar :: "addr jvm_prog \<Rightarrow> ty\<^sub>P \<Rightarrow> (addr,thread_id,addr jvm_thread_state',heap,addr) state set"
where
  "sc_jvm_state_invar P \<Phi> \<equiv>
   {s. jvm_mstate_of_jvm_mstate' s \<in> sc.execute.correct_jvm_state P \<Phi>} \<inter>
   {s. ts_ok (\<lambda>t (xcp, frs) h. jvm_state'_ok P (xcp, h, frs)) (thr s) (shr s)}"

fun JVM_final' :: "'addr jvm_thread_state' \<Rightarrow> bool"
where "JVM_final' (xcp, frs) \<longleftrightarrow> frs = []"

lemma shr_jvm_mstate_of_jvm_mstate' [simp]: "shr (jvm_mstate_of_jvm_mstate' s) = shr s"
by(cases s) clarsimp

lemma jvm_mstate_of_jvm_mstate'_sc_start_state [simp]:
  "jvm_mstate_of_jvm_mstate'
  (sc_start_state (\<lambda>C M Ts T (mxs, mxl0, ins, xt) vs. (None, [((ins, ins, xt), [], Null # vs @ replicate mxl0 undefined_value, C, M, 0)])) P C M vs) = sc_JVM_start_state P C M vs"
by(simp add: sc.start_state_def split_beta fun_eq_iff)

lemma sc_jvm_start_state_invar:
  assumes "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"
  and "sc_wf_start_state P C M vs"
  shows "sc_state_\<alpha> (sc_jvm_start_state_refine P C M vs) \<in> sc_jvm_state_invar P \<Phi>"
unfolding sc_jvm_state_invar_def Int_iff mem_Collect_eq
apply(rule conjI)
 apply(simp add: sc.execute.correct_jvm_state_initial[OF assms])
apply(rule ts_okI)
using `sc_wf_start_state P C M vs`
apply(auto simp add: sc.start_state_def split_beta sc_wf_start_state_iff split: split_if_asm dest: sees_method_idemp)
done

lemma invariant3p_sc_jvm_state_invar:
  assumes "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"
  shows "invariant3p (multithreaded_base.redT JVM_final' (\<lambda>t xm ta x'm'. Predicate.eval (sc_mexec P t xm) (ta, x'm')) convert_RA) (sc_jvm_state_invar P \<Phi>)"
proof(rule invariant3pI)
  fix s tl s'
  assume red: "multithreaded_base.redT JVM_final' (\<lambda>t xm ta x'm'. Predicate.eval (sc_mexec P t xm) (ta, x'm')) convert_RA s tl s'"
    and invar: "s \<in> sc_jvm_state_invar P \<Phi>"
  obtain t ta where tl: "tl = (t, ta)" by(cases tl)
  from red have red': "multithreaded_base.redT JVM_final (sc_execute_mexec P) convert_RA (jvm_mstate_of_jvm_mstate' s) (t, jvm_thread_action_of_jvm_thread_action' ta) (jvm_mstate_of_jvm_mstate' s')"
  proof(cases rule: multithreaded_base.redT.cases[consumes 1, case_names normal acquire])
    case (acquire s t x ln n s')
    thus ?thesis using tl by(cases s)(auto intro!: multithreaded_base.redT.redT_acquire)
  next
    case (normal t x s ta x' m' s')
    obtain xcp frs where x: "x = (xcp, frs)" by(cases x)
    with invar normal tl
    have correct: "sc.execute.correct_state P \<Phi> t (jvm_state_of_jvm_state' (xcp, shr s, frs))"
      and ok: "jvm_state'_ok P (xcp, shr s, frs)"
      apply -
      apply(case_tac [!] s)
      apply(fastforce simp add: sc_jvm_state_invar_def sc.execute.correct_jvm_state_def dest: ts_okD)+
      done
    note eq = sc.exec_correct_state(1)[OF assms this]
    with normal x tl
    have "sc_execute_mexec P t (jvm_thread_state_of_jvm_thread_state' x, shr (jvm_mstate_of_jvm_mstate' s)) (jvm_thread_action_of_jvm_thread_action' ta) (jvm_thread_state_of_jvm_thread_state' x', m')"
      by(auto simp add: sc.exec_1_def eq jvm_thread_action'_of_jvm_thread_action_def sc.execute.exec_1_iff)
    with normal tl show ?thesis
      by(cases s)(fastforce intro!: multithreaded_base.redT.redT_normal simp add: final_thread.actions_ok_iff fun_eq_iff map_redT_updTs elim: rev_iffD1[OF _ thread_oks_ts_change] cond_action_oks_final_change)
  qed
  moreover from invar
  have "sc.execute.correct_state_ts P \<Phi> (thr (jvm_mstate_of_jvm_mstate' s)) (shr (jvm_mstate_of_jvm_mstate' s))"
    and "lock_thread_ok (locks (jvm_mstate_of_jvm_mstate' s)) (thr (jvm_mstate_of_jvm_mstate' s))"
    by(simp_all add: sc_jvm_state_invar_def sc.execute.correct_jvm_state_def)
  ultimately have "sc.execute.correct_state_ts P \<Phi> (thr (jvm_mstate_of_jvm_mstate' s')) (shr (jvm_mstate_of_jvm_mstate' s'))"
    and "lock_thread_ok (locks (jvm_mstate_of_jvm_mstate' s')) (thr (jvm_mstate_of_jvm_mstate' s'))"
    by(blast intro: lifting_wf.redT_preserves[OF sc.execute.lifting_wf_correct_state, OF assms] sc.execute.exec_mthr.redT_preserves_lock_thread_ok)+
  hence "jvm_mstate_of_jvm_mstate' s' \<in> sc.execute.correct_jvm_state P \<Phi>"
    by(simp add: sc.execute.correct_jvm_state_def)
  moreover from red have "ts_ok (\<lambda>t (xcp, frs) h. \<forall>f\<in>set frs. frame'_ok P f) (thr s') (shr s')" unfolding tl
  proof(cases rule: multithreaded_base.redT.cases[consumes 1, case_names normal acquire])
    case acquire thus ?thesis using invar
      by(fastforce simp add: sc_jvm_state_invar_def intro!: ts_okI dest: ts_okD bspec split: split_if_asm)
  next
    case (normal t x s ta x' m' s')
    obtain xcp frs where x: "x = (xcp, frs)" by(cases x)
    with invar normal tl
    have correct: "sc.execute.correct_state P \<Phi> t (jvm_state_of_jvm_state' (xcp, shr s, frs))"
      and ok: "jvm_state'_ok P (xcp, shr s, frs)"
      apply -
      apply(case_tac [!] s)
      apply(fastforce simp add: sc_jvm_state_invar_def sc.execute.correct_jvm_state_def dest: ts_okD)+
      done
    from normal x invar show ?thesis
      apply(auto simp add: sc.exec_1_def final_thread.actions_ok_iff jvm_thread_action'_ok_def sc_jvm_state_invar_def)
      apply hypsubst_thin
      apply(drule sc.exec_correct_state(3)[OF assms correct ok])
      apply(rule ts_okI)
      apply(clarsimp split: split_if_asm simp add: jvm_thread_action'_ok_def)
      apply(drule (1) bspec)
      apply simp
      apply(case_tac "thr s t")
       apply(drule (2) redT_updTs_new_thread)
       apply clarsimp
       apply(drule (1) bspec)
       apply simp
       apply(drule (1) bspec)
       apply simp
      apply(erule thin_rl)
      apply(frule (1) redT_updTs_Some)
      apply(fastforce dest: ts_okD)
      done
  qed
  ultimately show "s' \<in> sc_jvm_state_invar P \<Phi>" by(simp add: sc_jvm_state_invar_def)
qed

lemma sc_exec_deterministic:
  assumes "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"
  shows "multithreaded_base.deterministic JVM_final' (\<lambda>t xm ta x'm'. Predicate.eval (sc_mexec P t xm) (ta, x'm')) convert_RA
     (sc_jvm_state_invar P \<Phi>)"
proof -
  from assms sc_deterministic_heap_ops
  have det: "multithreaded_base.deterministic JVM_final (sc_execute_mexec P) convert_RA {s. sc.execute.correct_state_ts P \<Phi> (thr s) (shr s)}"
    by(rule sc.execute.mexec_deterministic)(simp add: sc_spurious_wakeups)
  show ?thesis
  proof(rule multithreaded_base.determisticI)
    fix s t x ta' x' m' ta'' x'' m''
    assume inv: "s \<in> sc_jvm_state_invar P \<Phi>"
      and tst: "thr s t = \<lfloor>(x, no_wait_locks)\<rfloor>"
      and exec1: "Predicate.eval (sc_mexec P t (x, shr s)) (ta', x', m')"
      and exec2: "Predicate.eval (sc_mexec P t (x, shr s)) (ta'', x'', m'')"
      and aok1: "final_thread.actions_ok JVM_final' s t ta'"
      and aok2: "final_thread.actions_ok JVM_final' s t ta''"
    obtain xcp frs where x: "x = (xcp, frs)" by(cases x)
    from inv tst x have correct: "sc.execute.correct_state P \<Phi> t (jvm_state_of_jvm_state' (xcp, shr s, frs))"
      and ok: "jvm_state'_ok P (xcp, shr s, frs)"
      by(cases s, fastforce simp add: sc_jvm_state_invar_def sc.execute.correct_jvm_state_def dest: ts_okD)+
    note eq = sc.exec_correct_state(1)[OF assms this]

    from exec1 exec2 x
    have "sc_execute_mexec P t (jvm_thread_state_of_jvm_thread_state' x, shr (jvm_mstate_of_jvm_mstate' s)) (jvm_thread_action_of_jvm_thread_action' ta') (jvm_thread_state_of_jvm_thread_state' x', m')"
      and "sc_execute_mexec P t (jvm_thread_state_of_jvm_thread_state' x, shr (jvm_mstate_of_jvm_mstate' s)) (jvm_thread_action_of_jvm_thread_action' ta'') (jvm_thread_state_of_jvm_thread_state' x'', m'')"
      by(auto simp add: sc.exec_1_def eq jvm_thread_action'_of_jvm_thread_action_def sc.execute.exec_1_iff)
    moreover have "thr (jvm_mstate_of_jvm_mstate' s) t = \<lfloor>(jvm_thread_state_of_jvm_thread_state' x, no_wait_locks)\<rfloor>"
      using tst by(cases s) clarsimp
    moreover have "final_thread.actions_ok JVM_final (jvm_mstate_of_jvm_mstate' s) t (jvm_thread_action_of_jvm_thread_action' ta')"
      and "final_thread.actions_ok JVM_final (jvm_mstate_of_jvm_mstate' s) t (jvm_thread_action_of_jvm_thread_action' ta'')"
      using aok1 aok2
      by -(case_tac [!] s,auto simp add: final_thread.actions_ok_iff elim: rev_iffD1[OF _ thread_oks_ts_change] cond_action_oks_final_change)
    moreover have "sc.execute.correct_state_ts P \<Phi> (thr (jvm_mstate_of_jvm_mstate' s)) (shr (jvm_mstate_of_jvm_mstate' s))"
      using inv
      by(cases s)(auto intro!: ts_okI simp add: sc_jvm_state_invar_def sc.execute.correct_jvm_state_def dest: ts_okD)
    ultimately
    have "jvm_thread_action_of_jvm_thread_action' ta' = jvm_thread_action_of_jvm_thread_action' ta'' \<and>
          jvm_thread_state_of_jvm_thread_state' x' = jvm_thread_state_of_jvm_thread_state' x'' \<and>
          m' = m''"
      by-(drule (4) multithreaded_base.deterministicD[OF det], simp_all)
    moreover from exec1 exec2 x
    have "(ta', (fst x', m', snd x')) \<in> sc_exec P t (xcp, shr s, frs)"
      and "(ta'', (fst x'', m'', snd x'')) \<in> sc_exec P t (xcp, shr s, frs)"
      by(auto simp add: sc.exec_1_def)
    hence "jvm_ta_state'_ok P (ta', (fst x', m', snd x'))"
      and "jvm_ta_state'_ok P (ta'', (fst x'', m'', snd x''))"
      by(blast intro: sc.exec_correct_state[OF assms correct ok])+
    hence "ta' = jvm_thread_action'_of_jvm_thread_action P (jvm_thread_action_of_jvm_thread_action' ta')"
      and "ta'' = jvm_thread_action'_of_jvm_thread_action P (jvm_thread_action_of_jvm_thread_action' ta'')"
      and "x' = jvm_thread_state'_of_jvm_thread_state P (jvm_thread_state_of_jvm_thread_state' x')"
      and "x'' = jvm_thread_state'_of_jvm_thread_state P (jvm_thread_state_of_jvm_thread_state' x'')"
      apply -
      apply(case_tac [!] ta')
      apply(case_tac [!] ta'')
      apply(case_tac [!] x')
      apply(case_tac [!] x'')
      apply(fastforce simp add: jvm_thread_action'_of_jvm_thread_action_def jvm_thread_action'_ok_def intro!: map_idI[symmetric] convert_new_thread_action_eqI dest: bspec)+
      done
    ultimately
    show "ta' = ta'' \<and> x' = x'' \<and> m' = m''" by simp
  qed(rule invariant3p_sc_jvm_state_invar[OF assms])
qed

subsection {* Round-robin scheduler *}

interpretation JVM_rr!:
  sc_round_robin_base
    JVM_final' "sc_mexec P" convert_RA Jinja_output
  for P
.

definition sc_rr_JVM_start_state :: "nat \<Rightarrow> 'm prog \<Rightarrow> thread_id fifo round_robin"
where "sc_rr_JVM_start_state n0 P = JVM_rr.round_robin_start n0 (sc_start_tid P)"

definition exec_JVM_rr ::
  "nat \<Rightarrow> addr jvm_prog \<Rightarrow> cname \<Rightarrow> mname \<Rightarrow> addr val list \<Rightarrow>
  (thread_id \<times> (addr, thread_id) obs_event list,
   (addr, thread_id) locks \<times> ((thread_id, addr jvm_thread_state' \<times> addr released_locks) RBT.rbt \<times> heap) \<times>
   (thread_id, addr wait_set_status) RBT.rbt \<times> thread_id rs) tllist"
where
  "exec_JVM_rr n0 P C M vs = JVM_rr.exec P n0 (sc_rr_JVM_start_state n0 P) (sc_jvm_start_state_refine P C M vs)"

interpretation JVM_rr!:
  sc_round_robin
    JVM_final' "sc_mexec P" convert_RA Jinja_output
  for P
by(unfold_locales)

lemma JVM_rr:
  assumes "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"
  shows
  "sc_scheduler
     JVM_final' (sc_mexec P) convert_RA
     (JVM_rr.round_robin P n0) (pick_wakeup_via_sel (\<lambda>s P. rm_sel s (\<lambda>(k,v). P k v))) JVM_rr.round_robin_invar
     (sc_jvm_state_invar P \<Phi>)"
unfolding sc_scheduler_def
apply(rule JVM_rr.round_robin_scheduler)
apply(rule sc_exec_deterministic[OF assms])
done

subsection {* Random scheduler *}

interpretation JVM_rnd!:
  sc_random_scheduler_base
    JVM_final' "sc_mexec P" convert_RA Jinja_output
  for P
.

definition sc_rnd_JVM_start_state :: "Random.seed \<Rightarrow> random_scheduler"
where "sc_rnd_JVM_start_state seed = seed"

definition exec_JVM_rnd ::
  "Random.seed \<Rightarrow> addr jvm_prog \<Rightarrow> cname \<Rightarrow> mname \<Rightarrow> addr val list \<Rightarrow>
  (thread_id \<times> (addr, thread_id) obs_event list,
   (addr, thread_id) locks \<times> ((thread_id, addr jvm_thread_state' \<times> addr released_locks) RBT.rbt \<times> heap) \<times>
   (thread_id, addr wait_set_status) RBT.rbt \<times> thread_id rs) tllist"
where "exec_JVM_rnd seed P C M vs = JVM_rnd.exec P (sc_rnd_JVM_start_state seed) (sc_jvm_start_state_refine P C M vs)"

interpretation JVM_rnd!:
  sc_random_scheduler
    JVM_final' "sc_mexec P" convert_RA Jinja_output
  for P
by(unfold_locales)

lemma JVM_rnd:
  assumes "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"
  shows
  "sc_scheduler
    JVM_final' (sc_mexec P) convert_RA
    (JVM_rnd.random_scheduler P) (pick_wakeup_via_sel (\<lambda>s P. rm_sel s (\<lambda>(k,v). P k v))) (\<lambda>_ _. True)
    (sc_jvm_state_invar P \<Phi>)"
unfolding sc_scheduler_def
apply(rule JVM_rnd.random_scheduler_scheduler)
apply(rule sc_exec_deterministic[OF assms])
done

ML_val {* @{code exec_JVM_rr} *}

ML_val {* @{code exec_JVM_rnd} *}

end