theory Invariant
imports ViewShift Automation
begin

subsubsection \<open>Impredicative Invariants\<close>

context
fixes get_inv :: "gname \<Rightarrow> 'res::ucamera \<Rightarrow> inv option"
  and put_inv
assumes inv_inG: "inG get_inv put_inv"
begin

abbreviation fancy_upd' ("\<Turnstile>{_,_}=>_") where "fancy_upd' \<equiv> fancy_upd put_inv"
abbreviation wand_fupd' ("_={_,_}=\<^emph>_") where "wand_fupd' \<equiv> wand_fupd put_inv"
abbreviation linear_fupd' ("\<Turnstile>{_}=>_") where "linear_fupd' \<equiv> linear_fupd put_inv"
abbreviation wand_linear_fupd' ("_={_}=\<^emph>_") where "wand_linear_fupd' \<equiv> wand_linear_fupd put_inv"
abbreviation inv_raw where "inv_raw \<equiv> WorldSatisfaction.inv_raw put_inv"
abbreviation wsat :: "'res upred_f" where "wsat \<equiv> WorldSatisfaction.wsat put_inv"
abbreviation ownE :: "mask \<Rightarrow> 'res upred_f" where "ownE \<equiv> WorldSatisfaction.ownE put_inv"
abbreviation ownD :: "name fset \<Rightarrow> 'res upred_f" where "ownD \<equiv> WorldSatisfaction.ownD put_inv"
abbreviation ownI :: "name \<Rightarrow> 'res upred_f \<Rightarrow> 'res upred_f" where "ownI \<equiv> WorldSatisfaction.ownI put_inv"

text \<open>Semantic invariant definition\<close>
definition inv :: "namespace \<Rightarrow> 'res upred_f \<Rightarrow> 'res upred_f" where
  "inv N P = \<box>(\<forall>\<^sub>u E. ((\<upharpoonleft>((names N) \<subseteq> E)) \<longrightarrow>\<^sub>u
    (\<Turnstile>{E,E-(names N)}=> ((\<triangleright>P) \<^emph> ((\<triangleright>P) ={E-(names N), E}=\<^emph> \<upharpoonleft>True)))))"

lemma superset_split: "s \<subseteq> t \<Longrightarrow> t = s \<union> (t-s)" by auto

lemma inv_raw_acc: "names N \<subseteq> E \<Longrightarrow>
  ((inv_raw N P) ={E, E-(names N)}=\<^emph> ((\<triangleright>P) \<^emph> ((\<triangleright>P) ={E-(names N), E}=\<^emph> \<upharpoonleft>True)))"
apply (auto simp: fancy_upd_def[OF inv_inG] upred_sep_assoc_eq inv_raw_def[OF inv_inG] intro!: upred_wand_holdsI upred_existsE')
apply (rule upred_entails_trans[OF upred_entail_eqR[OF persistent_holds_sep']], pers_solver, rule inv_inG)
apply (auto intro!: upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]] upred_pure_impl)
apply (auto simp: upred_sep_assoc_eq intro!: upred_wandI)
apply (subst superset_split[of "names N"], assumption)
apply (rule upred_entails_substE[OF upred_entail_eqL[OF ownE_op_minus[OF inv_inG]]])
apply (auto simp: upred_sep_assoc_eq)
subgoal for i
apply (simp add: dnames_def)
apply (subst superset_split[of "{i}" "names N"], simp)
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF upred_entail_eqL[OF ownE_op_minus[OF inv_inG]], of "{i}" "names N"])
apply (auto simp: upred_sep_assoc_eq intro!: upred_entails_trans[OF _ updI] upred_entails_trans[OF _ except_zeroI])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm4_1])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF upred_entail_eqR[OF persistent_dupl]])
apply (pers_solver, rule inv_inG)
apply (simp add: upred_sep_assoc_eq)
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm3L])
apply (simp add: upred_sep_assoc_eq)
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF ownI_open[OF inv_inG], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF _ upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_frame)
apply (rule upred_entails_trans[OF _ upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm3L])
apply (simp add: upred_sep_assoc_eq)
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_frame)
apply (rule upred_entails_trans[OF _ upred_entails_eq[OF upred_sep_comm]])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (auto simp: upred_sep_assoc_eq intro!: upred_frame upred_wandI)
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
apply (simp add: upred_sep_assoc_eq)
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_substE[OF ownI_close[OF inv_inG], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (auto simp: insert_absorb intro!: upred_entails_substE[OF
    upred_entail_eqR[OF ownE_op_minus[OF inv_inG]], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (auto simp: Un_absorb1 intro!: upred_entails_substE[OF upred_entail_eqR[OF
    ownE_op_minus[OF inv_inG]], unfolded upred_sep_assoc_eq] upred_entails_trans[OF _ updI]
    upred_entails_trans[OF _ except_zeroI])
apply (rule upred_entails_trans[OF _ upred_sep_comm2R])
by (auto simp: upred_true_sep intro!: upred_frame)
done

lemma fresh_inv_name: "\<exists>\<iota>. \<iota> |\<notin>| E \<and> \<iota> \<in> names N"
proof -
  from infinite_names have "names N - fset E \<noteq> {}"
     using finite_fset infinite_super by fastforce
  then obtain \<iota> where "\<iota> \<in> names N - fset E" unfolding dnames_def by (cases E) auto
  then have "\<iota> |\<notin>| E \<and> \<iota> \<in> names N" by (auto simp add: dnames_def fmember.rep_eq)
  then show ?thesis by blast
qed

lemma inv_raw_alloc: "(\<triangleright>P) ={E}=\<^emph> (inv_raw N P)"
apply (auto simp: fancy_upd_def[OF inv_inG] upred_sep_assoc_eq intro!: upred_wand_holdsI upred_wandI)
apply (subst upred_sep_comm2_eq[of wsat])
apply (rule upred_entails_trans[OF _ upd_mono,OF _ except_zero_sepR])
apply (auto intro!: upred_entails_trans[OF _ upd_frameL] upred_frame)
apply (rule upred_wand_holdsE)
apply (subst upred_sep_comm)
apply (rule upred_entails_wand_holdsR[OF _ ownI_alloc[OF inv_inG, of "\<lambda>i. i \<in> names N"],
    OF _ allI[OF fresh_inv_name, of id, simplified]])
apply (rule upd_mono)
apply (auto intro!: upred_existsE')
apply (subst upred_sep_comm[of wsat])
apply (subst upred_sep_comm2_eq)
apply (auto intro!: upred_entails_trans[OF _ except_zeroI] upred_frame)
unfolding inv_raw_def[OF inv_inG]
subgoal for i
apply (rule upred_existsI[of _ _ i])
apply (subst upred_sep_comm)
by (auto simp: dnames_def intro!:upred_pure_impl upred_entails_conjI upred_pureI)
done

lemma inv_raw_alloc_open: "names N \<subseteq> E \<Longrightarrow>
  \<Turnstile>{E, E-names N}=> (inv_raw N P \<^emph> ((\<triangleright>P) ={E-names N, E}=\<^emph> upred_emp))"
  unfolding fancy_upd_def[OF inv_inG]
apply (rule upred_wand_holdsI)
apply (rule upred_wandE)
apply (rule upred_entails_trans[OF upred_wand_holdsE[OF ownI_alloc_open[OF inv_inG, of "\<lambda>i. i \<in> names N"]],
  OF allI[OF fresh_inv_name, of id, simplified], of P])
apply (auto simp: pull_exists_eq intro!: upred_wandI upred_entails_trans[OF upd_frameL] upd_mono upred_existsE')
apply (rule upred_entails_trans[OF upred_sep_comm4_1])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_pure_impl)
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
subgoal for i
apply (rule split_trans[of _ "ownE E \<^emph> ownI i P" "(ownE {i} -\<^emph> wsat) \<^emph> ownD {|i|} \<^emph> ownI i P"
  "ownE {i} \<^emph> ownE (names N - {i}) \<^emph> ownE (E - names N)", unfolded upred_sep_assoc_eq])
apply(rule can_be_split_R_R[OF persistent_dupl_split[OF persistent_ownI[OF inv_inG]], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF _ upred_sep_comm2R])
apply (rule upred_entails_trans[OF _ upred_entails_eq[OF upred_sep_comm2L]])
apply (auto simp: insert_absorb intro!: upred_entails_substI[OF
    upred_entail_eqL[OF ownE_op_minus[OF inv_inG]], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF _ upred_entails_eq[OF upred_sep_comm]])
apply (auto simp: Un_absorb1 upred_weakeningL upred_sep_assoc_eq
  intro!: upred_entails_trans[OF _ upred_entail_eqL[OF ownE_op_minus[OF inv_inG]], unfolded upred_sep_assoc_eq]
  upred_entails_trans[OF _ except_zeroI])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF _ upred_sep_comm3M])
apply (rule upred_entails_trans[OF _ upred_sep_comm2R])
apply (rule upred_frame)
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm4_1])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule split_frame[of _ "ownE {i} \<^emph> (ownE {i} -\<^emph> wsat) \<^emph> ownI i P"
  "ownE (names N - {i}) \<^emph> ownD {|i|}\<^emph> ownI i P" _ wsat
  "inv_raw N P \<^emph> ((\<triangleright>P) -\<^emph> (wsat \<^emph> ownE (E - names N)) ==\<^emph> \<diamondop>(wsat \<^emph> ownE E \<^emph> upred_emp))",
  unfolded upred_sep_assoc_eq])
