header {* \isaheader{Horwitz-Reps-Binkley Slice} *}

theory HRBSlice imports SDG begin

context SDG begin

subsection {* Set describing phase 1 of the two-phase slicer *}

inductive_set sum_SDG_slice1 :: "'node SDG_node \<Rightarrow> 'node SDG_node set"
  for n::"'node SDG_node"
  where refl_slice1:"valid_SDG_node n \<Longrightarrow> n \<in> sum_SDG_slice1 n"
  | cdep_slice1:
  "\<lbrakk>n'' s\<longrightarrow>\<^bsub>cd\<^esub> n'; n' \<in> sum_SDG_slice1 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice1 n"
  | ddep_slice1:
  "\<lbrakk>n'' s-V\<rightarrow>\<^bsub>dd\<^esub> n'; n' \<in> sum_SDG_slice1 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice1 n"
  | call_slice1:
  "\<lbrakk>n'' s-p\<rightarrow>\<^bsub>call\<^esub> n'; n' \<in> sum_SDG_slice1 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice1 n"
  | param_in_slice1:
  "\<lbrakk>n'' s-p:V\<rightarrow>\<^bsub>in\<^esub> n'; n' \<in> sum_SDG_slice1 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice1 n"
  | sum_slice1:
  "\<lbrakk>n'' s-p\<rightarrow>\<^bsub>sum\<^esub> n'; n' \<in> sum_SDG_slice1 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice1 n"

lemma slice1_cdep_slice1:
  "\<lbrakk>nx \<in> sum_SDG_slice1 n; n s\<longrightarrow>\<^bsub>cd\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice1 n'"
by(induct rule:sum_SDG_slice1.induct,
   auto intro:sum_SDG_slice1.intros sum_SDG_edge_valid_SDG_node)

lemma slice1_ddep_slice1:
  "\<lbrakk>nx \<in> sum_SDG_slice1 n; n s-V\<rightarrow>\<^bsub>dd\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice1 n'"
by(induct rule:sum_SDG_slice1.induct,
   auto intro:sum_SDG_slice1.intros sum_SDG_edge_valid_SDG_node)

lemma slice1_sum_slice1:
  "\<lbrakk>nx \<in> sum_SDG_slice1 n; n s-p\<rightarrow>\<^bsub>sum\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice1 n'"
by(induct rule:sum_SDG_slice1.induct,
   auto intro:sum_SDG_slice1.intros sum_SDG_edge_valid_SDG_node)

lemma slice1_call_slice1:
  "\<lbrakk>nx \<in> sum_SDG_slice1 n; n s-p\<rightarrow>\<^bsub>call\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice1 n'"
by(induct rule:sum_SDG_slice1.induct,
   auto intro:sum_SDG_slice1.intros sum_SDG_edge_valid_SDG_node)

lemma slice1_param_in_slice1:
  "\<lbrakk>nx \<in> sum_SDG_slice1 n; n s-p:V\<rightarrow>\<^bsub>in\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice1 n'"
by(induct rule:sum_SDG_slice1.induct,
   auto intro:sum_SDG_slice1.intros sum_SDG_edge_valid_SDG_node)

lemma is_SDG_path_slice1:
  "\<lbrakk>n is-ns\<rightarrow>\<^sub>d* n'; n' \<in> sum_SDG_slice1 n''\<rbrakk> \<Longrightarrow> n \<in> sum_SDG_slice1 n''"
proof(induct rule:intra_sum_SDG_path.induct)
  case isSp_Nil thus ?case by simp
