           (*-------------------------------------------*
            |        CSP-Prover on Isabelle2004         |
            |               February 2005               |
            |                   June 2005  (modified)   |
            |                 August 2005  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2005         |
            |                October 2005  (modified)   |
            |                  March 2007  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory CSP_T_law_fp
imports CSP_T_law_ufp
begin

(*****************************************************************

         1. cpo fixed point theory in CSP-Prover
         2.
         3.
         4.

 *****************************************************************)

(*  The following simplification rules are deleted in this theory file *)
(*  because they unexpectly rewrite UnionT and InterT.                 *)
(*                  Union (B ` A) = (UN x:A. B x)                      *)
(*                  Inter (B ` A) = (INT x:A. B x)                     *)

(*
declare Union_image_eq [simp del]
declare Inter_image_eq [simp del]
*)
declare Sup_image_eq [simp del]
declare Inf_image_eq [simp del]

(*=======================================================*
 |                                                       |
 |                        CPO                            |
 |                                                       |
 *=======================================================*)

(*-------------*
 |  existency  |
 *-------------*)

lemma semT_hasLFP_cpo:
 "Pf = PNfun ==> [[Pf]]Tfun hasLFP"
apply (rule Tarski_thm_EX)
apply (rule continuous_semTfun)
done

lemma semT_LFP_cpo:
  "[| Pf = PNfun ;
      FPmode = CPOmode | FPmode = MIXmode |]
  ==> [[$p]]T = LFP [[Pf]]Tfun p"
apply (simp add: semT_def semTf_def)
apply (simp add: traces_iff)
apply (simp add: MT_def)
apply (simp add: semTfix_def)
apply (force)
done

lemma semT_LFP_fun_cpo:
  "[| Pf = PNfun ;
      FPmode = CPOmode | FPmode = MIXmode |]
  ==> (%p. [[$p]]T) = LFP [[Pf]]Tfun"
apply (simp (no_asm) add: fun_eq_iff)
apply (simp add: semT_LFP_cpo)
done

(*---------*
 |    MT   |
 *---------*)

lemma MT_fixed_point_cpo:
      "[| (Pf::'p=>('p,'a) proc) = PNfun; FPmode = CPOmode | FPmode = MIXmode |]
        ==> [[Pf]]Tfun (MT::'p => 'a domT) = (MT::'p => 'a domT)"
apply (simp add: MT_def)
apply (simp add: semTfix_def)
apply (erule disjE)
apply (simp_all)
apply (rule LFP_fp)
apply (simp add: semT_hasLFP_cpo)
apply (rule LFP_fp)
apply (simp add: semT_hasLFP_cpo)
done

(*-------------*
 |  greatest   |
 *-------------*)

lemma ALL_cspT_greatest_cpo:
  "[| Pf = PNfun ;
       FPmode = CPOmode ;
       ALL p. (Pf p) << f =T f p |] ==> ALL p. f p <=T $p"
apply (simp add: eqT_def refT_def)
apply (fold semT_def)
apply (simp add: fun_eq_iff[THEN sym])
apply (fold order_prod_def)
apply (insert semT_LFP_fun_cpo[of "Pf"])
apply (simp)

apply (rule LFP_least)
apply (simp add: semT_hasLFP_cpo)

apply (simp add: semT_def semTfun_def semTf_def)
apply (simp add: traces_subst)
done

lemma cspT_greatest_cpo:
  "[| Pf = PNfun ;
       FPmode = CPOmode ;
       ALL p. (Pf p) << f =T f p |] ==> f p <=T $p"
by (simp add: ALL_cspT_greatest_cpo)

(*-------------------------------------------------------*
 |                                                       |
 |           Fixpoint unwind (CSP-Prover rule)           |
 |                                                       |
 *-------------------------------------------------------*)

lemma ALL_cspT_unwind_cpo:
   "[| Pf = PNfun ;
       FPmode = CPOmode | FPmode = MIXmode |]
     ==> ALL p. ($p =T Pf p)"
apply (simp add: cspT_semantics)
apply (simp add: traces_iff)
apply (simp add: MT_def)
apply (simp add: semTfix_def)
apply (simp add: fun_eq_iff[THEN sym])
apply (simp add: traces_semTfun)
apply (simp add: LFP_fp semT_hasLFP_cpo)
apply (force)
done

(*  csp law  *)

lemma cspT_unwind_cpo:
   "[| Pf = PNfun ;
       FPmode = CPOmode | FPmode = MIXmode |]
     ==> $p =T Pf p"
by (simp add: ALL_cspT_unwind_cpo)

(*-------------------------------------------------------*
 |                                                       |
 |    fixed point inducntion (CSP-Prover intro rule)     |
 |                                                       |
 *-------------------------------------------------------*)

(*** right ***)

lemma cspT_fp_induct_cpo_ref_right_ALL:
   "[| Pf = PNfun ;
       FPmode = CPOmode | FPmode = MIXmode ;
       Q <=T f p;
       ALL p. f p <=T (Pf p)<<f |]
    ==> Q <=T $p"
apply (simp add: refT_semT)
apply (insert cpo_fixpoint_induction_rev
       [of "[[Pf]]Tfun" "(%p. [[f p]]T)"])
apply (simp add: LFP_fp semT_hasLFP_cpo)
apply (simp add: fold_order_prod_def)
apply (simp add: semT_subst_semTfun)

apply (simp add: continuous_semTfun)
apply (simp add: order_prod_def)
apply (drule_tac x="p" in spec)+

apply (simp add: semT_LFP_cpo)
done

(*  csp law  *)

lemma cspT_fp_induct_cpo_ref_right:
   "[| Pf = PNfun ;
       FPmode = CPOmode | FPmode = MIXmode ;
       Q <=T f p;
       !! p. f p <=T (Pf p)<<f |]
    ==> Q <=T $p"
by (simp add: cspT_fp_induct_cpo_ref_right_ALL)

lemmas cspT_fp_induct_cpo_right
     = cspT_fp_induct_cpo_ref_right

(*=======================================================*
 |                                                       |
 |                    LFP <--> UFP                       |
 |                                                       |
 |                       MIXmode                         |
 |                                                       |
 *=======================================================*)