apply (rule can_be_split_mono[OF _ persistent_dupl_split[OF persistent_ownI[OF inv_inG]], unfolded upred_sep_assoc_eq])
apply (rule can_be_split_rev)
apply (rule can_be_split_refl)
subgoal unfolding can_be_split_def by (simp add: upred_entails_eq_eq upred_sep_assoc_eq)
apply (auto intro: upred_entails_trans[OF upred_weakeningL] upred_wand_apply)
apply (rule split_frame[of _ "ownI i P" _ _ "inv_raw N P"])
apply (rule can_be_split_rev)
apply (rule persistent_dupl_split, pers_solver, rule inv_inG)
apply (rule can_be_split_refl)
apply (auto simp: inv_raw_def[OF inv_inG] dnames_def upred_true_conj' upred_sep_assoc_eq intro!: upred_existsI[of _ _ i] upred_wandI)
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]]; simp add: upred_sep_assoc_eq)
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm4_2])
apply (rule upred_entails_substE[OF ownI_close[OF inv_inG], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (auto simp: insert_absorb intro!: upred_entails_substE[OF
    upred_entail_eqR[OF ownE_op_minus[OF inv_inG]], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
by (auto simp: Un_absorb1 upred_true_sep intro!: upred_entails_substE[OF
    upred_entail_eqR[OF ownE_op_minus[OF inv_inG]], unfolded upred_sep_assoc_eq] upred_entails_trans[OF _ updI]
    upred_entails_trans[OF _ except_zeroI])
done

lemma inv_raw_to_inv: "inv_raw N P -\<^emph> inv N P"
unfolding inv_def
apply (auto intro!: upred_wand_holdsI upred_entails_trans[OF _ upred_entail_eqL[OF pers_forall]]
  upred_forallI upred_entails_trans[OF _ upred_entail_eqR[OF upred_pers_impl_pure]] upred_implI_pure)
subgoal for E
apply (rule add_holds[OF upred_holds_persis[OF inv_raw_acc[of N E P]]], assumption)
by (auto intro!: upred_persis_frame[OF _ upred_wand_apply], pers_solver, rule inv_inG)
done

text \<open>
  The follow lemmata are the public API for invariants and should be enough to handle most proofs
  with invariants.
\<close>

lemma persistent_inv [pers_rule,log_prog_rule]: "persistent (inv N P)"
  unfolding inv_def by pers_solver

lemma inv_alter: "inv N P -\<^emph> (\<triangleright>\<box>(P -\<^emph> (Q \<^emph> (Q-\<^emph>P)))) -\<^emph> inv N Q"
apply (auto simp: inv_def intro!: upred_wand_holds2I upred_entails_trans[OF _ upred_entail_eqL[OF
    pers_forall]] upred_forallI upred_entails_trans[OF _ upred_entail_eqR[OF upred_pers_impl_pure]]
    upred_implI_pure)
apply (rule persistent_persisI, pers_solver)
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
subgoal for E
apply (auto intro!: upred_entails_substE[OF upred_persis_mono[OF upred_forall_inst[of _ E]]]
  upred_entails_substE[OF upred_persis_mono[OF upred_entail_eqL[OF upred_emp_impl]]])
apply (auto simp: upred_sep_assoc_eq intro!: upred_entails_substE[OF upred_persisE] fupd_frame_mono[OF inv_inG])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule split_trans[OF _ upred_entails_trans[OF upred_entail_eqR[OF upred_later_sep] upred_later_mono[OF
  upred_persis_mono_frame[OF upred_wand_apply[of P "Q\<^emph>(Q-\<^emph>P)"]]]]])
apply (rule can_be_split_sepL)
apply (rule can_be_split_rev)
apply (rule can_be_split_refl)
apply (auto intro!: split_frame[OF _ can_be_split_refl, of _ "\<triangleright>Q"])
apply (rule can_be_split_sepR)
unfolding can_be_split_def
apply (rule upred_later_sep)
apply (rule upred_wandI)
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF upred_entail_eqR[OF upred_later_sep], OF upred_entails_substE[OF
    upred_later_mono[OF upred_wand_apply]], unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
by (auto intro: upred_entails_trans[OF upred_wand_apply])
done

lemma inv_iff: "inv N P -\<^emph> (\<triangleright>\<box>((P \<longrightarrow>\<^sub>u Q) \<and>\<^sub>u (Q\<longrightarrow>\<^sub>uP))) -\<^emph> inv N Q"
apply (auto intro!: upred_wand_holds2I upred_entails_trans[OF _ upred_wand_holds2E[OF inv_alter], of _ N P])
apply (auto intro!: upred_sep_mono upred_later_mono)
apply (rule upred_entails_trans[OF upred_entail_eqR[OF persistent_dupl]], pers_solver)
apply (rule upred_persis_frame, pers_solver)
apply (auto intro!: upred_wandI)
apply (rule split_frame[of _ "((P \<longrightarrow>\<^sub>u Q) \<and>\<^sub>u (Q \<longrightarrow>\<^sub>u P)) \<^emph> P" _ _ Q])
apply (rule can_be_split_sepL; rule can_be_split_rev; rule can_be_split_refl)
apply (rule can_be_split_refl)
apply (rule upred_entails_trans[OF upred_entails_conj_sep])
apply (subst upred_conj_comm)
apply (subst upred_conj_comm2R)
apply (auto simp: upred_weakeningR' intro: upred_entails_substE'[OF upred_impl_apply, unfolded upred_conj_assoc])
apply (rule upred_entails_trans[OF upred_persisE])
apply (rule upred_wandI)
apply (rule upred_entails_trans[OF upred_entails_conj_sep])
apply (subst upred_conj_comm2R)
by (auto simp: upred_weakeningR' intro: upred_entails_substE'[OF upred_impl_apply, unfolded upred_conj_assoc])

lemma inv_alloc: "(\<triangleright>P) ={E}=\<^emph> inv N P"
  by (auto intro!: upred_wand_holdsI upred_entails_trans[OF _ fupd_mono[OF inv_inG upred_wand_holdsE[OF
    inv_raw_to_inv]]] upred_wand_holdsE[OF inv_raw_alloc])

lemma inv_alloc_open: "names N \<subseteq> E \<Longrightarrow>
  \<Turnstile>{E, E-names N}=> (inv N P \<^emph> ((\<triangleright>P) ={E-names N, E}=\<^emph> upred_emp))"
apply (auto simp: upred_holds_entails)
apply (rule add_holds[OF inv_raw_alloc_open[of N E P]], simp)
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
apply (rule upred_entails_trans[OF upred_weakeningL])
by (auto simp: upred_wand_holdsE[OF inv_raw_to_inv] intro!: fupd_mono[OF inv_inG] upred_sep_mono)

lemma inv_acc: "names N \<subseteq> E \<Longrightarrow>
  ((inv N P) ={E, E-(names N)}=\<^emph> ((\<triangleright>P) \<^emph> ((\<triangleright>P) ={E-(names N), E}=\<^emph> \<upharpoonleft>True)))"
  by (auto simp: inv_def intro!: upred_wand_holdsI upred_entails_trans[OF upred_persisE]
    upred_entails_trans[OF upred_forall_inst[of _ E]] upred_entails_trans[OF upred_entail_eqL[OF upred_emp_impl]])

lemma inv_combine: "\<lbrakk>names N1 \<inter> names N2 = {}; names N1 \<union> names N2 \<subseteq> names N\<rbrakk> \<Longrightarrow>
    inv N1 P -\<^emph> inv N2 Q -\<^emph> inv N (P\<^emph>Q)"
unfolding inv_def
apply (auto intro!: upred_wand_holds2I upred_persis_frame upred_forallI upred_implI_pure, pers_solver)
subgoal for E
apply (auto intro!: upred_entails_substE[OF upred_forall_inst[of _ "E - names N1"]])
apply (auto intro!: upred_entails_substE[OF upred_implE_pure, OF  _ upred_entails_refl])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
apply (auto intro!: upred_entails_substE[OF upred_persisE] upred_entails_substE[OF upred_forall_inst[of _ E]])
apply (auto intro!: upred_entails_substE[OF upred_implE_pure, OF _ upred_entails_refl])
apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of _ "E-names N1"]])
apply (rule fupd_frame_mono[OF inv_inG])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of _ "E-names N1-names N2"]])
apply (auto simp: upred_sep_assoc_eq intro!: fupd_frame_mono[OF inv_inG] upred_entails_trans[OF _
  upred_wand_holdsE[OF fupd_frame_split[OF inv_inG, of _ "(\<triangleright>(P \<^emph> Q))={E - names N,E}=\<^emph>upred_emp" "\<triangleright>(P\<^emph>Q)",
  OF can_be_split_rev, OF can_be_split_refl]]] upred_entails_substI[OF upred_entail_eqR[OF upred_later_sep]])
apply (rule upred_entails_trans[OF upred_sep_comm2R], rule upred_frame)
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
apply (rule upred_entails_trans[OF upred_sep_comm2R], rule upred_frame)
apply (auto intro!: upred_entails_trans[OF _ upred_wand_holdsE[OF fupd_mask_intro[OF inv_inG]]])
apply (auto simp: upred_sep_assoc_eq intro!: upred_wandI upred_entails_substE[OF upred_entail_eqL[OF
    upred_later_sep]])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of _ "E-names N1-names N2"]])
apply (auto simp: upred_true_sep intro!: fupd_frame_mono[OF inv_inG])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF upred_wand_apply, unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of _ "E-names N1"]])
apply (auto simp: upred_true_sep intro!: fupd_frame_mono[OF inv_inG])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm]])
by (auto intro: upred_entails_trans[OF upred_wand_apply])
done

lemma inv_combine_dup_l: "(\<box>(P -\<^emph> (P\<^emph>P))) -\<^emph> inv N P -\<^emph> inv N Q -\<^emph> inv N (P \<^emph>Q)"
apply (auto simp: inv_def intro!: upred_wand_holds2I upred_wandI upred_persis_frame upred_forallI
  upred_implI_pure, pers_solver)
apply (rule upred_entails_trans[OF upred_sep_comm2R])
subgoal for E
apply (auto intro!: upred_entails_substE[OF upred_persisE] upred_entails_substE[OF upred_forall_inst[of _ E]]
  upred_entails_substE[OF upred_entail_eqL[OF upred_emp_impl]])
apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of _ "E-names N"]])
apply (auto simp: upred_sep_assoc_eq intro!: fupd_frame_mono[OF inv_inG])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_trans[OF upred_sep_comm3L])
apply (rule upred_entails_trans[OF upred_sep_comm3M])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (auto simp: upred_sep_assoc_eq intro!: upred_entails_substE[OF upred_persisE] upred_entails_substE[OF
  upred_later_mono_extL[OF upred_wand_apply], unfolded upred_sep_assoc_eq]
  upred_entails_substE[OF upred_entail_eqL[OF upred_later_sep]])
apply (auto simp: upred_sep_assoc_eq intro!: upred_entails_trans[OF _ upred_wand_holdsE[OF
  fupd_frame_split[OF inv_inG, of _ "(\<triangleright>Q)\<^emph>((\<triangleright>(P \<^emph> Q))={E - names N,E}=\<^emph>upred_emp)" "\<triangleright>P"], OF can_be_split_sepL,
  OF can_be_split_rev, OF can_be_splitI[OF upred_later_sep]]])
apply (rule upred_frame)
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF upred_wand_apply, unfolded upred_sep_assoc_eq])
apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of _ E]])
apply (auto simp: upred_true_sep intro!: fupd_frame_mono[OF inv_inG])
apply (auto simp: upred_sep_assoc_eq intro!: upred_entails_trans[OF upred_forall_inst[of _ E]]
  upred_entails_trans[OF upred_entail_eqL[OF upred_emp_impl]] fupd_mono[OF inv_inG] upred_sep_mono upred_wandI
  upred_entails_substE[OF upred_entail_eqL[OF upred_later_sep]])
apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
apply (rule upred_entails_trans[OF upred_sep_comm2R])
apply (rule upred_entails_substE[OF upred_wand_apply, unfolded upred_sep_assoc_eq])
by (rule upred_weakeningR)
done
end

