Theory CDepInstantiations

section ‹Instantiate framework with control dependences›

theory CDepInstantiations imports 
  Slice 
  PDG 
  WeakOrderDependence 
begin

subsection‹Standard control dependence›

context StandardControlDependencePDG begin

lemma Exit_in_obs_slice_node:"(_Exit_)  obs n' (PDG_BS S)  (_Exit_)  S"
  by(auto elim:obsE PDG_path_CFG_path simp:PDG_BS_def split:if_split_asm)


abbreviation PDG_path' :: "'node  'node  bool" (‹_ d* _› [51,0] 80)
  where "n d* n'  PDG.PDG_path sourcenode targetnode valid_edge Def Use
  standard_control_dependence n n'"

lemma cd_closed:
  "n'  PDG_BS S; n controlss n'  n  PDG_BS S"
  by(simp add:PDG_BS_def)(blast dest:PDG_cdep_edge PDG_path_Append PDG_path_cdep)


lemma obs_postdominate:
  assumes "n  obs n' (PDG_BS S)" and "n  (_Exit_)" shows "n postdominates n'"
proof(rule ccontr)
  assume "¬ n postdominates n'"
  from n  obs n' (PDG_BS S) have "valid_node n" by(fastforce dest:in_obs_valid)
  with n  obs n' (PDG_BS S) n  (_Exit_) have "n postdominates n"
    by(fastforce intro:postdominate_refl)
  from n  obs n' (PDG_BS S) obtain as where "n' -as→* n"
    and "n'  set(sourcenodes as). n'  (PDG_BS S)"
    and "n  (PDG_BS S)" by(erule obsE)
  from n postdominates n ¬ n postdominates n' n' -as→* n
  obtain as' a as'' where [simp]:"as = as'@a#as''" and "valid_edge a"
    and "¬ n postdominates (sourcenode a)" and "n postdominates (targetnode a)"
    by -(erule postdominate_path_branch)
  from ¬ n postdominates (sourcenode a) valid_edge a valid_node n
  obtain asx  where "sourcenode a -asx→* (_Exit_)"
    and "n  set(sourcenodes asx)" by(auto simp:postdominate_def)
  from sourcenode a -asx→* (_Exit_) valid_edge a
  obtain ax asx' where [simp]:"asx = ax#asx'"
    apply - apply(erule path.cases)
    apply(drule_tac s="(_Exit_)" in sym)
    apply simp
    apply(drule Exit_source)
    by simp_all
  with sourcenode a -asx→* (_Exit_) have "sourcenode a -[]@ax#asx'→* (_Exit_)" 
    by simp
  hence "valid_edge ax" and [simp]:"sourcenode a = sourcenode ax"
    and "targetnode ax -asx'→* (_Exit_)"
    by(fastforce dest:path_split)+
  with n  set(sourcenodes asx) have "¬ n postdominates targetnode ax"
    by(fastforce simp:postdominate_def sourcenodes_def)
  from n  obs n' (PDG_BS S) n'  set(sourcenodes as). n'  (PDG_BS S)
  have "n  set (sourcenodes (a#as''))"
    by(fastforce elim:obs.cases simp:sourcenodes_def)
  from n' -as→* n have "sourcenode a -a#as''→* n"
    by(fastforce dest:path_split_second)
  with n postdominates (targetnode a) ¬ n postdominates targetnode ax
    valid_edge ax n  set (sourcenodes (a#as''))
  have "sourcenode a controlss n" by(fastforce simp:standard_control_dependence_def)
  with n  obs n' (PDG_BS S) have "sourcenode a  (PDG_BS S)"
    by(fastforce intro:cd_closed PDG_cdep_edge elim:obs.cases)
  with n'  set(sourcenodes as). n'  (PDG_BS S) 
  show False by(simp add:sourcenodes_def)
qed


lemma obs_singleton:"(m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {}"
proof(rule ccontr)
  assume "¬ ((m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {})"
  hence "nx nx'. nx  obs n (PDG_BS S)  nx'  obs n (PDG_BS S) 
    nx  nx'" by auto
  then obtain nx nx' where "nx  obs n (PDG_BS S)" and "nx'  obs n (PDG_BS S)"
    and "nx  nx'" by auto
  from nx  obs n (PDG_BS S) obtain as where "n -as→* nx" 
    and "n'  set(sourcenodes as). n'  (PDG_BS S)" and "nx  (PDG_BS S)" 
    by(erule obsE)
  from n -as→* nx have "valid_node nx" by(fastforce dest:path_valid_node)
  with nx  (PDG_BS S) have "obs nx (PDG_BS S) = {nx}" by -(rule n_in_obs)
  with n -as→* nx nx  obs n (PDG_BS S) nx'  obs n (PDG_BS S) nx  nx'
  have "as  []" by(fastforce elim:path.cases)
  with n -as→* nx nx  obs n (PDG_BS S) nx'  obs n (PDG_BS S) 
    nx  nx' obs nx (PDG_BS S) = {nx} n'  set(sourcenodes as). n'  (PDG_BS S)
  have "a as' as''. n -as'→* sourcenode a  targetnode a -as''→* nx 
                     valid_edge a  as = as'@a#as''  
                     obs (targetnode a) (PDG_BS S) = {nx}  
                    (¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
                       obs (sourcenode a) (PDG_BS S) = {}))"
  proof(induct arbitrary:nx' rule:path.induct)
    case (Cons_path n'' as n' a n)
    note [simp] = sourcenode a = n[THEN sym] targetnode a = n''[THEN sym]
    note more_than_one = n'  obs n (PDG_BS S) nx'  obs n (PDG_BS S) n'  nx'
    note IH = nx'. n'  obs n'' (PDG_BS S); nx'  obs n'' (PDG_BS S); n'  nx'; 
      obs n' (PDG_BS S) = {n'}; n'set (sourcenodes as). n'  (PDG_BS S); as  []
       a as' as''. n'' -as'→* sourcenode a  targetnode a -as''→* n' 
      valid_edge a  as = as'@a#as''  obs (targetnode a) (PDG_BS S) = {n'} 
      (¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
      obs (sourcenode a) (PDG_BS S) = {}))
    from n'set (sourcenodes (a#as)). n'  (PDG_BS S)
    have "n'set (sourcenodes as). n'  (PDG_BS S)" and "sourcenode a  (PDG_BS S)"
      by(simp_all add:sourcenodes_def)
    show ?case
    proof(cases "as = []")
      case True
      with n'' -as→* n' have [simp]:"n' = n''" by(fastforce elim:path.cases)
      from more_than_one
      have "¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
               obs (sourcenode a) (PDG_BS S) = {})"
        by auto
      with obs n' (PDG_BS S) = {n'} True valid_edge a show ?thesis
        apply(rule_tac x="a" in exI)
        apply(rule_tac x="[]" in exI)
        apply(rule_tac x="[]" in exI)
        by(auto intro!:empty_path)
    next
      case False
      hence "as  []" .
      from n'' -as→* n' n'set (sourcenodes as). n'  (PDG_BS S) 
      have "obs n' (PDG_BS S)  obs n'' (PDG_BS S)" by(rule path_obs_subset)
      show ?thesis
      proof(cases "obs n' (PDG_BS S) = obs n'' (PDG_BS S)")
        case True
        with n'' -as→* n' valid_edge a obs n' (PDG_BS S) = {n'} more_than_one
        show ?thesis
          apply(rule_tac x="a" in exI)
          apply(rule_tac x="[]" in exI)
          apply(rule_tac x="as" in exI)
          by(fastforce intro:empty_path)
      next
        case False
        with obs n' (PDG_BS S)  obs n'' (PDG_BS S)
        have "obs n' (PDG_BS S)  obs n'' (PDG_BS S)" by simp
        with obs n' (PDG_BS S) = {n'} obtain ni where "n'  obs n'' (PDG_BS S)"
          and "ni  obs n'' (PDG_BS S)" and "n'  ni" by auto
        from IH[OF this obs n' (PDG_BS S) = {n'} 
          n'set (sourcenodes as). n'  (PDG_BS S) as  []] obtain a' as' as''
          where "n'' -as'→* sourcenode a'" and "targetnode a' -as''→* n'"
          and "valid_edge a'" and [simp]:"as = as'@a'#as''" 
          and "obs (targetnode a') (PDG_BS S) = {n'}"
          and more_than_one':"¬ (m. obs (sourcenode a') (PDG_BS S) = {m}  
          obs (sourcenode a') (PDG_BS S) = {})"
          by blast
        from n'' -as'→* sourcenode a' valid_edge a
        have "n -a#as'→* sourcenode a'" by(fastforce intro:path.Cons_path)
        with targetnode a' -as''→* n' obs (targetnode a') (PDG_BS S) = {n'}
          more_than_one' valid_edge a' show ?thesis
          apply(rule_tac x="a'" in exI)
          apply(rule_tac x="a#as'" in exI)
          apply(rule_tac x="as''" in exI)
          by fastforce
      qed
    qed
  qed simp
  then obtain a as' as'' where "valid_edge a"
    and "obs (targetnode a) (PDG_BS S) = {nx}"
    and more_than_one:"¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
                         obs (sourcenode a) (PDG_BS S) = {})"
    by blast
  have "sourcenode a  (PDG_BS S)"
  proof(rule ccontr)
    assume "¬ sourcenode a  PDG_BS S"
    hence "sourcenode a  PDG_BS S" by simp
    with valid_edge a have "obs (sourcenode a) (PDG_BS S) = {sourcenode a}"
      by(fastforce intro!:n_in_obs)
    with more_than_one show False by simp
  qed
  with valid_edge a 
  have "obs (targetnode a) (PDG_BS S)  obs (sourcenode a) (PDG_BS S)"
    by(rule edge_obs_subset)
  with obs (targetnode a) (PDG_BS S) = {nx} 
  have "nx  obs (sourcenode a) (PDG_BS S)" by simp
  with more_than_one obtain m  where "m  obs (sourcenode a) (PDG_BS S)"
    and "nx  m" by auto
  from m  obs (sourcenode a) (PDG_BS S) 
  have "valid_node m" by(fastforce dest:in_obs_valid)
  from obs (targetnode a) (PDG_BS S) = {nx} have "valid_node nx" 
    by(fastforce dest:in_obs_valid)
  show False
  proof(cases "m postdominates (sourcenode a)")
    case True
    with nx  obs (sourcenode a) (PDG_BS S) m  obs (sourcenode a) (PDG_BS S)
    have "m postdominates nx"
      by(fastforce intro:postdominate_path_targetnode elim:obs.cases)
    with nx  m have "¬ nx postdominates m" by(fastforce dest:postdominate_antisym)
    have "(_Exit_) -[]→* (_Exit_)" by(fastforce intro:empty_path)
    with m postdominates nx have "nx  (_Exit_)"
      by(fastforce simp:postdominate_def sourcenodes_def)
    have "¬ nx postdominates (sourcenode a)"
    proof(rule ccontr)
      assume "¬ ¬ nx postdominates sourcenode a"
      hence "nx postdominates sourcenode a" by simp
      from m  obs (sourcenode a) (PDG_BS S) nx  obs (sourcenode a) (PDG_BS S)
      obtain asx' where "sourcenode a -asx'→* m" and "nx  set(sourcenodes asx')"
        by(fastforce elim:obs.cases)
      with nx postdominates sourcenode a have "nx postdominates m"
        by(rule postdominate_path_targetnode)
      with ¬ nx postdominates m show False by simp
    qed
    with nx  obs (sourcenode a) (PDG_BS S) valid_node nx nx  (_Exit_) 
    show False by(fastforce dest:obs_postdominate)
  next
    case False
    show False
    proof(cases "m = Exit")
      case True
      from m  obs (sourcenode a) (PDG_BS S) nx  obs (sourcenode a) (PDG_BS S)
      obtain xs where "sourcenode a -xs→* m" and "nx  set(sourcenodes xs)"
        by(fastforce elim:obsE)
      obtain x' xs' where [simp]:"xs = x'#xs'"
      proof(cases xs)
        case Nil
        with sourcenode a -xs→* m have [simp]:"sourcenode a = m" by fastforce
        with m  obs (sourcenode a) (PDG_BS S) 
        have "m  (PDG_BS S)" by(metis obsE)
        with valid_node m have "obs m (PDG_BS S) = {m}"
          by(rule n_in_obs)
        with nx  obs (sourcenode a) (PDG_BS S) nx  m have False
          by fastforce
        thus ?thesis by simp
      qed blast
      from sourcenode a -xs→* m have "sourcenode a = sourcenode x'" 
        and "valid_edge x'" and "targetnode x' -xs'→* m"
        by(auto elim:path_split_Cons)
      from targetnode x' -xs'→* m nx  set(sourcenodes xs) valid_edge x' 
        valid_node m True
      have "¬ nx postdominates (targetnode x')" 
        by(fastforce simp:postdominate_def sourcenodes_def)
      from nx  m True have "nx  (_Exit_)" by simp
      with obs (targetnode a) (PDG_BS S) = {nx}
      have "nx postdominates (targetnode a)"
        by(fastforce intro:obs_postdominate)
      from obs (targetnode a) (PDG_BS S) = {nx}
      obtain ys where "targetnode a -ys→* nx" 
        and "nx'  set(sourcenodes ys). nx'  (PDG_BS S)"
        and "nx  (PDG_BS S)" by(fastforce elim:obsE)
      hence "nx  set(sourcenodes ys)"by fastforce
      have "sourcenode a  nx"
      proof
        assume "sourcenode a = nx"
        from nx  obs (sourcenode a) (PDG_BS S)
        have "nx  (PDG_BS S)" by -(erule obsE)
        with valid_node nx have "obs nx (PDG_BS S) = {nx}" by -(erule n_in_obs)
        with sourcenode a = nx m  obs (sourcenode a) (PDG_BS S) 
          nx  m show False by fastforce
      qed
      with nx  set(sourcenodes ys) have "nx  set(sourcenodes (a#ys))"
        by(fastforce simp:sourcenodes_def)
      from valid_edge a targetnode a -ys→* nx
      have "sourcenode a -a#ys→* nx" by(fastforce intro:Cons_path)
      from sourcenode a -a#ys→* nx nx  set(sourcenodes (a#ys))
        nx postdominates (targetnode a) valid_edge x'
        ¬ nx postdominates (targetnode x') sourcenode a = sourcenode x'
      have "(sourcenode a) controlss nx"
        by(fastforce simp:standard_control_dependence_def)
      with nx  (PDG_BS S) have "sourcenode a  (PDG_BS S)"
        by(rule cd_closed)
      with valid_edge a have "obs (sourcenode a) (PDG_BS S) = {sourcenode a}"
        by(fastforce intro!:n_in_obs)
      with m  obs (sourcenode a) (PDG_BS S)
        nx  obs (sourcenode a) (PDG_BS S) nx  m
      show False by simp
    next
      case False
      with m  obs (sourcenode a) (PDG_BS S) valid_node m
        ¬ m postdominates sourcenode a 
      show False by(fastforce dest:obs_postdominate)
    qed
  qed
qed


lemma PDGBackwardSliceCorrect:
  "BackwardSlice sourcenode targetnode kind valid_edge
        (_Entry_) Def Use state_val PDG_BS"
proof(unfold_locales)
  fix n S assume "n  PDG_BS S"
  thus "valid_node n" by(rule PDG_BS_valid_node)
next
  fix n S assume "valid_node n" and "n  S"
  thus "n  PDG_BS S" by(fastforce intro:PDG_path_Nil simp:PDG_BS_def)
next
  fix n' S n V
  assume "n'  PDG_BS S" and "n influences V in n'"
  thus "n  PDG_BS S"
    by(auto dest:PDG.PDG_path_ddep[OF PDG_scd,OF PDG.PDG_ddep_edge[OF PDG_scd]]
            dest:PDG_path_Append simp:PDG_BS_def split:if_split_asm)
next
  fix n S
  have "(m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {}" 
    by(rule obs_singleton)
  thus "finite (obs n (PDG_BS S))" by fastforce
next
  fix n S
  have "(m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {}" 
    by(rule obs_singleton)
  thus "card (obs n (PDG_BS S))  1" by fastforce
qed

end


subsection‹Weak control dependence›

context WeakControlDependencePDG begin

lemma Exit_in_obs_slice_node:"(_Exit_)  obs n' (PDG_BS S)  (_Exit_)  S"
  by(auto elim:obsE PDG_path_CFG_path simp:PDG_BS_def split:if_split_asm)


lemma cd_closed:
  "n'  PDG_BS S; n weakly controls n'  n  PDG_BS S"
  by(simp add:PDG_BS_def)(blast dest:PDG_cdep_edge PDG_path_Append PDG_path_cdep)


lemma obs_strong_postdominate:
  assumes "n  obs n' (PDG_BS S)" and "n  (_Exit_)" 
  shows "n strongly-postdominates n'"
proof(rule ccontr)
  assume "¬ n strongly-postdominates n'"
  from n  obs n' (PDG_BS S) have "valid_node n" by(fastforce dest:in_obs_valid)
  with n  obs n' (PDG_BS S) n  (_Exit_) have "n strongly-postdominates n"
    by(fastforce intro:strong_postdominate_refl)
  from n  obs n' (PDG_BS S) obtain as where "n' -as→* n"
    and "n'  set(sourcenodes as). n'  (PDG_BS S)"
    and "n  (PDG_BS S)" by(erule obsE)
  from n strongly-postdominates n ¬ n strongly-postdominates n' n' -as→* n
  obtain as' a as'' where [simp]:"as = as'@a#as''" and "valid_edge a"
    and "¬ n strongly-postdominates (sourcenode a)" and 
    "n strongly-postdominates (targetnode a)"
    by -(erule strong_postdominate_path_branch)
  from n  obs n' (PDG_BS S) n'  set(sourcenodes as). n'  (PDG_BS S) 
  have "n  set (sourcenodes (a#as''))"
    by(fastforce elim:obs.cases simp:sourcenodes_def)
  from n' -as→* n have "sourcenode a -a#as''→* n"
    by(fastforce dest:path_split_second)
  from ¬ n strongly-postdominates (sourcenode a) valid_edge a valid_node n
  obtain a' where "sourcenode a' = sourcenode a"
    and "valid_edge a'" and "¬ n strongly-postdominates (targetnode a')"
    by(fastforce elim:not_strong_postdominate_predecessor_successor)
  with n strongly-postdominates (targetnode a) n  set (sourcenodes (a#as''))
    sourcenode a -a#as''→* n
  have "sourcenode a weakly controls n"
    by(fastforce simp:weak_control_dependence_def)
  with n  obs n' (PDG_BS S) have "sourcenode a  (PDG_BS S)"
    by(fastforce intro:cd_closed PDG_cdep_edge elim:obs.cases)
  with n'  set(sourcenodes as). n'  (PDG_BS S)
  show False by(simp add:sourcenodes_def)
qed


lemma obs_singleton:"(m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {}"
proof(rule ccontr)
  assume "¬ ((m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {})"
  hence "nx nx'. nx  obs n (PDG_BS S)  nx'  obs n (PDG_BS S) 
    nx  nx'" by auto
  then obtain nx nx' where "nx  obs n (PDG_BS S)" and "nx'  obs n (PDG_BS S)"
    and "nx  nx'" by auto
  from nx  obs n (PDG_BS S) obtain as where "n -as→* nx" 
    and "n'  set(sourcenodes as). n'  (PDG_BS S)" and "nx  (PDG_BS S)" 
    by(erule obsE)
  from n -as→* nx have "valid_node nx" by(fastforce dest:path_valid_node)
  with nx  (PDG_BS S) have "obs nx (PDG_BS S) = {nx}" by -(rule n_in_obs)
  with n -as→* nx nx  obs n (PDG_BS S) nx'  obs n (PDG_BS S) nx  nx'
  have "as  []" by(fastforce elim:path.cases)
  with n -as→* nx nx  obs n (PDG_BS S) nx'  obs n (PDG_BS S) 
    nx  nx' obs nx (PDG_BS S) = {nx} n'  set(sourcenodes as). n'  (PDG_BS S)
  have "a as' as''. n -as'→* sourcenode a  targetnode a -as''→* nx 
                     valid_edge a  as = as'@a#as''  
                     obs (targetnode a) (PDG_BS S) = {nx}  
                    (¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
                       obs (sourcenode a) (PDG_BS S) = {}))"
  proof(induct arbitrary:nx' rule:path.induct)
    case (Cons_path n'' as n' a n)
    note [simp] = sourcenode a = n[THEN sym] targetnode a = n''[THEN sym]
    note more_than_one = n'  obs n (PDG_BS S) nx'  obs n (PDG_BS S) n'  nx'
    note IH = nx'. n'  obs n'' (PDG_BS S); nx'  obs n'' (PDG_BS S); n'  nx'; 
      obs n' (PDG_BS S) = {n'}; n'set (sourcenodes as). n'  (PDG_BS S); as  []
       a as' as''. n'' -as'→* sourcenode a  targetnode a -as''→* n' 
      valid_edge a  as = as'@a#as''  obs (targetnode a) (PDG_BS S) = {n'} 
      (¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
      obs (sourcenode a) (PDG_BS S) = {}))
    from n'set (sourcenodes (a#as)). n'  (PDG_BS S)
    have "n'set (sourcenodes as). n'  (PDG_BS S)" and "sourcenode a  (PDG_BS S)"
      by(simp_all add:sourcenodes_def)
    show ?case
    proof(cases "as = []")
      case True
      with n'' -as→* n' have [simp]:"n' = n''" by(fastforce elim:path.cases)
      from more_than_one
      have "¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
               obs (sourcenode a) (PDG_BS S) = {})"
        by auto
      with obs n' (PDG_BS S) = {n'} True valid_edge a show ?thesis
        apply(rule_tac x="a" in exI)
        apply(rule_tac x="[]" in exI)
        apply(rule_tac x="[]" in exI)
        by(auto intro!:empty_path)
    next
      case False
      hence "as  []" .
      from n'' -as→* n' n'set (sourcenodes as). n'  (PDG_BS S) 
      have "obs n' (PDG_BS S)  obs n'' (PDG_BS S)" by(rule path_obs_subset)
      show ?thesis
      proof(cases "obs n' (PDG_BS S) = obs n'' (PDG_BS S)")
        case True
        with n'' -as→* n' valid_edge a obs n' (PDG_BS S) = {n'} more_than_one
        show ?thesis
          apply(rule_tac x="a" in exI)
          apply(rule_tac x="[]" in exI)
          apply(rule_tac x="as" in exI)
          by(fastforce intro:empty_path)
      next
        case False
        with obs n' (PDG_BS S)  obs n'' (PDG_BS S)
        have "obs n' (PDG_BS S)  obs n'' (PDG_BS S)" by simp
        with obs n' (PDG_BS S) = {n'} obtain ni where "n'  obs n'' (PDG_BS S)"
          and "ni  obs n'' (PDG_BS S)" and "n'  ni" by auto
        from IH[OF this obs n' (PDG_BS S) = {n'} 
          n'set (sourcenodes as). n'  (PDG_BS S) as  []] obtain a' as' as''
          where "n'' -as'→* sourcenode a'" and "targetnode a' -as''→* n'"
          and "valid_edge a'" and [simp]:"as = as'@a'#as''" 
          and "obs (targetnode a') (PDG_BS S) = {n'}"
          and more_than_one':"¬ (m. obs (sourcenode a') (PDG_BS S) = {m}  
          obs (sourcenode a') (PDG_BS S) = {})"
          by blast
        from n'' -as'→* sourcenode a' valid_edge a
        have "n -a#as'→* sourcenode a'" by(fastforce intro:path.Cons_path)
        with targetnode a' -as''→* n' obs (targetnode a') (PDG_BS S) = {n'}
          more_than_one' valid_edge a' show ?thesis
          apply(rule_tac x="a'" in exI)
          apply(rule_tac x="a#as'" in exI)
          apply(rule_tac x="as''" in exI)
          by fastforce
      qed
    qed
  qed simp
  then obtain a as' as'' where "valid_edge a"
    and "obs (targetnode a) (PDG_BS S) = {nx}"
    and more_than_one:"¬ (m. obs (sourcenode a) (PDG_BS S) = {m}  
                         obs (sourcenode a) (PDG_BS S) = {})"
    by blast
  have "sourcenode a  (PDG_BS S)"
  proof(rule ccontr)
    assume "¬ sourcenode a  PDG_BS S"
    hence "sourcenode a  PDG_BS S" by simp
    with valid_edge a have "obs (sourcenode a) (PDG_BS S) = {sourcenode a}"
      by(fastforce intro!:n_in_obs)
    with more_than_one show False by simp
  qed
  with valid_edge a 
  have "obs (targetnode a) (PDG_BS S)  obs (sourcenode a) (PDG_BS S)"
    by(rule edge_obs_subset)
  with obs (targetnode a) (PDG_BS S) = {nx} 
  have "nx  obs (sourcenode a) (PDG_BS S)" by simp
  with more_than_one obtain m  where "m  obs (sourcenode a) (PDG_BS S)"
    and "nx  m" by auto
  from m  obs (sourcenode a) (PDG_BS S) 
  have "valid_node m" by(fastforce dest:in_obs_valid)
  from obs (targetnode a) (PDG_BS S) = {nx} have "valid_node nx" 
    by(fastforce dest:in_obs_valid)
  show False
  proof(cases "m strongly-postdominates (sourcenode a)")
    case True
    with nx  obs (sourcenode a) (PDG_BS S) m  obs (sourcenode a) (PDG_BS S)
    have "m strongly-postdominates nx"
      by(fastforce intro:strong_postdominate_path_targetnode elim:obs.cases)
    with nx  m have "¬ nx strongly-postdominates m" 
      by(fastforce dest:strong_postdominate_antisym)
    have "(_Exit_) -[]→* (_Exit_)" by(fastforce intro:empty_path)
    with m strongly-postdominates nx have "nx  (_Exit_)"
      by(fastforce simp:strong_postdominate_def sourcenodes_def postdominate_def)
    have "¬ nx strongly-postdominates (sourcenode a)"
    proof(rule ccontr)
      assume "¬ ¬ nx strongly-postdominates sourcenode a"
      hence "nx strongly-postdominates sourcenode a" by simp
      from m  obs (sourcenode a) (PDG_BS S) nx  obs (sourcenode a) (PDG_BS S)
      obtain asx' where "sourcenode a -asx'→* m" and "nx  set(sourcenodes asx')"
        by(fastforce elim:obs.cases)
      with nx strongly-postdominates sourcenode a have "nx strongly-postdominates m"
        by(rule strong_postdominate_path_targetnode)
      with ¬ nx strongly-postdominates m show False by simp
    qed
    with nx  obs (sourcenode a) (PDG_BS S) valid_node nx nx  (_Exit_) 
    show False by(fastforce dest:obs_strong_postdominate)
  next
    case False
    show False
    proof(cases "m = Exit")
      case True
      from m  obs (sourcenode a) (PDG_BS S) nx  obs (sourcenode a) (PDG_BS S)
      obtain xs where "sourcenode a -xs→* m" and "nx  set(sourcenodes xs)"
        by(fastforce elim:obsE)
      obtain x' xs' where [simp]:"xs = x'#xs'"
      proof(cases xs)
        case Nil
        with sourcenode a -xs→* m have [simp]:"sourcenode a = m" by fastforce
        with m  obs (sourcenode a) (PDG_BS S) 
        have "m  (PDG_BS S)" by (metis obsE)
        with valid_node m have "obs m (PDG_BS S) = {m}"
          by(rule n_in_obs)
        with nx  obs (sourcenode a) (PDG_BS S) nx  m have False
          by fastforce
        thus ?thesis by simp
      qed blast
      from sourcenode a -xs→* m have "sourcenode a = sourcenode x'" 
        and "valid_edge x'" and "targetnode x' -xs'→* m"
        by(auto elim:path_split_Cons)
      from targetnode x' -xs'→* m nx  set(sourcenodes xs) valid_edge x' 
        valid_node m True
      have "¬ nx strongly-postdominates (targetnode x')" 
        by(fastforce simp:strong_postdominate_def postdominate_def sourcenodes_def)
      from nx  m True have "nx  (_Exit_)" by simp
      with obs (targetnode a) (PDG_BS S) = {nx}
      have "nx strongly-postdominates (targetnode a)"
        by(fastforce intro:obs_strong_postdominate)
      from obs (targetnode a) (PDG_BS S) = {nx}
      obtain ys where "targetnode a -ys→* nx" 
        and "nx'  set(sourcenodes ys). nx'  (PDG_BS S)"
        and "nx  (PDG_BS S)" by(fastforce elim:obsE)
      hence "nx  set(sourcenodes ys)"by fastforce
      have "sourcenode a  nx"
      proof
        assume "sourcenode a = nx"
        from nx  obs (sourcenode a) (PDG_BS S)
        have "nx  (PDG_BS S)" by -(erule obsE)
        with valid_node nx have "obs nx (PDG_BS S) = {nx}" by -(erule n_in_obs)
        with sourcenode a = nx m  obs (sourcenode a) (PDG_BS S) 
          nx  m show False by fastforce
      qed
      with nx  set(sourcenodes ys) have "nx  set(sourcenodes (a#ys))"
        by(fastforce simp:sourcenodes_def)
      from valid_edge a targetnode a -ys→* nx
      have "sourcenode a -a#ys→* nx" by(fastforce intro:Cons_path)
      from sourcenode a -a#ys→* nx nx  set(sourcenodes (a#ys))
        nx strongly-postdominates (targetnode a) valid_edge x'
        ¬ nx strongly-postdominates (targetnode x') sourcenode a = sourcenode x'
      have "(sourcenode a) weakly controls nx"
        by(fastforce simp:weak_control_dependence_def)
      with nx  (PDG_BS S) have "sourcenode a  (PDG_BS S)"
        by(rule cd_closed)
      with valid_edge a have "obs (sourcenode a) (PDG_BS S) = {sourcenode a}"
        by(fastforce intro!:n_in_obs)
      with m  obs (sourcenode a) (PDG_BS S)
        nx  obs (sourcenode a) (PDG_BS S) nx  m
      show False by simp
    next
      case False
      with m  obs (sourcenode a) (PDG_BS S) valid_node m
        ¬ m strongly-postdominates sourcenode a 
      show False by(fastforce dest:obs_strong_postdominate)
    qed
  qed
qed


lemma WeakPDGBackwardSliceCorrect:
  "BackwardSlice sourcenode targetnode kind valid_edge
        (_Entry_) Def Use state_val PDG_BS"
proof(unfold_locales)
  fix n S assume "n  PDG_BS S"
  thus "valid_node n" by(rule PDG_BS_valid_node)
next
  fix n S assume "valid_node n" and "n  S"
  thus "n  PDG_BS S" by(fastforce intro:PDG_path_Nil simp:PDG_BS_def)
next
  fix n' S n V assume "n'  PDG_BS S" and "n influences V in n'"
  thus "n  PDG_BS S"
    by(auto dest:PDG.PDG_path_ddep[OF PDG_wcd,OF PDG.PDG_ddep_edge[OF PDG_wcd]]
            dest:PDG_path_Append simp:PDG_BS_def split:if_split_asm)
next
  fix n S
  have "(m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {}" 
    by(rule obs_singleton)
  thus "finite (obs n (PDG_BS S))" by fastforce
next
  fix n S
  have "(m. obs n (PDG_BS S) = {m})  obs n (PDG_BS S) = {}" 
    by(rule obs_singleton)
  thus "card (obs n (PDG_BS S))  1" by fastforce
qed

end


subsection‹Weak order dependence›

context CFG_wf begin

lemma obs_singleton: 
  (*assumes valid:"valid_node n"*)
  shows "(m. obs n (wod_backward_slice S) = {m}) 
         obs n (wod_backward_slice S) = {}"
proof(rule ccontr)
  let ?WOD_BS = "wod_backward_slice S"
  assume "¬ ((m. obs n ?WOD_BS = {m})  obs n ?WOD_BS = {})"
  hence "nx nx'. nx  obs n ?WOD_BS  nx'  obs n ?WOD_BS 
    nx  nx'" by auto
  then obtain nx nx' where "nx  obs n ?WOD_BS" and "nx'  obs n ?WOD_BS"
    and "nx  nx'" by auto
  from nx  obs n ?WOD_BS obtain as where "n -as→* nx" 
    and "n'  set(sourcenodes as). n'  ?WOD_BS" and "nx  ?WOD_BS" 
    by(erule obsE)
  from n -as→* nx have "valid_node nx" by(fastforce dest:path_valid_node)
  with nx  ?WOD_BS have "obs nx ?WOD_BS = {nx}" by -(rule n_in_obs)
  with n -as→* nx nx  obs n ?WOD_BS nx'  obs n ?WOD_BS nx  nx' 
  have "as  []" by(fastforce elim:path.cases)
  with n -as→* nx nx  obs n ?WOD_BS nx'  obs n ?WOD_BS nx  nx' 
    obs nx ?WOD_BS = {nx} n'  set(sourcenodes as). n'  ?WOD_BS
  have "a as' as''. n -as'→* sourcenode a  targetnode a -as''→* nx 
                     valid_edge a  as = as'@a#as''  
                     obs (targetnode a) ?WOD_BS = {nx}  
                    (¬ (m. obs (sourcenode a) ?WOD_BS = {m}  
                       obs (sourcenode a) ?WOD_BS = {}))"
  proof(induct arbitrary:nx' rule:path.induct)
    case (Cons_path n'' as n' a n)
    note [simp] = sourcenode a = n[THEN sym] targetnode a = n''[THEN sym]
    note more_than_one = n'  obs n (?WOD_BS) nx'  obs n (?WOD_BS) n'  nx'
    note IH = nx'. n'  obs n'' (?WOD_BS); nx'  obs n'' (?WOD_BS); n'  nx'; 
      obs n' (?WOD_BS) = {n'}; n'set (sourcenodes as). n'  (?WOD_BS); as  []
       a as' as''. n'' -as'→* sourcenode a  targetnode a -as''→* n' 
      valid_edge a  as = as'@a#as''  obs (targetnode a) (?WOD_BS) = {n'} 
      (¬ (m. obs (sourcenode a) (?WOD_BS) = {m}  
      obs (sourcenode a) (?WOD_BS) = {}))
    from n'set (sourcenodes (a#as)). n'  (?WOD_BS)
    have "n'set (sourcenodes as). n'  (?WOD_BS)" and "sourcenode a  (?WOD_BS)"
      by(simp_all add:sourcenodes_def)
    show ?case
    proof(cases "as = []")
      case True
      with n'' -as→* n' have [simp]:"n' = n''" by(fastforce elim:path.cases)
      from more_than_one
      have "¬ (m. obs (sourcenode a) (?WOD_BS) = {m}  
               obs (sourcenode a) (?WOD_BS) = {})"
        by auto
      with obs n' (?WOD_BS) = {n'} True valid_edge a show ?thesis
        apply(rule_tac x="a" in exI)
        apply(rule_tac x="[]" in exI)
        apply(rule_tac x="[]" in exI)
        by(auto intro!:empty_path)
    next
      case False
      hence "as  []" .
      from n'' -as→* n' n'set (sourcenodes as). n'  (?WOD_BS) 
      have "obs n' (?WOD_BS)  obs n'' (?WOD_BS)" by(rule path_obs_subset)
      show ?thesis
      proof(cases "obs n' (?WOD_BS) = obs n'' (?WOD_BS)")
        case True
        with n'' -as→* n' valid_edge a obs n' (?WOD_BS) = {n'} more_than_one
        show ?thesis
          apply(rule_tac x="a" in exI)
          apply(rule_tac x="[]" in exI)
          apply(rule_tac x="as" in exI)
          by(fastforce intro:empty_path)
      next
        case False
        with obs n' (?WOD_BS)  obs n'' (?WOD_BS)
        have "obs n' (?WOD_BS)  obs n'' (?WOD_BS)" by simp
        with obs n' (?WOD_BS) = {n'} obtain ni where "n'  obs n'' (?WOD_BS)"
          and "ni  obs n'' (?WOD_BS)" and "n'  ni" by auto
        from IH[OF this obs n' (?WOD_BS) = {n'} 
          n'set (sourcenodes as). n'  (?WOD_BS) as  []] obtain a' as' as''
          where "n'' -as'→* sourcenode a'" and "targetnode a' -as''→* n'"
          and "valid_edge a'" and [simp]:"as = as'@a'#as''" 
          and "obs (targetnode a') (?WOD_BS) = {n'}"
          and more_than_one':"¬ (m. obs (sourcenode a') (?WOD_BS) = {m}  
          obs (sourcenode a') (?WOD_BS) = {})"
          by blast
        from n'' -as'→* sourcenode a' valid_edge a
        have "n -a#as'→* sourcenode a'" by(fastforce intro:path.Cons_path)
        with targetnode a' -as''→* n' obs (targetnode a') (?WOD_BS) = {n'}
          more_than_one' valid_edge a' show ?thesis
          apply(rule_tac x="a'" in exI)
          apply(rule_tac x="a#as'" in exI)
          apply(rule_tac x="as''" in exI)
          by fastforce
      qed
    qed
  qed simp
  then obtain a as' as'' where "valid_edge a"
    and "obs (targetnode a) (?WOD_BS) = {nx}"
    and more_than_one:"¬ (m. obs (sourcenode a) (?WOD_BS) = {m}  
                         obs (sourcenode a) (?WOD_BS) = {})"
    by blast
  have "sourcenode a  (?WOD_BS)"
  proof(rule ccontr)
    assume "¬ sourcenode a  ?WOD_BS"
    hence "sourcenode a  ?WOD_BS" by simp
    with valid_edge a have "obs (sourcenode a) (?WOD_BS) = {sourcenode a}"
      by(fastforce intro!:n_in_obs)
    with more_than_one show False by simp
  qed
  with valid_edge a 
  have "obs (targetnode a) (?WOD_BS)  obs (sourcenode a) (?WOD_BS)"
    by(rule edge_obs_subset)
  with obs (targetnode a) (?WOD_BS) = {nx} 
  have "nx  obs (sourcenode a) (?WOD_BS)" by simp
  with more_than_one obtain m  where "m  obs (sourcenode a) (?WOD_BS)"
    and "nx  m" by auto
  with nx  obs (sourcenode a) (?WOD_BS) obtain as2 
    where "sourcenode a -as2→* m" and "nx  set(sourcenodes as2)" 
    by(fastforce elim:obsE)
  from nx  obs (sourcenode a) (?WOD_BS) m  obs (sourcenode a) (?WOD_BS) 
  obtain as1 where "sourcenode a -as1→* nx" and "m  set(sourcenodes as1)"
    by(fastforce elim:obsE)
  from obs (targetnode a) (?WOD_BS) = {nx} obtain asx 
    where "targetnode a -asx→* nx" by(fastforce elim:obsE)
  have "asx'. targetnode a -asx'→* m  nx  set(sourcenodes asx')"
  proof(rule ccontr)
    assume "¬ (asx'. targetnode a -asx'→* m  nx  set (sourcenodes asx'))"
    then obtain asx' where "targetnode a -asx'→* m" and "nx  set (sourcenodes asx')"
      by blast
    show False
    proof(cases "nx  set(sourcenodes asx'). nx  ?WOD_BS")
      case True
      with targetnode a -asx'→* m m  obs (sourcenode a) (?WOD_BS) 
      have "m  obs (targetnode a) ?WOD_BS" by(fastforce intro:obs_elem elim:obsE)
      with nx  m obs (targetnode a) (?WOD_BS) = {nx} show False by simp
    next
      case False
      hence "nx  set(sourcenodes asx'). nx  ?WOD_BS" by blast
      then obtain nx' ns ns' where "sourcenodes asx' = ns@nx'#ns'" and "nx'  ?WOD_BS"
        and "nx  set ns. nx  ?WOD_BS" by(fastforce elim!:split_list_first_propE)
      from sourcenodes asx' = ns@nx'#ns' obtain ax ai ai' 
        where [simp]:"asx' = ai@ax#ai'" "ns = sourcenodes ai" "nx' = sourcenode ax"
        by(fastforce elim:map_append_append_maps simp:sourcenodes_def)
      from targetnode a -asx'→* m have "targetnode a -ai→* sourcenode ax"
        by(fastforce dest:path_split)
      with nx'  ?WOD_BS nx  set ns. nx  ?WOD_BS 
      have "nx'  obs (targetnode a) ?WOD_BS" by(fastforce intro:obs_elem)
      with obs (targetnode a) (?WOD_BS) = {nx} have "nx' = nx" by simp
      with nx  set (sourcenodes asx') show False by(simp add:sourcenodes_def)
    qed
  qed
  with nx  m sourcenode a -as1→* nx m  set(sourcenodes as1) 
    sourcenode a -as2→* m nx  set(sourcenodes as2) valid_edge a 
    targetnode a -asx→* nx
  have "sourcenode a wod nx,m" by(simp add:wod_def,blast)
  with nx  obs (sourcenode a) (?WOD_BS) m  obs (sourcenode a) (?WOD_BS) 
  have "sourcenode a  ?WOD_BS" by(fastforce elim:cd_closed elim:obsE)
  with sourcenode a  ?WOD_BS show False by simp
qed


lemma WODBackwardSliceCorrect:
  "BackwardSlice sourcenode targetnode kind valid_edge
        (_Entry_) Def Use state_val wod_backward_slice"
proof(unfold_locales)
  fix n S assume "n  wod_backward_slice S"
  thus "valid_node n" by(rule wod_backward_slice_valid_node)
next
  fix n S assume "valid_node n" and "n  S"
  thus "n  wod_backward_slice S" by(rule refl)
next
  fix n' S n V assume "n'  wod_backward_slice S" "n influences V in n'"
  thus "n  wod_backward_slice S"
    by -(rule dd_closed)
next
  fix n S
  have "(m. obs n (wod_backward_slice S) = {m})  
    obs n (wod_backward_slice S) = {}" 
    by(rule obs_singleton)
  thus "finite (obs n (wod_backward_slice S))" by fastforce
next
  fix n S 
  have "(m. obs n (wod_backward_slice S) = {m})  obs n (wod_backward_slice S) = {}" 
    by(rule obs_singleton)
  thus "card (obs n (wod_backward_slice S))  1" by fastforce
qed

end

end