lemma semT_guarded_LFP_UFP:
  "[| Pf = PNfun ; guardedfun Pf |]
   ==> LFP [[Pf]]Tfun = UFP [[Pf]]Tfun"
by (simp add: semT_hasUFP_cms hasUFP_LFP_UFP)

(*----------- refinement -----------*)

(*** left ***)

lemma cspT_fp_induct_mix_ref_left_ALL:
   "[| Pf = PNfun ;
       guardedfun Pf ;
       FPmode = MIXmode ;
       f p <=T Q ;
       ALL p. (Pf p)<<f <=T f p |]
    ==> $p <=T Q"
apply (simp add: refT_semT)
apply (insert cms_fixpoint_induction_ref
       [of "[[Pf]]Tfun" "(%p. [[f p]]T)" "UFP [[Pf]]Tfun"])
apply (simp add: semT_guarded_LFP_UFP[THEN sym])
apply (simp add: LFP_fp semT_hasLFP_cpo)

apply (simp add: fold_order_prod_def)
apply (simp add: semT_subst_semTfun)
apply (simp add: mono_semTfun)

apply (simp add: contra_alpha_to_contst contraction_alpha_semTfun)
apply (simp add: to_distance_rs)
apply (simp add: order_prod_def)
apply (drule_tac x="p" in spec)+
apply (simp add: semT_LFP_cpo)
done

(*  csp law  *)

lemma cspT_fp_induct_mix_ref_left:
   "[| Pf = PNfun ;
       guardedfun Pf ;
       FPmode = MIXmode ;
       f p <=T Q ;
       !! p. (Pf p)<<f <=T f p |]
    ==> $p <=T Q"
by (simp add: cspT_fp_induct_mix_ref_left_ALL)

(*----------- equality -----------*)

(*** left ***)

lemma cspT_fp_induct_mix_eq_left_ALL:
   "[| Pf = PNfun ;
       guardedfun Pf ;
       FPmode = MIXmode ;
       f p =T Q ;
       ALL p. (Pf p)<<f =T f p |]
    ==> $p =T Q"
apply (simp add: eqT_semT)
apply (simp add: fun_eq_iff[THEN sym])
apply (simp add: semT_subst_semTfun)
apply (insert semT_LFP_fun_cpo[of Pf])
apply (simp add: semT_guarded_LFP_UFP)
apply (subgoal_tac "(%p. [[$p]]T) = (%p. [[f p]]T)")
apply (simp add: fun_eq_iff)

apply (rule hasUFP_unique_solution[of "[[Pf]]Tfun"])
apply (simp_all add: semT_hasUFP_cms)
apply (simp add: UFP_fp semT_hasUFP_cms)
done

(*  csp law  *)

lemma cspT_fp_induct_mix_eq_left:
   "[| Pf = PNfun ;
       guardedfun Pf ;
       FPmode = MIXmode ;
       f p =T Q;
       !! p. (Pf p)<<f =T f p |]
    ==> $p =T Q"
by (simp add: cspT_fp_induct_mix_eq_left_ALL)

lemma cspT_fp_induct_mix_eq_right:
   "[| Pf = PNfun ;
       guardedfun Pf ;
       FPmode = MIXmode ;
       Q =T f p;
       !! p. f p =T (Pf p)<<f |]
    ==> Q =T $p"
apply (rule cspT_sym)
apply (rule cspT_fp_induct_mix_eq_left[of Pf f p Q])
apply (simp_all)
apply (rule cspT_sym)
apply (simp)
apply (rule cspT_sym)
apply (simp)
done

lemmas cspT_fp_induct_mix_left
     = cspT_fp_induct_mix_ref_left cspT_fp_induct_mix_eq_left

lemmas cspT_fp_induct_mix_right
     = cspT_fp_induct_cpo_ref_right cspT_fp_induct_mix_eq_right

(*=======================================================*
 |                                                       |
 |            mixing CPOmode and CMSmode                 |
 |                                                       |
 *=======================================================*)

lemma cspT_unwind:
   "[| Pf = PNfun ;
       FPmode = CPOmode
     | FPmode = CMSmode & guardedfun Pf
     | FPmode = MIXmode |]
     ==> $p =T Pf p"
apply (erule disjE)
apply (simp add: cspT_unwind_cpo)
apply (erule disjE)
apply (simp add: cspT_unwind_cms)
apply (simp add: cspT_unwind_cpo)
done

lemma cspT_fp_induct_ref_right:
   "[| Pf = PNfun ;
       FPmode = CPOmode
     | FPmode = CMSmode & guardedfun Pf
     | FPmode = MIXmode ;
       Q <=T f p;
       !! p. f p <=T (Pf p)<<f |]
    ==> Q <=T $p"
apply (erule disjE)
apply (simp add: cspT_fp_induct_cpo_right)
apply (erule disjE)
apply (simp add: cspT_fp_induct_cms_right)
apply (simp add: cspT_fp_induct_cpo_right)
done

lemma cspT_fp_induct_ref_left:
   "[| Pf = PNfun ;
       FPmode = CMSmode
     | FPmode = MIXmode ;
       guardedfun Pf ;
       f p <=T Q ;
       !! p. (Pf p)<<f <=T f p |]
    ==> $p <=T Q"
apply (erule disjE)
apply (simp add: cspT_fp_induct_cms_left)
apply (simp add: cspT_fp_induct_mix_left)
done

lemma cspT_fp_induct_eq_left:
   "[| Pf = PNfun ;
       FPmode = CMSmode
     | FPmode = MIXmode ;
       guardedfun Pf ;
       f p =T Q ;
       !! p. (Pf p)<<f =T f p |]
    ==> $p =T Q"
apply (erule disjE)
apply (simp add: cspT_fp_induct_cms_left)
apply (simp add: cspT_fp_induct_mix_left)
done

lemma cspT_fp_induct_eq_right:
   "[| Pf = PNfun ;
       FPmode = CMSmode
     | FPmode = MIXmode ;
       guardedfun Pf ;
       Q =T f p;
       !! p. f p =T (Pf p)<<f |]
    ==> Q =T $p"