subsubsection \<open>Cancelable Invariants\<close>
type_synonym cinvG = frac

context
fixes get_cinv :: "gname \<Rightarrow> 'res::ucamera \<Rightarrow> cinvG option option"
  and put_cinv
  and get_inv :: "gname \<Rightarrow> 'res::ucamera \<Rightarrow> inv option"
  and put_inv
assumes cinv_inG: "inG get_cinv put_cinv"
  and inv_inG: "inG get_inv put_inv"
begin

abbreviation fancy_upd'' ("\<Turnstile>{_,_}=>_") where "fancy_upd'' \<equiv> fancy_upd put_inv"
abbreviation wand_fupd'' ("_={_,_}=\<^emph>_") where "wand_fupd'' \<equiv> wand_fupd put_inv"
abbreviation linear_fupd'' ("\<Turnstile>{_}=>_") where "linear_fupd'' \<equiv> linear_fupd put_inv"
abbreviation wand_linear_fupd'' ("_={_}=\<^emph>_") where "wand_linear_fupd'' \<equiv> wand_linear_fupd put_inv"

definition cinv_own :: "gname \<Rightarrow> frac \<Rightarrow> 'res upred_f" where "cinv_own \<gamma> p = own put_cinv \<gamma> (Some p)"
definition cinv :: "namespace \<Rightarrow> gname \<Rightarrow> 'res upred_f \<Rightarrow> 'res upred_f" where
  "cinv N \<gamma> P = inv put_inv N (P \<or>\<^sub>u cinv_own \<gamma> 1)"

lemma cinv_persistent [pers_rule,log_prog_rule]: "persistent (cinv N \<gamma> P)"
  unfolding cinv_def by (rule persistent_inv[OF inv_inG])

