Theory SCDObservable

section ‹Observable sets w.r.t.\ standard control dependence›

theory SCDObservable imports Observable HRBSlice begin

context SDG begin

lemma matched_bracket_assms_variant:
  assumes "n1 -pcall n2  n1 -p:V'in n2" and "matched n2 ns' n3" 
  and "n3 -pret n4  n3 -p:Vout n4"
  and "call_of_return_node (parent_node n4) (parent_node n1)"
  obtains a a' where "valid_edge a" and "a'  get_return_edges a"
  and "sourcenode a = parent_node n1" and "targetnode a = parent_node n2"
  and "sourcenode a' = parent_node n3" and "targetnode a' = parent_node n4"
proof(atomize_elim)
  from n1 -pcall n2  n1 -p:V'in n2 obtain a Q r fs where "valid_edge a" 
    and "kind a = Q:r↪⇘pfs" and "parent_node n1 = sourcenode a"
    and "parent_node n2 = targetnode a"
    by(fastforce elim:SDG_edge.cases)
  from n3 -pret n4  n3 -p:Vout n4 obtain a' Q' f'
    where "valid_edge a'" and "kind a' = Q'↩⇘pf'"
    and "parent_node n3 = sourcenode a'" and "parent_node n4 = targetnode a'"
    by(fastforce elim:SDG_edge.cases)
  from valid_edge a' kind a' = Q'↩⇘pf'
  obtain ax where "valid_edge ax" and "Q r fs. kind ax = Q:r↪⇘pfs"
    and "a'  get_return_edges ax"
    by -(drule return_needs_call,fastforce+)
  from valid_edge a valid_edge ax kind a = Q:r↪⇘pfs Q r fs. kind ax = Q:r↪⇘pfs
  have "targetnode a = targetnode ax" by(fastforce dest:same_proc_call_unique_target)
  from valid_edge a' a'  get_return_edges ax valid_edge ax
  have "call_of_return_node (targetnode a') (sourcenode ax)"
    by(fastforce simp:return_node_def call_of_return_node_def)
  with call_of_return_node (parent_node n4) (parent_node n1) 
    parent_node n4 = targetnode a'
  have "sourcenode ax = parent_node n1" by fastforce
  with valid_edge ax a'  get_return_edges ax targetnode a = targetnode ax
    parent_node n2 = targetnode a parent_node n3 = sourcenode a' 
    parent_node n4 = targetnode a'
  show "a a'. valid_edge a  a'  get_return_edges a 
    sourcenode a = parent_node n1  targetnode a = parent_node n2 
    sourcenode a' = parent_node n3  targetnode a' = parent_node n4"
    by fastforce
qed

subsection ‹Observable set of standard control dependence is at most a singleton›

definition SDG_to_CFG_set :: "'node SDG_node set  'node set" ("_CFG")
  where "SCFG  {m. CFG_node m  S}"


lemma [intro]:"n  S. valid_SDG_node n  n  SCFG. valid_node n"
  by(fastforce simp:SDG_to_CFG_set_def)


lemma Exit_HRB_Slice:
  assumes "n  HRB_slice {CFG_node (_Exit_)}CFG" shows "n = (_Exit_)"