next
  case (isSp_Append_cdep n ns nx n')
  note IH = `nx \<in> sum_SDG_slice1 n'' \<Longrightarrow> n \<in> sum_SDG_slice1 n''`
  from `nx s\<longrightarrow>\<^bsub>cd\<^esub> n'` `n' \<in> sum_SDG_slice1 n''`
  have "nx \<in> sum_SDG_slice1 n''" by(rule cdep_slice1)
  from IH[OF this] show ?case .
next
  case (isSp_Append_ddep n ns nx V n')
  note IH = `nx \<in> sum_SDG_slice1 n'' \<Longrightarrow> n \<in> sum_SDG_slice1 n''`
  from `nx s-V\<rightarrow>\<^bsub>dd\<^esub> n'` `n' \<in> sum_SDG_slice1 n''`
  have "nx \<in> sum_SDG_slice1 n''" by(rule ddep_slice1)
  from IH[OF this] show ?case .
next
  case (isSp_Append_sum n ns nx p n')
  note IH = `nx \<in> sum_SDG_slice1 n'' \<Longrightarrow> n \<in> sum_SDG_slice1 n''`
  from `nx s-p\<rightarrow>\<^bsub>sum\<^esub> n'` `n' \<in> sum_SDG_slice1 n''`
  have "nx \<in> sum_SDG_slice1 n''" by(rule sum_slice1)
  from IH[OF this] show ?case .
qed

subsection {* Set describing phase 2 of the two-phase slicer *}

inductive_set sum_SDG_slice2 :: "'node SDG_node \<Rightarrow> 'node SDG_node set"
  for n::"'node SDG_node"
  where refl_slice2:"valid_SDG_node n \<Longrightarrow> n \<in> sum_SDG_slice2 n"
  | cdep_slice2:
  "\<lbrakk>n'' s\<longrightarrow>\<^bsub>cd\<^esub> n'; n' \<in> sum_SDG_slice2 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n"
  | ddep_slice2:
  "\<lbrakk>n'' s-V\<rightarrow>\<^bsub>dd\<^esub> n'; n' \<in> sum_SDG_slice2 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n"
  | return_slice2:
  "\<lbrakk>n'' s-p\<rightarrow>\<^bsub>ret\<^esub> n'; n' \<in> sum_SDG_slice2 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n"
  | param_out_slice2:
  "\<lbrakk>n'' s-p:V\<rightarrow>\<^bsub>out\<^esub> n'; n' \<in> sum_SDG_slice2 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n"
  | sum_slice2:
  "\<lbrakk>n'' s-p\<rightarrow>\<^bsub>sum\<^esub> n'; n' \<in> sum_SDG_slice2 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n"

lemma slice2_cdep_slice2:
  "\<lbrakk>nx \<in> sum_SDG_slice2 n; n s\<longrightarrow>\<^bsub>cd\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice2 n'"
by(induct rule:sum_SDG_slice2.induct,
   auto intro:sum_SDG_slice2.intros sum_SDG_edge_valid_SDG_node)

lemma slice2_ddep_slice2:
  "\<lbrakk>nx \<in> sum_SDG_slice2 n; n s-V\<rightarrow>\<^bsub>dd\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice2 n'"
by(induct rule:sum_SDG_slice2.induct,
   auto intro:sum_SDG_slice2.intros sum_SDG_edge_valid_SDG_node)

lemma slice2_sum_slice2:
  "\<lbrakk>nx \<in> sum_SDG_slice2 n; n s-p\<rightarrow>\<^bsub>sum\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice2 n'"
by(induct rule:sum_SDG_slice2.induct,
   auto intro:sum_SDG_slice2.intros sum_SDG_edge_valid_SDG_node)

lemma slice2_ret_slice2:
  "\<lbrakk>nx \<in> sum_SDG_slice2 n; n s-p\<rightarrow>\<^bsub>ret\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice2 n'"
by(induct rule:sum_SDG_slice2.induct,
   auto intro:sum_SDG_slice2.intros sum_SDG_edge_valid_SDG_node)

lemma slice2_param_out_slice2:
  "\<lbrakk>nx \<in> sum_SDG_slice2 n; n s-p:V\<rightarrow>\<^bsub>out\<^esub> n'\<rbrakk> \<Longrightarrow> nx \<in> sum_SDG_slice2 n'"
by(induct rule:sum_SDG_slice2.induct,
   auto intro:sum_SDG_slice2.intros sum_SDG_edge_valid_SDG_node)

lemma is_SDG_path_slice2:
  "\<lbrakk>n is-ns\<rightarrow>\<^sub>d* n'; n' \<in> sum_SDG_slice2 n''\<rbrakk> \<Longrightarrow> n \<in> sum_SDG_slice2 n''"
proof(induct rule:intra_sum_SDG_path.induct)
  case isSp_Nil thus ?case by simp
next
  case (isSp_Append_cdep n ns nx n')
  note IH = `nx \<in> sum_SDG_slice2 n'' \<Longrightarrow> n \<in> sum_SDG_slice2 n''`
  from `nx s\<longrightarrow>\<^bsub>cd\<^esub> n'` `n' \<in> sum_SDG_slice2 n''`
  have "nx \<in> sum_SDG_slice2 n''" by(rule cdep_slice2)
  from IH[OF this] show ?case .
next
  case (isSp_Append_ddep n ns nx V n')
  note IH = `nx \<in> sum_SDG_slice2 n'' \<Longrightarrow> n \<in> sum_SDG_slice2 n''`
  from `nx s-V\<rightarrow>\<^bsub>dd\<^esub> n'` `n' \<in> sum_SDG_slice2 n''`
  have "nx \<in> sum_SDG_slice2 n''" by(rule ddep_slice2)
  from IH[OF this] show ?case .
next
  case (isSp_Append_sum n ns nx p n')
  note IH = `nx \<in> sum_SDG_slice2 n'' \<Longrightarrow> n \<in> sum_SDG_slice2 n''`
  from `nx s-p\<rightarrow>\<^bsub>sum\<^esub> n'` `n' \<in> sum_SDG_slice2 n''`
  have "nx \<in> sum_SDG_slice2 n''" by(rule sum_slice2)
  from IH[OF this] show ?case .
qed

lemma slice2_is_SDG_path_slice2:
  "\<lbrakk>n is-ns\<rightarrow>\<^sub>d* n'; n'' \<in> sum_SDG_slice2 n\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n'"
proof(induct rule:intra_sum_SDG_path.induct)
  case isSp_Nil thus ?case by simp
next
  case (isSp_Append_cdep n ns nx n')
  from `n'' \<in> sum_SDG_slice2 n \<Longrightarrow> n'' \<in> sum_SDG_slice2 nx` `n'' \<in> sum_SDG_slice2 n`
  have "n'' \<in> sum_SDG_slice2 nx" .
  with `nx s\<longrightarrow>\<^bsub>cd\<^esub> n'` show ?case by -(rule slice2_cdep_slice2)
next
  case (isSp_Append_ddep n ns nx V n')
  from `n'' \<in> sum_SDG_slice2 n \<Longrightarrow> n'' \<in> sum_SDG_slice2 nx` `n'' \<in> sum_SDG_slice2 n`
  have "n'' \<in> sum_SDG_slice2 nx" .
  with `nx s-V\<rightarrow>\<^bsub>dd\<^esub> n'` show ?case by -(rule slice2_ddep_slice2)
next
  case (isSp_Append_sum n ns nx p n')
  from `n'' \<in> sum_SDG_slice2 n \<Longrightarrow> n'' \<in> sum_SDG_slice2 nx` `n'' \<in> sum_SDG_slice2 n`
  have "n'' \<in> sum_SDG_slice2 nx" .
  with `nx s-p\<rightarrow>\<^bsub>sum\<^esub> n'` show ?case by -(rule slice2_sum_slice2)
qed

subsection {* The backward slice using the Horwitz-Reps-Binkley slicer *}

text {* Note: our slicing criterion is a set of nodes, not a unique node. *}

inductive_set combine_SDG_slices :: "'node SDG_node set \<Rightarrow> 'node SDG_node set"
  for S::"'node SDG_node set"
  where combSlice_refl:"n \<in> S \<Longrightarrow> n \<in> combine_SDG_slices S"
  | combSlice_Return_parent_node:
  "\<lbrakk>n' \<in> S; n'' s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n'); n \<in> sum_SDG_slice2 n'\<rbrakk>
  \<Longrightarrow> n \<in> combine_SDG_slices S"

definition HRB_slice :: "'node SDG_node set \<Rightarrow> 'node SDG_node set"
  where "HRB_slice S \<equiv> {n'. \<exists>n \<in> S. n' \<in> combine_SDG_slices (sum_SDG_slice1 n)}"

lemma HRB_slice_cases[consumes 1,case_names phase1 phase2]:
  "\<lbrakk>x \<in> HRB_slice S; \<And>n nx. \<lbrakk>n \<in> sum_SDG_slice1 nx; nx \<in> S\<rbrakk> \<Longrightarrow> P n;
   \<And>nx n' n'' p n. \<lbrakk>n' \<in> sum_SDG_slice1 nx; n'' s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n');
                    n \<in> sum_SDG_slice2 n'; nx \<in> S\<rbrakk> \<Longrightarrow> P n\<rbrakk>
  \<Longrightarrow> P x"
  by(fastforce elim:combine_SDG_slices.cases simp:HRB_slice_def)

lemma HRB_slice_refl:
  assumes "valid_node m" and "CFG_node m \<in> S" shows "CFG_node m \<in> HRB_slice S"
proof -
  from `valid_node m` have "CFG_node m \<in> sum_SDG_slice1 (CFG_node m)"
    by(fastforce intro:refl_slice1)
  with `CFG_node m \<in> S` show ?thesis
    by(simp add:HRB_slice_def)(blast intro:combSlice_refl)
qed

lemma HRB_slice_valid_node: "n \<in> HRB_slice S \<Longrightarrow> valid_SDG_node n"
proof(induct rule:HRB_slice_cases)
  case (phase1 n nx) thus ?case
    by(induct rule:sum_SDG_slice1.induct,auto intro:sum_SDG_edge_valid_SDG_node)
next
  case (phase2 nx n' n'' p n)
  from `n \<in> sum_SDG_slice2 n'`
  show ?case
    by(induct rule:sum_SDG_slice2.induct,auto intro:sum_SDG_edge_valid_SDG_node)
qed

lemma valid_SDG_node_in_slice_parent_node_in_slice:
  assumes "n \<in> HRB_slice S" shows "CFG_node (parent_node n) \<in> HRB_slice S"
proof -
  from `n \<in> HRB_slice S` have "valid_SDG_node n" by(rule HRB_slice_valid_node)
  hence "n = CFG_node (parent_node n) \<or> CFG_node (parent_node n) \<longrightarrow>\<^bsub>cd\<^esub> n"
    by(rule valid_SDG_node_cases)
  thus ?thesis
  proof
    assume "n = CFG_node (parent_node n)"
    with `n \<in> HRB_slice S` show ?thesis by simp
  next
    assume "CFG_node (parent_node n) \<longrightarrow>\<^bsub>cd\<^esub> n"
    hence "CFG_node (parent_node n) s\<longrightarrow>\<^bsub>cd\<^esub> n" by(rule SDG_edge_sum_SDG_edge)
    with `n \<in> HRB_slice S` show ?thesis
      by(fastforce elim:combine_SDG_slices.cases
                 intro:combine_SDG_slices.intros cdep_slice1 cdep_slice2
                  simp:HRB_slice_def)
  qed
qed

lemma HRB_slice_is_SDG_path_HRB_slice:
  "\<lbrakk>n is-ns\<rightarrow>\<^sub>d* n'; n'' \<in> HRB_slice {n}; n' \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S"
proof(induct arbitrary:S rule:intra_sum_SDG_path.induct)
  case (isSp_Nil n) thus ?case by(fastforce simp:HRB_slice_def)
next
  case (isSp_Append_cdep n ns nx n')
  note IH = `\<And>S. \<lbrakk>n'' \<in> HRB_slice {n}; nx \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from IH[OF `n'' \<in> HRB_slice {n}`] have "n'' \<in> HRB_slice {nx}" by simp
  thus ?case
  proof(induct rule:HRB_slice_cases)
    case (phase1 n nx')
    from `nx' \<in> {nx}` have "nx' = nx" by simp
    with `n \<in> sum_SDG_slice1 nx'` `nx s\<longrightarrow>\<^bsub>cd\<^esub> n'` have "n \<in> sum_SDG_slice1 n'"
      by(fastforce intro:slice1_cdep_slice1)
    with `n' \<in> S` show ?case
      by(fastforce intro:combine_SDG_slices.combSlice_refl simp:HRB_slice_def)
  next
    case (phase2 nx'' nx' n'' p n)
    from `nx'' \<in> {nx}` have "nx'' = nx" by simp
    with `nx' \<in> sum_SDG_slice1 nx''` `nx s\<longrightarrow>\<^bsub>cd\<^esub> n'` have "nx' \<in> sum_SDG_slice1 n'"
      by(fastforce intro:slice1_cdep_slice1)
    with `n'' s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node nx')` `n \<in> sum_SDG_slice2 nx'` `n' \<in> S`
    show ?case by(fastforce intro:combine_SDG_slices.combSlice_Return_parent_node
                            simp:HRB_slice_def)
  qed
next
  case (isSp_Append_ddep n ns nx V n')
  note IH = `\<And>S. \<lbrakk>n'' \<in> HRB_slice {n}; nx \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from IH[OF `n'' \<in> HRB_slice {n}`] have "n'' \<in> HRB_slice {nx}" by simp
  thus ?case
  proof(induct rule:HRB_slice_cases)
    case (phase1 n nx')
    from `nx' \<in> {nx}` have "nx' = nx" by simp
    with `n \<in> sum_SDG_slice1 nx'` `nx s-V\<rightarrow>\<^bsub>dd\<^esub> n'` have "n \<in> sum_SDG_slice1 n'"
      by(fastforce intro:slice1_ddep_slice1)
    with `n' \<in> S` show ?case
      by(fastforce intro:combine_SDG_slices.combSlice_refl simp:HRB_slice_def)
  next
    case (phase2 nx'' nx' n'' p n)
    from `nx'' \<in> {nx}` have "nx'' = nx" by simp
    with `nx' \<in> sum_SDG_slice1 nx''` `nx s-V\<rightarrow>\<^bsub>dd\<^esub> n'` have "nx' \<in> sum_SDG_slice1 n'"
      by(fastforce intro:slice1_ddep_slice1)
    with `n'' s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node nx')` `n \<in> sum_SDG_slice2 nx'` `n' \<in> S`
    show ?case by(fastforce intro:combine_SDG_slices.combSlice_Return_parent_node
                            simp:HRB_slice_def)
  qed
next
  case (isSp_Append_sum n ns nx p n')
  note IH = `\<And>S. \<lbrakk>n'' \<in> HRB_slice {n}; nx \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from IH[OF `n'' \<in> HRB_slice {n}`] have "n'' \<in> HRB_slice {nx}" by simp
  thus ?case
  proof(induct rule:HRB_slice_cases)
    case (phase1 n nx')
    from `nx' \<in> {nx}` have "nx' = nx" by simp
    with `n \<in> sum_SDG_slice1 nx'` `nx s-p\<rightarrow>\<^bsub>sum\<^esub> n'` have "n \<in> sum_SDG_slice1 n'"
      by(fastforce intro:slice1_sum_slice1)
    with `n' \<in> S` show ?case
      by(fastforce intro:combine_SDG_slices.combSlice_refl simp:HRB_slice_def)
  next
    case (phase2 nx'' nx' n'' p' n)
    from `nx'' \<in> {nx}` have "nx'' = nx" by simp
    with `nx' \<in> sum_SDG_slice1 nx''` `nx s-p\<rightarrow>\<^bsub>sum\<^esub> n'` have "nx' \<in> sum_SDG_slice1 n'"
      by(fastforce intro:slice1_sum_slice1)
    with `n'' s-p'\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node nx')` `n \<in> sum_SDG_slice2 nx'` `n' \<in> S`
    show ?case by(fastforce intro:combine_SDG_slices.combSlice_Return_parent_node
                            simp:HRB_slice_def)
  qed
qed

lemma call_return_nodes_in_slice:
  assumes "valid_edge a" and "kind a = Q\<hookleftarrow>\<^bsub>p\<^esub>f"
  and "valid_edge a'" and "kind a' = Q':r'\<hookrightarrow>\<^bsub>p\<^esub>fs'" and "a \<in> get_return_edges a'"
  and "CFG_node (targetnode a) \<in> HRB_slice S"
  shows "CFG_node (sourcenode a) \<in> HRB_slice S"
  and "CFG_node (sourcenode a') \<in> HRB_slice S"
  and "CFG_node (targetnode a') \<in> HRB_slice S"
proof -
  from `valid_edge a'` `kind a' = Q':r'\<hookrightarrow>\<^bsub>p\<^esub>fs'` `a \<in> get_return_edges a'`
  have "CFG_node (sourcenode a') s-p\<rightarrow>\<^bsub>sum\<^esub> CFG_node (targetnode a)"
    by(fastforce intro:sum_SDG_call_summary_edge)
  with `CFG_node (targetnode a) \<in> HRB_slice S`
  show "CFG_node (sourcenode a') \<in> HRB_slice S"
    by(fastforce elim!:combine_SDG_slices.cases
                intro:combine_SDG_slices.intros sum_slice1 sum_slice2
                 simp:HRB_slice_def)
  from `CFG_node (targetnode a) \<in> HRB_slice S`
  obtain n\<^sub>c where "CFG_node (targetnode a) \<in> combine_SDG_slices (sum_SDG_slice1 n\<^sub>c)"
    and "n\<^sub>c \<in> S"
    by(simp add:HRB_slice_def) blast
  thus "CFG_node (sourcenode a) \<in> HRB_slice S"
  proof(induct "CFG_node (targetnode a)" rule:combine_SDG_slices.induct)
    case combSlice_refl
    from `valid_edge a` `kind a = Q\<hookleftarrow>\<^bsub>p\<^esub>f`
    have "CFG_node (sourcenode a) s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (targetnode a)"
      by(fastforce intro:sum_SDG_return_edge)
    with `valid_edge a`
    have "CFG_node (sourcenode a) \<in> sum_SDG_slice2 (CFG_node (targetnode a))"
      by(fastforce intro:sum_SDG_slice2.intros)
    with `CFG_node (targetnode a) \<in> sum_SDG_slice1 n\<^sub>c` `n\<^sub>c \<in> S`
      `CFG_node (sourcenode a) s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (targetnode a)`
    show ?case by(fastforce intro:combSlice_Return_parent_node simp:HRB_slice_def)
  next
    case (combSlice_Return_parent_node n' n'' p')
    from `valid_edge a` `kind a = Q\<hookleftarrow>\<^bsub>p\<^esub>f`
    have "CFG_node (sourcenode a) s-p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (targetnode a)"
      by(fastforce intro:sum_SDG_return_edge)
    with `CFG_node (targetnode a) \<in> sum_SDG_slice2 n'`
    have "CFG_node (sourcenode a) \<in> sum_SDG_slice2 n'"
      by(fastforce intro:sum_SDG_slice2.intros)
    with `n' \<in> sum_SDG_slice1 n\<^sub>c` `n'' s-p'\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n')` `n\<^sub>c \<in> S`
    show ?case by(fastforce intro:combine_SDG_slices.combSlice_Return_parent_node
                            simp:HRB_slice_def)
  qed
  from `valid_edge a'` `kind a' = Q':r'\<hookrightarrow>\<^bsub>p\<^esub>fs'` `a \<in> get_return_edges a'`
  have "CFG_node (targetnode a') s\<longrightarrow>\<^bsub>cd\<^esub> CFG_node (sourcenode a)"
    by(fastforce intro:sum_SDG_proc_entry_exit_cdep)
  with `CFG_node (sourcenode a) \<in> HRB_slice S` `n\<^sub>c \<in> S`
  show "CFG_node (targetnode a') \<in> HRB_slice S"
    by(fastforce elim!:combine_SDG_slices.cases
                intro:combine_SDG_slices.intros cdep_slice1 cdep_slice2
                 simp:HRB_slice_def)
qed

subsection {* Proof of Precision *}

lemma in_intra_SDG_path_in_slice2:
  "\<lbrakk>n i-ns\<rightarrow>\<^sub>d* n'; n'' \<in> set ns\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n'"
proof(induct rule:intra_SDG_path.induct)
  case iSp_Nil thus ?case by simp
next
  case (iSp_Append_cdep n ns nx n')
  note IH = `n'' \<in> set ns \<Longrightarrow> n'' \<in> sum_SDG_slice2 nx`
  from `n'' \<in> set (ns@[nx])` have "n'' \<in> set ns \<or> n'' = nx" by auto
  thus ?case
  proof
    assume "n'' \<in> set ns"
    from IH[OF this] have "n'' \<in> sum_SDG_slice2 nx" by simp
    with `nx \<longrightarrow>\<^bsub>cd\<^esub> n'` show ?thesis
      by(fastforce intro:slice2_cdep_slice2 SDG_edge_sum_SDG_edge)
  next
    assume "n'' = nx"
    from `nx \<longrightarrow>\<^bsub>cd\<^esub> n'` have "valid_SDG_node n'" by(rule SDG_edge_valid_SDG_node)
    hence "n' \<in> sum_SDG_slice2 n'" by(rule refl_slice2)
    with `nx \<longrightarrow>\<^bsub>cd\<^esub> n'` have "nx \<in> sum_SDG_slice2 n'"
      by(fastforce intro:cdep_slice2 SDG_edge_sum_SDG_edge)
    with `n'' = nx` show ?thesis by simp
  qed
next
  case (iSp_Append_ddep n ns nx V n')
  note IH = `n'' \<in> set ns \<Longrightarrow> n'' \<in> sum_SDG_slice2 nx`
  from `n'' \<in> set (ns@[nx])` have "n'' \<in> set ns \<or> n'' = nx" by auto
  thus ?case
  proof
    assume "n'' \<in> set ns"
    from IH[OF this] have "n'' \<in> sum_SDG_slice2 nx" by simp
    with `nx -V\<rightarrow>\<^bsub>dd\<^esub> n'` show ?thesis
      by(fastforce intro:slice2_ddep_slice2 SDG_edge_sum_SDG_edge)
  next
    assume "n'' = nx"
    from `nx -V\<rightarrow>\<^bsub>dd\<^esub> n'` have "valid_SDG_node n'" by(rule SDG_edge_valid_SDG_node)
    hence "n' \<in> sum_SDG_slice2 n'" by(rule refl_slice2)
    with `nx -V\<rightarrow>\<^bsub>dd\<^esub> n'` have "nx \<in> sum_SDG_slice2 n'"
      by(fastforce intro:ddep_slice2 SDG_edge_sum_SDG_edge)
    with `n'' = nx` show ?thesis by simp
  qed
qed

lemma in_intra_SDG_path_in_HRB_slice:
  "\<lbrakk>n i-ns\<rightarrow>\<^sub>d* n'; n'' \<in> set ns; n' \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S"
proof(induct arbitrary:S rule:intra_SDG_path.induct)
  case iSp_Nil thus ?case by simp
next
  case (iSp_Append_cdep n ns nx n')
  note IH = `\<And>S. \<lbrakk>n'' \<in> set ns; nx \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from `n'' \<in> set (ns@[nx])` have "n'' \<in> set ns \<or> n'' = nx" by auto
  thus ?case
  proof
    assume "n'' \<in> set ns"
    from IH[OF `n'' \<in> set ns`] have "n'' \<in> HRB_slice {nx}" by simp
    from this `nx \<longrightarrow>\<^bsub>cd\<^esub> n'` `n' \<in> S` show ?case
      by(fastforce elim:HRB_slice_cases slice1_cdep_slice1
        intro:bexI[where x="n'"] combine_SDG_slices.intros SDG_edge_sum_SDG_edge
        simp:HRB_slice_def)
  next
    assume "n'' = nx"
    from `nx \<longrightarrow>\<^bsub>cd\<^esub> n'` have "valid_SDG_node n'" by(rule SDG_edge_valid_SDG_node)
    hence "n' \<in> sum_SDG_slice1 n'" by(rule refl_slice1)
    with `nx \<longrightarrow>\<^bsub>cd\<^esub> n'` have "nx \<in> sum_SDG_slice1 n'"
      by(fastforce intro:cdep_slice1 SDG_edge_sum_SDG_edge)
    with `n'' = nx` `n' \<in> S` show ?case
      by(fastforce intro:combSlice_refl simp:HRB_slice_def)
  qed
next
  case (iSp_Append_ddep n ns nx V n')
  note IH = `\<And>S. \<lbrakk>n'' \<in> set ns; nx \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from `n'' \<in> set (ns@[nx])` have "n'' \<in> set ns \<or> n'' = nx" by auto
  thus ?case
  proof
    assume "n'' \<in> set ns"
    from IH[OF `n'' \<in> set ns`] have "n'' \<in> HRB_slice {nx}" by simp
    from this `nx -V\<rightarrow>\<^bsub>dd\<^esub> n'` `n' \<in> S` show ?case
      by(fastforce elim:HRB_slice_cases slice1_ddep_slice1
        intro:bexI[where x="n'"] combine_SDG_slices.intros SDG_edge_sum_SDG_edge
        simp:HRB_slice_def)
  next
    assume "n'' = nx"
    from `nx -V\<rightarrow>\<^bsub>dd\<^esub> n'` have "valid_SDG_node n'" by(rule SDG_edge_valid_SDG_node)
    hence "n' \<in> sum_SDG_slice1 n'" by(rule refl_slice1)
    with `nx -V\<rightarrow>\<^bsub>dd\<^esub> n'` have "nx \<in> sum_SDG_slice1 n'"
      by(fastforce intro:ddep_slice1 SDG_edge_sum_SDG_edge)
    with `n'' = nx` `n' \<in> S` show ?case
      by(fastforce intro:combSlice_refl simp:HRB_slice_def)
  qed
qed

lemma in_matched_in_slice2:
  "\<lbrakk>matched n ns n'; n'' \<in> set ns\<rbrakk> \<Longrightarrow> n'' \<in> sum_SDG_slice2 n'"
proof(induct rule:matched.induct)
  case matched_Nil thus ?case by simp
next
  case (matched_Append_intra_SDG_path n ns nx ns' n')
  note IH = `n'' \<in> set ns \<Longrightarrow> n'' \<in> sum_SDG_slice2 nx`
  from `n'' \<in> set (ns@ns')` have "n'' \<in> set ns \<or> n'' \<in> set ns'" by simp
  thus ?case
  proof
    assume "n'' \<in> set ns"
    from IH[OF this] have "n'' \<in> sum_SDG_slice2 nx" .
    with `nx i-ns'\<rightarrow>\<^sub>d* n'` show ?thesis
      by(fastforce intro:slice2_is_SDG_path_slice2
                        intra_SDG_path_is_SDG_path)
  next
    assume "n'' \<in> set ns'"
    with `nx i-ns'\<rightarrow>\<^sub>d* n'` show ?case by(rule in_intra_SDG_path_in_slice2)
  qed
next
  case (matched_bracket_call n\<^sub>0 ns n\<^sub>1 p n\<^sub>2 ns' n\<^sub>3 n\<^sub>4 V a a')
  note IH1 = `n'' \<in> set ns \<Longrightarrow> n'' \<in> sum_SDG_slice2 n\<^sub>1`
  note IH2 = `n'' \<in> set ns' \<Longrightarrow> n'' \<in> sum_SDG_slice2 n\<^sub>3`
  from `n\<^sub>1 -p\<rightarrow>\<^bsub>call\<^esub> n\<^sub>2` `matched n\<^sub>2 ns' n\<^sub>3` `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    `a' \<in> get_return_edges a` `valid_edge a`
    `sourcenode a = parent_node n\<^sub>1` `targetnode a = parent_node n\<^sub>2`
    `sourcenode a' = parent_node n\<^sub>3` `targetnode a' = parent_node n\<^sub>4`
  have "matched n\<^sub>1 ([]@n\<^sub>1#ns'@[n\<^sub>3]) n\<^sub>4"
    by(fastforce intro:matched.matched_bracket_call matched_Nil
                 elim:SDG_edge_valid_SDG_node)
  then obtain nsx where "n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4" by(erule matched_is_SDG_path)
  from `n'' \<in> set (ns@n\<^sub>1#ns'@[n\<^sub>3])`
  have "((n'' \<in> set ns \<or> n'' = n\<^sub>1) \<or> n'' \<in> set ns') \<or> n'' = n\<^sub>3" by auto
  thus ?case apply -
  proof(erule disjE)+
    assume "n'' \<in> set ns"
    from IH1[OF this] have "n'' \<in> sum_SDG_slice2 n\<^sub>1" .
    with `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` show ?thesis
      by -(rule slice2_is_SDG_path_slice2)
  next
    assume "n'' = n\<^sub>1"
    from `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` have "n\<^sub>1 \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:is_SDG_path_slice2 refl_slice2 is_SDG_path_valid_SDG_node)
    with `n'' = n\<^sub>1` show ?thesis by(fastforce intro:combSlice_refl simp:HRB_slice_def)
  next
    assume "n'' \<in> set ns'"
    from IH2[OF this] have "n'' \<in> sum_SDG_slice2 n\<^sub>3" .
    with `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` show ?thesis
      by(fastforce intro:slice2_ret_slice2 slice2_param_out_slice2
                        SDG_edge_sum_SDG_edge)
  next
    assume "n'' = n\<^sub>3"
    from `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n\<^sub>3 s-p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 s-p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4"
      by(fastforce intro:SDG_edge_sum_SDG_edge)
    hence "n\<^sub>3 \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:return_slice2 param_out_slice2 refl_slice2
                        sum_SDG_edge_valid_SDG_node)
    with `n'' = n\<^sub>3` show ?thesis by simp
  qed
next
  case (matched_bracket_param n\<^sub>0 ns n\<^sub>1 p V n\<^sub>2 ns' n\<^sub>3 V' n\<^sub>4 a a')
  note IH1 = `n'' \<in> set ns \<Longrightarrow> n'' \<in> sum_SDG_slice2 n\<^sub>1`
  note IH2 = `n'' \<in> set ns' \<Longrightarrow> n'' \<in> sum_SDG_slice2 n\<^sub>3`
  from `n\<^sub>1 -p:V\<rightarrow>\<^bsub>in\<^esub> n\<^sub>2` `matched n\<^sub>2 ns' n\<^sub>3` `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    `a' \<in> get_return_edges a` `valid_edge a`
    `sourcenode a = parent_node n\<^sub>1` `targetnode a = parent_node n\<^sub>2`
    `sourcenode a' = parent_node n\<^sub>3` `targetnode a' = parent_node n\<^sub>4`
  have "matched n\<^sub>1 ([]@n\<^sub>1#ns'@[n\<^sub>3]) n\<^sub>4"
    by(fastforce intro:matched.matched_bracket_param matched_Nil
                 elim:SDG_edge_valid_SDG_node)
  then obtain nsx where "n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4" by(erule matched_is_SDG_path)
  from `n'' \<in> set (ns@n\<^sub>1#ns'@[n\<^sub>3])`
  have "((n'' \<in> set ns \<or> n'' = n\<^sub>1) \<or> n'' \<in> set ns') \<or> n'' = n\<^sub>3" by auto
  thus ?case apply -
  proof(erule disjE)+
    assume "n'' \<in> set ns"
    from IH1[OF this] have "n'' \<in> sum_SDG_slice2 n\<^sub>1" .
    with `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` show ?thesis
      by -(rule slice2_is_SDG_path_slice2)
  next
    assume "n'' = n\<^sub>1"
    from `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` have "n\<^sub>1 \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:is_SDG_path_slice2 refl_slice2 is_SDG_path_valid_SDG_node)
    with `n'' = n\<^sub>1` show ?thesis by(fastforce intro:combSlice_refl simp:HRB_slice_def)
  next
    assume "n'' \<in> set ns'"
    from IH2[OF this] have "n'' \<in> sum_SDG_slice2 n\<^sub>3" .
    with `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` show ?thesis
      by(fastforce intro:slice2_param_out_slice2 SDG_edge_sum_SDG_edge)
  next
    assume "n'' = n\<^sub>3"
    from `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n\<^sub>3 s-p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4" by(rule SDG_edge_sum_SDG_edge)
    hence "n\<^sub>3 \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:param_out_slice2 refl_slice2 sum_SDG_edge_valid_SDG_node)
    with `n'' = n\<^sub>3` show ?thesis by simp
  qed
qed

lemma in_matched_in_HRB_slice:
  "\<lbrakk>matched n ns n'; n'' \<in> set ns; n' \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S"
proof(induct arbitrary:S rule:matched.induct)
   case matched_Nil thus ?case by simp
next
  case (matched_Append_intra_SDG_path n ns nx ns' n')
  note IH = `\<And>S. \<lbrakk>n'' \<in> set ns; nx \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from `n'' \<in> set (ns@ns')` have "n'' \<in> set ns \<or> n'' \<in> set ns'" by simp
  thus ?case
  proof
    assume "n'' \<in> set ns"
    from IH[OF `n'' \<in> set ns`] have "n'' \<in> HRB_slice {nx}" by simp
    with `nx i-ns'\<rightarrow>\<^sub>d* n'` `n' \<in> S` show ?thesis
      by(fastforce intro:HRB_slice_is_SDG_path_HRB_slice
                        intra_SDG_path_is_SDG_path)
  next
    assume "n'' \<in> set ns'"
    with `nx i-ns'\<rightarrow>\<^sub>d* n'` `n' \<in> S` show ?case
      by(fastforce intro:in_intra_SDG_path_in_HRB_slice simp:HRB_slice_def)
  qed
next
  case (matched_bracket_call n\<^sub>0 ns n\<^sub>1 p n\<^sub>2 ns' n\<^sub>3 n\<^sub>4 V a a')
  note IH1 = `\<And>S. \<lbrakk>n'' \<in> set ns; n\<^sub>1 \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  note IH2 = `\<And>S. \<lbrakk>n'' \<in> set ns'; n\<^sub>3 \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from `n\<^sub>1 -p\<rightarrow>\<^bsub>call\<^esub> n\<^sub>2` `matched n\<^sub>2 ns' n\<^sub>3` `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    `a' \<in> get_return_edges a` `valid_edge a`
    `sourcenode a = parent_node n\<^sub>1` `targetnode a = parent_node n\<^sub>2`
    `sourcenode a' = parent_node n\<^sub>3` `targetnode a' = parent_node n\<^sub>4`
  have "matched n\<^sub>1 ([]@n\<^sub>1#ns'@[n\<^sub>3]) n\<^sub>4"
    by(fastforce intro:matched.matched_bracket_call matched_Nil
                 elim:SDG_edge_valid_SDG_node)
  then obtain nsx where "n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4" by(erule matched_is_SDG_path)
  from `n'' \<in> set (ns@n\<^sub>1#ns'@[n\<^sub>3])`
  have "((n'' \<in> set ns \<or> n'' = n\<^sub>1) \<or> n'' \<in> set ns') \<or> n'' = n\<^sub>3" by auto
  thus ?case apply -
  proof(erule disjE)+
    assume "n'' \<in> set ns"
    from IH1[OF this] have "n'' \<in> HRB_slice {n\<^sub>1}" by simp
    with `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` `n\<^sub>4 \<in> S` show ?thesis
      by -(rule HRB_slice_is_SDG_path_HRB_slice)
  next
    assume "n'' = n\<^sub>1"
    from `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` have "n\<^sub>1 \<in> sum_SDG_slice1 n\<^sub>4"
      by(fastforce intro:is_SDG_path_slice1 refl_slice1 is_SDG_path_valid_SDG_node)
    with `n'' = n\<^sub>1` `n\<^sub>4 \<in> S` show ?thesis
      by(fastforce intro:combSlice_refl simp:HRB_slice_def)
  next
    assume "n'' \<in> set ns'"
    with `matched n\<^sub>2 ns' n\<^sub>3` have "n'' \<in> sum_SDG_slice2 n\<^sub>3"
      by(rule in_matched_in_slice2)
    with `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n'' \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:slice2_ret_slice2 slice2_param_out_slice2
                        SDG_edge_sum_SDG_edge)
    from `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "valid_SDG_node n\<^sub>4"
      by(fastforce intro:SDG_edge_valid_SDG_node)
    hence "n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4" by(rule refl_slice1)
    from `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    have "CFG_node (parent_node n\<^sub>3) -p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n\<^sub>4)"
      by(fastforce elim:SDG_edge.cases intro:SDG_return_edge)
    with `n'' \<in> sum_SDG_slice2 n\<^sub>4` `n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4` `n\<^sub>4 \<in> S`
    show ?case by(fastforce intro:combSlice_Return_parent_node SDG_edge_sum_SDG_edge
                            simp:HRB_slice_def)
  next
    assume "n'' = n\<^sub>3"
    from `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    have "CFG_node (parent_node n\<^sub>3) -p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n\<^sub>4)"
      by(fastforce elim:SDG_edge.cases intro:SDG_return_edge)
    from `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "valid_SDG_node n\<^sub>4"
      by(fastforce intro:SDG_edge_valid_SDG_node)
    hence "n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4" by(rule refl_slice1)
    from `valid_SDG_node n\<^sub>4` have "n\<^sub>4 \<in> sum_SDG_slice2 n\<^sub>4" by(rule refl_slice2)
    with `n\<^sub>3 -p\<rightarrow>\<^bsub>ret\<^esub> n\<^sub>4 \<or> n\<^sub>3 -p:V\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n\<^sub>3 \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:return_slice2 param_out_slice2 SDG_edge_sum_SDG_edge)
    with `n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4`
      `CFG_node (parent_node n\<^sub>3) -p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n\<^sub>4)` `n'' = n\<^sub>3` `n\<^sub>4 \<in> S`
    show ?case by(fastforce intro:combSlice_Return_parent_node SDG_edge_sum_SDG_edge
                            simp:HRB_slice_def)
  qed
next
  case (matched_bracket_param n\<^sub>0 ns n\<^sub>1 p V n\<^sub>2 ns' n\<^sub>3 V' n\<^sub>4 a a')
  note IH1 = `\<And>S. \<lbrakk>n'' \<in> set ns; n\<^sub>1 \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  note IH2 = `\<And>S. \<lbrakk>n'' \<in> set ns'; n\<^sub>3 \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from `n\<^sub>1 -p:V\<rightarrow>\<^bsub>in\<^esub> n\<^sub>2` `matched n\<^sub>2 ns' n\<^sub>3` `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    `a' \<in> get_return_edges a` `valid_edge a`
    `sourcenode a = parent_node n\<^sub>1` `targetnode a = parent_node n\<^sub>2`
    `sourcenode a' = parent_node n\<^sub>3` `targetnode a' = parent_node n\<^sub>4`
  have "matched n\<^sub>1 ([]@n\<^sub>1#ns'@[n\<^sub>3]) n\<^sub>4"
    by(fastforce intro:matched.matched_bracket_param matched_Nil
                 elim:SDG_edge_valid_SDG_node)
  then obtain nsx where "n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4" by(erule matched_is_SDG_path)
  from `n'' \<in> set (ns@n\<^sub>1#ns'@[n\<^sub>3])`
  have "((n'' \<in> set ns \<or> n'' = n\<^sub>1) \<or> n'' \<in> set ns') \<or> n'' = n\<^sub>3" by auto
  thus ?case apply -
  proof(erule disjE)+
    assume "n'' \<in> set ns"
    from IH1[OF this] have "n'' \<in> HRB_slice {n\<^sub>1}" by simp
    with `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` `n\<^sub>4 \<in> S` show ?thesis
      by -(rule HRB_slice_is_SDG_path_HRB_slice)
  next
    assume "n'' = n\<^sub>1"
    from `n\<^sub>1 is-nsx\<rightarrow>\<^sub>d* n\<^sub>4` have "n\<^sub>1 \<in> sum_SDG_slice1 n\<^sub>4"
      by(fastforce intro:is_SDG_path_slice1 refl_slice1 is_SDG_path_valid_SDG_node)
    with `n'' = n\<^sub>1` `n\<^sub>4 \<in> S` show ?thesis
      by(fastforce intro:combSlice_refl simp:HRB_slice_def)
  next
    assume "n'' \<in> set ns'"
    with `matched n\<^sub>2 ns' n\<^sub>3` have "n'' \<in> sum_SDG_slice2 n\<^sub>3"
      by(rule in_matched_in_slice2)
    with `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n'' \<in> sum_SDG_slice2 n\<^sub>4"
      by(fastforce intro:slice2_param_out_slice2 SDG_edge_sum_SDG_edge)
    from `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "valid_SDG_node n\<^sub>4" by(rule SDG_edge_valid_SDG_node)
    hence "n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4" by(rule refl_slice1)
    from `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    have "CFG_node (parent_node n\<^sub>3) -p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n\<^sub>4)"
      by(fastforce elim:SDG_edge.cases intro:SDG_return_edge)
    with `n'' \<in> sum_SDG_slice2 n\<^sub>4` `n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4` `n\<^sub>4 \<in> S`
    show ?case by(fastforce intro:combSlice_Return_parent_node SDG_edge_sum_SDG_edge
                            simp:HRB_slice_def)
  next
    assume "n'' = n\<^sub>3"
    from `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n\<^sub>3 s-p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4" by(rule SDG_edge_sum_SDG_edge)
    from `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "valid_SDG_node n\<^sub>4" by(rule SDG_edge_valid_SDG_node)
    hence "n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4" by(rule refl_slice1)
    from `valid_SDG_node n\<^sub>4` have "n\<^sub>4 \<in> sum_SDG_slice2 n\<^sub>4" by(rule refl_slice2)
    with `n\<^sub>3 s-p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4` have "n\<^sub>3 \<in> sum_SDG_slice2 n\<^sub>4" by(rule param_out_slice2)
    from `n\<^sub>3 -p:V'\<rightarrow>\<^bsub>out\<^esub> n\<^sub>4`
    have "CFG_node (parent_node n\<^sub>3) -p\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n\<^sub>4)"
      by(fastforce elim:SDG_edge.cases intro:SDG_return_edge)
    with `n\<^sub>3 \<in> sum_SDG_slice2 n\<^sub>4` `n\<^sub>4 \<in> sum_SDG_slice1 n\<^sub>4` `n'' = n\<^sub>3` `n\<^sub>4 \<in> S`
    show ?case by(fastforce intro:combSlice_Return_parent_node SDG_edge_sum_SDG_edge
                            simp:HRB_slice_def)
  qed
qed

theorem in_realizable_in_HRB_slice:
  "\<lbrakk>realizable n ns n'; n'' \<in> set ns; n' \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S"
proof(induct arbitrary:S rule:realizable.induct)
  case (realizable_matched n ns n') thus ?case by(rule in_matched_in_HRB_slice)
next
  case (realizable_call n\<^sub>0 ns n\<^sub>1 p n\<^sub>2 V ns' n\<^sub>3)
  note IH = `\<And>S. \<lbrakk>n'' \<in> set ns; n\<^sub>1 \<in> S\<rbrakk> \<Longrightarrow> n'' \<in> HRB_slice S`
  from `n'' \<in> set (ns@n\<^sub>1#ns')` have "(n'' \<in> set ns \<or> n'' = n\<^sub>1) \<or> n'' \<in> set ns'"
    by auto
  thus ?case apply -
  proof(erule disjE)+
    assume "n'' \<in> set ns"
    from IH[OF this] have "n'' \<in> HRB_slice {n\<^sub>1}" by simp
    hence "n'' \<in> HRB_slice {n\<^sub>2}"
    proof(induct rule:HRB_slice_cases)
      case (phase1 n nx)
      from `nx \<in> {n\<^sub>1}` have "nx = n\<^sub>1" by simp
      with `n \<in> sum_SDG_slice1 nx` `n\<^sub>1 -p\<rightarrow>\<^bsub>call\<^esub> n\<^sub>2 \<or> n\<^sub>1 -p:V\<rightarrow>\<^bsub>in\<^esub> n\<^sub>2`
      have "n \<in> sum_SDG_slice1 n\<^sub>2"
        by(fastforce intro:slice1_call_slice1 slice1_param_in_slice1
                          SDG_edge_sum_SDG_edge)
      thus ?case
        by(fastforce intro:combine_SDG_slices.combSlice_refl simp:HRB_slice_def)
    next
      case (phase2 nx n' n'' p' n)
      from `nx \<in> {n\<^sub>1}` have "nx = n\<^sub>1" by simp
      with `n' \<in> sum_SDG_slice1 nx` `n\<^sub>1 -p\<rightarrow>\<^bsub>call\<^esub> n\<^sub>2 \<or> n\<^sub>1 -p:V\<rightarrow>\<^bsub>in\<^esub> n\<^sub>2`
      have "n' \<in> sum_SDG_slice1 n\<^sub>2"
        by(fastforce intro:slice1_call_slice1 slice1_param_in_slice1
                          SDG_edge_sum_SDG_edge)
      with `n'' s-p'\<rightarrow>\<^bsub>ret\<^esub> CFG_node (parent_node n')` `n \<in> sum_SDG_slice2 n'` show ?case
        by(fastforce intro:combine_SDG_slices.combSlice_Return_parent_node
                     simp:HRB_slice_def)
    qed
    from `matched n\<^sub>2 ns' n\<^sub>3` obtain nsx where "n\<^sub>2 is-nsx\<rightarrow>\<^sub>d* n\<^sub>3"
      by(erule matched_is_SDG_path)
    with `n'' \<in> HRB_slice {n\<^sub>2}` `n\<^sub>3 \<in> S` show ?thesis
      by(fastforce intro:HRB_slice_is_SDG_path_HRB_slice)
  next
    assume "n'' = n\<^sub>1"
    from `matched n\<^sub>2 ns' n\<^sub>3` obtain nsx where "n\<^sub>2 is-nsx\<rightarrow>\<^sub>d* n\<^sub>3"
      by(erule matched_is_SDG_path)
    hence "n\<^sub>2 \<in> sum_SDG_slice1 n\<^sub>2"
      by(fastforce intro:refl_slice1 is_SDG_path_valid_SDG_node)
    with `n\<^sub>1 -p\<rightarrow>\<^bsub>call\<^esub> n\<^sub>2 \<or> n\<^sub>1 -p:V\<rightarrow>\<^bsub>in\<^esub> n\<^sub>2`
    have "n\<^sub>1 \<in> sum_SDG_slice1 n\<^sub>2"
      by(fastforce intro:call_slice1 param_in_slice1 SDG_edge_sum_SDG_edge)
    hence "n\<^sub>1 \<in> HRB_slice {n\<^sub>2}" by(fastforce intro:combSlice_refl simp:HRB_slice_def)
    with `n\<^sub>2 is-nsx\<rightarrow>\<^sub>d* n\<^sub>3` `n'' = n\<^sub>1` `n\<^sub>3 \<in> S` show ?thesis
      by(fastforce intro:HRB_slice_is_SDG_path_HRB_slice)
  next
    assume "n'' \<in> set ns'"
    from `matched n\<^sub>2 ns' n\<^sub>3` this `n\<^sub>3 \<in> S` show ?thesis
      by(rule in_matched_in_HRB_slice)
  qed
qed

lemma slice1_ics_SDG_path:
  assumes "n \<in> sum_SDG_slice1 n'" and "n \<noteq> n'"
  obtains ns where "CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n'" and "n \<in> set ns"
proof(atomize_elim)
  from `n \<in> sum_SDG_slice1 n'`
  have "n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)"
  proof(induct rule:sum_SDG_slice1.induct)
    case refl_slice1 thus ?case by simp
  next
    case (cdep_slice1 n'' n)
    from `n'' s\<longrightarrow>\<^bsub>cd\<^esub> n` have "valid_SDG_node n''" by(rule sum_SDG_edge_valid_SDG_node)
    hence "n'' ics-[]\<rightarrow>\<^sub>d* n''" by(rule icsSp_Nil)
    from `valid_SDG_node n''` have "valid_node (parent_node n'')"
      by(rule valid_SDG_CFG_node)
    thus ?case
    proof(cases "parent_node n'' = (_Exit_)")
      case True
      with `valid_SDG_node n''` have "n'' = CFG_node (_Exit_)"
        by(rule valid_SDG_node_parent_Exit)
      with `n'' s\<longrightarrow>\<^bsub>cd\<^esub> n` have False by(fastforce intro:Exit_no_sum_SDG_edge_source)
      thus ?thesis by simp
    next
      case False
      from `n'' s\<longrightarrow>\<^bsub>cd\<^esub> n` have "valid_SDG_node n''"
        by(rule sum_SDG_edge_valid_SDG_node)
      from this False obtain ns
        where "CFG_node (_Entry_) cc-ns\<rightarrow>\<^sub>d* n''"
        by(erule Entry_cc_SDG_path_to_inner_node)
      with `n'' s\<longrightarrow>\<^bsub>cd\<^esub> n` have "CFG_node (_Entry_) cc-ns@[n'']\<rightarrow>\<^sub>d* n"
        by(fastforce intro:ccSp_Append_cdep sum_SDG_edge_SDG_edge)
      hence "CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n"
        by(rule cc_SDG_path_ics_SDG_path)
      from `n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)`
      show ?thesis
      proof
        assume "n = n'"
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n` show ?thesis by fastforce
      next
        assume "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns"
        then obtain nsx where "CFG_node (_Entry_) ics-nsx\<rightarrow>\<^sub>d* n'" and "n \<in> set nsx"
          by blast
        then obtain ns' ns'' where "nsx = ns'@ns''" and "n ics-ns''\<rightarrow>\<^sub>d* n'"
          by -(erule ics_SDG_path_split)
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n`
        show ?thesis by(fastforce intro:ics_SDG_path_Append)
      qed
    qed
  next
    case (ddep_slice1 n'' V n)
    from `n'' s-V\<rightarrow>\<^bsub>dd\<^esub> n` have "valid_SDG_node n''" by(rule sum_SDG_edge_valid_SDG_node)
    hence "n'' ics-[]\<rightarrow>\<^sub>d* n''" by(rule icsSp_Nil)
    from `valid_SDG_node n''` have "valid_node (parent_node n'')"
      by(rule valid_SDG_CFG_node)
    thus ?case
    proof(cases "parent_node n'' = (_Exit_)")
      case True
      with `valid_SDG_node n''` have "n'' = CFG_node (_Exit_)"
        by(rule valid_SDG_node_parent_Exit)
      with `n'' s-V\<rightarrow>\<^bsub>dd\<^esub> n` have False by(fastforce intro:Exit_no_sum_SDG_edge_source)
      thus ?thesis by simp
    next
      case False
      from `n'' s-V\<rightarrow>\<^bsub>dd\<^esub> n` have "valid_SDG_node n''"
        by(rule sum_SDG_edge_valid_SDG_node)
      from this False obtain ns
        where "CFG_node (_Entry_) cc-ns\<rightarrow>\<^sub>d* n''"
        by(erule Entry_cc_SDG_path_to_inner_node)
     hence "CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n''"
        by(rule cc_SDG_path_ics_SDG_path)
      show ?thesis
      proof(cases "n'' = n")
        case True
        from `n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)`
        show ?thesis
        proof
          assume "n = n'"
          with `n'' = n` show ?thesis by simp
        next
          assume "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns"
          with `n'' = n` show ?thesis by fastforce
        qed
      next
        case False
        with `n'' s-V\<rightarrow>\<^bsub>dd\<^esub> n` `CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n''`
        have "CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n"
          by -(rule icsSp_Append_ddep)
        from `n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)`
        show ?thesis
        proof
          assume "n = n'"
          with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n` show ?thesis by fastforce
        next
          assume "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns"
          then obtain nsx where "CFG_node (_Entry_) ics-nsx\<rightarrow>\<^sub>d* n'" and "n \<in> set nsx"
            by blast
          then obtain ns' ns'' where "nsx = ns'@ns''" and "n ics-ns''\<rightarrow>\<^sub>d* n'"
            by -(erule ics_SDG_path_split)
          with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n`
          show ?thesis by(fastforce intro:ics_SDG_path_Append)
        qed
      qed
    qed
  next
    case (call_slice1 n'' p n)
    from `n'' s-p\<rightarrow>\<^bsub>call\<^esub> n` have "valid_SDG_node n''"
      by(rule sum_SDG_edge_valid_SDG_node)
    hence "n'' ics-[]\<rightarrow>\<^sub>d* n''" by(rule icsSp_Nil)
    from `valid_SDG_node n''` have "valid_node (parent_node n'')"
      by(rule valid_SDG_CFG_node)
    thus ?case
    proof(cases "parent_node n'' = (_Exit_)")
      case True
      with `valid_SDG_node n''` have "n'' = CFG_node (_Exit_)"
        by(rule valid_SDG_node_parent_Exit)
      with `n'' s-p\<rightarrow>\<^bsub>call\<^esub> n` have False by(fastforce intro:Exit_no_sum_SDG_edge_source)
      thus ?thesis by simp
    next
      case False
      from `n'' s-p\<rightarrow>\<^bsub>call\<^esub> n` have "valid_SDG_node n''"
        by(rule sum_SDG_edge_valid_SDG_node)
      from this False obtain ns
        where "CFG_node (_Entry_) cc-ns\<rightarrow>\<^sub>d* n''"
        by(erule Entry_cc_SDG_path_to_inner_node)
      with `n'' s-p\<rightarrow>\<^bsub>call\<^esub> n` have "CFG_node (_Entry_) cc-ns@[n'']\<rightarrow>\<^sub>d* n"
        by(fastforce intro:ccSp_Append_call sum_SDG_edge_SDG_edge)
      hence "CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n"
        by(rule cc_SDG_path_ics_SDG_path)
      from `n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)`
      show ?thesis
      proof
        assume "n = n'"
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n` show ?thesis by fastforce
      next
        assume "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns"
        then obtain nsx where "CFG_node (_Entry_) ics-nsx\<rightarrow>\<^sub>d* n'" and "n \<in> set nsx"
          by blast
        then obtain ns' ns'' where "nsx = ns'@ns''" and "n ics-ns''\<rightarrow>\<^sub>d* n'"
          by -(erule ics_SDG_path_split)
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n`
        show ?thesis by(fastforce intro:ics_SDG_path_Append)
      qed
    qed
  next
    case (param_in_slice1 n'' p V n)
    from `n'' s-p:V\<rightarrow>\<^bsub>in\<^esub> n` have "valid_SDG_node n''"
      by(rule sum_SDG_edge_valid_SDG_node)
    hence "n'' ics-[]\<rightarrow>\<^sub>d* n''" by(rule icsSp_Nil)
    from `valid_SDG_node n''` have "valid_node (parent_node n'')"
      by(rule valid_SDG_CFG_node)
    thus ?case
    proof(cases "parent_node n'' = (_Exit_)")
      case True
      with `valid_SDG_node n''` have "n'' = CFG_node (_Exit_)"
        by(rule valid_SDG_node_parent_Exit)
      with `n'' s-p:V\<rightarrow>\<^bsub>in\<^esub> n` have False by(fastforce intro:Exit_no_sum_SDG_edge_source)
      thus ?thesis by simp
    next
      case False
      from `n'' s-p:V\<rightarrow>\<^bsub>in\<^esub> n` have "valid_SDG_node n''"
        by(rule sum_SDG_edge_valid_SDG_node)
      from this False obtain ns
        where "CFG_node (_Entry_) cc-ns\<rightarrow>\<^sub>d* n''"
        by(erule Entry_cc_SDG_path_to_inner_node)
      hence "CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n''"
        by(rule cc_SDG_path_ics_SDG_path)
      with `n'' s-p:V\<rightarrow>\<^bsub>in\<^esub> n` have "CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n"
        by -(rule icsSp_Append_param_in)
      from `n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)`
      show ?thesis
      proof
        assume "n = n'"
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n` show ?thesis by fastforce
      next
        assume "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns"
        then obtain nsx where "CFG_node (_Entry_) ics-nsx\<rightarrow>\<^sub>d* n'" and "n \<in> set nsx"
          by blast
        then obtain ns' ns'' where "nsx = ns'@ns''" and "n ics-ns''\<rightarrow>\<^sub>d* n'"
          by -(erule ics_SDG_path_split)
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n`
        show ?thesis by(fastforce intro:ics_SDG_path_Append)
      qed
    qed
  next
    case (sum_slice1 n'' p n)
    from `n'' s-p\<rightarrow>\<^bsub>sum\<^esub> n` have "valid_SDG_node n''"
      by(rule sum_SDG_edge_valid_SDG_node)
    hence "n'' ics-[]\<rightarrow>\<^sub>d* n''" by(rule icsSp_Nil)
    from `valid_SDG_node n''` have "valid_node (parent_node n'')"
      by(rule valid_SDG_CFG_node)
    thus ?case
    proof(cases "parent_node n'' = (_Exit_)")
      case True
      with `valid_SDG_node n''` have "n'' = CFG_node (_Exit_)"
        by(rule valid_SDG_node_parent_Exit)
      with `n'' s-p\<rightarrow>\<^bsub>sum\<^esub> n` have False by(fastforce intro:Exit_no_sum_SDG_edge_source)
      thus ?thesis by simp
    next
      case False
      from `n'' s-p\<rightarrow>\<^bsub>sum\<^esub> n` have "valid_SDG_node n''"
        by(rule sum_SDG_edge_valid_SDG_node)
      from this False obtain ns
        where "CFG_node (_Entry_) cc-ns\<rightarrow>\<^sub>d* n''"
        by(erule Entry_cc_SDG_path_to_inner_node)
      hence "CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n''"
        by(rule cc_SDG_path_ics_SDG_path)
      with `n'' s-p\<rightarrow>\<^bsub>sum\<^esub> n` have "CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n"
        by -(rule icsSp_Append_sum)
      from `n = n' \<or> (\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns)`
      show ?thesis
      proof
        assume "n = n'"
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n` show ?thesis by fastforce
      next
        assume "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns"
        then obtain nsx where "CFG_node (_Entry_) ics-nsx\<rightarrow>\<^sub>d* n'" and "n \<in> set nsx"
          by blast
        then obtain ns' ns'' where "nsx = ns'@ns''" and "n ics-ns''\<rightarrow>\<^sub>d* n'"
          by -(erule ics_SDG_path_split)
        with `CFG_node (_Entry_) ics-ns@[n'']\<rightarrow>\<^sub>d* n`
        show ?thesis by(fastforce intro:ics_SDG_path_Append)
      qed
    qed
  qed
  with `n \<noteq> n'` show "\<exists>ns. CFG_node (_Entry_) ics-ns\<rightarrow>\<^sub>d* n' \<and> n \<in> set ns" by simp
qed

lemma slice2_irs_SDG_path:
  assumes "n \<in> sum_SDG_slice2 n'" and "valid_SDG_node n'"
  obtains ns where "n irs-ns\<rightarrow>\<^sub>d* n'"
using assms
by(induct rule:sum_SDG_slice2.induct,auto intro:intra_return_sum_SDG_path.intros)

theorem HRB_slice_realizable:
  assumes "n \<in> HRB_slice S" and "\<forall>n' \<in> S. valid_SDG_node n'" and "n \<notin> S"
  obtains n' ns where "n' \<in> S" and "realizable (CFG_node (_Entry_)) ns n'"
  and "n \<in> set ns"
proof(atomize_elim)
  from `n \<in> HRB_slice S` `n \<notin> S`
  show "\<exists>n' ns. n' \<in> S \<and> realizable (CFG_node (_Entry_)) ns n' \<and> n \<in> set ns"
  proof(induct rule:HRB_slice_cases)
    case (phase1 n nx)
    with `n \<notin> S` show ?case
      by(fastforce elim:slice1_ics_SDG_path ics_SDG_path_realizable)
  next
    case (phase2 n' nx n'' p n)
    from `\<forall>n' \<in> S. valid_SDG_node n'` `n' \<in> S` have "valid_SDG_node n'" by simp
    with `nx \<in> sum_SDG_slice1 n'` have "valid_SDG_node nx"
      by(auto elim:slice1_ics_SDG_path ics_SDG_path_split
              intro:ics_SDG_path_valid_SDG_node)
    with `n \<in> sum_SDG_slice2 nx`
    obtain nsx where "n irs-nsx\<rightarrow>\<^sub>d* nx" by(erule slice2_irs_SDG_path)
    show ?case
    proof(cases "n = nx")
      case True
      show ?thesis
      proof(cases "nx = n'")
        case True
        with `n = nx` `n \<notin> S` `n' \<in> S` have False by simp
        thus ?thesis by simp
      next
        case False
        with `nx \<in> sum_SDG_slice1 n'` obtain ns
          where "realizable (CFG_node (_Entry_)) ns n'" and "nx \<in> set ns"
          by(fastforce elim:slice1_ics_SDG_path ics_SDG_path_realizable)
        with `n = nx` `n' \<in> S` show ?thesis by blast
      qed
    next
      case False
      with `n irs-nsx\<rightarrow>\<^sub>d* nx` obtain ns
        where "realizable (CFG_node (_Entry_)) ns nx" and "n \<in> set ns"
        by(erule irs_SDG_path_realizable)
      show ?thesis
      proof(cases "nx = n'")
        case True
        with `realizable (CFG_node (_Entry_)) ns nx` `n \<in> set ns` `n' \<in> S`
        show ?thesis by blast
      next
        case False
        with `nx \<in> sum_SDG_slice1 n'` obtain nsx'
          where "CFG_node (_Entry_) ics-nsx'\<rightarrow>\<^sub>d* n'" and "nx \<in> set nsx'"
          by(erule slice1_ics_SDG_path)
        then obtain ns' where "nx ics-ns'\<rightarrow>\<^sub>d* n'" by -(erule ics_SDG_path_split)
        with `realizable (CFG_node (_Entry_)) ns nx`
        obtain ns'' where "realizable (CFG_node (_Entry_)) (ns@ns'') n'"
          by(erule realizable_Append_ics_SDG_path)
        with `n \<in> set ns` `n' \<in> S` show ?thesis by fastforce
      qed
    qed
  qed
qed

theorem HRB_slice_precise:
  "\<lbrakk>\<forall>n' \<in> S. valid_SDG_node n'; n \<notin> S\<rbrakk> \<Longrightarrow>
    n \<in> HRB_slice S =
    (\<exists>n' ns. n' \<in> S \<and> realizable (CFG_node (_Entry_)) ns n' \<and> n \<in> set ns)"
  by(fastforce elim:HRB_slice_realizable intro:in_realizable_in_HRB_slice)

end

end


(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: BSD-2-Clause
 *)

(* License: BSD, terms see file ./LICENSE *)

theory ArrayAssertion

imports
  "$L4V_ARCH/ArchArraysMemInstance"
  "StructSupport"

begin

lemma array_tag_n_eq:
  "(array_tag_n n :: ('a :: c_type['b :: finite]) field_desc typ_desc) =
  TypDesc (TypAggregate
    (map (\<lambda>n. DTPair (adjust_ti (typ_info_t TYPE('a)) (\<lambda>x. index x n)
            (\<lambda>x f. Arrays.update f n x)) (replicate n CHR ''1'')) [0..<n]))
  (typ_name (typ_uinfo_t TYPE('a)) @ ''_array_'' @ nat_to_bin_string (card (UNIV :: 'b :: finite set)))"
  apply (induct n)
   apply (simp add: typ_info_array array_tag_def eval_nat_numeral array_tag_n.simps empty_typ_info_def)
   apply (simp add: typ_info_array array_tag_def eval_nat_numeral array_tag_n.simps empty_typ_info_def)
   apply (simp add: ti_typ_combine_def Let_def)
   done

lemma typ_info_array':
  "typ_info_t TYPE ('a :: c_type['b :: finite]) =
  TypDesc (TypAggregate
    (map (\<lambda>n. DTPair (adjust_ti (typ_info_t TYPE('a)) (\<lambda>x. index x n)
            (\<lambda>x f. Arrays.update f n x)) (replicate n CHR ''1'')) [0..<(card (UNIV :: 'b :: finite set))]))
  (typ_name (typ_uinfo_t TYPE('a)) @ ''_array_'' @ nat_to_bin_string (card (UNIV :: 'b :: finite set)))"
  by (simp add: typ_info_array array_tag_def array_tag_n_eq)

definition
  "uinfo_array_tag_n_m (v :: 'a itself) n m = TypDesc
    (TypAggregate (map (\<lambda>i. DTPair (typ_uinfo_t TYPE('a)) (replicate i CHR ''1'')) [0 ..< n]))
    (typ_name (typ_uinfo_t TYPE('a :: c_type)) @ ''_array_'' @ nat_to_bin_string m)"

lemma map_td_list_map:
  "map_td_list f = map (map_td_pair f)"
  by (rule ext, rename_tac x) (induct_tac x, simp_all)

lemma uinfo_array_tag_n_m_eq:
  "n \<le> CARD('b)
    \<Longrightarrow> export_uinfo (array_tag_n n :: (('a :: wf_type)['b :: finite]) field_desc typ_desc)
        = uinfo_array_tag_n_m TYPE ('a) n (CARD('b))"
  apply (clarsimp simp: uinfo_array_tag_n_m_def array_tag_n_eq map_td_list_map
                        o_def adjust_ti_def map_td_map typ_uinfo_t_def export_uinfo_def)
  apply (fastforce intro: map_td_extI simp: field_norm_blah)
  done

lemma typ_uinfo_array_tag_n_m_eq:
  "typ_uinfo_t TYPE (('a :: wf_type)['b :: finite])
        = uinfo_array_tag_n_m TYPE ('a) (CARD('b)) (CARD('b))"
  by (simp add: typ_uinfo_t_def typ_info_array array_tag_def uinfo_array_tag_n_m_eq)

text \<open>Alternative to h_t_valid for arrays. This allows reasoning
about arrays of variable width.\<close>
definition h_t_array_valid :: "heap_typ_desc \<Rightarrow> ('a :: c_type) ptr \<Rightarrow> nat \<Rightarrow> bool" where
  "h_t_array_valid htd ptr n = valid_footprint htd (ptr_val ptr) (uinfo_array_tag_n_m TYPE ('a) n n)"

text \<open>Assertion that pointer p is within an array that continues for at least n more elements.\<close>
definition
  "array_assertion (p :: ('a :: c_type) ptr) n htd
    = (\<exists>q i j. h_t_array_valid htd q j
        \<and> p = CTypesDefs.ptr_add q (int i) \<and> i < j \<and> i + n \<le> j)"

lemma array_assertion_shrink_right:
  "array_assertion p n htd \<Longrightarrow> n' \<le> n \<Longrightarrow> array_assertion p n' htd"
  by (fastforce simp: array_assertion_def)

lemma array_assertion_shrink_leftD:
  "array_assertion p n htd \<Longrightarrow> j < n \<Longrightarrow> array_assertion (CTypesDefs.ptr_add p (int j)) (n - j) htd"
  apply (clarsimp simp: array_assertion_def)
  apply (rule exI, rule_tac x="i + j" in exI, rule exI, erule conjI)
  apply (simp add: CTypesDefs.ptr_add_def field_simps)
  done

lemma array_assertion_shrink_leftI:
  "array_assertion (CTypesDefs.ptr_add p (- (int j))) (n + j) htd
    \<Longrightarrow> n \<noteq> 0 \<Longrightarrow> array_assertion p n htd"
  apply (drule_tac j=j in array_assertion_shrink_leftD, simp)
  apply (simp add: CTypesDefs.ptr_add_def)
  done

lemma h_t_array_valid:
  "h_t_valid htd gd (p :: (('a :: wf_type)['b :: finite]) ptr)
    \<Longrightarrow> h_t_array_valid htd (ptr_coerce p :: 'a ptr) (CARD('b))"
  by (clarsimp simp: h_t_valid_def h_t_array_valid_def typ_uinfo_array_tag_n_m_eq)

lemma array_ptr_valid_array_assertionD:
  "h_t_valid htd gd (p :: (('a :: wf_type)['b :: finite]) ptr)
    \<Longrightarrow> array_assertion (ptr_coerce p :: 'a ptr) (CARD('b)) htd"
  apply (clarsimp simp: array_assertion_def dest!: h_t_array_valid)
  apply (fastforce intro: exI[where x=0])
  done

lemma array_ptr_valid_array_assertionI:
  "h_t_valid htd gd (q :: (('a :: wf_type)['b :: finite]) ptr)
    \<Longrightarrow> q = ptr_coerce p
    \<Longrightarrow> n \<le> CARD('b)
    \<Longrightarrow> array_assertion (p :: 'a ptr) n htd"
  by (auto dest: array_ptr_valid_array_assertionD
           simp: array_assertion_shrink_right)

text \<open>Derived from array_assertion, an appropriate assertion for performing
a pointer addition, or for dereferencing a pointer addition (the strong case).

In either case, there must be an array connecting the two ends of the pointer
transition, with the caveat that the last address can be just out of the array
if the pointer is not dereferenced, thus the strong/weak distinction.

If the pointer doesn't actually move, nothing is learned.
\<close>
definition ptr_add_assertion :: "('a :: c_type) ptr \<Rightarrow> int \<Rightarrow> bool \<Rightarrow> heap_typ_desc \<Rightarrow> bool" where
  "ptr_add_assertion ptr offs strong htd \<equiv>
    offs = 0 \<or>
    array_assertion (if offs < 0 then CTypesDefs.ptr_add ptr offs else ptr)
                    (if offs < 0 then nat (- offs) else if strong then Suc (nat offs) else nat offs)
                    htd"

lemma ptr_add_assertion_positive:
  "offs \<ge> 0 \<Longrightarrow> ptr_add_assertion ptr offs strong htd
    = (offs = 0 \<or> array_assertion ptr (case strong of True \<Rightarrow> Suc (nat offs)
        | False \<Rightarrow> nat offs) htd)"
  by (simp add: ptr_add_assertion_def)

lemma ptr_add_assertion_negative:
  "offs < 0 \<Longrightarrow> ptr_add_assertion ptr offs strong htd
    = array_assertion (CTypesDefs.ptr_add ptr offs) (nat (- offs)) htd"
  by (simp add: ptr_add_assertion_def)

lemma ptr_add_assertion_uint[simp]:
  "ptr_add_assertion ptr (uint offs) strong htd
    = (offs = 0 \<or> array_assertion ptr
        (case strong of True \<Rightarrow> Suc (unat offs) | False \<Rightarrow> unat offs) htd)"
  by (simp add: ptr_add_assertion_positive uint_0_iff unat_def
         split: bool.split)

text \<open>Ignore char and void pointers. The C standard specifies that arithmetic on
char and void pointers doesn't create any special checks.\<close>

definition ptr_add_assertion' :: "('a :: c_type) ptr \<Rightarrow> int \<Rightarrow> bool \<Rightarrow> heap_typ_desc \<Rightarrow> bool" where
  "ptr_add_assertion' ptr offs strong htd =
     (typ_uinfo_t TYPE('a) = typ_uinfo_t TYPE(word8)
      \<or> typ_uinfo_t TYPE ('a) = typ_uinfo_t TYPE(unit)
      \<or> ptr_add_assertion ptr offs strong htd)"

(* Useful for clearing away these assumptions. *)
lemma td_diff_from_typ_name:
  "typ_name td \<noteq> typ_name td' \<Longrightarrow> td \<noteq> td'"
  by clarsimp

lemma typ_name_void:
  "typ_name (typ_uinfo_t TYPE(unit)) = ''unit''"
 by (simp add: typ_uinfo_t_def)

lemmas ptr_add_assertion' = ptr_add_assertion'_def td_diff_from_typ_name typ_name_void

text \<open>Mechanism for retyping a range of memory to a non-constant array size.\<close>

definition ptr_arr_retyps :: "nat \<Rightarrow> ('a :: c_type) ptr \<Rightarrow> heap_typ_desc \<Rightarrow> heap_typ_desc" where
  "ptr_arr_retyps n p \<equiv>
    htd_update_list (ptr_val p)
        (map (\<lambda>i. list_map (typ_slice_t (uinfo_array_tag_n_m TYPE('a) n n) i))
             [0..<n * size_of TYPE('a)])"

lemma ptr_arr_retyps_to_retyp:
  "n = CARD('b :: finite)
    \<Longrightarrow> ptr_arr_retyps n (p :: ('c :: wf_type) ptr) = ptr_retyp (ptr_coerce p :: ('c['b]) ptr)"
  by (auto simp: ptr_arr_retyps_def ptr_retyp_def typ_slices_def typ_uinfo_array_tag_n_m_eq)

end


theory SINVAR_ACLcommunicateWith_impl
imports SINVAR_ACLcommunicateWith "../TopoS_Interface_impl"
begin

code_identifier code_module SINVAR_ACLcommunicateWith_impl => (Scala) SINVAR_ACLcommunicateWith

subsubsection {* List Implementation *}

fun sinvar :: "'v list_graph \<Rightarrow> ('v \<Rightarrow> 'v access_list) \<Rightarrow> bool" where
  "sinvar G nP = (\<forall> v \<in> set (nodesL G). accesses_okay (nP v) (set (succ_tran G v)))"

fun verify_globals :: "'v list_graph \<Rightarrow> ('v \<Rightarrow> 'v access_list) \<Rightarrow> unit \<Rightarrow> bool" where
  "verify_globals _ _ _ = True"

definition "NetModel_node_props (P::('v::vertex, 'v access_list, 'b) TopoS_Params) =
  (\<lambda> i. (case (node_properties P) i of Some property \<Rightarrow> property | None \<Rightarrow> SINVAR_ACLcommunicateWith.default_node_properties))"

definition "ACLcommunicateWith_offending_list = Generic_offending_list sinvar"

definition "ACLcommunicateWith_eval G P = (valid_list_graph G \<and>
  verify_globals G (SecurityInvariant.node_props SINVAR_ACLcommunicateWith.default_node_properties P) (model_global_properties P) \<and>
  sinvar G (SecurityInvariant.node_props SINVAR_ACLcommunicateWith.default_node_properties P))"

lemma sinvar_correct: "valid_list_graph G \<Longrightarrow> SINVAR_ACLcommunicateWith.sinvar (list_graph_to_graph G) nP = sinvar G nP"
by (metis SINVAR_ACLcommunicateWith.sinvar.simps SINVAR_ACLcommunicateWith_impl.sinvar.simps graph.select_convs(1) list_graph_to_graph_def succ_tran_correct)

interpretation SINVAR_ACLcommunicateWith_impl:TopoS_List_Impl
  where default_node_properties=SINVAR_ACLcommunicateWith.default_node_properties
  and sinvar_spec=SINVAR_ACLcommunicateWith.sinvar
  and sinvar_impl=sinvar
  and verify_globals_spec=SINVAR_ACLcommunicateWith.verify_globals
  and verify_globals_impl=verify_globals
  and receiver_violation=SINVAR_ACLcommunicateWith.receiver_violation
  and offending_flows_impl=ACLcommunicateWith_offending_list
  and node_props_impl=NetModel_node_props
  and eval_impl=ACLcommunicateWith_eval
 apply(unfold TopoS_List_Impl_def)
 apply(rule conjI)
  apply(rule conjI)
   apply(simp add: TopoS_ACLcommunicateWith)
  apply(rule conjI)
   apply(intro allI impI)
   apply(fact sinvar_correct)
  apply(simp)
 apply(rule conjI)
  apply(unfold ACLcommunicateWith_offending_list_def)
  apply(intro allI impI)
  apply(rule Generic_offending_list_correct)
   apply(assumption)
  apply(simp only: sinvar_correct)
 apply(rule conjI)
  apply(intro allI)
  apply(simp only: NetModel_node_props_def)
  apply(metis ACLcommunicateWith.node_props.simps ACLcommunicateWith.node_props_eq_node_props_formaldef)
 apply(simp only: ACLcommunicateWith_eval_def)
 apply(intro allI impI)
 apply(rule TopoS_eval_impl_proofrule[OF TopoS_ACLcommunicateWith])
  apply(simp only: sinvar_correct)
 apply(simp)
done

subsubsection {* packing *}
  definition SINVAR_LIB_ACLcommunicateWith:: "('v::vertex, 'v access_list, unit) TopoS_packed" where
    "SINVAR_LIB_ACLcommunicateWith \<equiv>
    \<lparr> nm_name = ''ACLcommunicateWith'',
      nm_receiver_violation = SINVAR_ACLcommunicateWith.receiver_violation,
      nm_default = SINVAR_ACLcommunicateWith.default_node_properties,
      nm_sinvar = sinvar,
      nm_verify_globals = verify_globals,
      nm_offending_flows = ACLcommunicateWith_offending_list,
      nm_node_props = NetModel_node_props,
      nm_eval = ACLcommunicateWith_eval
      \<rparr>"
  interpretation SINVAR_LIB_ACLcommunicateWith_interpretation: TopoS_modelLibrary SINVAR_LIB_ACLcommunicateWith
      SINVAR_ACLcommunicateWith.sinvar SINVAR_ACLcommunicateWith.verify_globals
    apply(unfold TopoS_modelLibrary_def SINVAR_LIB_ACLcommunicateWith_def)
    apply(rule conjI)
     apply(simp)
    apply(simp)
    by(unfold_locales)

text {* Examples*}
  text{*
    1 can acceess 2 and 3
    2 can access 3
  *}
  definition exampleG :: "nat list_graph" where
    "exampleG \<equiv> \<lparr> nodesL = [1, 2, 3],
                    edgesL = [(1,2), (2,3)]\<rparr>"

  definition examplenP :: "nat \<Rightarrow> nat access_list" where
    "examplenP \<equiv> ((\<lambda>v. SINVAR_ACLcommunicateWith.default_node_properties)
                    (1 := AccessList [2,3]))
                    (2 := AccessList [3])"

  lemma "sinvar exampleG examplenP" by eval
  value "ACLcommunicateWith_offending_list exampleG examplenP"

  hide_const exampleG examplenP

hide_const (open) NetModel_node_props
hide_const (open) sinvar verify_globals

end


(*  Title:      JinjaThreads/BV/BVSpec.thy
    Author:     Cornelia Pusch, Gerwin Klein, Andreas Lochbihler

    Based on the theory Jinja/BV/BVSpec
*)

section \<open>The Bytecode Verifier \label{sec:BVSpec}\<close>

theory BVSpec
imports
  Effect
begin

text \<open>
  This theory contains a specification of the BV. The specification
  describes correct typings of method bodies; it corresponds
  to type \emph{checking}.
\<close>

\<comment> \<open>The method type only contains declared classes:\<close>
definition check_types :: "'m prog \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> ty\<^sub>i' err list \<Rightarrow> bool"
where
  "check_types P mxs mxl \<tau>s \<equiv> set \<tau>s \<subseteq> states P mxs mxl"

\<comment> \<open>An instruction is welltyped if it is applicable and its effect\<close>
\<comment> \<open>is compatible with the type at all successor instructions:\<close>
definition wt_instr :: "['m prog,ty,nat,pc,ex_table,'addr instr,pc,ty\<^sub>m] \<Rightarrow> bool"
  ("_,_,_,_,_ \<turnstile> _,_ :: _" [60,0,0,0,0,0,0,61] 60)
where
  "P,T,mxs,mpc,xt \<turnstile> i,pc :: \<tau>s \<equiv>
  app i P mxs T pc mpc xt (\<tau>s!pc) \<and>
  (\<forall>(pc',\<tau>') \<in> set (eff i P pc xt (\<tau>s!pc)). P \<turnstile> \<tau>' \<le>' \<tau>s!pc')"

\<comment> \<open>The type at @{text "pc=0"} conforms to the method calling convention:\<close>
definition wt_start :: "['m prog,cname,ty list,nat,ty\<^sub>m] \<Rightarrow> bool"
where
  "wt_start P C Ts mxl\<^sub>0 \<tau>s \<equiv>
  P \<turnstile> Some ([],OK (Class C)#map OK Ts@replicate mxl\<^sub>0 Err) \<le>' \<tau>s!0"

\<comment> \<open>A method is welltyped if the body is not empty,\<close>
\<comment> \<open>if the method type covers all instructions and mentions\<close>
\<comment> \<open>declared classes only, if the method calling convention is respected, and\<close>
\<comment> \<open>if all instructions are welltyped.\<close>
definition wt_method :: "['m prog,cname,ty list,ty,nat,nat,'addr instr list, ex_table,ty\<^sub>m] \<Rightarrow> bool"
where
  "wt_method P C Ts T\<^sub>r mxs mxl\<^sub>0 is xt \<tau>s \<equiv>
  0 < size is \<and> size \<tau>s = size is \<and>
  check_types P mxs (1+size Ts+mxl\<^sub>0) (map OK \<tau>s) \<and>
  wt_start P C Ts mxl\<^sub>0 \<tau>s \<and>
  (\<forall>pc < size is. P,T\<^sub>r,mxs,size is,xt \<turnstile> is!pc,pc :: \<tau>s)"

\<comment> \<open>A program is welltyped if it is wellformed and all methods are welltyped\<close>
definition wf_jvm_prog_phi :: "ty\<^sub>P \<Rightarrow> 'addr jvm_prog \<Rightarrow> bool" ("wf'_jvm'_prog\<^bsub>_\<^esub>")
where
  "wf_jvm_prog\<^bsub>\<Phi>\<^esub> \<equiv>
    wf_prog (\<lambda>P C (M,Ts,T\<^sub>r,(mxs,mxl\<^sub>0,is,xt)).
      wt_method P C Ts T\<^sub>r mxs mxl\<^sub>0 is xt (\<Phi> C M))"

definition wf_jvm_prog :: "'addr jvm_prog \<Rightarrow> bool"
where
  "wf_jvm_prog P \<equiv> \<exists>\<Phi>. wf_jvm_prog\<^bsub>\<Phi>\<^esub> P"

lemma wt_jvm_progD:
  "wf_jvm_prog\<^bsub>\<Phi>\<^esub> P \<Longrightarrow> \<exists>wt. wf_prog wt P"
(*<*) by (unfold wf_jvm_prog_phi_def, blast) (*>*)

lemma wt_jvm_prog_impl_wt_instr:
  "\<lbrakk> wf_jvm_prog\<^bsub>\<Phi>\<^esub> P;
      P \<turnstile> C sees M:Ts \<rightarrow> T = \<lfloor>(mxs,mxl\<^sub>0,ins,xt)\<rfloor> in C; pc < size ins \<rbrakk>
  \<Longrightarrow> P,T,mxs,size ins,xt \<turnstile> ins!pc,pc :: \<Phi> C M"
(*<*)
  apply (unfold wf_jvm_prog_phi_def)
  apply (drule (1) sees_wf_mdecl)
  apply (simp add: wf_mdecl_def wt_method_def)
  done
(*>*)

lemma wt_jvm_prog_impl_wt_start:
  "\<lbrakk> wf_jvm_prog\<^bsub>\<Phi>\<^esub> P;
     P \<turnstile> C sees M:Ts \<rightarrow> T = \<lfloor>(mxs,mxl\<^sub>0,ins,xt)\<rfloor> in C \<rbrakk> \<Longrightarrow>
  0 < size ins \<and> wt_start P C Ts mxl\<^sub>0 (\<Phi> C M)"
(*<*)
  apply (unfold wf_jvm_prog_phi_def)
  apply (drule (1) sees_wf_mdecl)
  apply (simp add: wf_mdecl_def wt_method_def)
  done
(*>*)

end


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

header{*The n_german Protocol Case Study*}

theory n_german_lemma_inv__42_on_rules imports n_german_lemma_on_inv__42
begin
section{*All lemmas on causal relation between inv__42*}
lemma lemma_inv__42_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__42  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__42) done
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

end


theory Renaming_Auto
  imports
    Renaming
    Utils
    ZF.Finite
    ZF.List
  keywords "rename" :: thy_decl % "ML"
    and "simple_rename" :: thy_decl % "ML"
    and "src"
    and "tgt"
  abbrevs "simple_rename" = ""
begin

lemmas app_fun = apply_iff[THEN iffD1]
lemmas nat_succI = nat_succ_iff[THEN iffD2]

ML_file \<open>renaming.ML\<close>
ML\<open>
  fun renaming_def mk_ren name from to ctxt =
    let val to = to |> Syntax.read_term ctxt
        val from = from |> Syntax.read_term ctxt
        val (tc_lemma,action_lemma,fvs,r) = mk_ren from to ctxt
        val (tc_lemma,action_lemma) =
          (Renaming.fix_vars tc_lemma fvs ctxt, Renaming.fix_vars action_lemma fvs ctxt)
        val ren_fun_name = Binding.name (name ^ "_fn")
        val ren_fun_def =  Binding.name (name ^ "_fn_def")
        val ren_thm = Binding.name (name ^ "_thm")
    in
      Local_Theory.note   ((ren_thm, []), [tc_lemma,action_lemma]) ctxt |> snd |>
      Local_Theory.define ((ren_fun_name, NoSyn), ((ren_fun_def, []), r)) |> snd
  end;
\<close>

ML\<open>
local

  val ren_parser = Parse.position (Parse.string --
      (Parse.$$$ "src" |-- Parse.string --| Parse.$$$ "tgt" -- Parse.string));

  val _ =
   Outer_Syntax.local_theory \<^command_keyword>\<open>rename\<close> "ML setup for synthetic definitions"
     (ren_parser >> (fn ((name,(from,to)),_) => renaming_def Renaming.sum_rename name from to ))

  val _ =
   Outer_Syntax.local_theory \<^command_keyword>\<open>simple_rename\<close> "ML setup for synthetic definitions"
     (ren_parser >> (fn ((name,(from,to)),_) => renaming_def Renaming.ren_thm name from to ))

in
end
\<close>
end


section {*composition\_of\_fixed\_point\_iterators*}
theory
  composition_of_fixed_point_iterators

imports
  operations_on_discrete_event_systems

begin

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont1: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator ((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Star_Controllable_Subset SigmaUC (des_langUM P))) IsDES
  (predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S))) (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Star_Controllable_Subset)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Specification_Satisfaction)
   apply(force)
  apply(rename_tac Q)(*strict*)
  apply(simp add: DES_controllability_def)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont1_bf: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Star_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES)
  IsDES
  (predicate_AND (predicate_AND IsDES DES_nonblockingness) ((predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S)))))
  (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Nonblockingness_DES)
   apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont1)
    apply(force)
   apply(force)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont1_bf_Enforce_Valid_DES: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Star_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES) UNIVmap
  (predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) ((predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S))))))
  (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    prefer 2
    apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont1_bf)
     apply(force)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Valid_DES)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_IteratorX_F_spec_cont1_bf_Enforce_Valid_DES: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_IteratorX (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Star_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES)
(predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) ((predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S))))))"
  apply(rule_tac ssubst)
   apply(rule Characteristic_Fixed_Point_IteratorX_vs_Characteristic_Fixed_Point_Iterator)
  apply(rule Characteristic_Fixed_Point_Iterator_weakening)
  apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont1_bf_Enforce_Valid_DES)
   apply(force)
  apply(force)
  done

corollary unused_decomposition_sound_and_least_restrictive: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> F = (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Star_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES)
  \<Longrightarrow> gfp (\<lambda>X. F (inf X (F Y))) = gfp (\<lambda>X. F (inf X Y))"
  apply(rule gfp_invariant)
  apply(rule_tac
      t="F"
      and s="(((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Star_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES)"
      in ssubst)
   apply(force)
  apply(rule unused_Characteristic_Fixed_Point_IteratorX_F_spec_cont1_bf_Enforce_Valid_DES)
   apply(force)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec2_cont: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator ((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Controllable_Subset SigmaUC (des_langUM P))) IsDES
(predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S)))
  (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Controllable_Subset)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Specification_Satisfaction)
   apply(force)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec2_cont_bf: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES) IsDES
(predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S))))
  (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    prefer 2
    apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec2_cont)
     apply(force)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Nonblockingness_DES)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont2_bf_Enforce_Valid_DES: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES) UNIVmap
  (predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S)))))
  (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    prefer 2
    apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec2_cont_bf)
     apply(force)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Valid_DES)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_IteratorX_F_spec_cont2_bf_Enforce_Valid_DES: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_IteratorX (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES) (predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (DES_controllability SigmaUC P)) (predicate_AND IsDES (DES_specification_satisfied S)))))"
  apply(rule_tac
      P="\<lambda>X. X"
      in ssubst)
   apply(rule Characteristic_Fixed_Point_IteratorX_vs_Characteristic_Fixed_Point_Iterator)
  apply(rule Characteristic_Fixed_Point_Iterator_weakening)
  apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont2_bf_Enforce_Valid_DES)
   apply(force)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont4: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator ((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Marked_Controllable_Subset SigmaUC (des_langUM P))) (predicate_AND IsDES DES_nonblockingness)
(predicate_AND (predicate_AND IsDES (predicate_AND DES_nonblockingness (DES_controllability SigmaUC P))) (predicate_AND IsDES (DES_specification_satisfied S)))
 (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Marked_Controllable_Subset)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Specification_Satisfaction)
   apply(force)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont4_bf: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Marked_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES) IsDES
(predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (predicate_AND DES_nonblockingness (DES_controllability SigmaUC P))) (predicate_AND IsDES (DES_specification_satisfied S))))
 (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    prefer 2
    apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont4)
     apply(force)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Nonblockingness_DES)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_spec_cont4_bf_Enforce_Valid_DES: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator
  (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Marked_Controllable_Subset SigmaUC (des_langUM P) ))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES)
  UNIVmap
  (predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (predicate_AND DES_nonblockingness (DES_controllability SigmaUC P))) (predicate_AND IsDES (DES_specification_satisfied S)))))
  (predicate_AND IsDES (DES_specification_satisfied S))"
  apply(rule Characteristic_Composition_of_Fixed_Point_Iterators)
    prefer 2
    apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont4_bf)
     apply(force)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Valid_DES)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_IteratorX_F_spec_cont4_bf_Enforce_Valid_DES: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_IteratorX (((Enforce_Specification_Satisfaction S)\<circ>(Enforce_Marked_Controllable_Subset SigmaUC (des_langUM P)))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES) (predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (predicate_AND DES_nonblockingness (DES_controllability SigmaUC P))) (predicate_AND IsDES (DES_specification_satisfied S)))))"
  apply(rule_tac
      P="\<lambda>X. X"
      in ssubst)
   apply(rule Characteristic_Fixed_Point_IteratorX_vs_Characteristic_Fixed_Point_Iterator)
  apply(rule Characteristic_Fixed_Point_Iterator_weakening)
  apply(rule unused_Characteristic_Fixed_Point_Iterator_F_spec_cont4_bf_Enforce_Valid_DES)
   apply(force)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_bf_spec: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (Enforce_Nonblockingness_DES\<circ>(\<lambda>C. Enforce_Specification_Satisfaction S C)) IsDES
  (predicate_AND (predicate_AND IsDES (DES_specification_satisfied S)) (predicate_AND IsDES DES_nonblockingness)) (predicate_AND IsDES DES_nonblockingness)"
  apply(rule_tac Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Specification_Satisfaction)
    apply(force)
   apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Nonblockingness_DES)
  apply(rename_tac Q)(*strict*)
  apply(force)
  done