lemma timeless_cinv_own: "timeless (cinv_own \<gamma> p)"
  unfolding cinv_own_def inG.own_def[OF cinv_inG]
  apply (rule own_timeless')
  unfolding dcamera_val_def discrete_val_def
  apply (auto simp: inG.put_ne[OF cinv_inG] ofe_refl ofe_limit valid_def inG.put_n_valid[OF cinv_inG]
    valid_raw_frac_def valid_raw_option_def)
  by (metis (mono_tags, lifting) cinv_inG d_equiv inG.put_ne inG.put_ne2)+

lemma cinv_upred_own_valid: "cinv_own \<gamma> q1 -\<^emph> cinv_own \<gamma> q2 -\<^emph> \<upharpoonleft>(q1\<cdot>q2\<le>1)"
unfolding cinv_own_def
apply (rule upred_entails_wand_holdsR2[OF _ inG.own_valid2[OF cinv_inG]])
apply (simp add: op_prod_def \<epsilon>_left_id op_option_def)
apply (simp add: upred_entails.rep_eq upred_valid.rep_eq upred_pure.rep_eq prod_n_valid_def \<epsilon>_n_valid)
apply (simp add: valid_raw_option_def valid_frac[symmetric] split: option.splits)
by (metis dcamera_valid_iff less_eq_frac.rep_eq one_frac.rep_eq valid_raw_frac.rep_eq)

lemma cinv_own_1_l: "cinv_own \<gamma> 1 -\<^emph> cinv_own \<gamma> q -\<^emph> \<upharpoonleft>False"
proof (rule upred_wand_holds2I)
  from one_op have "(1\<cdot>q \<le> 1) \<longleftrightarrow> False" by (simp add: less_le_not_le)
  with upred_wand_holds2E[OF cinv_upred_own_valid, of \<gamma> 1 q] show "cinv_own \<gamma> 1 \<^emph> cinv_own \<gamma> q \<turnstile> \<upharpoonleft>False"
    by simp
qed

lemma cinv_acc_strong: "names N \<subseteq> E \<Longrightarrow>
  (cinv N \<gamma> P) -\<^emph> (cinv_own \<gamma> p ={E,E-names N}=\<^emph>
  ((\<triangleright>P) \<^emph> cinv_own \<gamma> p \<^emph> (\<forall>\<^sub>u E'. (((\<triangleright>P) \<or>\<^sub>u cinv_own \<gamma> 1) ={E',names N \<union> E'}=\<^emph> upred_emp))))"
  apply (rule upred_wand_holds2I)
  apply (rule add_holds[OF inv_acc[OF inv_inG, of N "names N", simplified]])
  apply (subst cinv_def)
  apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
  apply (rule upred_entails_substE[OF upred_wand_apply, unfolded upred_sep_assoc_eq])
  apply (rule add_holds[OF fupd_mask_frameR[OF inv_inG, of "names N" "E-names N"]])
  apply simp
  apply (rule upred_entails_substE[OF upred_wand_apply, unfolded upred_sep_assoc_eq])
  apply (simp add: Un_absorb1)
  apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of E "E -names N" "E-names N"]])
  apply (auto simp: upred_sep_assoc_eq intro!: fupd_frame_mono[OF inv_inG])
  apply (rule upred_entails_trans[OF upred_sep_comm2R])
  apply (rule upred_entails_substE[OF upred_entail_eqL[OF upred_later_disj]])
  apply (rule upred_disjE')
  apply (rule upred_entails_trans[OF _ upred_wand_holdsE[OF fupd_frame_split[OF inv_inG]]]) prefer 2
  apply (rule can_be_split_rev) apply (rule can_be_split_sepR) apply (rule can_be_split_refl)
  apply (rule upred_frame)
  apply (rule upred_entails_trans[OF _ upred_wand_holdsE[OF fupd_frame_split[OF inv_inG]]]) prefer 2
  apply (rule can_be_split_rev) apply (rule can_be_split_refl)
  apply (subst upred_sep_comm, rule upred_frame)
  apply (rule upred_entails_trans[OF _ upred_wand_holdsE[OF fupd_intro[OF inv_inG]]])
  apply (auto intro!: upred_sep_mono upred_forallI)[1]
  subgoal for E'
    apply (rule upred_entails_trans[OF upred_wand_mono[OF upred_entail_eqR[OF upred_later_disj] upred_entails_refl]])
    apply (rule upred_wandI)
    apply (subst upred_sep_comm)
    apply (rule upred_entails_trans[OF upred_wand_apply'])
    apply (rule upred_disjE) apply (auto intro: upred_disjIL)
    apply (rule upred_entails_trans[OF upred_laterI]) apply (auto intro: upred_disjIR)
    apply (rule add_holds[OF fupd_mask_frameR[OF inv_inG, of "{}" E' "names N" upred_emp, simplified]])
    by (auto intro: upred_entails_trans[OF upred_wand_apply])
  apply (rule elim_modal_entails'[OF elim_modal_timeless[OF timeless_cinv_own[unfolded timeless_def] is_except_zero_fupd]])
  apply (rule inv_inG)
  apply (rule upred_entails_trans[OF upred_entails_eq[OF upred_sep_comm2L]])
  apply (rule upred_entails_trans[OF upred_sep_comm2R])
  by (auto intro: upred_entails_substE[OF upred_wand_holds2E[OF cinv_own_1_l], unfolded upred_sep_assoc_eq])

lemma cinv_acc: "names N \<subseteq> E \<Longrightarrow>
  ((cinv N \<gamma> P) -\<^emph> (cinv_own \<gamma> p ={E,E-names N}=\<^emph> ((\<triangleright>P) \<^emph> cinv_own \<gamma> p \<^emph> ((\<triangleright>P) ={E-names N,E}=\<^emph>upred_emp))))"
  apply (rule upred_wand_holdsI)
  apply (rule upred_entails_trans[OF upred_entail_eqR[OF persistent_dupl]], pers_solver)
  apply (rule upred_wandI)
  apply (auto intro!: upred_entails_substE[OF upred_wand_holds2E[OF cinv_acc_strong], simplified upred_sep_assoc_eq, of N E])
  apply (rule upred_entails_trans[OF _ fupd_mask_trans[OF inv_inG, of E "E -names N" "E-names N"]])
  apply (auto simp: upred_sep_assoc_eq intro!: fupd_frame_mono[OF inv_inG])
  apply (rule upred_entails_trans[OF _ upred_wand_holdsE[OF fupd_frame_split[OF inv_inG]]])
  prefer 2 apply (rule can_be_split_rev, rule can_be_split_refl, unfold upred_sep_assoc_eq)
  apply (rule upred_entails_trans[OF upred_sep_comm2R]) apply (rule upred_frame)
  apply (rule upred_entails_trans[OF upred_sep_comm2R]) apply (rule upred_frame)
  apply (rule upred_entails_substE[OF upred_forall_inst[of _ "E-names N"]])
  apply (rule upred_entails_trans[OF _ upred_wand_holdsE[OF fupd_intro[OF inv_inG]]])
  apply (rule upred_wandI)
  apply (rule upred_entails_trans[OF upred_sep_comm2R])
  apply (auto simp: Un_absorb1 intro!: upred_entails_substE[OF upred_wand_apply', unfolded upred_sep_assoc_eq] upred_disjIL)
  by (rule upred_weakeningR)
end
end


theory Failures_TickTock_Renaming
  imports Failures_TickTock
begin

lemma inv_map_evt_tick: "inv (map_evt f) tick = tick"
  unfolding inv_def by (rule some_equality, auto, case_tac x, auto)

lemma ttevt2F_map_evt:
  "ttevt2F (map_evt f x) = lift_renaming_func f (ttevt2F x)"
  by (metis evt.exhaust evt.simps(8) evt.simps(9) lift_renaming_func.simps(1) lift_renaming_func.simps(3) ttevt2F.simps(1) ttevt2F.simps(2))

lemma ttproc2F_ExtChoiceTT_eq_ExtChoiceF:
  assumes P_wf: "TTwf P" and Q_wf: "TTwf Q" and TT1_P: "TT1 P" and TT1_Q: "TT1 Q"
  shows "ttproc2F (RenamingTT P f) = RenamingF (ttproc2F P) f"
  unfolding RenamingTT_def RenamingF_def ttproc2F_def
proof auto
  fix a b y x
  assume case_assms: "Some (a, b) = tt2F y" "x \<in> P" "y \<in> rename_trace f x"

  thm map_evt_def

  have "\<And>a b y. Some (a, b) = tt2F y \<Longrightarrow> y \<in> rename_trace f x \<Longrightarrow>
    \<exists>s. map (map_evt f) s = a \<and> (\<exists>y. Some (s, map_evt f -` b) = tt2F y \<and> y \<lesssim>\<^sub>C x)"
  proof (induct x rule:ttWF.induct, auto)
    fix Y
    show "\<exists>y. Some ([], {y. ttevt2F (map_evt f y) \<in> Y}) = tt2F y \<and> y \<lesssim>\<^sub>C [[lift_renaming_func f -` Y]\<^sub>R]"
      by (rule_tac x="[[lift_renaming_func f -` Y]\<^sub>R]" in exI, auto, (case_tac x, auto)+)
  next
    fix e \<sigma> a b s'
    assume ind_hyp: "\<And>a b y. Some (a, b) = tt2F y \<Longrightarrow> y \<in> rename_trace f \<sigma> \<Longrightarrow>
      \<exists>s. map (map_evt f) s = a \<and> (\<exists>y. Some (s, map_evt f -` b) = tt2F y \<and> y \<lesssim>\<^sub>C \<sigma>)"
    assume "Some (a, b) = (case tt2F s' of None \<Rightarrow> None | Some fl \<Rightarrow> Some (evt (f e) # fst fl, snd fl))" "s' \<in> rename_trace f \<sigma>"
    then have case_assms2: "Some (a, b) = tt2F ([Event (f e)]\<^sub>E # s')" "s' \<in> rename_trace f \<sigma>"
      by (cases "tt2F s'", auto)

    obtain a' where a'_assms: "a = evt (f e) # a' \<and> Some (a', b) = tt2F s'"
      using case_assms2(1) by (cases a, auto, (cases "tt2F s'", auto)+)

    obtain s y where s_y_assms: "map (map_evt f) s = a' \<and> Some (s, map_evt f -` b) = tt2F y \<and> y \<lesssim>\<^sub>C \<sigma>"
      using a'_assms case_assms2(2) ind_hyp by blast
    then show "\<exists>s. map (map_evt f) s = a \<and> (\<exists>y. Some (s, map_evt f -` b) = tt2F y \<and> y \<lesssim>\<^sub>C [Event e]\<^sub>E # \<sigma>)"
      using a'_assms by (rule_tac x="evt e # s" in exI, auto, rule_tac x="[Event e]\<^sub>E # y" in exI, auto, cases "tt2F y", auto)
  qed
  then have "\<exists>s. map (map_evt f) s = a \<and> (\<exists>y. Some (s, map_evt f -` b) = tt2F y \<and> y \<lesssim>\<^sub>C x)"
    using case_assms(1) case_assms(3) by blast
  then show "\<exists>s. map (map_evt f) s = a \<and> (\<exists>y. Some (s, map_evt f -` b) = tt2F y \<and> y \<in> P)"
    using TT1_P case_assms(2) unfolding TT1_def by blast
next
  fix b s y
  assume case_assms: "Some (s, map_evt f -` b) = tt2F y" "y \<in> P"

  have "\<And>b s. Some (s, map_evt f -` b) = tt2F y \<Longrightarrow>  \<exists>y'. Some (map (map_evt f) s, b) = tt2F y' \<and> (\<exists>x. y' \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C y)"
  proof (induct y rule:ttWF.induct, auto)
    fix X b
    assume case_assm2: "map_evt f -` b = {x. ttevt2F x \<in> X}"
    then obtain Y where Y_assm: "b = {x. ttevt2F x \<in> Y}"
      unfolding vimage_def by (smt Some_tt2F_concat_refusal Some_tt2F_set)
    then show "\<exists>y'. Some ([], b) = tt2F y' \<and> (\<exists>x. y' \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [[X]\<^sub>R])"
      apply (rule_tac x="[[{e\<in>Y. e \<noteq> Tock}]\<^sub>R]" in exI, auto)
      apply (metis evt.exhaust ttevent.simps(3) ttevent.simps(7) ttevt2F.simps(1) ttevt2F.simps(2))
      apply (rule_tac x="[[{e\<in>X. e \<noteq> Tock}]\<^sub>R]" in exI, auto)
      apply (case_tac x, auto)
      apply (metis Y_assm case_assm2 evt.simps(9) mem_Collect_eq ttevt2F.simps(1) vimage_eq)
      apply (metis case_assm2 evt.simps(8) mem_Collect_eq ttevt2F.simps(2) vimage_def)
      using lift_renaming_func.elims apply blast
      apply (case_tac x, auto)
      apply (metis (mono_tags, lifting) Collect_mem_eq Collect_mono_iff Y_assm case_assm2 evt.simps(9) mem_Collect_eq ttevt2F.simps(1) vimage_def)
      by (metis case_assm2 evt.simps(8) mem_Collect_eq ttevt2F.simps(2) vimage_def)
  next
    fix e \<sigma> b s
    assume ind_hyp: "\<And>b s. Some (s, map_evt f -` b) = tt2F \<sigma> \<Longrightarrow>
               \<exists>y'. Some (map (map_evt f) s, b) = tt2F y' \<and> (\<exists>x. y' \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C \<sigma>)"
    assume "Some (s, map_evt f -` b) = (case tt2F \<sigma> of None \<Rightarrow> None | Some fl \<Rightarrow> Some (evt e # fst fl, snd fl))"
    then obtain s' where s'_assms: "tt2F \<sigma> = Some (s', map_evt f -` b) \<and> s = evt e # s'"
      by (cases "tt2F \<sigma>", auto)

    obtain y' x where "Some (map (map_evt f) s', b) = tt2F y' \<and> y' \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C \<sigma>"
      using ind_hyp s'_assms by presburger
    then show "\<exists>y'. Some (map (map_evt f) s, b) = tt2F y' \<and> (\<exists>x. y' \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [Event e]\<^sub>E # \<sigma>)"
      apply (rule_tac x="[Event (f e)]\<^sub>E # y'" in exI, auto)
      apply (metis (mono_tags, lifting) evt.simps(9) fst_conv list.simps(9) option.simps(5) s'_assms snd_conv)
      by (rule_tac x="[Event e]\<^sub>E # x" in exI, auto)
  qed
  then have "\<exists>y'. Some (map (map_evt f) s, b) = tt2F y' \<and> (\<exists>x. y' \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C y)"
    using case_assms(1) by blast
  then show "\<exists>y. Some (map (map_evt f) s, b) = tt2F y \<and> (\<exists>x\<in>P. y \<in> rename_trace f x)"
    using TT1_P TT1_def case_assms(2) by blast
next
  fix y xa
  assume case_assms: "xa \<in> P" "y \<in> rename_trace f xa"

  have "\<And>y. ttWF xa \<Longrightarrow> y \<in> rename_trace f xa \<Longrightarrow> \<exists>s. map (map_evt f) s = tt2T y \<and> (\<exists>y'. s = tt2T y' \<and> y' \<lesssim>\<^sub>C xa)"
  proof (induct xa rule:ttWF.induct, auto)
    show "\<exists>y'. [] = tt2T y' \<and> y' \<lesssim>\<^sub>C []"
      by (rule_tac x="[]" in exI, auto)
  next
    fix Y
    show "\<exists>y'. [] = tt2T y' \<and> y' \<lesssim>\<^sub>C [[lift_renaming_func f -` Y]\<^sub>R]"
      by (rule_tac x="[]" in exI, auto)
  next
    show "\<exists>s. map (map_evt f) s = [tick] \<and> (\<exists>y'. s = tt2T y' \<and> y' \<lesssim>\<^sub>C [[Tick]\<^sub>E])"
      by (rule_tac x="[tick]" in exI, auto, rule_tac x="[[Tick]\<^sub>E]" in exI, auto)
  next
    fix e \<sigma> s'
    assume ind_hyp: "\<And>y. y \<in> rename_trace f \<sigma> \<Longrightarrow> \<exists>s. map (map_evt f) s = tt2T y \<and> (\<exists>y'. s = tt2T y' \<and> y' \<lesssim>\<^sub>C \<sigma>)"
    assume case_assms2: "ttWF \<sigma>" "s' \<in> rename_trace f \<sigma>"
    then obtain s y' where "map (map_evt f) s = tt2T s' \<and> s = tt2T y' \<and> y' \<lesssim>\<^sub>C \<sigma>"
      using ind_hyp by blast
    then show "\<exists>s. map (map_evt f) s = evt (f e) # tt2T s' \<and> (\<exists>y'. s = tt2T y' \<and> y' \<lesssim>\<^sub>C [Event e]\<^sub>E # \<sigma>)"
      by (rule_tac x="evt e # s" in exI, auto, rule_tac x="[Event e]\<^sub>E # y'" in exI, auto)
  next
    fix \<sigma> Y s'a
    show "\<exists>y'. [] = tt2T y' \<and> y' \<lesssim>\<^sub>C [lift_renaming_func f -` Y]\<^sub>R # [Tock]\<^sub>E # \<sigma>"
      by (rule_tac x="[]" in exI, auto)
  qed
  then have "\<exists>s. map (map_evt f) s = tt2T y \<and> (\<exists>y'. s = tt2T y' \<and> y' \<lesssim>\<^sub>C xa)"
    using P_wf TTwf_def case_assms(1) case_assms(2) by blast
  then show "\<exists>s. map (map_evt f) s = tt2T y \<and> (\<exists>y. s = tt2T y \<and> y \<in> P)"
    using TT1_P TT1_def case_assms(1) by blast
next
  fix y
  assume case_assms: "y \<in> P"

  have "ttWF y \<Longrightarrow> \<exists>ya. map (map_evt f) (tt2T y) = tt2T ya \<and> (\<exists>x. ya \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C y)"
  proof (induct y rule:ttWF.induct, auto)
    show "\<exists>ya. [] = tt2T ya \<and> (\<exists>x. ya \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [])"
      by (rule_tac x="[]" in exI, auto, rule_tac x="[]" in exI, auto)
  next
    fix X
    show "\<exists>ya. [] = tt2T ya \<and> (\<exists>x. ya \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [[X]\<^sub>R])"
      by (rule_tac x="[]" in exI, auto, rule_tac x="[]" in exI, auto)
  next
    show "\<exists>ya. [tick] = tt2T ya \<and> (\<exists>x. ya \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [[Tick]\<^sub>E])"
      by (rule_tac x="[[Tick]\<^sub>E]" in exI, auto, rule_tac x="[[Tick]\<^sub>E]" in exI, auto)
  next
    fix e \<sigma> ya x
    assume "ttWF \<sigma>" "map (map_evt f) (tt2T \<sigma>) = tt2T ya" "ya \<in> rename_trace f x" "x \<lesssim>\<^sub>C \<sigma>"
    then show "\<exists>yaa. evt (f e) # tt2T ya = tt2T yaa \<and> (\<exists>x. yaa \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [Event e]\<^sub>E # \<sigma>)"
      by (rule_tac x="[Event (f e)]\<^sub>E # ya" in exI, auto, rule_tac x="[Event e]\<^sub>E # x" in exI, auto)
  next
    fix X and ya :: "'c tttrace" and x \<sigma> :: "'a tttrace"
    assume "ttWF \<sigma>" "map (map_evt f) (tt2T \<sigma>) = tt2T ya" "ya \<in> rename_trace f x" "x \<lesssim>\<^sub>C \<sigma>"
    then show "\<exists>ya. [] = tt2T ya \<and> (\<exists>x. ya \<in> rename_trace f x \<and> x \<lesssim>\<^sub>C [X]\<^sub>R # [Tock]\<^sub>E # \<sigma>)"
      by (rule_tac x="[]" in exI, auto, rule_tac x="[]" in exI, auto)
  qed
  then show "\<exists>ya. map (map_evt f) (tt2T y) = tt2T ya \<and> (\<exists>x\<in>P. ya \<in> rename_trace f x)"
    using P_wf TT1_P TT1_def TTwf_def case_assms by blast
qed

end


(*  Title:      HOL/Auth/n_germanSimp_lemma_inv__10_on_rules.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_germanSimp Protocol Case Study*}

theory n_germanSimp_lemma_inv__10_on_rules imports n_germanSimp_lemma_on_inv__10
begin
section{*All lemmas on causal relation between inv__10*}
lemma lemma_inv__10_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__10  p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__0 N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__1 N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqSVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__0 N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqE__part__0Vsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvReqE__part__1 N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvReqE__part__1Vsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__0Vsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInv__part__1Vsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendInvAckVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvInvAckVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntSVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_SendGntE N i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_SendGntEVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntSVsinv__10) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_RecvGntEVsinv__10) done
    }

  ultimately show "invHoldForRule s f r (invariants N)"
  by satx
qed

end


(*  Title:      HOL/Auth/n_german_lemma_on_inv__32.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__32 imports n_german_base
begin
section{*All lemmas on causal relation between inv__32 and some rule r*}
lemma n_RecvReqVsinv__32:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_RecvReq N i)" and
a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
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_RecvReq N i" apply fastforce done
from a2 obtain p__Inv3 p__Inv4 where a2:"p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(i=p__Inv3)\<or>(i~=p__Inv3\<and>i~=p__Inv4)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv4)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Para (Ident ''Cache'') p__Inv4) ''State'')) (Const E)) (eqn (IVar (Para (Ident ''ShrSet'') p__Inv3)) (Const true))))" in exI, auto) done
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i=p__Inv3)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Para (Ident ''Cache'') p__Inv4) ''State'')) (Const E)) (eqn (IVar (Para (Ident ''ShrSet'') p__Inv3)) (Const true))))" in exI, auto) done
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i~=p__Inv3\<and>i~=p__Inv4)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Field (Para (Ident ''Cache'') p__Inv4) ''State'')) (Const E)) (eqn (IVar (Para (Ident ''ShrSet'') p__Inv3)) (Const true))))" in exI, auto) done
  then have "invHoldForRule s f r (invariants N)" by auto
}
ultimately show "invHoldForRule s f r (invariants N)" by satx
qed

