Theory DynPDG

chapter ‹Dynamic Slicing›

section ‹Dynamic Program Dependence Graph›

theory DynPDG imports 
  "../Basic/DynDataDependence" 
  "../Basic/CFGExit_wf" 
  "../Basic/DynStandardControlDependence"
  "../Basic/DynWeakControlDependence"
begin

subsection ‹The dynamic PDG›

locale DynPDG = 
  CFGExit_wf sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
  for sourcenode :: "'edge ⇒ 'node" and targetnode :: "'edge ⇒ 'node"
  and kind :: "'edge ⇒ 'state edge_kind" and valid_edge :: "'edge ⇒ bool"
  and Entry :: "'node" (‹'('_Entry'_')›) and Def :: "'node ⇒ 'var set"
  and Use :: "'node ⇒ 'var set" and state_val :: "'state ⇒ 'var ⇒ 'val"
  and Exit :: "'node" (‹'('_Exit'_')›) +
  fixes dyn_control_dependence :: "'node ⇒ 'node ⇒ 'edge list ⇒ bool" 
(‹_ controls _ via _› [51,0,0])
  assumes Exit_not_dyn_control_dependent:"n controls n' via as ⟹ n' ≠ (_Exit_)"
  assumes dyn_control_dependence_path:
  "n controls n' via as  ⟹ n -as→* n' ∧ as ≠ []"

begin

inductive cdep_edge :: "'node ⇒ 'edge list ⇒ 'node ⇒ bool" 
    (‹_ -_→cd _› [51,0,0] 80)
  and ddep_edge :: "'node ⇒ 'var ⇒ 'edge list ⇒ 'node ⇒ bool"
    (‹_ -'{_'}_→dd _› [51,0,0,0] 80)
  and DynPDG_edge :: "'node ⇒ 'var option ⇒ 'edge list ⇒ 'node ⇒ bool"

where
      ― ‹Syntax›
  "n -as→cd n' == DynPDG_edge n None as n'"
  | "n -{V}as→dd n' == DynPDG_edge n (Some V) as n'"

      ― ‹Rules›
  | DynPDG_cdep_edge:
  "n controls n' via as ⟹ n -as→cd n'"

  | DynPDG_ddep_edge:
  "n influences V in n' via as ⟹ n -{V}as→dd n'"


inductive DynPDG_path :: "'node ⇒ 'edge list ⇒ 'node ⇒ bool"
(‹_ -_→d* _› [51,0,0] 80) 

where DynPDG_path_Nil:
  "valid_node n ⟹ n -[]→d* n"

  | DynPDG_path_Append_cdep:
  "⟦n -as→d* n''; n'' -as'→cd n'⟧ ⟹ n -as@as'→d* n'"

  | DynPDG_path_Append_ddep:
  "⟦n -as→d* n''; n'' -{V}as'→dd n'⟧ ⟹ n -as@as'→d* n'"


lemma DynPDG_empty_path_eq_nodes:"n -[]→d* n' ⟹ n = n'"
apply - apply(erule DynPDG_path.cases) 
  apply simp
 apply(auto elim:DynPDG_edge.cases dest:dyn_control_dependence_path)
by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)


lemma DynPDG_path_cdep:"n -as→cd n' ⟹ n -as→d* n'"
apply(subgoal_tac "n -[]@as→d* n'")
 apply simp
apply(rule DynPDG_path_Append_cdep, rule DynPDG_path_Nil)
by(auto elim!:DynPDG_edge.cases dest:dyn_control_dependence_path path_valid_node)

lemma DynPDG_path_ddep:"n -{V}as→dd n' ⟹ n -as→d* n'"
apply(subgoal_tac "n -[]@as→d* n'")
 apply simp
apply(rule DynPDG_path_Append_ddep, rule DynPDG_path_Nil)
by(auto elim!:DynPDG_edge.cases dest:path_valid_node simp:dyn_data_dependence_def)

lemma DynPDG_path_Append:
  "⟦n'' -as'→d* n'; n -as→d* n''⟧ ⟹ n -as@as'→d* n'"
