theory ReduceAction
  imports ReduceProper ReduceWTS
begin

  (* ###### constructive permission definitions.
      the idea here is that i want to constructively state which permissions are being consumed.
      the difficult part is that because the "permissions consumed" involves
  *)

datatype gen_act =
  NoResAct
  | AddResAct string p_type (*perm_use_env*)
  | Add2ResAct string string p_type
  | ReadResAct
  | WriteResAct string perm_use_env

fun red_env :: "pt_env \<Rightarrow> gen_act \<Rightarrow> pt_env" where
  "red_env env NoResAct = env"
| "red_env env (AddResAct x tau) = add_env env (Loc x) tau"
| "red_env env (Add2ResAct x1 x2 tau) = add_env (add_env env (Loc x1) (ChanTy tau SEnd)) (Loc x2) (ChanTy tau REnd)"
| "red_env env ReadResAct = env"
| "red_env env (WriteResAct x r_s) = env"

fun red_delta :: "owner_env \<Rightarrow> gen_act \<Rightarrow> owner_env" where
  "red_delta delta (WriteResAct x r_s) = ext_delta delta (delta x) r_s"
| "red_delta delta (AddResAct x tau) = add_delta delta x x"
| "red_delta delta (Add2ResAct x1 x2 tau) = add_delta (add_delta delta x1 x1) x2 x2"
| "red_delta delta r_ax = delta"

fun exp_red_use_env where
  "exp_red_use_env r_s NoResAct = r_s"
  (* remove resources used to create the value, add the new perm *)
| "exp_red_use_env r_s (AddResAct x tau) = add_use_env r_s (Loc x) OwnPerm"
| "exp_red_use_env r_s (Add2ResAct x1 x2 tau) = add_use_env (add_use_env r_s (Loc x1) OwnPerm) (Loc x2) OwnPerm"
| "exp_red_use_env r_s ReadResAct = r_s"
| "exp_red_use_env r_s (WriteResAct x r_s') = (diff_use_env r_s r_s')"

fun end_red_use_env where
  "end_red_use_env r_s (WriteResAct x r_s') = (diff_use_env r_s r_s')"
| "end_red_use_env r_s r_ax = r_s"
  (*
fun red_nres_map :: "nres_map \<Rightarrow> gen_act \<Rightarrow> nres_map" where
  "red_nres_map rs_map NoResAct = rs_map"
| "red_nres_map rs_map (AddResAct x tau r_s) = add_env rs_map x r_s"
| "red_nres_map rs_map (Add2ResAct x1 x2 tau) = add_env (add_env rs_map x1 empty_use_env) x2 empty_use_env"
| "red_nres_map rs_map ReadResAct = rs_map"
| "red_nres_map rs_map (WriteResAct x r_s) = add_env rs_map x (comp_use_env (nres_lookup rs_map x) r_s)"
  *)

  (*
fun safe_act where
  "safe_act s r_s NoResAct = True"
| "safe_act s r_s (AddResAct x tau r_x) = (s x = None \<and> leq_use_env r_x r_s)"
| "safe_act s r_s (Add2ResAct x1 x2 tau) = (s x1 = None \<and> s x2 = None \<and> x1 \<noteq> x2)"
| "safe_act s r_s ReadResAct = True"
| "safe_act s r_s (WriteResAct x r_x) = (s x \<noteq> None \<and> leq_use_env r_x r_s)"

fun corr_act where
  "corr_act ax NoResAct = (ax = NoAct)"
| "corr_act ax (AddResAct x tau r_s) = (ax = MakeAct x)"
| "corr_act ax (Add2ResAct x1 x2 tau) = (ax = Mk2Act x1 x2)"
| "corr_act ax ReadResAct = (\<exists> x. ax = UseAct x)"
| "corr_act ax (WriteResAct x r_s) = (\<exists> x. ax = UseAct x)"
  *)

fun safe_act where
  "safe_act s r_s NoResAct = True"
| "safe_act s r_s (AddResAct x tau) = (s x = None)"
| "safe_act s r_s (Add2ResAct x1 x2 tau) = (s x1 = None \<and> s x2 = None \<and> x1 \<noteq> x2)"
| "safe_act s r_s ReadResAct = True"
| "safe_act s r_s (WriteResAct x r_x) = (s x \<noteq> None \<and> leq_use_env r_x r_s)"

definition corr_act where
  "corr_act ax g_ax = True"

lemma leq_safe_act: "\<lbrakk> safe_act s r_x g_ax; leq_use_env r_x r_s \<rbrakk> \<Longrightarrow> safe_act s r_s g_ax"
  apply (case_tac g_ax)
      apply (auto)
   apply (rule_tac r_sb="r_x" in trans_leq_use_env)
    apply (auto)
  done

definition valid_reduct where
  "valid_reduct r_exp = (\<forall> are s1 env delta r_f r_s1 e1 tau r_s2 rx ax s2 e2. (
    r_exp are (s1, e1) ax (s2, e2) \<and> well_typed env delta r_s1 e1 tau r_s2 rx \<and>
    well_typed_state s1 env delta \<and> (*valid_exp_use_env s1 r_f \<and> *) sub_use_env s1 r_f \<and> leq_use_env r_s1 r_f) \<longrightarrow>
    (\<exists> g_ax. well_typed (red_env env g_ax) (red_delta delta g_ax) (exp_red_use_env r_s1 g_ax) e2 tau (end_red_use_env r_s2 g_ax) (end_red_use_env rx g_ax) \<and>
      well_typed_state s2 (red_env env g_ax) (red_delta delta g_ax) \<and>
      (*valid_exp_use_env s2 (exp_red_use_env r_f g_ax)*) sub_use_env s2 (exp_red_use_env r_f g_ax) \<and> safe_act s1 (infl_use_env r_f r_s2) g_ax \<and> corr_act ax g_ax)
  )"