lemma n_SendInvEVsinv__32:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendInvE  i)" and
a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
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_SendInvE  i" apply fastforce done
from a2 obtain p__Inv3 p__Inv4 where a2:"p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(i=p__Inv3)\<or>(i~=p__Inv3\<and>i~=p__Inv4)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv4)"
  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__Inv3)"
  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__Inv3\<and>i~=p__Inv4)"
  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_SendInvSVsinv__32:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendInvS  i)" and
a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
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_SendInvS  i" apply fastforce done
from a2 obtain p__Inv3 p__Inv4 where a2:"p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(i=p__Inv3)\<or>(i~=p__Inv3\<and>i~=p__Inv4)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv4)"
  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__Inv3)"
  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__Inv3\<and>i~=p__Inv4)"
  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__32:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)" and
a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
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__Inv3 p__Inv4 where a2:"p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(i=p__Inv3)\<or>(i~=p__Inv3\<and>i~=p__Inv4)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv4)"
  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__Inv3)"
  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__Inv3\<and>i~=p__Inv4)"
  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__32:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)" and
a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
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__Inv3 p__Inv4 where a2:"p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(i=p__Inv3)\<or>(i~=p__Inv3\<and>i~=p__Inv4)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv4)"
  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__Inv3)"
  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__Inv3\<and>i~=p__Inv4)"
  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__32:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)" and
a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
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__Inv3 p__Inv4 where a2:"p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(i=p__Inv3)\<or>(i~=p__Inv3\<and>i~=p__Inv4)" apply (cut_tac a1 a2, auto) done
moreover {
  assume b1: "(i=p__Inv4)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Para (Ident ''InvSet'') p__Inv3)) (Const true)) (eqn (IVar (Field (Para (Ident ''Chan2'') p__Inv4) ''Cmd'')) (Const GntE))))" in exI, auto) done
  then have "invHoldForRule s f r (invariants N)" by auto
}
moreover {
  assume b1: "(i=p__Inv3)"
  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__Inv3\<and>i~=p__Inv4)"
  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_StoreVsinv__32:
  assumes a1: "\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendReqESVsinv__32:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendReqES  i" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_RecvInvAckVsinv__32:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendGntSVsinv__32:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendGntS  i" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendReqSVsinv__32:
  assumes a1: "\<exists> j. j\<le>N\<and>r=n_SendReqS  j" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendGntEVsinv__32:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendGntE N i" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

lemma n_SendReqEIVsinv__32:
  assumes a1: "\<exists> i. i\<le>N\<and>r=n_SendReqEI  i" and
  a2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__32  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  apply (rule noEffectOnRule, cut_tac a1 a2, auto) done

end


theory rg_cond
  imports invariant
begin

section \<open>Rely-guarantee condition of events\<close>

subsection \<open>defs of rely-guarantee conditions\<close>

text \<open>local variables do not change\<close>
definition lvars_nochange :: "Thread \<Rightarrow> State \<Rightarrow> State \<Rightarrow> bool"
  where "lvars_nochange t r s \<equiv>
  (ret r t = ret s t) \<and> (ret_mem r t = ret_mem s t) (*\<and> (tmout r t = tmout s t) *)
\<and> (endt r t = endt s t) \<and> (posting_msg r t = posting_msg s t) (*\<and> (get_msg r t = get_msg s t)*)
\<and> (th r t = th s t) \<and> (need_resched r t = need_resched s t) (*\<and> (statPend r t = statPend s t) *)"

definition lvars_nochange_rel :: "Thread \<Rightarrow> (State \<times> State) set"
  where "lvars_nochange_rel t \<equiv> {(s,r). lvars_nochange t s r}"

definition lvars_nochange_4all :: "(State \<times> State) set"
  where "lvars_nochange_4all \<equiv> {(s,r). \<forall>t. lvars_nochange t s r}"

definition timestat_nochange :: "Thread \<Rightarrow> State \<Rightarrow> State \<Rightarrow> bool"
  where "timestat_nochange t r s \<equiv> (tmout r t = tmout s t) \<and> (statPend r t = statPend s t)"

definition timestat_nochange_rel :: "Thread \<Rightarrow> (State \<times> State) set"
  where "timestat_nochange_rel t \<equiv> {(s,r). timestat_nochange t s r}"

definition timestat_nochange_4all :: "(State \<times> State) set"
  where "timestat_nochange_4all \<equiv> {(s,r). \<forall>t. timestat_nochange t s r}"

text \<open>global variables do not change\<close>
definition gvars_nochange :: "State \<Rightarrow> State \<Rightarrow> bool"
  where "gvars_nochange s r \<equiv> cur r = cur s \<and> tick r = tick s \<and> thd_state r = thd_state s
                            \<and> OS_MEMs r = OS_MEMs s \<and> OS_MEM_info r = OS_MEM_info s
                            \<and> OSMailBoxs r = OSMailBoxs s \<and> OSMailbox_info r = OSMailbox_info s"

definition gvars_nochange_rel :: "(State \<times> State) set"
  where "gvars_nochange_rel \<equiv> {(s,r). gvars_nochange s r}"

text \<open>static configurations of the OS_MEM do not change\<close>

definition gvars_conf :: "State \<Rightarrow> State \<Rightarrow> bool"
where "gvars_conf s r \<equiv>
           OS_MEMs r = OS_MEMs s \<and> OSMailBoxs r = OSMailBoxs s
         \<and> (\<forall>p. OSMemAddr (OS_MEM_info s p) = OSMemAddr (OS_MEM_info r p)
            \<and> OSMemBlkSize (OS_MEM_info s p) = OSMemBlkSize (OS_MEM_info r p)
            \<and> OSMemNBlks (OS_MEM_info s p) = OSMemNBlks (OS_MEM_info r p))
         \<and> (\<forall>p. buf (OSMailbox_info s p) = buf (OSMailbox_info r p))"

definition gvars_conf_stable :: "(State \<times> State) set"
  where "gvars_conf_stable \<equiv> {(s,r). gvars_conf s r}"

definition Schedule_rely :: "(State \<times> State) set"
  where "Schedule_rely \<equiv> {(s,r). inv s \<longrightarrow> inv r} \<union> Id"

definition Schedule_guar :: "(State \<times> State) set"
  where "Schedule_guar \<equiv> ({(s,r). inv s \<longrightarrow> inv r}
         \<inter> \<lbrace>\<ordmasculine>OS_MEMs = \<ordfeminine>OS_MEMs \<and> \<ordmasculine>OS_MEM_info = \<ordfeminine>OS_MEM_info \<and>
            \<ordmasculine>tick = \<ordfeminine>tick \<and> \<ordmasculine>OSMailBoxs = \<ordfeminine>OSMailBoxs \<and>
            \<ordmasculine>OSMailbox_info = \<ordfeminine>OSMailbox_info\<rbrace>
         \<inter> (\<Inter>t. lvars_nochange_rel t)) \<union> Id"

definition Schedule_RGCond :: "Thread \<Rightarrow> (State) PiCore_Hoare.rgformula"
  where "Schedule_RGCond t \<equiv>
          RG[{s. inv s},
          Schedule_rely,  Schedule_guar,
  {s. inv s}]"

definition Tick_rely :: "(State \<times> State) set"
where "Tick_rely \<equiv> \<lbrace>\<ordmasculine>tick = \<ordfeminine>tick\<rbrace> \<union> Id"

definition Tick_guar :: "(State \<times> State) set"
where "Tick_guar \<equiv> (\<lbrace>\<ordfeminine>tick = \<ordmasculine>tick + 1 \<and> \<ordmasculine>cur = \<ordfeminine>cur \<and> \<ordmasculine>thd_state = \<ordfeminine>thd_state
                      \<and> \<ordmasculine>OSMailBoxs = \<ordfeminine>OSMailBoxs \<and> \<ordmasculine>OSMailbox_info = \<ordfeminine>OSMailbox_info
                      \<and> \<ordmasculine>OS_MEMs = \<ordfeminine>OS_MEMs \<and> \<ordmasculine>OS_MEM_info = \<ordfeminine>OS_MEM_info\<rbrace>
                      \<inter> (\<Inter>t. lvars_nochange_rel t)) \<union> Id"