apply (erule disjE)
apply (simp add: cspT_fp_induct_cms_right)
apply (simp add: cspT_fp_induct_mix_right)
done

(*** cpo and cms ***)

lemmas cspT_fp_induct_right = cspT_fp_induct_ref_right cspT_fp_induct_eq_right
lemmas cspT_fp_induct_left = cspT_fp_induct_ref_left cspT_fp_induct_eq_left

(****************** to add them again ******************)
(* 2013
declare Union_image_eq [simp]
declare Inter_image_eq [simp]
*)

declare Sup_image_eq [simp]
declare Inf_image_eq [simp]

end


theory TS_Refinement_Proof_Rules
imports  TS_Proof_Rules
begin

lemma exists_ops_vts_push: "ops_wfs s c \<Longrightarrow> \<exists>ts'. ops_vts_push t ts' s"
  apply(simp add: ops_vts_push_def getTs_def)
  apply(case_tac "ops s = {}")
   apply simp
  apply(case_tac "ops_matched s = {}", simp_all)
    apply (simp add: gt_ex)
  apply(unfold ops_wfs_def)[1]
   apply simp
  apply(case_tac "ops_matched s = {}", simp_all)
   apply(rule_tac x = "Max(snd ` ops s) + 1" in exI)
   apply(unfold ops_wfs_def)[1]
  apply(intro conjI, elim conjE, simp_all)
  apply (metis (no_types, lifting) add.commute finite_imageI image_eqI image_is_empty less_add_one member_less_max pos_add_strict zero_less_one)
   apply (metis Max_less_iff equals0D finite_imageI infinite_growing less_add_same_cancel1 zero_less_double_add_iff_zero_less_single_add zero_less_two)
  apply(subgoal_tac "snd` ops_matched s \<subseteq> ops s")
   apply(subgoal_tac "fst` ops_matched s \<subseteq> ops s")
    defer
   apply(unfold ops_wfs_def)[1]
  apply linarith
   apply(unfold ops_wfs_def)[1]
   apply linarith
  apply(rule_tac x = "Max (snd `(ops s)) +1" in exI)
  apply(intro allI impI conjI)
    apply(unfold ops_wfs_def getTs_def getOp_def ops_init_def, simp)[1]
  apply(subgoal_tac "finite(snd ` ops s)")
  apply (simp add: add.commute add_strict_increasing)
    apply simp
   apply(subgoal_tac "finite(snd ` ops s)")
  apply(subgoal_tac "Max (snd ` ops s) + 1 > Max (snd ` ops s)")
  using Max_less_iff apply blast
  using less_add_one apply blast
    apply(unfold ops_wfs_def getTs_def getOp_def ops_init_def, simp)[1]
  apply(unfold ops_wfs_def getTs_def getOp_def ops_init_def, simp)[1]
  apply(subgoal_tac "ba \<le> Max (snd ` ops s)")
   apply linarith
  apply simp
  by (metis Max.coboundedI finite_imageI image_iff image_subset_iff prod.exhaust_sel snd_eqD)

lemma exist_ops_vts_pop: "ops_wfs s c \<Longrightarrow> \<exists> ts'. ops_vts_pop t ts' s"
  apply(simp add: ops_vts_pop_def ops_init_matched_pairs_def getTs_def)
  apply(case_tac "ops s = {}")
  apply simp
  apply(case_tac "ops_matched s = {}", simp_all)
    apply (simp add: gt_ex)
  apply(unfold ops_wfs_def)[1]
   apply simp
   apply(rule_tac x = "Max(snd ` ops s) + 1" in exI)
    apply(unfold ops_wfs_def, simp_all)[1]
 apply (intro conjI)
  apply (simp add: add.commute add_strict_increasing)
   apply (metis Max_less_iff equals0D finite_imageI infinite_growing less_add_same_cancel1 zero_less_double_add_iff_zero_less_single_add zero_less_two)
  apply(intro allI conjI impI)
  apply(elim conjE, intro disjI2)
  apply(subgoal_tac " (aa, ba) \<in> ops s") defer
   apply (metis imageI old.prod.inject prod.collapse subset_iff)
  apply(simp add: getTs_def getOp_def ops_init_def)
  by (metis Max.coboundedI add.commute add_strict_increasing finite_imageI image_iff snd_eqD zero_less_one)

(*****************************************)

definition "ref_client_thrView t ac cc \<equiv> \<forall> x . tst (thrView ac t x) \<le> tst (thrView cc t x) "

definition "ref_Top ss ls \<equiv> \<forall> w . lib_lastWr ls Top = w \<and> lib_value ls w \<noteq> Null \<longrightarrow>
           (\<exists> op . op\<notin>fst`(ops_matched ss) \<and> getOp op = PUSH \<and> op\<in>ops ss
                  \<and> op_value op ss = lib_value ls (lib_lastWr ls (lib_value ls w)))"

definition "ref_addr_push f als cls ps \<equiv> \<forall> ad . ad\<in>addr ps \<longrightarrow>
           (\<exists> op . op\<in>ops als \<and> getOp op = PUSH \<and> f ad = op \<and> lib_value cls (lib_lastWr cls ad) = op_value op als)"

definition "refs t f ps als cls acs ccs \<equiv> ref_client_thrView t acs ccs \<and> ref_addr_push f als cls ps"

lemmas [simp] = refs_def

lemma "f a = b \<Longrightarrow> c\<notin>dom f \<Longrightarrow> f' = f(c:=d) \<Longrightarrow> f' c = d"
  by simp

(*
ps  = program state
ccs = concrete client state
acs = abstract client state
ccl = concrete stack library state
als = abstract stack library state
*)

lemma lib_last_in_writes_on: "lib_wfs cls ccs \<Longrightarrow> lib_writes_on cls x \<noteq> {} \<Longrightarrow> lib_lastWr cls x \<in> lib_writes_on cls x"
  apply(simp add: lib_wfs_def lib_writes_on_def lib_lastWr_def tst_def var_def)
  apply(subgoal_tac "finite(snd ` {w. fst w = x \<and> w \<in> lib_writes cls})")
   apply safe
  defer
   apply blast
  apply(subgoal_tac " Max (snd ` {w. fst w = x \<and> w \<in> lib_writes cls}) \<in>  (snd ` {w. fst w = x \<and> w \<in> lib_writes cls})")
  apply (simp add: image_iff)
  using Max_in by blast