lemma red_contain_env: "\<lbrakk> safe_act s r_s g_ax; sub_env s env \<rbrakk> \<Longrightarrow> contain_env (red_env env g_ax) env"
  apply (case_tac g_ax)
      apply (auto)
      apply (rule_tac id_contain_env)
     apply (rule_tac add_contain_env)
     apply (simp add: sub_env_def)
     apply (erule_tac x="Loc x21" in allE)
     apply (auto)
    apply (rule_tac env_b="add_env env (Loc x31) (ChanTy x33 SEnd)" in trans_contain_env)
     apply (rule_tac add_contain_env)
     apply (simp add: add_env_def)
     apply (case_tac "env (Loc x32)")
      apply (auto)
     apply (simp add: sub_env_def)
     apply (erule_tac x="Loc x32" in allE)
     apply (auto)
    apply (rule_tac add_contain_env)
    apply (case_tac "env (Loc x31)")
     apply (auto)
    apply (simp add: sub_env_def)
    apply (erule_tac x="Loc x31" in allE)
    apply (auto)
   apply (rule_tac id_contain_env)
  apply (rule_tac id_contain_env)
  done

    (* ##### safe-reduction specific validity lemmas ##### *)

lemma red_sep_nres_map: "\<lbrakk> p_map u = Some r_s; disj_nres_map p_map; sub_nres_map s1 p_map;
  safe_act s1 r_s g_ax; sub_use_env s1 r_s \<rbrakk> \<Longrightarrow> sep_nres_map (exp_red_use_env r_s g_ax) (rem_env p_map u)"
  apply (simp add: sep_nres_map_def)
  apply (auto)
    (* we dont have to check x = u, since u has been removed from the map *)
  apply (case_tac "u = x")
   apply (auto)
   apply (simp add: nres_lookup_def)
   apply (simp add: rem_env_def)
   apply (rule_tac empty_strong_disj_use_env2)
    (* otherwise, the lookup is the same as it was in p_map *)
  apply (cut_tac rs_map="p_map" and x="u" and y="x" in nres_rem_diff)
   apply (auto)
    (* from here we do case analysis on the possible ways that r_s has been modified *)
    (* if it has not been modified the case is simple *)
  apply (case_tac "exp_red_use_env r_s g_ax = r_s")
   apply (simp add: disj_nres_map_def)
   apply (erule_tac x="u" in allE)
   apply (erule_tac x="x" in allE)
   apply (auto)
   apply (simp add: nres_lookup_def)
    (* make case: if x21 has been added, the rest of r_s is disjoint from p_map x *)
  apply (case_tac g_ax)
     apply (auto)
    apply (rule_tac add_strong_disj_use_env)
     apply (simp add: disj_nres_map_def)
     apply (erule_tac x="u" in allE)
     apply (erule_tac x="x" in allE)
     apply (auto)
     apply (simp add: nres_lookup_def)
    (* now we have to prove that x21 was not in p_map, which should be true since p_map is sub-ordinate to s *)
    apply (case_tac "p_map x")
     apply (simp add: nres_lookup_def)
     apply (simp add: empty_use_env_def)
    apply (simp add: sub_nres_map_def)
    apply (erule_tac x="x" in allE)
    apply (simp add: sub_use_env_def)
    apply (erule_tac x="Loc x21" in allE)
    apply (auto)
    (* make 2 case: start by assuming we have p_map x *)
   apply (case_tac "p_map x")
    apply (simp add: nres_lookup_def)
    apply (rule_tac empty_strong_disj_use_env2)
    (* otherwise, prove r_s disjoint from p_map x *)
   apply (rule_tac add_strong_disj_use_env)
    apply (rule_tac add_strong_disj_use_env)
     apply (simp add: disj_nres_map_def)
     apply (erule_tac x="u" in allE)
     apply (erule_tac x="x" in allE)
     apply (auto)
     apply (simp add: nres_lookup_def)
    (* after this, prove x31 / x32 do not appear in p_map x *)
    apply (simp add: sub_nres_map_def)
    apply (erule_tac x="x" in allE)
    apply (simp add: sub_use_env_def)
    apply (erule_tac x="Loc x31" in allE)
    apply (auto)
   apply (simp add: sub_nres_map_def)
   apply (erule_tac x="x" in allE)
   apply (simp add: sub_use_env_def)
   apply (erule_tac x="Loc x32" in allE)
    apply (auto)
    (* write case: otherwise, x42 was removed from r_s, so disjointness should be simple *)
  apply (rule_tac r_s="r_s" in strong_disj_leq_use_env1)
   apply (simp add: disj_nres_map_def)
   apply (erule_tac x="u" in allE)
   apply (erule_tac x="x" in allE)
   apply (auto)
   apply (simp add: nres_lookup_def)
  apply (rule_tac self_diff_leq_use_env)
  done

(*
lemma red_sep_nres_map2: "\<lbrakk> p_map v = Some r_p; p_map u = Some r_s; u \<noteq> v; disj_nres_map p_map;
  safe_act s1 r_s g_ax; sep_nres_map r_p rs_map \<rbrakk> \<Longrightarrow> sep_nres_map r_p (red_nres_map rs_map g_ax)"
  apply (case_tac g_ax)
      apply (auto)
    (* make case *)
    apply (rule_tac add_sep_nres_map)
     apply (simp)
    apply (rule_tac r_s="r_s" in strong_disj_leq_use_env2)
     apply (simp add: disj_nres_map_def)
     apply (auto)
    apply (erule_tac x="v" in allE)
    apply (erule_tac x="u" in allE)
    apply (simp add: nres_lookup_def)
    (* make 2 case *)
   apply (rule_tac add_sep_nres_map)
    apply (rule_tac add_sep_nres_map)
     apply (simp)
    apply (rule_tac empty_strong_disj_use_env2)
   apply (rule_tac empty_strong_disj_use_env2)
    (* write case *)
  apply (rule_tac add_sep_nres_map)
   apply (simp)
  apply (rule_tac strong_disj_comp_use_env1)
   apply (simp add: sep_nres_map_def)
  apply (rule_tac r_s="r_s" in strong_disj_leq_use_env2)
   apply (simp add: disj_nres_map_def)
   apply (erule_tac x="v" in allE)
   apply (erule_tac x="u" in allE)
   apply (simp add: nres_lookup_def)
  apply (simp)
  done    *)

definition loc_use_env where
  "loc_use_env r_s = (\<forall> x. case x of
    Var x \<Rightarrow> r_s (Var x) = NoPerm
    | Loc y \<Rightarrow> True
  )"

lemma wtedi_strong_disj_use_env: "\<lbrakk> strong_disj_use_env r_s r_ex; leq_use_env r_x r_s; loc_use_env r_ex \<rbrakk> \<Longrightarrow> strong_disj_use_env (add_use_env r_x (Var x) r) r_ex"
  apply (rule_tac r_s="add_use_env r_s (Var x) r" in strong_disj_leq_use_env1)
   apply (simp add: strong_disj_use_env_def)
   apply (simp add: add_use_env_def)
   apply (auto)
   apply (simp add: loc_use_env_def)
   apply (erule_tac x="Var x" in allE)
   apply (erule_tac x="Var x" in allE)
   apply (auto)
  apply (rule_tac dist_add_leq_use_env)
  apply (simp)
  done
    (*
lemma wtedx_adjust: "\<lbrakk> well_typed env delta r_s e1 t1 r_s2 rx1; well_typed env delta r_s2 e2 t2 r_s3 rx2; leq_use_env r_s (diff_use_env r_s3 r_ex) \<rbrakk> \<Longrightarrow>
  well_typed env delta r_s e1 t1 r_s rx1 \<and> well_typed env delta r_s e2 t2 r_s rx2"
  apply (auto)
   apply (rule_tac r_c="r_s2" in well_typed_decr_end_perm)
     apply (simp)
    apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
     apply (rule_tac diff_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
   apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leqx)
   apply (auto)
  apply (rule_tac r_c="r_s3" in well_typed_decr_end_perm)
    apply (rule_tac ?r_s1.0="r_s2" in well_typed_incr_start_perm)
     apply (simp)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac r_sb="diff_use_env r_s3 r_ex" in trans_leq_use_env)
    apply (rule_tac self_diff_leq_use_env)
   apply (simp)
  apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
   apply (rule_tac r_sb="r_s2" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (rule_tac well_typed_perm_leqx)
  apply (auto)
  done

lemma well_typed_ext_deltax: "\<lbrakk> well_typed env delta r_s e tau r_s r_x; strong_disj_use_env r_x r_ex; mem_val_env env; loc_use_env r_ex \<rbrakk> \<Longrightarrow>
  well_typed env (ext_delta delta x r_ex) r_s e tau r_s r_x"
  apply (induct e arbitrary: env r_s tau r_x)
        apply (auto)
    (* var case *)
      apply (case_tac "owner_name (ext_delta delta x r_ex) xa \<noteq> owner_name delta xa")
       apply (case_tac xa)
        apply (auto)
      apply (case_tac "req_type tau_x \<noteq> Ref")
       apply (simp add: mem_val_env_def)
       apply (erule_tac x="Loc (delta x2)" in allE)
       apply (auto)
       apply (case_tac tau_x)
             apply (auto)
      apply (case_tac "r_x (Loc (delta x2)) = NoPerm")
       apply (case_tac "comp_use_env (ereq_use_env (Loc (delta x2)) tau_x) r_exa (Loc (delta x2)) = OwnPerm")
        apply (cut_tac r_s="r_s" and r_x="comp_use_env (ereq_use_env (Loc (delta x2)) tau_x) r_exa" in self_diff_weak_use_env)
          apply (simp)
         apply (rule_tac dist_comp_leq_use_env)
          apply (auto)
        apply (simp add: weak_use_env_def)
       apply (cut_tac r_x="diff_use_env (ereq_use_env (Loc (delta x2)) tau_x) (comp_use_env (ereq_use_env (Loc (delta x2)) tau_x) r_exa)" and r_s="r_x" and x="Loc (delta x2)" in leq_use_none)
         apply (simp_all)
       apply (cut_tac r_s="ereq_use_env (Loc (delta x2)) tau_x" and r_x="comp_use_env (ereq_use_env (Loc (delta x2)) tau_x) r_exa" and x="Loc (delta x2)" in diff_use_eq)
        apply (auto)
       apply (simp add: ereq_use_env_def)
       apply (simp add: one_use_env_def)
       apply (simp add: end_req_perm_def)
      apply (simp add: strong_disj_use_env_def)
      apply (simp add: ext_delta_def)
      apply (auto)
    (* pair case *)
     apply (cut_tac env="env" and r_s="r_s" and ?e1.0="e1" and ?e2.0="e2" in wtedx_adjust)
        apply (auto)
     apply (rule_tac x="r_s" in exI)
     apply (rule_tac x="r_s" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_x" in strong_disj_leq_use_env1)
       apply (auto)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_x" in strong_disj_leq_use_env1)
      apply (auto)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_end" in exI)
   apply (rule_tac x="r_s'" in exI)
   apply (cut_tac r_x="rxa" and x="x1a" and r="r" and r_ex="r_x" and r_s="r_s1" in wtedi_strong_disj_use_env)
      apply (auto)
   apply (case_tac "\<not> mem_val_env (add_env env (Var x1a) t1)")
    apply (simp add: mem_val_env_def)
    apply (simp add: add_env_def)
   apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_x" in strong_disj_leq_use_env1)
    apply (auto)
  apply (rule_tac well_typed_perm_leq)
  apply (auto)
  done    *)

lemma well_typed_ext_delta_ih: "\<lbrakk> well_typed env delta r_s1 e tau r_s2 rx; strong_disj_use_env r_s1 r_x; mem_val_env env; loc_use_env r_x \<rbrakk> \<Longrightarrow>
  well_typed env (ext_delta delta x r_x) r_s1 e tau r_s2 rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
        apply (auto)
    (* var case *)
      apply (case_tac "owner_name (ext_delta delta x r_x) xa \<noteq> owner_name delta xa")
       apply (case_tac xa)
        apply (auto)
      apply (case_tac "req_type tau_x \<noteq> Ref")
       apply (simp add: mem_val_env_def)
       apply (erule_tac x="Loc (delta x2)" in allE)
       apply (auto)
       apply (case_tac tau_x)
             apply (auto)
      apply (case_tac "r_s1 (Loc (delta x2)) = NoPerm")
       apply (cut_tac r_x="ereq_use_env (Loc (delta x2)) tau_x" and r_s="r_s1" and x="Loc (delta x2)" in leq_use_none)
         apply (simp_all)
       apply (simp add: ereq_use_env_def)
       apply (simp add: one_use_env_def)
       apply (simp add: end_req_perm_def)
      apply (simp add: strong_disj_use_env_def)
      apply (simp add: ext_delta_def)
      apply (auto)
    (* pair case *)
     apply (rule_tac x="r_s2a" in exI)
     apply (rule_tac x="r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
     apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_x" in strong_disj_leq_use_env1)
       apply (auto)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="r_s2a" in exI)
    apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_x" in strong_disj_leq_use_env1)
      apply (auto)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_end" in exI)
   apply (rule_tac x="r_s'" in exI)
   apply (cut_tac r_x="rxa" and x="x1a" and r="r" and r_ex="r_x" and r_s="r_s1" in wtedi_strong_disj_use_env)
      apply (auto)
   apply (case_tac "\<not> mem_val_env (add_env env (Var x1a) t1)")
    apply (simp add: mem_val_env_def)
    apply (simp add: add_env_def)
   apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="r_s3" in exI)
  apply (auto)
  apply (cut_tac r_x="r_s2a" and r_s="r_s1" and r_ex="r_x" in strong_disj_leq_use_env1)
    apply (auto)
  apply (rule_tac well_typed_perm_leq)
  apply (auto)
  done