definition Tick_RGCond :: "(State) PiCore_Hoare.rgformula"
  where "Tick_RGCond \<equiv>
          RG[\<lbrace>True\<rbrace>, Tick_rely, Tick_guar, \<lbrace>True\<rbrace>]"

definition OSMemGet_pre ::  "Thread \<Rightarrow> State set"
  where "OSMemGet_pre t \<equiv> {s. inv s}"

definition OSMemGet_rely ::  "Thread \<Rightarrow> (State \<times> State) set"
  where "OSMemGet_rely t \<equiv>
   ((lvars_nochange_rel t \<inter> gvars_conf_stable
    \<inter> {(s,r). inv s \<longrightarrow> inv r}
    \<inter> {(s,r).(cur s = Some t \<longrightarrow> OS_MEM_info s = OS_MEM_info r
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r))}) \<union> Id)
"

definition OSMemGet_guar ::  "Thread \<Rightarrow> (State \<times> State) set"
  where "OSMemGet_guar t \<equiv>
        ((gvars_conf_stable \<inter>
        {(s,r). (cur s \<noteq> Some t \<longrightarrow> gvars_nochange s r \<and> lvars_nochange t s r)
                 \<and> (cur s = Some t \<longrightarrow> inv s \<longrightarrow> inv r)
                 \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r)} \<inter> \<lbrace>\<ordmasculine>tick = \<ordfeminine>tick\<rbrace>) \<union> Id)
"

definition OSMemGet_post ::  "Thread \<Rightarrow> State set"
  where "OSMemGet_post t \<equiv> {s. inv s
                            \<and> (ret s t = OS_ERR_NONE \<longrightarrow> (\<exists>blk. ret_mem s t = Some blk))
                            \<and> (ret s t = OS_ERR_MEM_NO_FREE_BLKS \<longrightarrow> ret_mem s t = None)}"

definition OSMemGet_RGCond :: "Thread \<Rightarrow>(State) PiCore_Hoare.rgformula"
  where "OSMemGet_RGCond t  \<equiv> RG[OSMemGet_pre t,
                                OSMemGet_rely t,
                                OSMemGet_guar t,
                                OSMemGet_post t]"

definition OSMemPut_pre ::  "Thread \<Rightarrow> State set"
  where "OSMemPut_pre t \<equiv> {s. inv s}"

definition OSMemPut_rely ::  "Thread \<Rightarrow>(State \<times> State) set"
  where "OSMemPut_rely t \<equiv>
   ((lvars_nochange_rel t \<inter> gvars_conf_stable
    \<inter> {(s,r). inv s \<longrightarrow> inv r}
    \<inter> {(s,r).(cur s = Some t \<longrightarrow> OS_MEM_info s = OS_MEM_info r
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r))}) \<union> Id)
"
definition OSMemPut_guar ::  "Thread \<Rightarrow>(State \<times> State) set"
  where "OSMemPut_guar t \<equiv>
  ((gvars_conf_stable \<inter>
  {(s,r). (cur s \<noteq> Some t \<longrightarrow> gvars_nochange s r \<and> lvars_nochange t s r)
     \<and> (cur s = Some t \<longrightarrow> inv s \<longrightarrow> inv r)
     \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r)} \<inter> \<lbrace>\<ordmasculine>tick = \<ordfeminine>tick\<rbrace>) \<union> Id)
"

definition OSMemPut_post ::  "Thread \<Rightarrow> State set"
  where "OSMemPut_post t \<equiv> {s. inv s}"

definition OSMemPut_RGCond :: "Thread \<Rightarrow> (State) PiCore_Hoare.rgformula"
  where "OSMemPut_RGCond t  \<equiv> RG[OSMemPut_pre t,
                                OSMemPut_rely t,
                                OSMemPut_guar t,
                                OSMemPut_post t]"

lemma OSMem_eq_guar: "OSMemPut_guar x = OSMemGet_guar x"
  by(simp add:OSMemPut_guar_def OSMemGet_guar_def)

lemma OSMem_eq_rely: "OSMemPut_rely x = OSMemGet_rely x"
  by(simp add:OSMemPut_rely_def OSMemGet_rely_def)

definition
OSMboxPost_pre :: "Thread \<Rightarrow> State set"
  where "OSMboxPost_pre t \<equiv> {s. inv s}"

definition OSMboxPost_guar :: "Thread \<Rightarrow> (State \<times> State) set"
where "OSMboxPost_guar t \<equiv>
        ((gvars_conf_stable \<inter>
          {(s,r). (cur s \<noteq> Some t \<longrightarrow> gvars_nochange s r \<and> lvars_nochange t s r)
                  \<and> (cur s = Some t \<longrightarrow> inv s \<longrightarrow> inv r)
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r) }
          \<inter> \<lbrace>\<ordmasculine>tick = \<ordfeminine>tick\<rbrace>) \<union> Id)"

definition OSMboxPost_rely :: "Thread \<Rightarrow> (State \<times> State) set"
where "OSMboxPost_rely t \<equiv>
   ((lvars_nochange_rel t \<inter> gvars_conf_stable
    \<inter> {(s,r). inv s \<longrightarrow> inv r}
    \<inter> {(s,r).(cur s = Some t \<longrightarrow> OSMailbox_info s = OSMailbox_info r
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r))}) \<union> Id)"

definition OSMboxPost_post :: "Thread \<Rightarrow> State set"
  where "OSMboxPost_post t \<equiv> {s. inv s}"

definition OSMboxPost_RGCond :: "Thread \<Rightarrow>  (State) PiCore_Hoare.rgformula"
  where "OSMboxPost_RGCond t  \<equiv>
          RG[OSMboxPost_pre t,
             OSMboxPost_rely t,
              OSMboxPost_guar t,
              OSMboxPost_post t]"

definition OSMboxAccept_pre :: "Thread \<Rightarrow> State set"
  where "OSMboxAccept_pre t \<equiv> {s. inv s}"

definition OSMboxAccept_rely :: "Thread \<Rightarrow> (State \<times> State) set"
  where "OSMboxAccept_rely t \<equiv>
   ((lvars_nochange_rel t \<inter> gvars_conf_stable
    \<inter> {(s,r). inv s \<longrightarrow> inv r}
    \<inter> {(s,r).(cur s = Some t \<longrightarrow> OSMailbox_info s = OSMailbox_info r
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r))}) \<union> Id)"     \<comment> \<open>The rely condition of Mem_alloc is the same as one of Mem_free \<close>

definition OSMboxAccept_guar :: "Thread \<Rightarrow> (State \<times> State) set"
  where "OSMboxAccept_guar t \<equiv>
        ((gvars_conf_stable \<inter>
          {(s,r). (cur s \<noteq> Some t \<longrightarrow> gvars_nochange s r \<and> lvars_nochange t s r)
                  \<and> (cur s = Some t \<longrightarrow> inv s \<longrightarrow> inv r)
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r) }
          \<inter> \<lbrace>\<ordmasculine>tick = \<ordfeminine>tick\<rbrace>) \<union> Id)"

definition OSMboxAccept_post :: "Thread \<Rightarrow> State set"
  where "OSMboxAccept_post t \<equiv> {s. inv s}"

definition OSMboxAccept_RGCond :: "Thread \<Rightarrow>  (State) PiCore_Hoare.rgformula"
  where "OSMboxAccept_RGCond t  \<equiv>
          RG[OSMboxAccept_pre t,
             OSMboxAccept_rely t,
              OSMboxAccept_guar t,
              OSMboxAccept_post t]"

definition OSMboxPend_pre :: "Thread \<Rightarrow> State set"
where "OSMboxPend_pre t \<equiv> {s. inv s }"

definition OSMboxPend_rely :: "Thread \<Rightarrow> (State \<times> State) set"
where "OSMboxPend_rely t \<equiv>
   ((lvars_nochange_rel t  \<inter>  gvars_conf_stable
    \<inter> {(s,r). inv s \<longrightarrow> inv r}
    \<inter> {(s,r).(cur s = Some t \<longrightarrow> OSMailbox_info s = OSMailbox_info r
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r))}) \<union> Id)"

definition OSMboxPend_guar :: "Thread \<Rightarrow> (State \<times> State) set"
  where "OSMboxPend_guar t \<equiv>
        ((gvars_conf_stable \<inter>
          {(s,r). (cur s \<noteq> Some t \<longrightarrow> gvars_nochange s r \<and> lvars_nochange t s r)
                  \<and> (cur s = Some t \<longrightarrow> inv s \<longrightarrow> inv r)
                  \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r) }
          \<inter> \<lbrace>\<ordmasculine>tick = \<ordfeminine>tick\<rbrace>) \<union> Id)"

lemma OSMbox_eq_rely1 : "OSMboxPost_rely t = OSMboxAccept_rely t"
  by (simp add: OSMboxPost_rely_def OSMboxAccept_rely_def)

lemma OSMbox_eq_rely2 : "OSMboxPost_rely t = OSMboxPend_rely t"
  by (simp add: OSMboxPost_rely_def OSMboxPend_rely_def)

lemma OSMbox_eq_rely3 : "OSMboxPend_rely t = OSMboxAccept_rely t"
  by (simp add: OSMboxAccept_rely_def OSMboxPend_rely_def)

lemmas OSMbox_eq_rely = OSMbox_eq_rely1 OSMbox_eq_rely2 OSMbox_eq_rely3

lemma OSMbox_eq_guar1 : "OSMboxPost_guar t = OSMboxAccept_guar t"
  by (simp add: OSMboxPost_guar_def OSMboxAccept_guar_def)

lemma OSMbox_eq_guar2 : "OSMboxPost_guar t = OSMboxPend_guar t"
  by (simp add: OSMboxPost_guar_def OSMboxPend_guar_def)

lemma OSMbox_eq_guar3 : "OSMboxPend_guar t = OSMboxAccept_guar t"
  by (simp add: OSMboxAccept_guar_def OSMboxPend_guar_def)

lemmas OSMbox_eq_guar = OSMbox_eq_guar1 OSMbox_eq_guar2 OSMbox_eq_guar3

definition OSMboxPend_post :: "Thread \<Rightarrow> State set"
  where "OSMboxPend_post t \<equiv> {s. inv s }"

definition OSMboxPend_RGCond :: "Thread \<Rightarrow>  (State) PiCore_Hoare.rgformula"
  where "OSMboxPend_RGCond t  \<equiv>
          RG[OSMboxPend_pre t,
             OSMboxPend_rely t,
              OSMboxPend_guar t,
              OSMboxPend_post t]"

subsection \<open>stablility, subset relations of rely-guarantee conditions\<close>

lemma stable_inv_free_rely:
  "(s,r) \<in> OSMemPut_rely t \<Longrightarrow> inv s \<Longrightarrow> inv r"
  using OSMemPut_rely_def by blast