apply(induct rule:DynPDG_path.induct)
  apply(auto intro:DynPDG_path.intros)
 apply(rotate_tac 1,drule DynPDG_path_Append_cdep,simp+)
apply(rotate_tac 1,drule DynPDG_path_Append_ddep,simp+)
done


lemma DynPDG_path_Exit:"⟦n -as→d* n'; n' = (_Exit_)⟧ ⟹ n = (_Exit_)"
apply(induct rule:DynPDG_path.induct)
by(auto elim:DynPDG_edge.cases dest:Exit_not_dyn_control_dependent 
        simp:dyn_data_dependence_def)


lemma DynPDG_path_not_inner:
  "⟦n -as→d* n'; ¬ inner_node n'⟧ ⟹ n = n'"
proof(induct rule:DynPDG_path.induct)
  case (DynPDG_path_Nil n)
  thus ?case by simp
next
  case (DynPDG_path_Append_cdep n as n'' as' n')
  from ‹n'' -as'→cd n'› ‹¬ inner_node n'› have False
    apply -
    apply(erule DynPDG_edge.cases) apply(auto simp:inner_node_def)
      apply(fastforce dest:dyn_control_dependence_path path_valid_node)
     apply(fastforce dest:dyn_control_dependence_path path_valid_node)
    by(fastforce dest:Exit_not_dyn_control_dependent)
  thus ?case by simp
next
  case (DynPDG_path_Append_ddep n as n'' V as' n')
  from ‹n'' -{V}as'→dd n'› ‹¬ inner_node n'› have False
    apply -
    apply(erule DynPDG_edge.cases) 
    by(auto dest:path_valid_node simp:inner_node_def dyn_data_dependence_def)
  thus ?case by simp
qed


lemma DynPDG_cdep_edge_CFG_path:
  assumes "n -as→cd n'" shows "n -as→* n'" and "as ≠ []"
  using ‹n -as→cd n'›
  by(auto elim:DynPDG_edge.cases dest:dyn_control_dependence_path)

lemma DynPDG_ddep_edge_CFG_path:
  assumes "n -{V}as→dd n'" shows "n -as→* n'" and "as ≠ []"
  using ‹n -{V}as→dd n'›
  by(auto elim:DynPDG_edge.cases simp:dyn_data_dependence_def)

lemma DynPDG_path_CFG_path:
  "n -as→d* n' ⟹ n -as→* n'"
proof(induct rule:DynPDG_path.induct)
  case DynPDG_path_Nil thus ?case by(rule empty_path)
next
  case (DynPDG_path_Append_cdep n as n'' as' n')
  from ‹n'' -as'→cd n'› have "n'' -as'→* n'"
    by(rule DynPDG_cdep_edge_CFG_path(1))
  with ‹n -as→* n''› show ?case by(rule path_Append)
next
  case (DynPDG_path_Append_ddep n as n'' V as' n')
  from ‹n'' -{V}as'→dd n'› have "n'' -as'→* n'"
    by(rule DynPDG_ddep_edge_CFG_path(1))
  with ‹n -as→* n''› show ?case by(rule path_Append)
qed