definition loc_restr where
  "loc_restr r_s = (\<lambda> x. case x of
    Var x \<Rightarrow> NoPerm
    | Loc y \<Rightarrow> r_s x
  )"

lemma loc_restr_ext_delta: "ext_delta delta x r_s = ext_delta delta x (loc_restr r_s)"
  apply (case_tac "\<forall> y. ext_delta delta x r_s y= ext_delta delta x (loc_restr r_s) y")
   apply (auto)
  apply (simp add: ext_delta_def)
  apply (simp add: loc_restr_def)
  done

lemma loc_restr_use_env: "loc_use_env (loc_restr r_s)"
  apply (simp add: loc_use_env_def)
  apply (auto)
  apply (case_tac x)
   apply (auto)
  apply (simp add: loc_restr_def)
  done

lemma loc_restr_leq_use_env: "leq_use_env (loc_restr r_s) r_s"
  apply (simp add: leq_use_env_def)
  apply (simp add: loc_restr_def)
  apply (auto)
  apply (case_tac x)
   apply (auto)
  apply (case_tac "r_s (Loc x2)")
    apply (auto)
  done

lemma dist_loc_restr_leq_use_env: "\<lbrakk> leq_use_env r_x r_s \<rbrakk> \<Longrightarrow> leq_use_env (loc_restr r_x) (loc_restr r_s)"
  apply (simp add: loc_restr_def)
  apply (simp add: leq_use_env_def)
  apply (auto)
  apply (erule_tac x="x" in allE)
  apply (case_tac x)
   apply (auto)
  done

lemma well_typed_ext_delta: "\<lbrakk> well_typed env delta r_s1 e tau r_s2 rx; strong_disj_use_env r_s1 r_x; mem_val_env env \<rbrakk> \<Longrightarrow>
  well_typed env (ext_delta delta x r_x) r_s1 e tau r_s2 rx"
  apply (cut_tac delta="delta" and x="x" and r_s="r_x" in loc_restr_ext_delta)
  apply (auto)
  apply (rule_tac well_typed_ext_delta_ih)
     apply (auto)
   apply (rule_tac r_s="r_x" in strong_disj_leq_use_env2)
    apply (simp)
   apply (rule_tac loc_restr_leq_use_env)
  apply (rule_tac loc_restr_use_env)
  done

lemma well_typed_ext_deltax: "\<lbrakk> well_typed env delta r_x e tau r_x r_x; leq_use_env r_x r_s; strong_disj_use_env r_x r_ex; mem_val_env env \<rbrakk> \<Longrightarrow>
  well_typed env (ext_delta delta x r_ex) r_s e tau r_s r_x"
  apply (rule_tac r_s="r_x" in well_typed_incr_simul_perm)
   apply (simp)
  apply (rule_tac well_typed_ext_delta)
    apply (auto)
  done

end


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

theory n_deadlock_lemma_on_inv__2 imports n_deadlock_base
begin
section{*All lemmas on causal relation between inv__2 and some rule r*}
lemma n_TryVsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_Try  i)" and
a2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__2  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_Try  i" apply fastforce done
from a2 obtain p__Inv4 where a2:"p__Inv4\<le>N\<and>f=inv__2  p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(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__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_CritVsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_Crit  i)" and
a2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__2  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_Crit  i" apply fastforce done
from a2 obtain p__Inv4 where a2:"p__Inv4\<le>N\<and>f=inv__2  p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(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__Inv4)"
  have "?P1 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_ExitVsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_Exit  i)" and