proof -
  from n  HRB_slice {CFG_node (_Exit_)}CFG 
  have "CFG_node n  HRB_slice {CFG_node (_Exit_)}"
    by(simp add:SDG_to_CFG_set_def)
  thus ?thesis
  proof(induct "CFG_node n" rule:HRB_slice_cases)
    case (phase1 nx)
    from nx  {CFG_node (_Exit_)} have "nx = CFG_node (_Exit_)" by simp
    with CFG_node n  sum_SDG_slice1 nx
    have "CFG_node n = CFG_node (_Exit_)  
      (n Vopt popt b. sum_SDG_edge n Vopt popt b (CFG_node (_Exit_)))"
      by(induct rule:sum_SDG_slice1.induct) auto
    then show ?thesis by(fastforce dest:Exit_no_sum_SDG_edge_target)
  next
    case (phase2 nx n' n'' p)
    from nx  {CFG_node (_Exit_)} have "nx = CFG_node (_Exit_)" by simp
    with n'  sum_SDG_slice1 nx
    have "n' = CFG_node (_Exit_)  
      (n Vopt popt b. sum_SDG_edge n Vopt popt b (CFG_node (_Exit_)))"
      by(induct rule:sum_SDG_slice1.induct) auto
    hence "n' = CFG_node (_Exit_)" by(fastforce dest:Exit_no_sum_SDG_edge_target)
    with CFG_node n  sum_SDG_slice2 n'
    have "CFG_node n = CFG_node (_Exit_)  
      (n Vopt popt b. sum_SDG_edge n Vopt popt b (CFG_node (_Exit_)))"
      by(induct rule:sum_SDG_slice2.induct) auto
    then show ?thesis by(fastforce dest:Exit_no_sum_SDG_edge_target)
  qed
qed


lemma Exit_in_obs_intra_slice_node:
  assumes "(_Exit_)  obs_intra n' HRB_slice SCFG"
  shows "CFG_node (_Exit_)  S"
proof -
  let ?S' = "HRB_slice SCFG"
  from (_Exit_)  obs_intra n' ?S' obtain as where "n' -asι* (_Exit_)"
    and "nx  set(sourcenodes as). nx  ?S'" and "(_Exit_)  ?S'"
    by(erule obs_intraE)
  from (_Exit_)  ?S' 
  have "CFG_node (_Exit_)  HRB_slice S" by(simp add:SDG_to_CFG_set_def)
  thus ?thesis
  proof(induct "CFG_node (_Exit_)" rule:HRB_slice_cases)
    case (phase1 nx)
    thus ?case
      by(induct "CFG_node (_Exit_)" rule:sum_SDG_slice1.induct,
        auto dest:Exit_no_sum_SDG_edge_source)
  next
    case (phase2 nx n' n'' p)
    from CFG_node (_Exit_)  sum_SDG_slice2 n' n'  sum_SDG_slice1 nx nx  S
    show ?case
      apply(induct n"CFG_node (_Exit_)" rule:sum_SDG_slice2.induct)
      apply(auto dest:Exit_no_sum_SDG_edge_source)
      apply(hypsubst_thin)
      apply(induct n"CFG_node (_Exit_)" rule:sum_SDG_slice1.induct)
      apply(auto dest:Exit_no_sum_SDG_edge_source)
      done
  qed
qed


lemma obs_intra_postdominate:
  assumes "n  obs_intra n' HRB_slice SCFG" and "¬ method_exit n"
  shows "n postdominates n'"
proof(rule ccontr)
  assume "¬ n postdominates n'"
  from n  obs_intra n' HRB_slice SCFG have "valid_node n" 
    by(fastforce dest:in_obs_intra_valid)
  with n  obs_intra n' HRB_slice SCFG ¬ method_exit n have "n postdominates n"
    by(fastforce intro:postdominate_refl)
  from n  obs_intra n' HRB_slice SCFG obtain as where "n' -asι* n"
    and all_notinS:"n'  set(sourcenodes as). n'  HRB_slice SCFG"
    and "n  HRB_slice SCFG" by(erule obs_intraE)
  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)"  and "intra_kind (kind a)"
    by(fastforce elim!:postdominate_path_branch simp:intra_path_def)
  from n' -asι* n have "sourcenode a -a#as''ι* n"
    by(fastforce elim:path_split intro:Cons_path simp:intra_path_def)
  with ¬ n postdominates (sourcenode a) valid_edge a valid_node n 
  obtain asx pex where "sourcenode a -asxι* pex" and "method_exit pex" 
    and "n  set(sourcenodes asx)" by(fastforce simp:postdominate_def)
  have "asx  []"
  proof
    assume "asx = []"
    with sourcenode a -asxι* pex have "sourcenode a = pex" 
      by(fastforce simp:intra_path_def)
    from method_exit pex show False
    proof(rule method_exit_cases)
      assume "pex = (_Exit_)"
      with sourcenode a = pex have "sourcenode a = (_Exit_)" by simp
      with valid_edge a show False by(rule Exit_source)
    next
      fix a' Q f p
      assume "pex = sourcenode a'" and "valid_edge a'" and "kind a' = Q↩⇘pf"
      from valid_edge a' kind a' = Q↩⇘pf valid_edge a intra_kind (kind a)
        sourcenode a = pex pex = sourcenode a'
      show False by(fastforce dest:return_edges_only simp:intra_kind_def)
    qed
  qed
  then obtain ax asx' where [simp]:"asx = ax#asx'" by(cases asx) auto
  with sourcenode a -asxι* pex have "sourcenode a -ax#asx'→* pex"
    by(simp add:intra_path_def)
  hence "valid_edge ax" and [simp]:"sourcenode a = sourcenode ax"
    and "targetnode ax -asx'→* pex" by(auto elim:path_split_Cons)
  with sourcenode a -asxι* pex have "targetnode ax -asx'ι* pex"
    by(simp add:intra_path_def)
  with valid_edge ax n  set(sourcenodes asx) method_exit pex
  have "¬ n postdominates targetnode ax"
    by(fastforce simp:postdominate_def sourcenodes_def)
  from n  obs_intra n' HRB_slice SCFG all_notinS 
  have "n  set (sourcenodes (a#as''))"
    by(fastforce elim:obs_intra.cases simp:sourcenodes_def)
  from sourcenode a -asxι* pex have "intra_kind (kind ax)"
    by(simp add:intra_path_def)
  with sourcenode a -a#as''ι* n n postdominates (targetnode a) 
    ¬ n postdominates targetnode ax valid_edge ax 
    n  set (sourcenodes (a#as'')) intra_kind (kind a)
  have "(sourcenode a) controls n"
    by(fastforce simp:control_dependence_def)
  hence "CFG_node (sourcenode a) s⟶cd CFG_node n"
    by(fastforce intro:sum_SDG_cdep_edge)
  with n  obs_intra n' HRB_slice SCFG have "sourcenode a  HRB_slice SCFG"
    by(auto elim!:obs_intraE combine_SDG_slices.cases 
            intro:combine_SDG_slices.intros sum_SDG_slice1.intros 
                  sum_SDG_slice2.intros simp:HRB_slice_def SDG_to_CFG_set_def)
  with all_notinS show False by(simp add:sourcenodes_def)
qed



lemma obs_intra_singleton_disj: 
  assumes "valid_node n"
  shows "(m. obs_intra n HRB_slice SCFG = {m})  
         obs_intra n HRB_slice SCFG = {}"
proof(rule ccontr)
  assume "¬ ((m. obs_intra n HRB_slice SCFG = {m})  
             obs_intra n HRB_slice SCFG = {})"
  hence "nx nx'. nx  obs_intra n HRB_slice SCFG  
    nx'  obs_intra n HRB_slice SCFG  nx  nx'" by auto
  then obtain nx nx' where "nx  obs_intra n HRB_slice SCFG" 
    and "nx'  obs_intra n HRB_slice SCFG" and "nx  nx'" by auto
  from nx  obs_intra n HRB_slice SCFG obtain as where "n -asι* nx" 
    and all:"n'  set(sourcenodes as). n'  HRB_slice SCFG" 
    and "nx  HRB_slice SCFG" 
    by(erule obs_intraE)
  from n -asι* nx have "n -as→* nx" and "a  set as. intra_kind (kind a)"
    by(simp_all add:intra_path_def)
  hence "valid_node nx" by(fastforce dest:path_valid_node)
  with nx  HRB_slice SCFG have "obs_intra nx HRB_slice SCFG = {nx}" 
    by -(rule n_in_obs_intra)
  with n -as→* nx nx  obs_intra n HRB_slice SCFG 
    nx'  obs_intra n HRB_slice SCFG nx  nx' have "as  []" 
    by(fastforce elim:path.cases simp:intra_path_def)
  with n -as→* nx nx  obs_intra n HRB_slice SCFG 
    nx'  obs_intra n HRB_slice SCFG nx  nx' 
    obs_intra nx HRB_slice SCFG = {nx} a  set as. intra_kind (kind a) all
  have "a as' as''. n -as'ι* sourcenode a  targetnode a -as''ι* nx 
                     valid_edge a  as = as'@a#as''  intra_kind (kind a) 
                     obs_intra (targetnode a) HRB_slice SCFG = {nx}  
                    (¬ (m. obs_intra (sourcenode a) HRB_slice SCFG = {m}  
                       obs_intra (sourcenode a) HRB_slice SCFG = {}))"
  proof(induct arbitrary:nx' rule:path.induct)
    case (Cons_path n'' as n' a n)
    note IH = nx'. n'  obs_intra n'' HRB_slice SCFG; 
                       nx'  obs_intra n'' HRB_slice SCFG; n'  nx'; 
                       obs_intra n' HRB_slice SCFG = {n'};
                       aset as. intra_kind (kind a);
                       n'set (sourcenodes as). n'  HRB_slice SCFG; as  []
       a as' as''. n'' -as'ι* sourcenode a  targetnode a -as''ι* n' 
        valid_edge a  as = as'@a#as''  intra_kind (kind a) 
        obs_intra (targetnode a) HRB_slice SCFG = {n'} 
        (¬ (m. obs_intra (sourcenode a) HRB_slice SCFG = {m}  
           obs_intra (sourcenode a) HRB_slice SCFG = {}))
    note more_than_one = n'  obs_intra n HRB_slice SCFG
      nx'  obs_intra n HRB_slice SCFG n'  nx'
    from aset (a#as). intra_kind (kind a)
    have "aset as. intra_kind (kind a)" and "intra_kind (kind a)" by simp_all
    from n'set (sourcenodes (a#as)). n'  HRB_slice SCFG
    have all:"n'set (sourcenodes as). n'  HRB_slice SCFG"
      by(simp 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 sourcenode a = n
      have "¬ (m. obs_intra (sourcenode a) HRB_slice SCFG = {m}  
               obs_intra (sourcenode a) HRB_slice SCFG = {})"
        by auto
      with targetnode a = n'' obs_intra n' HRB_slice SCFG = {n'}
        sourcenode a = n True valid_edge a intra_kind (kind 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 simp:intra_path_def)
    next
      case False
      from n'' -as→* n' aset (a # as). intra_kind (kind a)
      have "n'' -asι* n'" by(simp add:intra_path_def)
      with all 
      have subset:"obs_intra n' HRB_slice SCFG  obs_intra n'' HRB_slice SCFG"
        by -(rule path_obs_intra_subset)
      thus ?thesis
      proof(cases "obs_intra n' HRB_slice SCFG = obs_intra n'' HRB_slice SCFG")
        case True
        with n'' -asι* n' valid_edge a sourcenode a = n targetnode a = n''
          obs_intra n' HRB_slice SCFG = {n'} intra_kind (kind a) 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 simp:intra_path_def)
      next
        case False
        with subset
        have "obs_intra n' HRB_slice SCFG  obs_intra n'' HRB_slice SCFG" by simp
        with obs_intra n' HRB_slice SCFG = {n'} 
        obtain ni where "n'  obs_intra n'' HRB_slice SCFG"
          and "ni  obs_intra n'' HRB_slice SCFG" and "n'  ni" by auto
        from IH[OF this obs_intra n' HRB_slice SCFG = {n'} 
          aset as. intra_kind (kind a) all as  []] obtain a' as' as''
          where "n'' -as'ι* sourcenode a'" 
          and hyps:"targetnode a' -as''ι* n'" "valid_edge a'" "as = as'@a'#as''" 
            "intra_kind (kind a')" "obs_intra (targetnode a') HRB_slice SCFG = {n'}"
            "¬ (m. obs_intra (sourcenode a') HRB_slice SCFG = {m}  
                                obs_intra (sourcenode a') HRB_slice SCFG = {})"
          by blast
        from n'' -as'ι* sourcenode a' valid_edge a sourcenode a = n 
          targetnode a = n'' intra_kind (kind a) intra_kind (kind a')
        have "n -a#as'ι* sourcenode a'"
          by(fastforce intro:path.Cons_path simp:intra_path_def)
        with hyps 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 "intra_kind (kind a)"
    and "obs_intra (targetnode a) HRB_slice SCFG = {nx}"
    and more_than_one:"¬ (m. obs_intra (sourcenode a) HRB_slice SCFG = {m}  
                         obs_intra (sourcenode a) HRB_slice SCFG = {})"
    by blast
  have "sourcenode a  HRB_slice SCFG"
  proof(rule ccontr)
    assume "¬ sourcenode a  HRB_slice SCFG"
    hence "sourcenode a  HRB_slice SCFG" by simp
    with valid_edge a
    have "obs_intra (sourcenode a) HRB_slice SCFG = {sourcenode a}"
      by(fastforce intro!:n_in_obs_intra)
    with more_than_one show False by simp
  qed
  with valid_edge a intra_kind (kind a)
  have "obs_intra (targetnode a) HRB_slice SCFG  
        obs_intra (sourcenode a) HRB_slice SCFG"
    by(rule edge_obs_intra_subset)
  with obs_intra (targetnode a) HRB_slice SCFG = {nx} 
  have "nx  obs_intra (sourcenode a) HRB_slice SCFG" by simp
  with more_than_one obtain m 
    where "m  obs_intra (sourcenode a) HRB_slice SCFG" and "nx  m" by auto
  from m  obs_intra (sourcenode a) HRB_slice SCFG have "valid_node m" 
    by(fastforce dest:in_obs_intra_valid)
  from obs_intra (targetnode a) HRB_slice SCFG = {nx} have "valid_node nx"
    by(fastforce dest:in_obs_intra_valid)
  show False
  proof(cases "m postdominates (sourcenode a)")
    case True
    with nx  obs_intra (sourcenode a) HRB_slice SCFG
      m  obs_intra (sourcenode a) HRB_slice SCFG
    have "m postdominates nx"
      by(fastforce intro:postdominate_inner_path_targetnode elim:obs_intraE)
    with nx  m have "¬ nx postdominates m" by(fastforce dest:postdominate_antisym)
    with valid_node nx valid_node m obtain asx pex where "m -asxι* pex"
      and "method_exit pex" and "nx  set(sourcenodes asx)"
      by(fastforce simp:postdominate_def)
    have "¬ nx postdominates (sourcenode a)"
    proof
      assume "nx postdominates sourcenode a"
      from nx  obs_intra (sourcenode a) HRB_slice SCFG
        m  obs_intra (sourcenode a) HRB_slice SCFG
      obtain asx' where "sourcenode a -asx'ι* m" and "nx  set(sourcenodes asx')"
        by(fastforce elim:obs_intraE)
      with m -asxι* pex have "sourcenode a -asx'@asxι* pex"
        by(fastforce intro:path_Append simp:intra_path_def)
      with nx  set(sourcenodes asx) nx  set(sourcenodes asx') 
        nx postdominates sourcenode a method_exit pex show False
        by(fastforce simp:sourcenodes_def postdominate_def)
    qed
    show False
    proof(cases "method_exit nx")
      case True
      from m postdominates nx obtain xs where "nx -xsι* m"
        by -(erule postdominate_implies_inner_path)
      with True have "nx = m"
        by(fastforce dest!:method_exit_inner_path simp:intra_path_def)
      with nx  m show False by simp
    next
      case False
      with nx  obs_intra (sourcenode a) HRB_slice SCFG
      have "nx postdominates sourcenode a" by(rule obs_intra_postdominate)
      with ¬ nx postdominates (sourcenode a) show False by simp
    qed
  next
    case False
    show False
    proof(cases "method_exit m")
      case True
      from m  obs_intra (sourcenode a) HRB_slice SCFG
        nx  obs_intra (sourcenode a) HRB_slice SCFG
      obtain xs where "sourcenode a -xsι* m" and "nx  set(sourcenodes xs)"
        by(fastforce elim:obs_intraE)
      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 simp:intra_path_def)
        with m  obs_intra (sourcenode a) HRB_slice SCFG 
        have "m  HRB_slice SCFG" by(metis obs_intraE)
        with valid_node m have "obs_intra m HRB_slice SCFG = {m}"
          by(rule n_in_obs_intra)
        with nx  obs_intra (sourcenode a) HRB_slice SCFG 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"
        and "intra_kind (kind x')"
        by(auto elim:path_split_Cons simp:intra_path_def)
      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)
      show False
      proof(cases "method_exit nx")
        case True
        from m  obs_intra (sourcenode a) HRB_slice SCFG
          nx  obs_intra (sourcenode a) HRB_slice SCFG
        have "get_proc m = get_proc nx"
          by(fastforce elim:obs_intraE dest:intra_path_get_procs)
        with method_exit m method_exit nx have "m = nx"
          by(rule method_exit_unique)
        with nx  m show False by simp
      next 
        case False
        with obs_intra (targetnode a) HRB_slice SCFG = {nx}
        have "nx postdominates (targetnode a)"
          by(fastforce intro:obs_intra_postdominate)
        from obs_intra (targetnode a) HRB_slice SCFG = {nx}
        obtain ys where "targetnode a -ysι* nx" 
          and "nx'  set(sourcenodes ys). nx'  HRB_slice SCFG"
          and "nx  HRB_slice SCFG" by(fastforce elim:obs_intraE)
        hence "nx  set(sourcenodes ys)"by fastforce
        have "sourcenode a  nx"
        proof
          assume "sourcenode a = nx"
          from nx  obs_intra (sourcenode a) HRB_slice SCFG
          have "nx  HRB_slice SCFG" by -(erule obs_intraE)
          with valid_node nx
          have "obs_intra nx HRB_slice SCFG = {nx}" by -(erule n_in_obs_intra)
          with sourcenode a = nx m  obs_intra (sourcenode a) HRB_slice SCFG 
            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 intra_kind (kind a)
        have "sourcenode a -a#ysι* nx"
          by(fastforce intro:Cons_path simp:intra_path_def)
        from sourcenode a -a#ysι* nx nx  set(sourcenodes (a#ys))
          intra_kind (kind a) nx postdominates (targetnode a)
          valid_edge x' intra_kind (kind x') ¬ nx postdominates (targetnode x')
          sourcenode a = sourcenode x'
        have "(sourcenode a) controls nx"
          by(fastforce simp:control_dependence_def)
        hence "CFG_node (sourcenode a)cd CFG_node nx" 
          by(fastforce intro:SDG_cdep_edge)
        with nx  HRB_slice SCFG have "sourcenode a  HRB_slice SCFG"
          by(fastforce elim!:combine_SDG_slices.cases
                       dest:SDG_edge_sum_SDG_edge cdep_slice1 cdep_slice2 
                      intro:combine_SDG_slices.intros
                       simp:HRB_slice_def SDG_to_CFG_set_def)
        with valid_edge a 
        have "obs_intra (sourcenode a) HRB_slice SCFG = {sourcenode a}"
          by(fastforce intro!:n_in_obs_intra)
        with m  obs_intra (sourcenode a) HRB_slice SCFG
          nx  obs_intra (sourcenode a) HRB_slice SCFG nx  m
        show False by simp
      qed
    next
      case False
      with m  obs_intra (sourcenode a) HRB_slice SCFG
      have "m postdominates (sourcenode a)" by(rule obs_intra_postdominate)
      with ¬ m postdominates (sourcenode a) show False by simp
    qed
  qed
qed



lemma obs_intra_finite:"valid_node n  finite (obs_intra n HRB_slice SCFG)"
by(fastforce dest:obs_intra_singleton_disj[of _ S])

lemma obs_intra_singleton:"valid_node n  card (obs_intra n HRB_slice SCFG)  1"
by(fastforce dest:obs_intra_singleton_disj[of _ S])


lemma obs_intra_singleton_element:
  "m  obs_intra n HRB_slice SCFG  obs_intra n HRB_slice SCFG = {m}"
apply -
apply(frule in_obs_intra_valid)
apply(drule obs_intra_singleton_disj) apply auto
done


lemma obs_intra_the_element: 
  "m  obs_intra n HRB_slice SCFG  (THE m. m  obs_intra n HRB_slice SCFG) = m"
by(fastforce dest:obs_intra_singleton_element)


lemma obs_singleton_element:
  assumes "ms  obs ns HRB_slice SCFG" and "n  set (tl ns). return_node n"
  shows "obs ns HRB_slice SCFG = {ms}"
proof -
  from ms  obs ns HRB_slice SCFG n  set (tl ns). return_node n
  obtain nsx n nsx' n' where "ns = nsx@n#nsx'" and "ms = n'#nsx'"
    and split:"n'  obs_intra n HRB_slice SCFG"
    "nx  set nsx'. nx'. call_of_return_node nx nx'  nx'  HRB_slice SCFG"
    "xs x xs'. nsx = xs@x#xs'  obs_intra x HRB_slice SCFG  {}
     (x''  set (xs'@[n]). nx. call_of_return_node x'' nx  
                                   nx  HRB_slice SCFG)"
    by(erule obsE)
  from n'  obs_intra n HRB_slice SCFG
  have "obs_intra n HRB_slice SCFG = {n'}"
    by(fastforce intro!:obs_intra_singleton_element)
  { fix xs assume "xs  ms" and "xs  obs ns HRB_slice SCFG"
    from xs  obs ns HRB_slice SCFG n  set (tl ns). return_node n
    obtain zs z zs' z' where "ns = zs@z#zs'" and "xs = z'#zs'"
      and "z'  obs_intra z HRB_slice SCFG"
      and "z'  set zs'. nx'. call_of_return_node z' nx'  nx'  HRB_slice SCFG"
      and "xs x xs'. zs = xs@x#xs'  obs_intra x HRB_slice SCFG  {}
       (x''  set (xs'@[z]). nx. call_of_return_node x'' nx  
                                     nx  HRB_slice SCFG)"
      by(erule obsE)
    with ns = nsx@n#nsx' split
    have "nsx = zs  n = z  nsx' = zs'"
      by -(rule obs_split_det[of _ _ _ _ _ _ "HRB_slice SCFG"],fastforce+)
    with obs_intra n HRB_slice SCFG = {n'} z'  obs_intra z HRB_slice SCFG
    have "z' = n'" by simp
    with xs  ms ms = n'#nsx' xs = z'#zs' nsx = zs  n = z  nsx' = zs'
    have False by simp }
  with ms  obs ns HRB_slice SCFG show ?thesis by fastforce
qed


lemma obs_finite:"n  set (tl ns). return_node n 
   finite (obs ns HRB_slice SCFG)"
by(cases "obs ns HRB_slice SCFG = {}",auto dest:obs_singleton_element[of _ _ S])

lemma obs_singleton:"n  set (tl ns). return_node n 
   card (obs ns HRB_slice SCFG)  1"
by(cases "obs ns HRB_slice SCFG = {}",auto dest:obs_singleton_element[of _ _ S])

lemma obs_the_element: 
  "ms  obs ns HRB_slice SCFG; n  set (tl ns). return_node n 
   (THE ms. ms  obs ns HRB_slice SCFG) = ms"
by(cases "obs ns HRB_slice SCFG = {}",auto dest:obs_singleton_element[of _ _ S])
  

end

end