lemma stable_inv_free_rely1: "stable \<lbrace> \<acute>inv \<rbrace> (OSMemPut_rely t)"
  using stable_inv_free_rely unfolding stable_def by auto

lemma stable_inv_alloc_rely:
  "(s,r) \<in> OSMemGet_rely t \<Longrightarrow> inv s \<Longrightarrow> inv r"
  using OSMemGet_rely_def by blast

lemma stable_inv_alloc_rely1: "stable \<lbrace> \<acute>inv \<rbrace> (OSMemGet_rely t)"
  by (simp add: stable_def stable_inv_alloc_rely)

lemma stable_inv_sched_rely:
  "(s,r) \<in> Schedule_rely \<Longrightarrow> inv s \<Longrightarrow> inv r"
  using Schedule_rely_def by blast

lemma stable_inv_sched_rely1: "stable \<lbrace>\<acute>inv\<rbrace> Schedule_rely"
  by (simp add: stable_def stable_inv_sched_rely)

lemma OSMemPut_guar_stb_inv: "stable \<lbrace>\<acute>inv \<rbrace> (OSMemPut_guar t)"
proof-
  {
    fix x
    assume a0: "inv x"
    {
      fix y
      assume b0: "(x,y) \<in> OSMemPut_guar t"
      hence "(x,y) \<in> {(s,r). (cur s \<noteq> Some t \<longrightarrow> gvars_nochange s r \<and> lvars_nochange t s r)
             \<and> (cur s = Some t \<longrightarrow> inv s \<longrightarrow> inv r)
             \<and> (\<forall>t'. t' \<noteq> t \<longrightarrow> lvars_nochange t' s r)}"
        using OSMemPut_guar_def gvars_nochange_def lvars_nochange_def by auto
      hence "(cur x \<noteq> Some t \<longrightarrow> gvars_nochange x y \<and> lvars_nochange t x y)
              \<and> (cur x = Some t \<longrightarrow> inv x \<longrightarrow>inv y)
              \<and> (\<forall>t' . t' \<noteq> t \<longrightarrow> lvars_nochange t' x y)" by simp
      hence "inv y"
        apply(case_tac "cur x \<noteq> Some t", simp)
         apply (simp add: gvars_nochange_def lvars_nochange_def) using a0 apply clarify
         apply(simp add:inv_def)
         apply (rule conjI) apply(simp add:inv_cur_def)
         apply (rule conjI, simp add: inv_OS_Mem_info_def inv_OS_Mem_info_mp_def)
        apply (simp add: inv_thd_waitq_def) apply blast
        using a0 by auto
    }
  }
  then show ?thesis by (simp add:stable_def)
qed

lemma OSMemGet_guar_stb_inv: "stable \<lbrace> \<acute>inv \<rbrace> (OSMemGet_guar t)"
  apply(subgoal_tac "OSMemGet_guar t = OSMemPut_guar t")
  using OSMemPut_guar_stb_inv apply simp
  by (simp add: OSMemGet_guar_def OSMemPut_guar_def)

lemma sched_guar_stb_inv:
  "(s,r)\<in>Schedule_guar \<Longrightarrow> inv s \<Longrightarrow> inv r"
  apply(simp add: Schedule_guar_def)
  apply(erule disjE) by auto

lemma Tick_guar_stb_inv: "(s,r) \<in> Tick_guar \<Longrightarrow> inv s \<Longrightarrow> inv r"
  apply (simp add: Tick_guar_def)
  apply (erule disjE)
   apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def  inv_OS_Mem_info_mp_def inv_thd_waitq_def)
   apply auto
  done

lemma OSMemGet_pre_stb: "stable (OSMemGet_pre t) (OSMemGet_rely t)"
  by (simp add: OSMemGet_pre_def stable_inv_alloc_rely1)

lemma OSMemGet_post_stb: "stable (OSMemGet_post t) (OSMemGet_rely t)"
  apply (simp add: OSMemGet_post_def stable_def OSMemGet_rely_def, clarsimp)
  apply (case_tac "ret x t = OS_ERR_NONE", clarsimp)
   apply (simp add: lvars_nochange_def lvars_nochange_rel_def)
   apply (metis zero_neq_neg_numeral)
  apply (case_tac "ret x t = OS_ERR_MEM_NO_FREE_BLKS", clarsimp)
   apply (simp add: lvars_nochange_def lvars_nochange_rel_def)
   apply auto[1]
  using lvars_nochange_def lvars_nochange_rel_def by auto

lemma OSMemPut_pre_stb: "stable (OSMemPut_pre t) (OSMemPut_rely t)"
  by (simp add: OSMemPut_pre_def stable_inv_free_rely1)

lemma OSMemPut_post_stb: "stable (OSMemPut_pre t) (OSMemPut_rely t)"
  by (simp add: OSMemPut_pre_stb)

lemma OSMboxPend_pre_stable:" stable (OSMboxPend_pre t) (OSMboxPend_rely t) "
  by(simp add:OSMboxPend_pre_def OSMboxPend_rely_def stable_def gvars_conf_stable_def gvars_conf_def)

lemma OSMboxPend_post_stable:" stable (OSMboxPend_post t) (OSMboxPend_rely t) "
  by(simp add:OSMboxPend_post_def OSMboxPend_rely_def stable_def)

lemma OSMboxPost_pre_stable:" stable (OSMboxPost_pre t) (OSMboxPost_rely t) "
  by(simp add:OSMboxPost_pre_def OSMboxPost_rely_def stable_def gvars_conf_stable_def gvars_conf_def)

lemma OSMboxPost_post_stable:" stable (OSMboxPost_post t) (OSMboxPost_rely t) "
  by(simp add:OSMboxPost_post_def OSMboxPost_rely_def stable_def)

lemma OSMboxAccept_pre_stable:" stable (OSMboxAccept_pre t) (OSMboxAccept_rely t) "
  by(simp add:OSMboxAccept_pre_def OSMboxAccept_rely_def stable_def gvars_conf_stable_def gvars_conf_def)

lemma OSMboxAccept_post_stable:" stable (OSMboxAccept_post t) (OSMboxAccept_rely t) "
  by(simp add:OSMboxAccept_post_def OSMboxAccept_rely_def stable_def)

lemma OSMemGetguar_in_OSMemGetrely: "t1 \<noteq> t2 \<Longrightarrow> OSMemGet_guar t1 \<subseteq> OSMemGet_rely t2"
  apply clarify
proof -
  fix a b
  assume p0: "t1 \<noteq> t2"
    and  p1: "(a,b) \<in> OSMemGet_guar t1"
  hence p2: "(a,b) \<in> gvars_conf_stable
                \<and> (cur a \<noteq> Some t1 \<longrightarrow> gvars_nochange a b \<and> lvars_nochange t1 a b)
                \<and> (cur a = Some t1 \<longrightarrow> inv a \<longrightarrow> inv b)
                \<and> (\<forall>t'. t' \<noteq> t1 \<longrightarrow> lvars_nochange t' a b) \<and> (tick a = tick b)  \<or> a = b"
    by (simp add: OSMemGet_guar_def)
  from p0 and p2 have
  "(a,b) \<in> lvars_nochange_rel t2 \<and> (a,b) \<in> gvars_conf_stable
    \<and> (inv a \<longrightarrow> inv b)
    \<and> (cur a = Some t2 \<longrightarrow> OS_MEM_info a = OS_MEM_info b
            \<and> (\<forall>t'. t' \<noteq> t2 \<longrightarrow> lvars_nochange t' a b))
    \<or> a = b"
    apply clarify
    apply(rule conjI) apply (simp add:lvars_nochange_rel_def)
    apply(rule conjI) apply simp
    apply(rule conjI) apply (metis CollectI OSMemGet_guar_stb_inv mem_Collect_eq p1 stable_def)
    apply clarify
    apply (rule conjI) apply(simp add:gvars_nochange_def)
    by auto
  thus "(a,b) \<in> OSMemGet_rely t2" unfolding OSMemGet_rely_def by simp
qed

lemma Schedguar_in_OSMemGetrely: "Schedule_guar \<subseteq> OSMemGet_rely t2"
  apply clarify
proof-
  fix a b
  assume p0: "(a,b) \<in> Schedule_guar"
  hence p1: "(inv a \<longrightarrow> inv b) \<and> OS_MEMs a = OS_MEMs b \<and> OS_MEM_info a = OS_MEM_info b
            \<and> OSMailBoxs a = OSMailBoxs b \<and> OSMailbox_info a = OSMailbox_info b
            \<and> (a,b)\<in>(\<Inter>t. lvars_nochange_rel t) \<or> a = b"
    apply (clarsimp)
    by (intro conjI, simp_all add: Schedule_guar_def)
  hence "(a,b) \<in> lvars_nochange_rel t2 \<and> (a,b) \<in> gvars_conf_stable
         \<and> (inv a \<longrightarrow> inv b)
         \<and> (cur a = Some t2 \<longrightarrow> OS_MEM_info a = OS_MEM_info b
                \<and> (\<forall>t'. t' \<noteq> t2 \<longrightarrow> lvars_nochange t' a b))
         \<or> a = b"
    apply clarify
    apply (rule conjI, simp add: lvars_nochange_rel_def)
    apply(rule conjI, simp add: gvars_conf_stable_def gvars_conf_def)
    apply (rule conjI, simp, clarsimp)
    by (simp add: lvars_nochange_rel_def mem_Collect_eq)
  thus "(a,b) \<in> OSMemGet_rely t2" by(simp add: OSMemGet_rely_def)
qed

lemma OSMemGetguar_in_schedrely: "OSMemGet_guar t \<subseteq> Schedule_rely"
  apply(simp add:OSMemGet_guar_def Schedule_rely_def)
  apply clarify
  apply(case_tac "cur a = Some t")
    apply simp
  apply clarify
  apply (simp add: gvars_nochange_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_cur_def
      inv_thd_waitq_def inv_def)
  by blast

lemma Schedule_guar_in_Tick_rely : "Schedule_guar \<subseteq> Tick_rely"
  apply (simp add: Schedule_guar_def Tick_rely_def)
  apply auto[1]
  done

lemma OSMemPut_guar_in_Tick_rely:  "OSMemPut_guar t \<subseteq> Tick_rely"
  apply (simp add: OSMemPut_guar_def Tick_rely_def)
  apply auto[1]
  done

lemma Tick_guar_in_OSMemPut_rely: "Tick_guar \<subseteq> OSMemPut_rely t"
  apply (simp add: Tick_guar_def OSMemPut_rely_def)
  apply auto
  apply (simp add: gvars_conf_stable_def gvars_conf_def)
   apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_thd_waitq_def)
   apply auto[1]
  apply (simp add: lvars_nochange_def lvars_nochange_rel_def)
  done

lemma Tick_guar_in_Schedule_rely: "Tick_guar \<subseteq> Schedule_rely"
  apply (simp add: Tick_guar_def Schedule_rely_def)
  apply (simp add: lvars_nochange_def lvars_nochange_rel_def)
  apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_thd_waitq_def)
  apply auto
  done

lemma Schedule_guar_in_OSMboxPost_rely : "Schedule_guar \<subseteq> OSMboxPost_rely t"
  apply (simp add: Schedule_guar_def OSMboxPost_rely_def)
  apply (simp add: gvars_conf_stable_def gvars_conf_def lvars_nochange_def lvars_nochange_rel_def)
  apply auto
  done

lemma Schedule_guar_in_OSMboxPend_rely : "Schedule_guar \<subseteq> OSMboxPend_rely t"
  apply (simp add: Schedule_guar_def OSMboxPend_rely_def)
  apply (simp add: gvars_conf_stable_def gvars_conf_def lvars_nochange_def lvars_nochange_rel_def)
  apply auto
  done

lemma Schedule_guar_in_OSMboxAccept_rely : "Schedule_guar \<subseteq> OSMboxAccept_rely t"
    apply (simp add: Schedule_guar_def OSMboxAccept_rely_def)
  apply (simp add: gvars_conf_stable_def gvars_conf_def lvars_nochange_def lvars_nochange_rel_def)
  apply auto
  done

lemma OSMboxPost_guar_in_Schedule_rely : "OSMboxPost_guar t \<subseteq> Schedule_rely"
  apply (simp add: OSMboxPost_guar_def Schedule_rely_def)
  apply auto
  apply (simp add: gvars_nochange_def gvars_conf_stable_def gvars_conf_def lvars_nochange_def)
  apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_thd_waitq_def)
  by blast

lemma OSMboxPend_guar_in_Schedule_rely : "OSMboxPend_guar t \<subseteq> Schedule_rely"
  apply (simp add: OSMboxPend_guar_def Schedule_rely_def)
  apply auto
  apply (simp add: gvars_nochange_def gvars_conf_stable_def gvars_conf_def lvars_nochange_def)
  apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_thd_waitq_def)
  by blast

lemma OSMboxAccept_guar_in_Schedule_rely : "OSMboxAccept_guar t \<subseteq> Schedule_rely"
  apply (simp add: OSMboxAccept_guar_def Schedule_rely_def)
  apply auto
  apply (simp add: gvars_nochange_def gvars_conf_stable_def gvars_conf_def lvars_nochange_def)
  apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_thd_waitq_def)
  by blast

lemma OSMboxguar_in_OSMboxrely : "t1 \<noteq> t2 \<Longrightarrow> OSMboxPost_guar t1 \<subseteq> OSMboxPost_rely t2"
  apply clarify
proof -
  fix a b
  assume p0: "t1 \<noteq> t2"
    and  p1: "(a,b) \<in> OSMboxPost_guar t1"
  hence p2: "(a,b) \<in> gvars_conf_stable
                \<and> (cur a \<noteq> Some t1 \<longrightarrow> gvars_nochange a b \<and> lvars_nochange t1 a b)
                \<and> (cur a = Some t1 \<longrightarrow> inv a \<longrightarrow> inv b)
                \<and> (\<forall>t'. t' \<noteq> t1 \<longrightarrow> lvars_nochange t' a b) \<and> (tick a = tick b)  \<or> a = b"
    by (simp add: OSMboxPost_guar_def)
  from p0 and p2 have
  "(a,b) \<in> lvars_nochange_rel t2 \<and> (a,b) \<in> gvars_conf_stable
    \<and> (inv a \<longrightarrow> inv b)
    \<and> (cur a = Some t2 \<longrightarrow> OSMailbox_info a = OSMailbox_info b
            \<and> (\<forall>t'. t' \<noteq> t2 \<longrightarrow> lvars_nochange t' a b))
    \<or> a = b"
    apply clarify
    apply(rule conjI) apply (simp add:lvars_nochange_rel_def)
    apply(rule conjI) apply simp
    apply(rule conjI)
    apply (meson OSMboxPost_guar_in_Schedule_rely contra_subsetD p1 stable_inv_sched_rely)
    apply clarify
    apply (rule conjI) apply(simp add:gvars_nochange_def)
    by auto
  thus "(a,b) \<in> OSMboxPost_rely t2" unfolding OSMboxPost_rely_def by simp
qed

lemma OSMboxguar_in_OSMemrely : "t1 \<noteq> t2 \<Longrightarrow> OSMboxPost_guar t1 \<subseteq> OSMemPut_rely t2"
  apply clarify
proof -
  fix a b
  assume p0: "t1 \<noteq> t2"
    and  p1: "(a,b) \<in> OSMboxPost_guar t1"
  hence p2: "(a,b) \<in> gvars_conf_stable
                \<and> (cur a \<noteq> Some t1 \<longrightarrow> gvars_nochange a b \<and> lvars_nochange t1 a b)
                \<and> (cur a = Some t1 \<longrightarrow> inv a \<longrightarrow> inv b)
                \<and> (\<forall>t'. t' \<noteq> t1 \<longrightarrow> lvars_nochange t' a b) \<and> (tick a = tick b)  \<or> a = b"
    by (simp add: OSMboxPost_guar_def)
  from p0 and p2 have
  "(a,b) \<in> lvars_nochange_rel t2 \<and> (a,b) \<in> gvars_conf_stable
    \<and> (inv a \<longrightarrow> inv b)
    \<and> (cur a = Some t2 \<longrightarrow> OS_MEM_info a = OS_MEM_info b
            \<and> (\<forall>t'. t' \<noteq> t2 \<longrightarrow> lvars_nochange t' a b))
    \<or> a = b"
    apply clarify
    apply(rule conjI) apply (simp add:lvars_nochange_rel_def)
    apply(rule conjI) apply simp
    apply(rule conjI)
    apply (meson OSMboxPost_guar_in_Schedule_rely contra_subsetD p1 stable_inv_sched_rely)
    apply clarify
    apply (rule conjI) apply(simp add:gvars_nochange_def)
    by auto
  thus "(a,b) \<in> OSMemPut_rely t2" unfolding OSMemPut_rely_def by simp
qed

lemma OSMemguar_in_OSMboxrely : "t1 \<noteq> t2 \<Longrightarrow> OSMemPut_guar t1 \<subseteq> OSMboxPost_rely t2"
  apply clarify
proof -
  fix a b
  assume p0: "t1 \<noteq> t2"
    and  p1: "(a,b) \<in> OSMemPut_guar t1"
  hence p2: "(a,b) \<in> gvars_conf_stable
                \<and> (cur a \<noteq> Some t1 \<longrightarrow> gvars_nochange a b \<and> lvars_nochange t1 a b)
                \<and> (cur a = Some t1 \<longrightarrow> inv a \<longrightarrow> inv b)
                \<and> (\<forall>t'. t' \<noteq> t1 \<longrightarrow> lvars_nochange t' a b) \<and> (tick a = tick b)  \<or> a = b"
    by (simp add: OSMemPut_guar_def)
  from p0 and p2 have
  "(a,b) \<in> lvars_nochange_rel t2 \<and> (a,b) \<in> gvars_conf_stable
    \<and> (inv a \<longrightarrow> inv b)
    \<and> (cur a = Some t2 \<longrightarrow> OSMailbox_info a = OSMailbox_info b
            \<and> (\<forall>t'. t' \<noteq> t2 \<longrightarrow> lvars_nochange t' a b))
    \<or> a = b"
    apply clarify
    apply(rule conjI) apply (simp add:lvars_nochange_rel_def)
    apply(rule conjI) apply simp
    apply(rule conjI)
    using OSMemGetguar_in_schedrely OSMem_eq_guar p1 stable_inv_sched_rely apply blast
    apply clarify
    apply (rule conjI) apply(simp add:gvars_nochange_def)
    by auto
  thus "(a,b) \<in> OSMboxPost_rely t2" unfolding OSMboxPost_rely_def by simp
qed

lemma Tick_guar_in_OSMboxrely : "Tick_guar \<subseteq> OSMboxPost_rely x"
  apply (simp add: Tick_guar_def OSMboxPost_rely_def)
  apply (simp add: gvars_conf_stable_def gvars_conf_def lvars_nochange_def lvars_nochange_rel_def)
  apply (simp add: inv_def inv_cur_def inv_OS_Mem_info_def inv_OS_Mem_info_mp_def inv_thd_waitq_def)
  by auto

end


(*  Title:       variants/b_fwdrreps/OAodv.thy
    License:     BSD 2-Clause. See LICENSE.
    Author:      Timothy Bourke, Inria
*)

section "The `open' AODV model"

theory B_OAodv
imports B_Aodv AWN.OAWN_SOS_Labels AWN.OAWN_Convert
begin

text \<open>Definitions for stating and proving global network properties over individual processes.\<close>

definition \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V' :: "((ip \<Rightarrow> state) \<times> ((state, msg, pseqp, pseqp label) seqp)) set"
where "\<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V' \<equiv> {(\<lambda>i. aodv_init i, \<Gamma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V PAodv)}"

abbreviation opaodv
  :: "ip \<Rightarrow> ((ip \<Rightarrow> state) \<times> (state, msg, pseqp, pseqp label) seqp, msg seq_action) automaton"
where
  "opaodv i \<equiv> \<lparr> init = \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V', trans = oseqp_sos \<Gamma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V i \<rparr>"

lemma initiali_aodv [intro!, simp]: "initiali i (init (opaodv i)) (init (paodv i))"
  unfolding \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V_def \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V'_def by rule simp_all

lemma oaodv_control_within [simp]: "control_within \<Gamma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V (init (opaodv i))"
  unfolding \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V'_def by (rule control_withinI) (auto simp del: \<Gamma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V_simps)

lemma \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V'_labels [simp]: "(\<sigma>, p) \<in> \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V' \<Longrightarrow>  labels \<Gamma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V p = {PAodv-:0}"
  unfolding \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V'_def by simp

lemma oaodv_init_kD_empty [simp]:
  "(\<sigma>, p) \<in> \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V' \<Longrightarrow> kD (rt (\<sigma> i)) = {}"
  unfolding \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V'_def kD_def by simp

lemma oaodv_init_vD_empty [simp]:
  "(\<sigma>, p) \<in> \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V' \<Longrightarrow> vD (rt (\<sigma> i)) = {}"
  unfolding \<sigma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V'_def vD_def by simp

lemma oaodv_trans: "trans (opaodv i) = oseqp_sos \<Gamma>\<^sub>A\<^sub>O\<^sub>D\<^sub>V i"
  by simp

declare
  oseq_invariant_ctermsI [OF aodv_wf oaodv_control_within aodv_simple_labels oaodv_trans, cterms_intros]
  oseq_step_invariant_ctermsI [OF aodv_wf oaodv_control_within aodv_simple_labels oaodv_trans, cterms_intros]

end