a2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__2  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_Exit  i" apply fastforce done
from a2 obtain p__Inv4 where a2:"p__Inv4\<le>N\<and>f=inv__2  p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(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__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_IdleVsinv__2:
assumes a1: "(\<exists> i. i\<le>N\<and>r=n_Idle  i)" and
a2: "(\<exists> p__Inv4. p__Inv4\<le>N\<and>f=inv__2  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_Idle  i" apply fastforce done
from a2 obtain p__Inv4 where a2:"p__Inv4\<le>N\<and>f=inv__2  p__Inv4" apply fastforce done
have "(i=p__Inv4)\<or>(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__Inv4)"
  have "?P3 s"
  apply (cut_tac a1 a2 b1, simp, rule_tac x="(neg (andForm (eqn (IVar (Para (Ident ''n'') p__Inv4)) (Const C)) (eqn (IVar (Para (Ident ''n'') i)) (Const E))))" 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
end


theory TS_Pop_Invariants_Local_Proof
imports  TS_Proof_Rules
begin

lemma written_vals_CAS_Rel_diff_var: "cls ccs CAS\<^sup>R[lib(y), b, v, v']\<^sub>t cls' ccs' \<Longrightarrow> x\<noteq>y \<Longrightarrow> written_vals cls' x =  written_vals cls x"
  apply(simp add: lib_CAS_Rel_step_def written_vals_def, elim exE conjE)
  apply(case_tac "lib_value cls (a, ba) = v", simp_all)
  apply(simp add: lib_update_r_def all_updates_l lib_writes_on_def var_def tst_def lib_value_def)
  apply safe
     apply simp
  apply auto[1]
    apply (smt Lib.lib_write_record.select_convs(1) a_is_x fst_conv image_iff mem_Collect_eq)
  apply (smt fresh_ts_not_in_writes image_iff mem_Collect_eq)
    apply (smt fresh_ts_not_in_writes image_iff mem_Collect_eq)
  apply(simp add: lib_read_def all_updates_l lib_writes_on_def var_def tst_def lib_value_def)
  apply auto[1]
  apply(simp add: lib_read_def all_updates_l lib_writes_on_def var_def tst_def lib_value_def)
  apply auto[1]
  done

lemma pop_globals_inv:
  assumes "wfs ccs"
      and "lib_wfs cls ccs"
      and "lib_pop t v ps cls ccs ps' cls' ccs'"
      and "pop_inv t l (pc ps t) cls ccs  ps"
      and "glb_inv ps cls"
      and "glb ps cls"
    shows "glb_inv ps' cls'"
  apply(simp add: glb_inv_def)
proof (intro conjI)
  show "glb_inv9 ps'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv9_def; case_tac "pc ps t"; simp_all; elim exE conjE)
        apply(simp add: globals glb_inv16_def)
        apply(intro allI impI)
        apply(case_tac "t \<noteq> ta")
         apply auto[1]
        apply(subgoal_tac "ntop ps' ta\<in>addr_val ps")
         apply blast
        apply(subgoal_tac "ntop ps' ta \<in> lib_value cls ` lib_writes_on cls (Suc (top ps t))")
         apply (metis gr_implies_not_zero insertE subsetD)
        apply simp
    apply(simp add: lib_read_step_def lib_read_def all_updates_l lib_visible_writes_def)
    apply blast
        done
    next
  show "glb_inv1 ps' cls'"
    using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
  apply(simp add: lib_pop_def pop_inv_def glb_inv1_def; case_tac "pc ps t"; simp_all; elim exE conjE)
  apply(simp_all add: globals)
  apply (metis lib_read_writes_on_diff_var_pres_backwards read_pres_value)
  apply (metis lib_read_writes_on_diff_var_pres_backwards read_pres_value)
  apply(simp add: globals lib_CAS_Rel_step_def, elim exE conjE)
  apply(case_tac "lib_value cls (a, b) = prog_state.top ps t", simp_all)
  apply(simp add: lib_update_r_def all_updates_l lib_value_def lib_writes_on_def)
  apply(intro allI conjI impI)
  apply blast
  apply(simp add: lib_read_def all_updates_l lib_syncing_def)
  apply(intro allI impI conjI)
  apply(simp add: lib_value_def lib_writes_on_def)
  by blast
next
  show "glb_inv3 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def; case_tac "pc ps t"; simp_all; elim exE conjE)
           apply(simp add: globals)
        apply (metis (no_types, lifting) lib_lastWr_def lib_last_in_visible_writes lib_visible_writes_def mem_Collect_eq read_pres_value read_pres_writes_on_diff_var)
         apply(simp_all add: globals)
        apply (simp add: rd_preserves_last)
        by (smt Diff_iff cvd_CAS_R_success_d_obs_post cvd_CAS_R_success_read_val empty_iff failed_CAS_preserves_last insert_iff lib_cvd_exist_last_write lib_d_obs_def lib_d_obs_t_def)
next
  show "glb_inv4 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
        apply(elim conjE)
        apply (simp add: lib_pop_def pop_inv_def glb_inv4_def; case_tac "pc ps t"; simp_all; elim exE conjE)
          apply(simp add: globals)
          apply (simp add: rd_A_preserves_last)
          using rd_preserves_last apply auto[1]
          by (metis succ_CAS_preserves_last)
    next
  show "glb_inv5 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv5_def; case_tac "pc ps t"; simp_all; elim exE conjE)
        apply (metis Diff_subset le_less psubsetI psubset_subset_trans)
        done
  show "glb_inv6 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv6_def; case_tac "pc ps t"; simp_all; elim exE conjE)
        apply(simp add: globals)
        using rd_A_preserves_last apply auto[1]
        using rd_preserves_last apply auto[1]
        by (metis Diff_iff Suc_eq_plus1 glb_inv11_def succ_CAS_preserves_last)
  show "glb_inv7 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
    apply(simp add: lib_pop_def pop_inv_def glb_inv7_def; case_tac "pc ps t"; simp_all; elim exE conjE)
      apply(simp add: globals)
          apply(intro allI impI conjI)
      apply(subgoal_tac "lib_writes_on cls' Top = lib_writes_on cls Top")
  apply(subgoal_tac "lib_releasing cls' (a, b) = lib_releasing cls (a, b)")
        apply (metis (full_types)  assms(1) assms(2) read_pres_value)
       apply(simp add: lib_read_step_def lib_read_def all_updates_l, elim conjE exE)
       apply(simp add:lib_releasing_def)
          apply (metis (full_types) read_pres_writes_on_diff_var)
         apply(simp add: lib_read_step_def lib_read_def all_updates_l, elim conjE exE)
         apply (case_tac "lib_syncing cls (a, b) False", simp_all)
        apply (simp add: lib_syncing_def)
         apply(intro allI conjI impI)
                 apply(simp add:lib_value_def lib_valid_fresh_ts_def lib_visible_writes_def lib_read_step_def lib_read_def all_updates_l lib_writes_on_def lib_releasing_def)
      apply blast
         apply(simp add: lib_CAS_Rel_step_def lib_read_def all_updates_l, elim conjE exE)
  apply(case_tac "lib_value cls (a, b) = prog_state.top ps t", simp_all)
         apply(simp add:lib_value_def lib_valid_fresh_ts_def lib_visible_writes_def lib_read_def all_updates_l lib_writes_on_def lib_releasing_def)
       apply(case_tac "(a, b) \<in> lib_writes_on cls Top")
       apply(simp add:lib_value_def lib_valid_fresh_ts_def lib_visible_writes_def lib_update_r_def all_updates_l lib_writes_on_def lib_releasing_def)
        apply(simp add:lib_value_def lib_valid_fresh_ts_def lib_visible_writes_def lib_update_r_def all_updates_l lib_writes_on_def lib_releasing_def)
        by(simp add:lib_value_def lib_valid_fresh_ts_def lib_visible_writes_def lib_read_step_def lib_read_def all_updates_l lib_writes_on_def lib_releasing_def)
      next
  show "glb_inv8 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
    apply(simp add: lib_pop_def pop_inv_def glb_inv8_def; case_tac "pc ps t"; simp_all; elim exE conjE; simp add: globals)
        using rd_A_preserves_last apply auto[1]
        using rd_preserves_last apply auto[1]
        by (smt Diff_iff cvd_CAS_R_success_read_val empty_iff insert_iff lib_cvd_exist_last_write succ_CAS_preserves_last)
    next
  show "glb_inv10 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv10_def; case_tac "pc ps t"; simp_all; elim exE conjE)
  apply(simp add: globals)
        using rd_A_preserves_last apply auto[1]
         apply (simp add: lastTop_def rd_preserves_last)
        apply(intro conjI impI allI, simp add: globals)
        apply(case_tac "\<not>res ps' t", simp_all)

        using failed_CAS_preserves_last apply metis
        apply(elim conjE)
        apply(subgoal_tac "lib_value cls' (lib_lastWr cls' Top) = ntop ps t")
         apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write succ_CAS_preserves_last)
        apply(subgoal_tac "[lib Top =\<^sub>t (ntop ps t)] cls'")
        apply(simp add: lib_d_obs_def lib_d_obs_t_def)
              using cvd_CAS_R_success_d_obs_post by metis
    next
      show "glb_inv11 ps' cls'"
        using assms
        apply(simp add: glb_inv_def)
        apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv11_def; case_tac "pc ps t"; simp_all; elim exE conjE)
  apply(simp add: globals)
        by (metis Diff_iff)
  show "glb_inv12 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv12_def; case_tac "pc ps t"; simp_all; elim exE conjE)
  apply(simp add: globals pop_inv_def)
  apply(case_tac "pc ps t"; simp add: lib_pop_def globals pop_inv_def)
        by (metis finite_Diff)
    next
      show "glb_inv13 ps' cls'"
        using assms
  apply(simp add: glb_inv_def)
  apply(elim conjE)
      apply(simp add: lib_pop_def pop_inv_def glb_inv12_def; case_tac "pc ps t"; simp_all; elim exE conjE)
  apply(simp add: globals pop_inv_def)
          apply(case_tac "pc ps t"; simp add: lib_pop_def globals pop_inv_def)
        apply (metis lib_read_pres_last rd_A_preserves_values rd_A_preserves_writes_on written_addr_def)
         apply(simp add: globals pop_inv_def)
          apply(simp add: written_addr_def)
       apply(intro allI impI conjI)
         apply (metis (no_types, lifting) image_cong lib_read_writes_on_diff_var_pres_backwards rd_preserves_last read_pres_value)
         apply (metis image_cong lib_read_writes_on_diff_var_pres_backwards read_pres_value)
         apply(simp add: globals pop_inv_def)
  apply(case_tac "res ps' t", simp_all)
     apply(intro allI impI conjI)
    apply(simp add: written_addr_def, elim conjE)
  apply(case_tac " ad \<in> lib_value cls `
             lib_writes_on cls Top")
           apply (metis succ_CAS_preserves_last)
          apply(subgoal_tac "ntop ps t = ad", simp)
           apply(case_tac "ntop ps t = Null")
            apply auto[1]
           apply(intro disjI2)
           apply(subgoal_tac "x = top ps t", simp)
            apply(subgoal_tac "top ps t\<in>pushed_addr ps \<and> top ps t \<noteq> Null")
             apply(subgoal_tac "Suc ad \<noteq> Top")
              apply(subgoal_tac "lib_value cls' (lib_lastWr cls' (Suc ad)) = lib_value cls (lib_lastWr cls (Suc ad))", simp)
        apply (metis)
          apply (metis succ_CAS_preserves_last)

        apply metis
        apply (smt lib_cvd_exist_last_write)
           apply (metis cvd_CAS_R_success_read_val)
  using  CAS_Top_written_addr_post2[where b = "n_val ps t" and cls' = cls' and cls=cls
          and a = "ntop ps t" and t=t]
  apply (smt CAS_Top_written_addr_post2 Diff_empty Diff_insert0 Null_def insert_Diff insert_iff nat_less_le)
          apply (metis CAS_Top_written_addr_post Diff_iff Null_def singletonI written_addr_def)
       apply(intro allI impI conjI)
   apply(simp add: written_addr_def, elim conjE)
  apply (metis failed_CAS_Top_written_addr_post succ_CAS_preserves_last)
   apply(simp add: written_addr_def, elim conjE)
  by (metis (full_types) failed_CAS_Top_written_addr_post)
    next
      show "glb_inv14 ps' cls'"
        using assms
        apply(simp add: glb_inv_def)
        apply(elim conjE)
    apply(simp add: lib_pop_def pop_inv_def glb_inv11_def; case_tac "pc ps t"; simp_all; elim exE conjE)
  apply(simp add: globals)
         apply(intro allI impI conjI)
          apply(simp add: written_addr_def, elim conjE)
          apply (metis lib_read_writes_on_diff_var_pres_backwards rd_A_preserves_last rd_A_preserves_values)
  apply(simp add: globals)
         apply(intro allI impI conjI)
         apply(simp add: written_addr_def, elim conjE)
        apply (metis (no_types, lifting) image_cong lib_read_writes_on_diff_var_pres_backwards rd_preserves_last read_pres_value)
        apply(simp add: globals)
        apply(case_tac "\<not>res ps' t", simp_all)
           apply(intro allI impI conjI)
         apply(simp add: written_addr_def, elim conjE)
        apply (metis failed_CAS_Top_written_addr_post succ_CAS_preserves_last)
           apply(intro allI impI conjI)
        apply(simp add: written_addr_def, elim conjE)
        apply(subgoal_tac "lib_value cls' ` lib_writes_on cls' Top = lib_value cls ` lib_writes_on cls Top \<union> {ntop ps t}", simp_all)
        apply (smt cvd_CAS_R_success_read_val lib_cvd_exist_last_write succ_CAS_preserves_last)
        using success_CAS_Top_written_addr_post
        by (metis Un_commute insert_is_Un)
    next show "glb_inv15 ps'"
    using assms
  apply(simp add: glb_inv_def )
  apply(elim conjE)
     apply (simp add: lib_pop_def)
   apply(case_tac "pc ps t", simp_all)
         apply(simp add: glb_inv15_def)
    apply(simp add: glb_inv15_def)
     apply (simp add: glb_inv15_def)
    done

next
  show "glb_inv16 ps' cls'"
    using assms
  apply(simp add:  globals glb_inv16_def)
      apply (simp add: lib_pop_def)
    apply(elim conjE)
   apply(case_tac "pc ps t", simp_all)
    apply(intro conjI impI allI)
      apply (metis rd_A_preserves_values rd_A_preserves_writes_on written_addr_def)
     apply(intro conjI impI allI)
    apply(subgoal_tac "written_addr cls' = written_addr cls \<and>  lib_value cls' ` lib_writes_on cls' (Suc ad) = lib_value cls ` lib_writes_on cls (Suc ad)", elim conjE, simp)
     apply(intro conjI impI allI)
      apply(simp add: written_addr_def)
    apply (metis image_cong lib_read_writes_on_diff_var_pres_backwards lib_value_read_pres)
    apply (metis image_cong lib_read_writes_on_diff_var_pres_backwards read_pres_value)
    apply(case_tac "\<not>res ps' t", simp_all)
  apply (smt failed_CAS_Rel_preserves_writes_on_diff_var failed_CAS_Top_written_addr_post2 image_subset_iff write_value_CAS_R_diff_var)
    apply(intro allI impI, elim conjE)
    apply(case_tac "ntop ps t = 0")
     apply(subgoal_tac "written_addr cls' = written_addr cls", simp)
    apply(subgoal_tac "lib_value cls' ` lib_writes_on cls' (Suc ad) =
          lib_value cls ` lib_writes_on cls (Suc ad)", simp)
    apply(subgoal_tac "Suc ad \<noteq> Top", simp)

    using CAS_Rel_preserves_writes_on_diff_var write_value_CAS_R_diff_var apply auto[1]
      apply auto[1]
     apply(simp add: written_addr_def)
    apply(subgoal_tac "lib_value cls' ` lib_writes_on cls' Top =
lib_value cls ` lib_writes_on cls Top \<union> {ntop ps t}")
    apply simp
     apply (simp add: success_CAS_Top_written_addr_post)
    apply(subgoal_tac "written_addr cls' = written_addr cls \<union> {ntop ps t}", simp)
     apply(elim disjE)
    apply(subgoal_tac "top ps t \<in> pushed_addr ps")
      apply(simp add: pop_inv_def; elim conjE exE)
     apply(subgoal_tac "lib_value cls' ` lib_writes_on cls' (Suc ad) =
          lib_value cls ` lib_writes_on cls (Suc ad)", simp)
  apply metis

    apply (metis (no_types, lifting) CAS_Rel_preserves_value_diff_var CAS_Rel_preserves_writes_on_diff_var image_cong)
    apply(simp add: pop_inv_def, elim conjE)
    apply (metis (no_types, lifting) cvd_CAS_R_success_read_val lib_cvd_exist_last_write)
        apply(subgoal_tac "lib_value cls' ` lib_writes_on cls' (Suc ad) =
          lib_value cls ` lib_writes_on cls (Suc ad)", simp)
     apply(subgoal_tac "Suc ad \<noteq> Top", simp)
   using CAS_Rel_preserves_writes_on_diff_var write_value_CAS_R_diff_var apply auto[1]
    apply auto[1]
   using success_CAS_Top_written_addr_post2 by auto
qed

lemma cobs_to_failed_cas_pres:
  assumes "wfs ccs"
      and "lib_wfs cls ccs"
      and "cobs_to t ps cls ccs"
      and "cls ccs CAS\<^sup>R[lib(x), False, a, b]\<^sub>t' cls' ccs' "
      and "pushed_addr ps' = pushed_addr ps"
    shows "cobs_to t ps' cls' ccs'"
  using assms
  apply(simp add: cobs_to_def)
  apply safe
     apply(subgoal_tac "\<exists>vl. [libTop = ad1]\<lparr>libad2 =\<^sub>t vl \<rparr> cls")
      apply(elim exE conjE)
      apply(rule_tac x=vl in exI)
  using failed_CASR_pres_c_obs_lib_only apply blast
  apply(subgoal_tac "agt ad1 ad2 ps' cls' = agt ad1 ad2 ps cls")
      apply simp
     apply(simp add: agt_def clss_def nxt_rel_def)
  apply(subgoal_tac "{(a, lib_value cls' (lib_lastWr cls' (Suc a))) |a.
           a \<in> pushed_addr ps} = {(a, lib_value cls (lib_lastWr cls (Suc a))) |a.
           a \<in> pushed_addr ps}")
      apply simp
     apply(subgoal_tac "\<forall> a . a\<in>pushed_addr ps \<longrightarrow> lib_value cls' (lib_lastWr cls' (Suc a)) = lib_value cls (lib_lastWr cls (Suc a))")
      apply auto[1]
     apply safe
  apply (simp add: failed_CAS_preserves_last)
     apply(subgoal_tac "\<exists>vl. [libTop = ad1]\<lparr>libSuc(ad2) =\<^sub>t vl \<rparr> cls")
      apply(elim exE conjE)
     apply(rule_tac x=vl in exI)
  using failed_CASR_pres_c_obs_lib_only apply blast
  apply(subgoal_tac "agt ad1 ad2 ps' cls' = agt ad1 ad2 ps cls")
      apply simp
     apply(simp add: agt_def clss_def nxt_rel_def)
  apply(subgoal_tac "{(a, lib_value cls' (lib_lastWr cls' (Suc a))) |a.
           a \<in> pushed_addr ps} = {(a, lib_value cls (lib_lastWr cls (Suc a))) |a.
           a \<in> pushed_addr ps}")
      apply simp
     apply(subgoal_tac "\<forall> a . a\<in>pushed_addr ps \<longrightarrow> lib_value cls' (lib_lastWr cls' (Suc a)) = lib_value cls (lib_lastWr cls (Suc a))")
     apply auto[1]
  apply (simp add: failed_CAS_preserves_last)
  using failed_CASR_pres_c_obs_lib_only apply blast
  using failed_CASR_pres_c_obs_lib_only by blast

lemma pop_inv:
  assumes "wfs ccs"
      and "lib_wfs cls ccs"
      and "lib_pop t v ps cls ccs ps' cls' ccs'"
      and "pop_inv t l (pc ps t) cls ccs  ps"
      and "glb_inv ps cls"
    shows "pop_inv t l (pc ps' t) cls' ccs'  ps'"
  proof(cases "pc ps t")
    case L1
    then show ?thesis
      using assms
      apply(case_tac "pc ps' t"; simp)
      apply(simp add: lib_pop_def pop_inv_def; elim exE conjE)
           apply(intro conjI)
             apply(simp add: cobs_to_def)
      apply (metis agt_pushed_same2rd_before_state lib_c_obs_lib_only_pres_read_var)
      using lib_read_cvd_pres apply blast
      apply auto[1]
      apply(simp add: lib_pop_def pop_inv_def; elim exE conjE; intro conjI)
              apply(simp add: cobs_to_def)
      apply (metis agt_pushed_same2rd_before_state lib_c_obs_lib_only_pres_read_var)
               apply(simp add: dobs_to_def)

               apply(intro allI impI)
               apply(elim disjE conjE)
                apply(subgoal_tac "agt (prog_state.top ps' t) ad ps cls")
                 apply(case_tac "ad = top ps' t")
      apply(simp add:  agt_def to_p4_def)
      apply (meson cobs_to_def lib_read_transfer)
                 apply(subgoal_tac "top ps' t\<in>pushed_addr ps")
                  apply(subgoal_tac "(\<exists>vl. [libTop = (top ps' t)]\<lparr>lib(ad) =\<^sub>t vl \<rparr> cls)
\<and> (\<exists>vl. [libTop = (top ps' t)]\<lparr>libSuc(ad) =\<^sub>t vl \<rparr> cls)")
      apply(elim conjE, intro conjI)
      using lib_read_transfer apply blast
      using lib_read_transfer apply blast
                  apply (simp add: cobs_to_def)
  apply(simp add: agt_def clss_def nxt_rel_def trancl_def)
  using converse_tranclpE
      apply (metis (no_types, lifting))
      using agt_pushed_same2rd_before_state apply blast

               apply(subgoal_tac "(\<exists>vl. [libTop = (ad)]\<lparr>lib(ad) =\<^sub>t vl \<rparr> cls) \<and>
                      (\<exists>vl. [libTop = (ad)]\<lparr>libSuc(ad) =\<^sub>t vl \<rparr> cls)")
      using lib_read_transfer apply blast
      apply (simp add: cobs_to_def)
            apply auto[1]
      using lib_read_cvd_pres apply blast
            apply (meson cobs_to_def lib_read_transfer)
           apply(simp add: cobs_to_def)
           apply(intro conjI impI)
   apply(subgoal_tac "(\<exists>vl. [libTop = (top ps' t)]\<lparr>libSuc
      (top ps' t) =\<^sub>t vl \<rparr> cls)", elim exE conjE)
      apply(rule_tac x="vl" in exI)
        apply(intro conjI)
             apply (simp add: lib_read_transfer)
            apply(subgoal_tac "[libSuc (prog_state.top ps' t) =\<^sub>t vl] cls'")
             apply(simp add: lib_d_obs_t_def lib_d_obs_def, elim conjE)
      apply(subgoal_tac "lib_value cls'
        (lib_lastWr cls' (Suc (prog_state.top ps' t))) =
       lib_value cls
        (lib_lastWr cls (Suc (prog_state.top ps' t)))")
      apply(subgoal_tac "top ps' t\<in>written_addr cls")
      apply(simp add: globals)
               apply blast
      apply(simp add: written_addr_def)
      using read_value_in_written apply auto[1]
      apply (simp add: rd_A_preserves_last)
      apply (simp add: lib_read_transfer)
      apply blast
      apply(simp add: written_addr_def)
      using rd_A_preserves_values rd_A_preserves_writes_on read_value_in_written apply auto[1]
      apply(case_tac "pc ps' t"; simp)
         apply(simp add: globals lib_pop_def pop_inv_def; elim exE conjE)
         apply (metis PC.distinct(11) PC.distinct(3) fun_upd_same neq0_conv)
            apply(simp add: globals lib_pop_def pop_inv_def; elim exE conjE)
   apply (metis PC.distinct(13) PC.distinct(5) fun_upd_same neq0_conv)
            apply(simp add: globals lib_pop_def pop_inv_def; elim exE conjE)
       apply auto[1]
            apply(simp add: globals lib_pop_def pop_inv_def; elim exE conjE)
      by auto
  next
    case L2
    then show ?thesis
      using assms
      apply(simp add: lib_pop_def pop_inv_def; elim exE conjE)
      apply(case_tac "pc ps' t"; simp)
      apply(intro conjI impI)
             apply (simp add: cobs_to_read_pres)
            apply (simp add: dobs_to_def)
            apply (metis agt_pushed_same2rd_relax_before_state lib_d_obs_pres_read)
      apply(case_tac "top ps t \<in> pushed_addr ps ", simp_all)
      using read_lib_d_obs apply blast
           apply(subgoal_tac "glb_inv16 ps cls" , simp add: glb_inv16_def)
            apply(subgoal_tac "ntop ps' t \<in> lib_value cls`(lib_writes_on cls (Suc (prog_state.top ps t)))")
      apply blast
  apply(simp add: lib_read_step_def lib_read_def all_updates_l lib_visible_writes_def)
  apply blast
        apply(simp add: globals)
      using lib_read_cvd_pres apply blast
      using lib_d_obs_pres_read apply blast
       apply (metis lib_d_obs_def lib_d_obs_t_def rd_preserves_last read_lib_d_obs)
       apply(simp add: written_addr_def)

       apply (metis image_cong lib_read_writes_on_diff_var_pres_backwards read_pres_value)
      using lib_d_obs_pres_read apply blast
      done
  next
    case L3
    then show ?thesis
      using assms
      apply(case_tac "\<not> res ps' t")
      apply(simp add: lib_pop_def pop_inv_def; elim exE conjE)
      apply (metis cobs_to_failed_cas_pres cvd_CAS_R_cvd failed_CAS_Top_written_addr_post2)
      apply(subgoal_tac "top ps t \<in> pushed_addr ps")
      apply(simp add: lib_pop_def pop_inv_def; elim exE conjE; intro conjI impI)

          apply (meson cvd_CAS_R_cvd)
         apply (metis cvd_CAS_R_success_d_obs_post d_obs_post_CAS_R_diff_var_post)
        apply(simp add: written_addr_def)
     using success_CAS_Top_written_addr_post apply auto[1]
      defer
           apply(simp add: lib_pop_def pop_inv_def globals; elim exE conjE)
     apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write)
(*
     apply(simp add: cobs_to_def)
     apply(intro conjI impI allI)
     apply(elim disjE conjE)
           apply(subgoal_tac "ad1 \<notin>{Top, Null} \<and> ad2 \<notin>{Top, Null}")
    apply(subgoal_tac "agt ad1 ad2 ps cls")
    apply(subgoal_tac "\<exists>vl. [libTop = ad1]\<lparr>libad2 =\<^sub>t vl \<rparr> cls")
            apply (metis Null_def insertCI successful_CAS_lib_c_obs_lib_diff_value_press)
     apply blast
      apply (simp add: agt_pop_successful_cas_before)
    apply(simp add: globals)
         apply (metis gr_zeroI subsetD)
            apply(subgoal_tac "ad1 \<notin>{Top, Null} \<and> ad2 \<notin>{Top, Null}")
      apply(subgoal_tac "\<exists>vl. [libTop = ad1]\<lparr>libad2 =\<^sub>t vl \<rparr> cls")
   apply (metis Null_def insertCI successful_CAS_lib_c_obs_lib_diff_value_press)
            apply(simp add: globals)
            apply(simp add: globals)
        apply (metis gr_zeroI subsetD)
       apply(subgoal_tac "ntop ps t \<in> pushed_addr ps")
        apply(case_tac "ad1 = ntop ps t")
         apply(subgoal_tac "agt ad1 ad2 ps cls")
          apply(subgoal_tac "\<exists>vl. [libTop = ad1]\<lparr>libad2 =\<^sub>t vl \<rparr> cls")
     apply(elim exE)
sledgehammer
     defer
     apply blast
     oops
        defer
     apply(simp add: globals)
     apply (metis gr_zeroI subsetD)
*)
     done
  next
    case L4
    then show ?thesis
    using assms
    by(simp add: lib_pop_def pop_inv_def; elim exE conjE)
  next
    case L5
    then show ?thesis
    using assms
    by(simp add: lib_pop_def pop_inv_def; elim exE conjE)
  next
    case L6
    then show ?thesis
      using assms
      by(simp add: lib_pop_def pop_inv_def; elim exE conjE)
  qed

lemma "cls ccs[n \<leftarrow> lib(x)]\<^sub>t cls' ccs' \<Longrightarrow> n\<in> lib_value cls `(lib_writes_on cls (x))"
  apply(simp add: lib_read_step_def lib_read_def all_updates_l lib_visible_writes_def)
  apply blast
  done

lemma "agt ad1 ad ps cls \<Longrightarrow>
       ad1 \<in> pushed_addr ps"
  apply(simp add: agt_def clss_def nxt_rel_def trancl_def)
  using converse_tranclpE apply fastforce
  done

lemma dd:
  assumes "(a,b)\<in>f\<^sup>+"
      and "(t,d)\<in>f"
      and "(a,t)\<notin>f\<^sup>+"
      and "a \<noteq> t"
      and "\<forall> e . (e,e)\<notin>f\<^sup>+"
      and "\<forall> e. (a,e)\<in>f\<^sup>+ \<and> (e,b)\<in>f\<^sup>+ \<longrightarrow> e \<noteq> t"
      and "f' = f - {(t,d)}"
    shows "(a,b)\<in>f'\<^sup>+"
  using assms
  apply(induction a b rule: trancl.induct)
   apply simp
   apply auto[1]
  by (metis Pair_inject insertE insert_Diff trancl.trancl_into_trancl)

lemma pop_gloabals_total_order:
  assumes "wfs ccs"
      and "lib_wfs cls ccs"
      and "lib_pop t v ps cls ccs ps' cls' ccs'"
      and "pop_inv t l (pc ps t) cls ccs  ps"
      and "glb_inv ps cls"
      and "glb ps cls"
      and "to ps cls"
    shows "to ps' cls'"
  apply(simp add: to_def)
  proof(intro conjI)
    show "to_p1 ps' cls'"
    proof(cases "pc ps t")
      case L1
      then show ?thesis
        using assms
        apply(simp add: globals to_p4_def to_p3_def lib_pop_def pop_inv)
        apply(intro allI impI)
        by (metis agt_pushed_same2rd)
    next
      case L2
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv)
        apply(intro allI impI, elim conjE)
        by (metis agt_pushed_same2rd_relax)
    next
      case L3
      then show ?thesis
      using assms
      apply(simp add: globals lib_pop_def pop_inv to_p4_def)
      apply(intro allI impI conjI, elim conjE)
      apply(case_tac "\<not>res ps' t", simp_all)
       apply (simp add: agt_def failed_cas_preserves_clss)
      apply(subgoal_tac "nxt_rel ps' cls' = nxt_rel ps cls - {(top ps t, ntop ps t)}")
       defer
       apply(simp add: nxt_rel_def)
      apply(subgoal_tac "\<forall> e . e\<in>pushed_addr ps \<longrightarrow> lib_value cls' (lib_lastWr cls' (Suc e)) = lib_value cls (lib_lastWr cls (Suc e))")
      apply safe
      apply simp
       apply simp
             apply simp
      apply(subgoal_tac "pushed_addr ps = {}")
             apply simp
      apply(simp add: to_simps)
       apply (metis a_not_in_pushed_clss agt_def lastTop_def)
       apply simp
      apply(simp add:pop_inv_def to_simps)
       apply (metis succ_CAS_preserves_last)
       apply (metis succ_CAS_preserves_last)
      apply(simp add:pop_inv_def to_simps)
       apply (metis a_not_in_pushed_clss agt_def lastTop_def)
      apply(case_tac "agt a b ps cls")
      apply(subgoal_tac "\<not>agt a (top ps t) ps cls ")
       apply(subgoal_tac "\<forall> e. (a,e)\<in>(nxt_rel ps cls)\<^sup>+ \<and> (e,b)\<in>(nxt_rel ps cls)\<^sup>+ \<longrightarrow> e \<noteq> (top ps t)")
        apply(simp add: agt_def clss_def)
         apply (metis (no_types, lifting) dd Diff_empty Diff_insert0 a_not_in_pushed_nxt_rel converse_tranclE)
        apply (metis agt_def clss_def)
      apply(simp add: pop_inv_def to_simps globals )
       apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write no_nxt_no_agt)
      apply(subgoal_tac "agt  b a ps cls")
      apply(subgoal_tac "agt  b a ps' cls'")
        apply blast

      apply(subgoal_tac "\<not>agt b (top ps t) ps cls ")
       apply(subgoal_tac "\<forall> e. (b,e)\<in>(nxt_rel ps cls)\<^sup>+ \<and> (e,a)\<in>(nxt_rel ps cls)\<^sup>+ \<longrightarrow> e \<noteq> (top ps t)")
        apply(simp add: agt_def clss_def)
         apply (metis (no_types, lifting) dd Diff_empty Diff_insert0 a_not_in_pushed_nxt_rel converse_tranclE)
        apply (metis agt_def clss_def)
       apply(simp add: pop_inv_def to_simps globals )
      apply (metis assms(2) cvd_CAS_R_success_read_val lib_cvd_exist_last_write no_nxt_no_agt)
      by blast
    next
      case L4
      then show ?thesis
      using assms
      by(simp add: globals lib_pop_def pop_inv)
    next
      case L5
      then show ?thesis
      using assms
      by(simp add: globals lib_pop_def pop_inv)
    next
      case L6
      then show ?thesis
        using assms
      by(simp add: globals lib_pop_def pop_inv)
    qed
    next  show "to_p2 ps' cls'"
    proof(cases "pc ps t")
      case L1
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv)
        by (metis (no_types, lifting) agt_pushed_same2rd lastTop_def rd_A_preserves_last to_p2_def)

    next
      case L2
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv)
        by (metis (no_types, lifting) agt_pushed_same2rd_relax lastTop_def rd_preserves_last to_p2_def)
    next
      case L3
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv to_simps)
        apply(intro conjI impI allI)
        apply(case_tac "\<not> res ps' t", simp_all)
         apply (metis (no_types, lifting) agt_def failed_CAS_preserves_last failed_cas_preserves_clss)
      apply(subgoal_tac "nxt_rel ps' cls' = nxt_rel ps cls - {(top ps t, ntop ps t)}")
       defer
       apply(simp add: nxt_rel_def)
      apply(subgoal_tac "\<forall> e . e\<in>pushed_addr ps \<longrightarrow> lib_value cls' (lib_lastWr cls' (Suc e)) = lib_value cls (lib_lastWr cls (Suc e))")
      apply safe
      apply simp
       apply simp
             apply simp
      apply(subgoal_tac "pushed_addr ps = {}")
             apply simp
      apply(simp add: to_simps)
       apply (metis a_not_in_pushed_clss agt_def)
       apply simp
      apply(simp add:pop_inv_def to_simps)
       apply (metis succ_CAS_preserves_last)
       apply (metis succ_CAS_preserves_last)
      apply(simp add:pop_inv_def to_simps)
       apply (metis a_not_in_pushed_clss agt_def)

        apply(subgoal_tac "lib_value cls' (lib_lastWr cls' Top) = ntop ps t")
         defer
        apply(simp add: pop_inv_def)
         apply (metis cvd_CAS_R_success_read_val succ_CAS_last_value)
        apply simp
        apply(case_tac "ntop ps t = Null")
        apply(subgoal_tac "pushed_addr ps = {top ps t}")
          apply simp
         apply(simp add:pop_inv_def )
        apply(subgoal_tac "lastTop cls \<noteq> Null \<and>
  lastVal cls (lastTop cls + 1) = Null \<and> to ps cls \<and> glb_inv ps cls \<and> glb ps cls")
        using l5[where cls=cls  and ps=ps]
        apply (simp add: glb_inv_def)
              apply (metis cvd_CAS_R_success_read_val empty_iff lastTop_def lib_cvd_exist_last_write subset_singleton_iff)
          apply(simp add:pop_inv_def to_simps globals)
         apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write)
        apply(simp add: agt_def clss_def)
        apply(subgoal_tac "agt (ntop ps t) a ps cls")
        apply(subgoal_tac " \<forall>e. (ntop ps t, e) \<in> (nxt_rel ps cls)\<^sup>+ \<and>
      (e, a) \<in> (nxt_rel ps cls)\<^sup>+ \<longrightarrow>
      e \<noteq> prog_state.top ps t")
          apply(subgoal_tac "(ntop ps t, a) \<in> (nxt_rel ps cls)\<^sup>+ \<and>
  (top ps t, ntop ps t) \<in> nxt_rel ps cls \<and> (ntop ps t, prog_state.top ps t) \<notin> (nxt_rel ps cls)\<^sup>+")
        apply(elim conjE, simp add: pop_inv_def, elim conjE exE)
        using  dd[where a = "ntop ps t" and t = "top ps t" and f = "nxt_rel ps cls"  and f' = "nxt_rel ps' cls'"]
           apply (metis a_not_in_pushed_nxt_rel converse_tranclE)
          apply(intro conjI)
            apply (simp add: agt_def clss_def)
        apply(simp add: agt_def clss_def to_simps globals pop_inv_def, elim conjE exE)
        apply (metis Diff_empty Diff_insert0 Diff_insert_absorb a_not_in_pushed_nxt_rel converse_tranclE cvd_CAS_R_success_read_val lib_cvd_exist_last_write mk_disjoint_insert)
        apply(simp add: agt_def clss_def to_simps globals pop_inv_def, elim conjE exE)
          apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write)
        apply(simp add: agt_def clss_def to_simps globals pop_inv_def, elim conjE exE)
        apply(intro allI impI)
        apply (smt cvd_CAS_R_success_read_val lib_cvd_exist_last_write trancl_trans)
        apply(simp add: agt_def clss_def to_simps globals pop_inv_def, elim conjE exE)
        apply(subgoal_tac " (top ps t, a) \<in> (nxt_rel ps cls)\<^sup>+ \<and>  (top ps t, ntop ps t) \<in> (nxt_rel ps cls)")
        using nothing_between_a_nxt[where a = "top ps t" and cls=cls  and ps=ps]
        apply (simp add: globals to_simps agt_def clss_def)
        apply (metis a_not_in_pushed_nxt_rel)
        by (smt Diff_empty Diff_insert0 Diff_insert_absorb a_not_in_pushed_nxt_rel converse_tranclE cvd_CAS_R_success_read_val lib_cvd_exist_last_write mk_disjoint_insert)
    next
      case L4
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def pop_inv)
    next
      case L5
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def pop_inv)
    next
      case L6
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def pop_inv)
    qed
  next  show "to_p3 ps' cls'"
    proof(cases "pc ps t")
      case L1
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv)
        by (metis agt_pushed_same2rd to_p3_def)
    next
      case L2
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv)
        by (metis agt_pushed_same2rd_relax to_p3_def)
    next
      case L3
      then show ?thesis
        using assms
                apply(simp add: globals lib_pop_def pop_inv to_simps)
        apply(case_tac "\<not> res ps' t", simp_all)
         apply (metis (no_types, lifting) agt_def failed_cas_preserves_clss)
      apply(subgoal_tac "nxt_rel ps' cls' = nxt_rel ps cls - {(top ps t, ntop ps t)}")
       defer
       apply(simp add: nxt_rel_def)
      apply(subgoal_tac "\<forall> e . e\<in>pushed_addr ps \<longrightarrow> lib_value cls' (lib_lastWr cls' (Suc e)) = lib_value cls (lib_lastWr cls (Suc e))")
      apply safe
      apply simp
       apply simp
             apply simp
      apply(subgoal_tac "pushed_addr ps = {}")
             apply simp
      apply(simp add: to_simps)
       apply (metis a_not_in_pushed_clss agt_def)
       apply simp
      apply(simp add:pop_inv_def to_simps)
       apply (metis succ_CAS_preserves_last)
       apply (metis succ_CAS_preserves_last)
      apply(simp add:pop_inv_def to_simps)
         apply (metis a_not_in_pushed_clss agt_def)
        apply(case_tac "ntop ps t = Null")
        apply(subgoal_tac "pushed_addr ps = {top ps t}")
          apply simp
         apply(simp add:pop_inv_def )
        apply(subgoal_tac "lastTop cls \<noteq> Null \<and>
  lastVal cls (lastTop cls + 1) = Null \<and> to ps cls \<and> glb_inv ps cls \<and> glb ps cls")
        using l5[where cls=cls  and ps=ps]
        apply (simp add: glb_inv_def)
              apply (metis cvd_CAS_R_success_read_val empty_iff lastTop_def lib_cvd_exist_last_write subset_singleton_iff)
          apply(simp add:pop_inv_def to_simps globals)
         apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write)
        apply(subgoal_tac "agt a 0 ps cls") defer
         apply auto[1]
        apply (simp add: pop_inv_def, elim conjE exE)
        apply(simp add: agt_def clss_def)
        apply(subgoal_tac "(a, 0) \<in> (nxt_rel ps cls)\<^sup>+")
         apply(subgoal_tac "(a, prog_state.top ps t) \<notin> (nxt_rel ps cls)\<^sup>+")
          apply(subgoal_tac "a \<noteq> prog_state.top ps t")
        apply(subgoal_tac "\<forall>e. (a, e) \<in> (nxt_rel ps cls)\<^sup>+ \<and>
      (e, 0) \<in> (nxt_rel ps cls)\<^sup>+ \<longrightarrow>
      e \<noteq> prog_state.top ps t")
        using  dd[where  t = "top ps t" and f = "nxt_rel ps cls"
                  and f' = "nxt_rel ps' cls'" and b=0 and d="ntop ps t"]
      apply (metis Diff_empty Diff_insert0 a_not_in_pushed_nxt_rel converse_tranclE)
      apply blast
        apply blast
      apply (metis cvd_CAS_R_success_read_val lib_cvd_exist_last_write trancl_trans)
      by meson
    next
      case L4
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def pop_inv)
    next
      case L5
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def pop_inv)
    next
      case L6
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def pop_inv)
    qed
  next  show "to_p4 ps' cls'"
    proof(cases "pc ps t")
      case L1
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv to_p4_def)
        by (metis (full_types) agt_def agt_pushed_same2rd_before_state)
    next
      case L2
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv to_p4_def)
        by (meson agt_def agt_pushed_same2rd_relax_before_state)
    next
      case L3
      then show ?thesis
        using assms
        apply(simp add: globals lib_pop_def pop_inv to_p4_def)
        apply(case_tac "\<not> res ps' t", simp_all)
         apply (metis failed_cas_preserves_clss)
   apply(subgoal_tac "nxt_rel ps' cls' = nxt_rel ps cls - {(top ps t, ntop ps t)}")
       defer
       apply(simp add: nxt_rel_def)
      apply(subgoal_tac "\<forall> e . e\<in>pushed_addr ps \<longrightarrow> lib_value cls' (lib_lastWr cls' (Suc e)) = lib_value cls (lib_lastWr cls (Suc e))")
      apply safe
      apply simp
       apply simp
             apply simp
      apply(subgoal_tac "pushed_addr ps = {}")
             apply simp
              apply(simp add: to_simps)
        apply (metis nat_less_le no_nxt_no_agt)
       apply simp
      apply(simp add:pop_inv_def to_simps)
       apply (metis succ_CAS_preserves_last)
       apply (metis succ_CAS_preserves_last)
      apply(simp add:pop_inv_def to_simps)
        apply (metis nat_less_le no_nxt_no_agt)
        apply(simp add: clss_def)
             by (meson Diff_subset trancl_mono)
    next
      case L4
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def )
    next
      case L5
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def )
    next
      case L6
      then show ?thesis
        using assms
        by(simp add: globals lib_pop_def )
    qed
  qed

end