lemma ops_vts_push_max: "ops_wfs als acs \<Longrightarrow> ops_vts_push t (Max (snd ` ops als) + 1) als"
  apply(simp add: ops_vts_push_def getTs_def getOp_def)
  apply (intro conjI)
    apply(unfold ops_wfs_def ops_init_def getOp_def getTs_def)[1]
  apply simp
    apply (simp add: add.commute add_strict_increasing)
    apply(unfold ops_wfs_def ops_init_def getOp_def getTs_def)[1]
  apply simp
    apply (simp add: add.commute add_strict_increasing)
  apply (meson Max.coboundedI add_le_same_cancel2 finite_imageI not_one_le_zero)
    apply(unfold ops_wfs_def ops_init_def getOp_def getTs_def lastOp_def)[1]
  apply simp
  apply (simp add: add.commute add_strict_increasing )
  apply(intro allI impI conjI, elim conjE exE)
  apply(intro disjI2)
  apply clarsimp
  by (metis Max.coboundedI add_strict_increasing finite_imageI image_eqI image_subset_iff snd_conv zero_less_one)

lemma ops_vts_pop_max: "ops_wfs als acs \<Longrightarrow> ops_vts_pop t (Max (snd ` ops als) + 1) als"
  apply(simp add: ops_vts_pop_def getTs_def getOp_def)
  apply (intro conjI)
    apply(unfold ops_wfs_def ops_init_def)[1]
  apply simp
    apply (simp add: add.commute add_strict_increasing)
    apply(unfold ops_wfs_def ops_init_def)[1]
  apply (simp add: getOp_def getTs_def)
  apply (metis (mono_tags, hide_lams) Max_ge add_le_same_cancel1 finite_imageI  not_one_le_zero)
  apply(intro conjI allI impI disjI2)
  apply(unfold ops_wfs_def ops_init_def)[1]
  apply (simp add: getOp_def getTs_def ops_init_matched_pairs_def)
  apply(elim conjE, simp)
  apply(subgoal_tac "(aa, ba)\<in> ops als") defer
  apply (metis (mono_tags, hide_lams) fst_conv imageI snd_eqD subset_iff subset_refl)
  by (metis Max_ge add.commute add_strict_increasing finite_imageI image_iff snd_eqD zero_less_one)