lemma DynPDG_path_split: 
  "n -as→d* n' ⟹
  (as = [] ∧ n = n') ∨ 
  (∃n'' asx asx'. (n -asx→cd n'') ∧ (n'' -asx'→d* n') ∧ 
        (as = asx@asx')) ∨
  (∃n'' V asx asx'. (n -{V}asx→dd n'') ∧ (n'' -asx'→d* n') ∧ 
        (as = asx@asx'))"
proof(induct rule:DynPDG_path.induct)
  case (DynPDG_path_Nil n) thus ?case by auto
next
  case (DynPDG_path_Append_cdep n as n'' as' n')
  note IH = ‹as = [] ∧ n = n'' ∨
    (∃nx asx asx'. n -asx→cd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx') ∨
    (∃nx V asx asx'. n -{V}asx→dd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx')›
  from IH show ?case
  proof
    assume "as = [] ∧ n = n''"
    with ‹n'' -as'→cd n'› have "valid_node n'"
      by(fastforce intro:path_valid_node(2) DynPDG_path_CFG_path 
                        DynPDG_path_cdep)
    with ‹as = [] ∧ n = n''› ‹n'' -as'→cd n'›
    have "∃n'' asx asx'. n -asx→cd n'' ∧ n'' -asx'→d* n' ∧ as@as' = asx@asx'"
      by(auto intro:DynPDG_path_Nil)
    thus ?thesis by simp
  next
    assume "(∃nx asx asx'. n -asx→cd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx') ∨
      (∃nx V asx asx'. n -{V}asx→dd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx')"
    thus ?thesis
    proof
      assume "∃nx asx asx'. n -asx→cd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx'"
      then obtain nx asx asx' where "n -asx→cd nx" and "nx -asx'→d* n''"
        and "as = asx@asx'" by auto
      from ‹n'' -as'→cd n'› have "n'' -as'→d* n'" by(rule DynPDG_path_cdep)
      with ‹nx -asx'→d* n''› have "nx -asx'@as'→d* n'"
        by(fastforce intro:DynPDG_path_Append)
      with ‹n -asx→cd nx› ‹as = asx@asx'›
      have "∃n'' asx asx'. n -asx→cd n'' ∧ n'' -asx'→d* n' ∧ as@as' = asx@asx'"
        by auto
      thus ?thesis by simp
    next
      assume "∃nx V asx asx'. n -{V}asx→dd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx'"
      then obtain nx V asx asx' where "n -{V}asx→dd nx" and "nx -asx'→d* n''"
        and "as = asx@asx'" by auto
      from ‹n'' -as'→cd n'› have "n'' -as'→d* n'" by(rule DynPDG_path_cdep)
      with ‹nx -asx'→d* n''› have "nx -asx'@as'→d* n'"
        by(fastforce intro:DynPDG_path_Append)
      with ‹n -{V}asx→dd nx› ‹as = asx@asx'›
      have "∃n'' V asx asx'. n -{V}asx→dd n'' ∧ n'' -asx'→d* n' ∧ as@as' = asx@asx'"
        by auto
      thus ?thesis by simp
    qed
  qed
next
  case (DynPDG_path_Append_ddep n as n'' V as' n')
  note IH = ‹as = [] ∧ n = n'' ∨
    (∃nx asx asx'. n -asx→cd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx') ∨
    (∃nx V asx asx'. n -{V}asx→dd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx')›
  from IH show ?case
  proof
    assume "as = [] ∧ n = n''"
    with ‹n'' -{V}as'→dd n'› have "valid_node n'"
      by(fastforce intro:path_valid_node(2) DynPDG_path_CFG_path 
                        DynPDG_path_ddep)
    with ‹as = [] ∧ n = n''› ‹n'' -{V}as'→dd n'›
    have "∃n'' V asx asx'. n -{V}asx→dd n'' ∧ n'' -asx'→d* n' ∧ as@as' = asx@asx'"
      by(fastforce intro:DynPDG_path_Nil)
    thus ?thesis by simp
  next
    assume "(∃nx asx asx'. n -asx→cd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx') ∨
      (∃nx V asx asx'. n -{V}asx→dd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx')"
    thus ?thesis
    proof
      assume "∃nx asx asx'. n -asx→cd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx'"
      then obtain nx asx asx' where "n -asx→cd nx" and "nx -asx'→d* n''"
        and "as = asx@asx'" by auto
      from ‹n'' -{V}as'→dd n'› have "n'' -as'→d* n'" by(rule DynPDG_path_ddep)
      with ‹nx -asx'→d* n''› have "nx -asx'@as'→d* n'"
        by(fastforce intro:DynPDG_path_Append)
      with ‹n -asx→cd nx› ‹as = asx@asx'›
      have "∃n'' asx asx'. n -asx→cd n'' ∧ n'' -asx'→d* n' ∧ as@as' = asx@asx'"
        by auto
      thus ?thesis by simp
    next
      assume "∃nx V asx asx'. n -{V}asx→dd nx ∧ nx -asx'→d* n'' ∧ as = asx@asx'"
      then obtain nx V' asx asx' where "n -{V'}asx→dd nx" and "nx -asx'→d* n''"
        and "as = asx@asx'" by auto
      from ‹n'' -{V}as'→dd n'› have "n'' -as'→d* n'" by(rule DynPDG_path_ddep)
      with ‹nx -asx'→d* n''› have "nx -asx'@as'→d* n'"
        by(fastforce intro:DynPDG_path_Append)
      with ‹n -{V'}asx→dd nx› ‹as = asx@asx'›
      have "∃n'' V asx asx'. n -{V}asx→dd n'' ∧ n'' -asx'→d* n' ∧ as@as' = asx@asx'"
        by auto
      thus ?thesis by simp
    qed
  qed
qed


lemma DynPDG_path_rev_cases [consumes 1,
  case_names DynPDG_path_Nil DynPDG_path_cdep_Append DynPDG_path_ddep_Append]:
  "⟦n -as→d* n'; ⟦as = []; n = n'⟧ ⟹ Q;
    ⋀n'' asx asx'. ⟦n -asx→cd n''; n'' -asx'→d* n'; 
                       as = asx@asx'⟧ ⟹ Q;
    ⋀V n'' asx asx'. ⟦n -{V}asx→dd n''; n'' -asx'→d* n'; 
                       as = asx@asx'⟧ ⟹ Q⟧
  ⟹ Q"
by(blast dest:DynPDG_path_split)



lemma DynPDG_ddep_edge_no_shorter_ddep_edge:
  assumes ddep:"n -{V}as→dd n'"
  shows "∀as' a as''. tl as = as'@a#as'' ⟶ ¬ sourcenode a -{V}a#as''→dd n'"
proof -
  from ddep have influence:"n influences V in n' via as"
    by(auto elim!:DynPDG_edge.cases)
  then obtain  a asx where as:"as = a#asx"
    and notin:"n ∉ set (sourcenodes asx)"
    by(auto dest:dyn_influence_source_notin_tl_edges simp:dyn_data_dependence_def)
  from influence as
  have imp:"∀nx ∈ set (sourcenodes asx). V ∉ Def nx"
    by(auto simp:dyn_data_dependence_def)
  { fix as' a' as'' 
    assume eq:"tl as = as'@a'#as''"
      and ddep':"sourcenode a' -{V}a'#as''→dd n'"
    from eq as notin have noteq:"sourcenode a' ≠ n" by(auto simp:sourcenodes_def)
    from ddep' have "V ∈ Def (sourcenode a')"
      by(auto elim!:DynPDG_edge.cases simp:dyn_data_dependence_def)
    with eq as noteq imp have False by(auto simp:sourcenodes_def) }
  thus ?thesis by blast
qed



lemma no_ddep_same_state:
  assumes path:"n -as→* n'" and Uses:"V ∈ Use n'" and preds:"preds (kinds as) s"
  and no_dep:"∀as' a as''. as = as'@a#as'' ⟶ ¬ sourcenode a -{V}a#as''→dd n'"
  shows "state_val (transfers (kinds as) s) V = state_val s V"
proof -
  { fix n''
    assume inset:"n'' ∈ set (sourcenodes as)" and Defs:"V ∈ Def n''"
    hence "∃nx ∈ set (sourcenodes as). V ∈ Def nx" by auto
    then obtain nx ns' ns'' where nodes:"sourcenodes as = ns'@nx#ns''"
        and Defs':"V ∈ Def nx" and notDef:"∀nx' ∈ set ns''. V ∉ Def nx'"
      by(fastforce elim!:rightmost_element_property)
    from nodes obtain as' a as''
      where as'':"sourcenodes as'' = ns''" and as:"as=as'@a#as''"
      and source:"sourcenode a = nx"
      by(fastforce elim:map_append_append_maps simp:sourcenodes_def)
    from as path have path':"sourcenode a -a#as''→* n'"
      by(fastforce dest:path_split_second)
    from notDef as'' source
    have "∀n'' ∈ set (sourcenodes as''). V ∉ Def n''"
      by(auto simp:sourcenodes_def)
    with path' Defs' Uses source
    have influence:"nx influences V in n' via (a#as'')"
      by(simp add:dyn_data_dependence_def)
    hence "nx ∉ set (sourcenodes as'')" by(rule dyn_influence_source_notin_tl_edges)
    with influence source
    have "∃asx a'. sourcenode a' -{V}a'#asx→dd n' ∧ sourcenode a' = nx ∧
          (∃asx'. a#as'' = asx'@a'#asx)"
      by(fastforce intro:DynPDG_ddep_edge)
    with nodes no_dep as have False by(auto simp:sourcenodes_def) }
  hence "∀n ∈ set (sourcenodes as). V ∉ Def n" by auto
  with wf path preds show ?thesis by(fastforce intro:CFG_path_no_Def_equal)
qed


lemma DynPDG_ddep_edge_only_first_edge:
  "⟦n -{V}a#as→dd n'; preds (kinds (a#as)) s⟧ ⟹ 
    state_val (transfers (kinds (a#as)) s) V = state_val (transfer (kind a) s) V"
  apply -
  apply(erule DynPDG_edge.cases)
  apply auto
  apply(frule dyn_influence_Cons_source)
  apply(frule dyn_influence_source_notin_tl_edges)
  by(erule dyn_influence_only_first_edge)


lemma Use_value_change_implies_DynPDG_ddep_edge:
  assumes "n -as→* n'" and "V ∈ Use n'" and "preds (kinds as) s" 
  and "preds (kinds as) s'" and "state_val s V = state_val s' V"
  and "state_val (transfers (kinds as) s) V ≠ 
             state_val (transfers (kinds as) s') V"
  obtains as' a as'' where "as = as'@a#as''"
  and "sourcenode a -{V}a#as''→dd n'"
  and "state_val (transfers (kinds as) s) V = 
       state_val (transfers (kinds (as'@[a])) s) V"
  and "state_val (transfers (kinds as) s') V = 
       state_val (transfers (kinds (as'@[a])) s') V"
proof(atomize_elim)
  show "∃as' a as''. as = as'@a#as'' ∧
                     sourcenode a -{V}a#as''→dd n' ∧
             state_val (transfers (kinds as) s) V = 
             state_val (transfers (kinds (as'@[a])) s) V ∧
             state_val (transfers (kinds as) s') V = 
             state_val (transfers (kinds (as'@[a])) s') V"
  proof(cases "∀as' a as''. as = as'@a#as'' ⟶
                 ¬ sourcenode a -{V}a#as''→dd n'")
    case True
    with ‹n -as→* n'› ‹V ∈ Use n'› ‹preds (kinds as) s› ‹preds (kinds as) s'›
    have "state_val (transfers (kinds as) s) V = state_val s V"
      and "state_val (transfers (kinds as) s') V = state_val s' V"
      by(auto intro:no_ddep_same_state)
    with ‹state_val s V = state_val s' V› 
      ‹state_val (transfers (kinds as) s) V ≠ state_val (transfers (kinds as) s') V›
    show ?thesis by simp
  next
    case False
    then obtain as' a as'' where [simp]:"as = as'@a#as''"
      and "sourcenode a -{V}a#as''→dd n'" by auto
    from ‹preds (kinds as) s› have "preds (kinds (a#as'')) (transfers (kinds as') s)"
      by(simp add:kinds_def preds_split)
    with ‹sourcenode a -{V}a#as''→dd n'› have all:
      "state_val (transfers (kinds (a#as'')) (transfers (kinds as') s)) V = 
       state_val (transfer (kind a) (transfers (kinds as') s)) V"
      by(auto dest!:DynPDG_ddep_edge_only_first_edge)
    from ‹preds (kinds as) s'› 
    have "preds (kinds (a#as'')) (transfers (kinds as') s')"
      by(simp add:kinds_def preds_split)
    with ‹sourcenode a -{V}a#as''→dd n'› have all':
      "state_val (transfers (kinds (a#as'')) (transfers (kinds as') s')) V = 
       state_val (transfer (kind a) (transfers (kinds as') s')) V"
      by(auto dest!:DynPDG_ddep_edge_only_first_edge)
    hence eq:"⋀s. transfers (kinds as) s =
      transfers (kinds (a#as'')) (transfers (kinds as') s)"
      by(simp add:transfers_split[THEN sym] kinds_def)
    with all have "state_val (transfers (kinds as) s) V = 
                   state_val (transfers (kinds (as'@[a])) s) V"
      by(simp add:transfers_split kinds_def)
    moreover
    from eq all' have "state_val (transfers (kinds as) s') V = 
                       state_val (transfers (kinds (as'@[a])) s') V"
      by(simp add:transfers_split kinds_def)
    ultimately show ?thesis using ‹sourcenode a -{V}a#as''→dd n'› by simp blast
  qed
qed


end


subsection ‹Instantiate dynamic PDG›

subsubsection ‹Standard control dependence›

locale DynStandardControlDependencePDG =
  Postdomination sourcenode targetnode kind valid_edge Entry Exit +
  CFGExit_wf sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
  for sourcenode :: "'edge ⇒ 'node" and targetnode :: "'edge ⇒ 'node"
  and kind :: "'edge ⇒ 'state edge_kind" and valid_edge :: "'edge ⇒ bool"
  and Entry :: "'node" (‹'('_Entry'_')›) and Def :: "'node ⇒ 'var set"
  and Use :: "'node ⇒ 'var set" and state_val :: "'state ⇒ 'var ⇒ 'val"
  and Exit :: "'node" (‹'('_Exit'_')›)

begin

lemma DynPDG_scd:
  "DynPDG sourcenode targetnode kind valid_edge (_Entry_) 
          Def Use state_val (_Exit_) dyn_standard_control_dependence"
proof(unfold_locales)
  fix n n' as assume "n controlss n' via as"
  show "n' ≠ (_Exit_)"
  proof
    assume "n' = (_Exit_)"
    with ‹n controlss n' via as› show False
      by(fastforce intro:Exit_not_dyn_standard_control_dependent)
  qed
next
  fix n n' as assume "n controlss n' via as"
  thus "n -as→* n' ∧ as ≠ []"
    by(fastforce simp:dyn_standard_control_dependence_def)
qed


end

subsubsection ‹Weak control dependence›

locale DynWeakControlDependencePDG = 
  StrongPostdomination sourcenode targetnode kind valid_edge Entry Exit +
  CFGExit_wf sourcenode targetnode kind valid_edge Entry Def Use state_val Exit
  for sourcenode :: "'edge ⇒ 'node" and targetnode :: "'edge ⇒ 'node"
  and kind :: "'edge ⇒ 'state edge_kind" and valid_edge :: "'edge ⇒ bool"
  and Entry :: "'node" (‹'('_Entry'_')›) and Def :: "'node ⇒ 'var set"
  and Use :: "'node ⇒ 'var set" and state_val :: "'state ⇒ 'var ⇒ 'val"
  and Exit :: "'node" (‹'('_Exit'_')›)

begin

lemma DynPDG_wcd:
  "DynPDG sourcenode targetnode kind valid_edge (_Entry_) 
          Def Use state_val (_Exit_) dyn_weak_control_dependence"
proof(unfold_locales)
  fix n n' as assume "n weakly controls n' via as"
  show "n' ≠ (_Exit_)"
  proof
    assume "n' = (_Exit_)"
    with ‹n weakly controls n' via as› show False
      by(fastforce intro:Exit_not_dyn_weak_control_dependent)
  qed
next
  fix n n' as assume "n weakly controls n' via as"
  thus "n -as→* n' ∧ as ≠ []"
    by(fastforce simp:dyn_weak_control_dependence_def)
qed


end


subsection ‹Data slice›

definition (in CFG) empty_control_dependence :: "'node ⇒ 'node ⇒ 'edge list ⇒ bool"
where "empty_control_dependence n n' as ≡ False"

lemma (in CFGExit_wf) DynPDG_scd:
  "DynPDG sourcenode targetnode kind valid_edge (_Entry_)
          Def Use state_val  (_Exit_) empty_control_dependence"
proof(unfold_locales)
  fix n n' as assume "empty_control_dependence n n' as"
  thus "n' ≠ (_Exit_)" by(simp add:empty_control_dependence_def)
next
  fix n n' as assume "empty_control_dependence n n' as"
  thus "n -as→* n' ∧ as ≠ []" by(simp add:empty_control_dependence_def)
qed

end