lemma unused_Characteristic_Fixed_Point_Iterator_F_bf_cont4_bf_des: "
  IsDES P
  \<Longrightarrow> IsDES S
  \<Longrightarrow> Characteristic_Fixed_Point_Iterator (Enforce_Nonblockingness_DES\<circ>(Enforce_Marked_Controllable_Subset SigmaUC (des_langUM P))\<circ>Enforce_Nonblockingness_DES\<circ>Enforce_Valid_DES) UNIVmap
  (predicate_AND IsDES (predicate_AND (predicate_AND IsDES DES_nonblockingness) (predicate_AND (predicate_AND IsDES (predicate_AND DES_nonblockingness (DES_controllability SigmaUC P))) (predicate_AND IsDES DES_nonblockingness)))) (predicate_AND IsDES DES_nonblockingness)"
  apply(rule_tac
      ?Qinter1.0="IsDES"
      and ?Qinter2.0="IsDES"
      in Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Valid_DES)
   prefer 2
   apply(rename_tac Q)(*strict*)
   apply(force)
  apply(rule_tac
      ?Qinter1.0="(predicate_AND IsDES DES_nonblockingness)"
      and ?Qinter2.0="(predicate_AND IsDES DES_nonblockingness)"
      in Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Nonblockingness_DES)
   prefer 2
   apply(rename_tac Q)(*strict*)
   apply(force)
  apply(rule_tac
      ?Qinter1.0="IsDES"
      and ?Qinter2.0="IsDES"
      in Characteristic_Composition_of_Fixed_Point_Iterators)
    apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Marked_Controllable_Subset)
    apply(force)
   prefer 2
   apply(rename_tac Q)(*strict*)
   apply(force)
  apply(rule Characteristic_Fixed_Point_Iterator_Enforce_Nonblockingness_DES)
  done

end