lemma lastUnmatchedPush_max: "ops_wfs als acs \<Longrightarrow> ops_unmatched_push als \<noteq> {} \<Longrightarrow> lastUnmatchedPush (Max (snd ` ops als) + 1)
        (PUSH, Max (snd ` ops_unmatched_push als)) als"
  apply(simp add: lastUnmatchedPush_def ops_umatched_upto_ts_def)
  apply(intro conjI)
    apply(intro disjI1)
    apply(subgoal_tac "fst` ops_unmatched_push als = {PUSH}")
  defer
     apply(simp add: ops_unmatched_push_def)
     apply(simp add: ops_on_def ops_mtch_push_def getOp_def)
  apply blast
    defer defer
    apply(subgoal_tac "finite (ops_unmatched_push als)")
  apply (metis Domain.DomainI Domain_fst Max_in RangeE Range_snd empty_is_image finite_imageI  singletonD)
  apply(unfold ops_wfs_def ops_init_def)[1]
    apply (simp add: getOp_def getTs_def ops_init_matched_pairs_def)
  apply(simp add: ops_unmatched_push_def ops_on_def ops_mtch_push_def)
   apply(simp_all add: getTs_def)
  apply(subgoal_tac "ops_unmatched_push als \<subseteq> ops als")
    apply(subgoal_tac "finite (ops_unmatched_push als)")
    apply(subgoal_tac "finite (ops als)")
  apply (smt Max_less_iff empty_is_image finite_imageI image_iff less_add_one subset_empty subset_iff)
   apply(unfold ops_wfs_def ops_init_def)[1]
  apply blast
  apply(unfold ops_wfs_def ops_init_def)[1]
    apply (simp add: getOp_def getTs_def ops_init_matched_pairs_def)
    apply(simp add: ops_unmatched_push_def ops_on_def ops_mtch_push_def)
    apply(simp add: ops_unmatched_push_def ops_on_def ops_mtch_push_def)
   apply blast

  apply(subgoal_tac "Max (snd `
         {opp.
          (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and> snd opp < Max (snd ` ops als) + 1}) \<in> snd ` ops_init als \<union> snd ` ops_unmatched_push als")
   defer
  apply(subgoal_tac " {opp.
          (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and> snd opp < Max (snd ` ops als) + 1} \<noteq> {}")
  apply(subgoal_tac "finite({opp.
          (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and> snd opp < Max (snd ` ops als) + 1})")
  apply (smt Max_in UnI1 UnI2 empty_is_image finite_imageI image_iff mem_Collect_eq)
    apply(unfold ops_wfs_def ops_init_def)[1]
  apply(simp add: ops_unmatched_push_def getOp_def ops_on_def)
     apply(unfold ops_wfs_def ops_init_def)[1]
  apply(simp add: ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
  apply (metis (no_types, lifting)  Max.coboundedI add.commute add_strict_increasing finite_imageI  imageI image_cong snd_eqD surj_pair zero_less_one)
  apply(case_tac "Max (snd `
         {opp.
          (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and> snd opp < Max (snd ` ops als) + 1})
    \<in> snd ` ops_init als")
   apply(subgoal_tac "\<exists> op . op\<in>ops_unmatched_push als")
    apply (elim exE)
  apply(subgoal_tac "op\<in>{opp.
                (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and>
                snd opp < Max (snd ` ops als) + 1}")
     apply(subgoal_tac "getOp op = PUSH")
  defer
  apply(simp add: getOp_def ops_unmatched_push_def ops_on_def)
  apply(simp add: getOp_def ops_unmatched_push_def ops_on_def ops_mtch_push_def)
     apply(unfold ops_wfs_def ops_init_def)[1]
     apply(simp add: ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
  apply (metis (no_types, lifting) Max_ge add.commute add_strict_increasing finite_imageI imageI old.prod.exhaust snd_conv zero_less_one)
  apply blast
   defer
   apply simp
  apply(subgoal_tac "op\<in>{opp.
                (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and>
                snd opp < Max (snd ` ops als) + 1}")
    apply(subgoal_tac "\<forall> ts . ts \<in> snd ` ops_init als \<longrightarrow> getTs op > ts")
     defer
     apply(intro allI impI)
  apply(simp add: getTs_def)
     apply(unfold ops_wfs_def ops_init_def)[1]
     apply(simp add: getTs_def getOp_def)
  apply(elim conjE exE)
     apply(simp add: ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
  apply (smt OP.distinct(1) imageE mem_Collect_eq prod.collapse)
  apply blast
   defer
   apply(subgoal_tac "\<forall> opp . opp\<in>ops_init als \<longrightarrow> getTs opp < getTs op")
  defer
  using getTs_def apply blast
  defer
  apply(subgoal_tac "\<forall> oppp opinit. oppp\<in>{opp.
                (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and>
                snd opp < Max (snd ` ops als) + 1} \<and> opinit\<in>ops_init als \<longrightarrow> getTs oppp \<le> getTs opinit")
    apply (simp add: leD)
   apply(intro allI impI)
   apply(simp add: ops_init_def)
  apply(subgoal_tac "finite({opp.
             (opp \<in> ops_unmatched_push als \<or> getOp opp = INIT \<and> opp \<in> ops als) \<and>
             snd opp < Max (snd ` ops als) + 1})")
  apply(subgoal_tac "{opp.
             (opp \<in> ops_unmatched_push als \<or> getOp opp = INIT \<and> opp \<in> ops als) \<and>
             snd opp < Max (snd ` ops als) + 1} \<noteq> {}")
    apply (metis (mono_tags, lifting) Max_less_iff finite_imageI getTs_def imageI image_is_empty infinite_growing mem_Collect_eq)
    apply blast
     apply(unfold ops_wfs_def ops_init_def)[1]
   apply(simp add: getTs_def getOp_def)

 apply(simp add: getTs_def ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
  apply simp
  apply(subgoal_tac "ops_unmatched_push als \<subseteq> ops als") defer
 apply(simp add: getTs_def ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
  apply blast
  apply(subgoal_tac "ops_init als \<subseteq> ops als") defer
 apply(simp add: ops_init_def  getTs_def ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
   apply blast
  apply(subgoal_tac "{opp. (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and> snd opp < Max (snd ` ops als) + 1} = {opp. (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als)}")
   defer
   apply(subgoal_tac " Max (snd ` ops als) + 1 >  Max (snd ` ops als)")
  apply(subgoal_tac "\<forall> opp . opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als \<longrightarrow> getTs opp < Max (snd ` ops als) + 1")
     apply (metis getTs_def)
    apply(intro allI impI)
    apply(simp add: getTs_def)
    apply(elim disjE)
  apply(subgoal_tac "\<forall> opp . opp \<in> ops_unmatched_push als \<longrightarrow> getTs opp \<le> Max (snd ` ops als) ")
apply (metis add.commute getTs_def le_less_trans less_add_one)
     apply(intro allI impI)
  apply(unfold ops_wfs_def)[1]
  apply simp
  apply (metis Max.coboundedI finite_imageI getTs_def imageI subset_iff)
  apply(unfold ops_wfs_def)[1]
  apply simp
  apply (metis (no_types, lifting) Max.coboundedI add.commute add_strict_increasing finite_imageI getOp_def imageI mem_Collect_eq old.prod.exhaust old.prod.inject ops_init_def prod.collapse snd_conv  zero_less_one)
  apply linarith
  apply simp
  apply(subgoal_tac "finite(snd ` {opp. opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als})")
  apply(subgoal_tac "finite(snd ` ops_unmatched_push als)")
  apply (smt Max.coboundedI Max_eq_if image_iff mem_Collect_eq)
 apply(simp add: ops_init_def  getTs_def ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
   apply(unfold ops_wfs_def)[1]
  apply simp
 apply(simp add: ops_init_def  getTs_def ops_unmatched_push_def getOp_def ops_on_def ops_mtch_push_def)
   apply(unfold ops_wfs_def)[1]
  apply simp
  done

lemma lastUnmatchedPush_lastPush: "ops_wfs als acs \<Longrightarrow> op = lastPush als \<Longrightarrow> op \<in> ops als \<Longrightarrow> op \<notin> fst ` ops_matched als  \<Longrightarrow> lastUnmatchedPush (Max (snd ` ops als) + 1) op als"
  apply(simp add:lastUnmatchedPush_def)
  apply safe
   apply(simp add: ops_umatched_upto_ts_def lastPush_def ops_unmatched_push_def)
   apply safe
     apply (simp add: getOp_def ops_on_def)
  using ops_mtch_push_def apply auto[1]
   apply (simp add: getOp_def ops_on_def ops_mtch_push_def getTs_def)
  apply(subgoal_tac "{opp. fst opp = PUSH \<and> opp \<in> ops als} -
          {opp. fst opp = PUSH \<and> opp \<in> fst ` ops_matched als} \<subseteq> ops als")
  apply(subgoal_tac " Max (snd `
         ({opp. fst opp = PUSH \<and> opp \<in> ops als} -
          {opp. fst opp = PUSH \<and> opp \<in> fst ` ops_matched als}))
    \<le> Max (snd ` ops als)")
  apply linarith
    defer
    apply blast defer
   apply(unfold ops_wfs_def getOp_def, simp)[1]
  apply(subgoal_tac "{opp. fst opp = PUSH \<and> opp \<in> ops als} -
          {opp. fst opp = PUSH \<and> opp \<in> fst ` ops_matched als} \<noteq> {}")
  apply (meson Max_mono finite_imageI image_is_empty image_mono)
  apply (metis (mono_tags, lifting) Collect_mono_iff Diff_eq_empty_iff fst_conv image_is_empty)
  apply(simp add: ops_umatched_upto_ts_def lastPush_def getTs_def)
  apply(subgoal_tac "{opp.
          (opp \<in> ops_unmatched_push als \<or> opp \<in> ops_init als) \<and>
          snd opp < Max (snd ` ops als) + 1} = ops_unmatched_push als \<union> ops_init als")
   defer
  apply(simp add: ops_unmatched_push_def ops_mtch_push_def ops_init_def ops_on_def getOp_def)
   apply safe
     apply blast
    apply clarsimp
    defer
  apply(subgoal_tac "snd (a, b) \<le> Max (snd ` ops als)")
  apply linarith
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def, simp)[1]
  apply (simp add: rev_image_eqI)
   apply simp
   defer
  apply(subgoal_tac "b \<le> Max (snd ` ops als)")
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def, simp)[1]
   apply(case_tac "b \<in> snd ` ops als")
  apply(subgoal_tac "finite(snd ` ops als)")
  using Max_ge apply blast
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def, simp)[1]
   apply (simp add: rev_image_eqI)
  apply(subgoal_tac "Max (snd ` (ops_unmatched_push als \<union> ops_init als)) = Max (snd ` (ops_unmatched_push als))")
   apply linarith
  apply(subgoal_tac "Max (snd ` (ops_unmatched_push als \<union> ops_init als)) = Max (snd ` (ops_unmatched_push als)) \<or> Max (snd ` (ops_unmatched_push als \<union> ops_init als)) = Max (snd ` ( ops_init als))")
   apply(subgoal_tac "\<forall> op1 op2. op1\<in>snd `(ops_unmatched_push als) \<and> op2\<in>snd `(ops_init als) \<longrightarrow> op1 > op2")
    apply(subgoal_tac "finite(ops_init als)")
     apply(subgoal_tac "finite(ops_unmatched_push als)")
      apply(subgoal_tac "ops_init als \<noteq> {} \<and> ops_unmatched_push als \<noteq> {}")
  apply(elim conjE)
       apply (smt Max_in Un_empty Un_iff finite_UnI finite_imageI image_Un image_is_empty member_less_max not_max)
  apply(intro conjI)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def, simp)[1]
   apply auto[1]
       apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  apply (simp add: Collect_mono_iff)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  apply (simp add: Collect_mono_iff)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  apply(intro allI impI conjI)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  apply (smt OP.distinct(1) image_iff mem_Collect_eq prod.collapse set_diff_eq)
   apply(intro disjI1)
    apply(subgoal_tac "finite(ops_init als)")
   apply(subgoal_tac "finite(ops_unmatched_push als)")
  apply(subgoal_tac "ops_unmatched_push als \<noteq> {}")
   apply(subgoal_tac "\<forall> op1 op2. op1\<in>snd `(ops_unmatched_push als) \<and> op2\<in>snd `(ops_init als) \<longrightarrow> op1 > op2")
  apply (smt Max_in Un_empty Un_iff finite_UnI finite_imageI image_Un image_is_empty member_less_max not_max)
     apply(intro allI impI)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  apply (smt OP.distinct(1) image_iff mem_Collect_eq prod.collapse set_diff_eq)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  apply (metis (mono_tags, lifting) Collect_mono_iff fst_conv)
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
    apply(unfold ops_wfs_def getOp_def ops_init_def getTs_def ops_init_def ops_unmatched_push_def ops_on_def ops_mtch_push_def, simp)[1]
  done

definition "cli_lib_mView cls w \<equiv>   ((lib_modView cls) w) Lib.CVARS"
definition "cli_stack_mView als op \<equiv>   ((ops_modView_cli als) op)"

lemmas shorthands [simp] = TopL_def  cli_lib_mView_def cli_stack_mView_def

(* nxt ps a = lastNxtVal cls a *)
definition "rr f ps als cls \<equiv>
  (\<forall> a .  a \<in> pushed_addr ps \<longrightarrow>
            (getTs (f a) > getTs (f (lastNxtVal cls a)))
          \<and> (\<forall> op . op \<in> ops_unmatched_push als \<and> op \<noteq> f a \<and> op \<noteq> f (lastNxtVal cls a) \<longrightarrow>
                        getTs op < getTs (f (lastNxtVal cls a)) \<or> getTs op > getTs (f a))
          \<and> f a \<in> ops_unmatched_push als
          \<and> lastNxtVal cls a \<in> pushed_addr ps \<union> {Null}
          \<and> (lastTop cls \<noteq> Null \<longrightarrow>
                (\<exists> op opl . f a = op \<and> op\<in>ops_unmatched_push als
                          \<and> f (lastTop cls) = opl \<and> opl\<in>ops_unmatched_push als
                          \<and> opl = lastPush als))
          \<and> op_value (f a) als = lib_value cls (lib_lastWr cls a)
          \<and> lastNxtVal cls a \<noteq> lastTop cls)
 \<and> (\<forall>a1 a2. a1 \<in> pushed_addr ps \<and> a2 \<in> pushed_addr ps \<and> f a1 = f a2 \<longrightarrow> a1 = a2)
 \<and> (\<exists> op . op\<in>ops_init als \<and> f Null = op)
                "

definition "rr_cliV f cls als ps \<equiv>
   (\<forall> ad w l. ad\<in>pushed_addr ps \<and> w\<in>lib_writes_on cls Top \<and> lib_value cls w = ad \<longrightarrow>
              tst ((cli_lib_mView cls w) l) \<ge> tst ((cli_stack_mView als (f ad)) l))"
(*not correct
definition "rr_cliV_abst f cls als ps \<equiv> (\<forall> ad x . ad\<in>pushed_addr ps \<longrightarrow> snd (ops_modView_cli als (f (ad)) x) \<ge> snd (ops_modView_cli als (f (nxt ps ad)) x))"
*)

definition "rr_cliV_thView t f ccs cls als ps \<equiv> \<forall> ad l . ad\<in>pushed_addr ps \<longrightarrow> tst (ops_modView_cli als (f (ad)) l)
       \<le> tst (thrView ccs t l)"

definition "rr_f_pushed_unmatched f cls als ps \<equiv> ops_unmatched_push als = {f a | a .  a\<in>pushed_addr ps}"

lemma max_minus_max: "finite A \<Longrightarrow> A \<noteq> {} \<Longrightarrow> a\<in>A \<Longrightarrow> b\<in>A \<Longrightarrow> a > b \<Longrightarrow> a = Max A
\<Longrightarrow> (\<forall> e . e\<in>A \<and> e \<noteq> Max A \<longrightarrow> e \<le> b) \<Longrightarrow> b = Max (A-{a})"
  apply(subgoal_tac "A-{a} \<noteq> {}")
  defer
  apply blast
    apply(subgoal_tac "finite (A-{a})")
  defer
   apply simp
  apply (subgoal_tac "\<forall> e . e\<in>A  \<longrightarrow> e \<le> Max A")
  defer
  using Max_ge apply blast
  apply (subgoal_tac "a \<noteq> b")
  defer
   apply blast
  apply(subgoal_tac "b\<in>A-{a}")
   defer
  apply blast
  by (metis DiffD1 Diff_insert_absorb Max_eqI mk_disjoint_insert)

lemma nxt_TopLV_oneBeforeLast: "ops_wfs als acs \<Longrightarrow> lib_wfs cls ccs \<Longrightarrow>
       lastTop cls \<noteq> Null \<Longrightarrow> glb_inv ps cls \<Longrightarrow>  ops_wfs als acs \<Longrightarrow>
        lastNxtVal cls (lastTop cls) \<noteq> Null \<Longrightarrow>
        rr f ps als cls \<Longrightarrow>
        f (lastNxtVal cls (lastTop cls)) = oneBeforeLastPush als"
  apply(simp add: rr_def oneBeforeLastPush_def glb_inv_def)
  apply(subgoal_tac "f (lastTop cls) = lastPush als")
  defer
   apply (metis Null_def  glb_inv3_def order.strict_implies_not_eq)
  apply(subgoal_tac "f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top))) \<in> ops_unmatched_push als")
  apply(subgoal_tac "snd (f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top)))) = Max (snd ` (ops_unmatched_push als - {lastPush als}))")
  apply(subgoal_tac "fst (f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top)))) = PUSH")
   apply simp
    apply (metis lastTop_def   lastVal_def  prod.collapse)
  apply(subgoal_tac "(lastNxtVal cls (lib_value cls (lib_lastWr cls Top)))\<in>pushed_addr ps")
    apply(simp add: glb_inv1_def glb_inv2_def glb_inv3_def glb_inv4_def glb_inv5_def)
  apply(simp add: getTs_def getOp_def, elim conjE exE)
  apply(simp add: ops_unmatched_push_def ops_on_def getOp_def ops_init_def getTs_def ops_mtch_push_def)
  apply (metis Null_def Suc_eq_plus1 glb_inv3_def gr_implies_not_zero lastNxtVal_def lastTop_def lastVal_def)
    using Null_def glb_inv3_def not_less_zero
    defer
    apply (metis Suc_eq_plus1 lastNxtVal_def lastTop_def lastVal_def)
  apply(subgoal_tac "Max (snd`(ops_unmatched_push als)) = snd (lastPush als)") defer
   apply (simp add: lastPush_def)
  apply(subgoal_tac "(snd ` (ops_unmatched_push als - {lastPush als})) = (snd ` (ops_unmatched_push als)) - {snd (lastPush als)}")
   defer
   apply (simp add: lastPush_def getTs_def getOp_def ops_unmatched_push_def)
  apply safe
     apply blast
      apply blast
  apply(simp add: ops_on_def)
  apply (simp add: getOp_def)
  apply (metis snd_conv)
  apply simp
  apply (metis DiffI Diff_insert image_eqI insert_iff snd_conv)
  apply simp
  apply(subgoal_tac "snd (f (lastTop cls)) > snd (f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top))))")
     defer
    apply (metis Nat.add_0_right Null_def One_nat_def add_Suc_right getTs_def glb_inv3_def gr_implies_not0 lastNxtVal_def lastTop_def lastVal_def)
  apply(subgoal_tac "snd (f (lastTop cls))\<in> snd ` ops_unmatched_push als")
  defer
  apply (metis Null_def  equals0I glb_inv3_def imageI  less_numeral_extra(3))
  apply(subgoal_tac "snd (f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top)))) \<in> snd ` ops_unmatched_push als")
   apply(subgoal_tac "lastNxtVal cls (lib_value cls (lib_lastWr cls Top)) \<in> pushed_addr ps")
  apply simp
      defer
    apply (metis Nat.add_0_right Null_def One_nat_def add_Suc_right glb_inv3_def gr_implies_not0 lastNxtVal_def lastTop_def lastVal_def)
  apply simp
     apply(subgoal_tac "(\<forall> e . e\<in>(snd ` ops_unmatched_push als) \<and> e \<noteq> Max (snd ` ops_unmatched_push als) \<longrightarrow> e \<le> snd (f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top)))))")
   defer
   apply(intro allI impI)
  apply(case_tac " e = snd (f (lastNxtVal cls (lib_value cls (lib_lastWr cls Top))))")
    apply linarith
   apply simp
  apply(subgoal_tac "\<forall> a b. a\<in>pushed_addr ps \<and>
                b \<in> snd`(ops_unmatched_push als) \<and>  b \<noteq> snd (f a) \<and>  b \<noteq> snd(f (lastNxtVal cls a)) \<longrightarrow>
                b < snd (f (lastNxtVal cls a)) \<or> snd (f a) < b") defer
    apply(simp add: getTs_def)
    apply(intro allI impI conjI)
    apply(erule_tac x = aa in allE, simp, elim conjE)
    apply(erule_tac x = PUSH in allE)
    apply(erule_tac x = ba in allE)
  apply(subgoal_tac "(PUSH, ba) \<in> ops_unmatched_push als \<and>
       (PUSH, ba) \<noteq> f aa \<and> (PUSH, ba) \<noteq> f (lastNxtVal cls aa)")
    apply simp
    apply(intro conjI)
  apply(simp add: ops_on_def getOp_def ops_unmatched_push_def)
  apply force
       apply (metis sndI)
    apply simp
    apply (metis sndI) defer
  apply(elim conjE)
  apply(erule_tac x = "lastTop cls" in allE)
   apply(erule_tac x = "lastTop cls" in allE)
  apply(erule_tac x = "lastTop cls" in allE)
  apply(erule_tac x = "e" in allE)
   apply simp
  apply(subgoal_tac "lib_value cls (lib_lastWr cls Top) \<in> pushed_addr ps \<and>
       e \<in> snd ` ops_on PUSH als", simp)
    apply(subgoal_tac "snd (lastPush als) > e", simp)
    apply(subgoal_tac "Max ( snd ` (ops_unmatched_push als)) = snd (lastPush als)", simp)
        apply(subgoal_tac "finite(snd ` ops_unmatched_push als)")
    apply simp
    apply (simp add: lastTop_def)
  apply(unfold ops_wfs_def ops_mtch_push_def getOp_def getTs_def ops_on_def ops_unmatched_push_def lastPush_def ops_init_def)[1]
  apply (metis (no_types, lifting) Collect_mem_eq Collect_mono_iff Diff_eq_empty_iff finite.emptyI finite_Diff finite_Diff2 finite_imageI  set_diff_eq)
       apply blast
  apply(subgoal_tac "finite(snd ` ops_unmatched_push als)")
       apply(subgoal_tac "(snd ` ops_unmatched_push als) \<noteq> {}")
        apply (metis member_less_max)
       apply blast
  apply(unfold ops_wfs_def ops_mtch_push_def getOp_def getTs_def ops_on_def ops_unmatched_push_def lastPush_def ops_init_def)[1]
  apply (metis (no_types, lifting) Collect_mem_eq Collect_mono_iff Diff_eq_empty_iff finite.emptyI finite_Diff finite_Diff2 finite_imageI set_diff_eq)
     apply simp
    apply(intro conjI)
    apply (simp add: bot_nat_def glb_inv3_def lastTop_def)
    apply (metis (no_types, lifting) DiffD1 image_iff ops_unmatched_push_def)
    apply clarsimp
  apply(subgoal_tac "finite(snd ` ops_unmatched_push als)")
  apply(subgoal_tac "(snd ` ops_unmatched_push als) \<noteq> {}")
    apply (simp add: max_minus_max)
    apply blast
  apply(unfold ops_wfs_def ops_mtch_push_def getOp_def getTs_def ops_on_def ops_unmatched_push_def lastPush_def ops_init_def)[1]
  apply (metis (no_types, lifting) Collect_mem_eq Collect_mono_iff Diff_eq_empty_iff finite.emptyI finite_Diff finite_Diff2 finite_imageI set_diff_eq)
 done

end


           (*-------------------------------------------*
            |                   Test                    |
            |        CSP-Prover on Isabelle2005         |
            |                  April 2006               |
            |                                           |
            |        CSP-Prover on Isabelle2009         |
            |                   June 2009  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory Test_proof
imports CSP_F_Main
begin

(*****************************************************************

   "(a -> P) |[{a}]| (a -> Q) =F a -> (P |[{a}]| Q)" is proven
   by the following three strategies:

         1. semantical proof
         2. algebraic proof
         3. tactic proof
         4.

 *****************************************************************)

(*---------------------------------------------------------------*
    semantical proof by the difinition of traces and failures
 *---------------------------------------------------------------*)

lemma semantical_proof:
  "(a -> P) |[{a}]| (a -> Q) =F a -> (P |[{a}]| Q)"
apply (simp add: cspF_eqF_semantics)
apply (rule)

(* trace *)
apply (rule order_antisym)

 (* <= *)
 apply (rule)     (* subdomTI is automatically applied *)
 apply (simp add: in_traces)
 apply (auto simp add: par_tr_nil par_tr_head_Ev_Ev)

 (* => *)
 apply (auto simp add: in_traces)
 apply (simp add: par_tr_head)
 apply (rule_tac x="<Ev a> ^^^ sa" in exI)
 apply (rule_tac x="<Ev a> ^^^ ta" in exI)
 apply (auto)

(* failures *)
apply (rule order_antisym)

 (* <= *)
 apply (rule)
 apply (simp add: in_failures)
 apply (elim conjE exE disjE)
 apply (simp_all add: par_tr_nil par_tr_head_Ev_Ev)
 apply (force)
 apply (force)
 apply (force)

 (* => *)
 apply (rule)
 apply (simp add: in_failures)
 apply (elim conjE exE disjE)
 apply (simp_all)
 apply (rule_tac x="X - {(Ev a)}" in exI)
 apply (rule_tac x="X - {(Ev a)}" in exI)
 apply (simp)
 apply (rule_tac x="Y" in exI)
 apply (rule_tac x="Z" in exI)
 apply (simp)
 apply (simp add: par_tr_head)
 apply (rule_tac x="<Ev a> ^^^ sb" in exI)
 apply (rule_tac x="<Ev a> ^^^ t" in exI)
 apply (auto)
done

(*---------------------------------------------------------------*
          manual syntactical proof by algebraic CSP laws
 *---------------------------------------------------------------*)

lemma syntactical_proof:
  "(a -> P) |[{a}]| (a -> Q) =F a -> (P |[{a}]| Q)"
apply (rule cspF_rw_left)
apply (rule cspF_decompo)
apply (simp)
apply (rule cspF_step)
apply (rule cspF_step)

apply (rule cspF_rw_left)
apply (rule cspF_step)

apply (rule cspF_rw_right)
apply (rule cspF_step)

apply (rule cspF_decompo)
apply (simp)
apply (simp)
done

(*---------------------------------------------------------------*
            semi-automatic syntactical proof by tactics
 *---------------------------------------------------------------*)

lemma tactical_proof:
  "(a -> P) |[{a}]| (a -> Q) =F a -> (P |[{a}]| Q)"
apply (cspF_auto)+
apply (auto)
done

end