section‹The specification of computing dominators›
theory Cfg imports Main begin
text‹The specification of computing dominators is defined.
For fast data flow analysis presented by CHK cite‹"Dominance_Algorithm"›,
a directed graph with explicit node list and sets of initial nodes is defined.
Each node refers to its rPO (reverse PostOrder) number w.r.t a DFST, and
related properties as assumptions are handled using a locale.›
type_synonym 'a digraph = "('a ×'a) set"
record 'a graph_rec =
g_V :: "'a list"
g_V0 :: "'a set"
g_E :: "'a digraph"
tail :: "'a × 'a ==> 'a"
head :: "'a × 'a ==> 'a"
definition wf_cfg :: "'a graph_rec ==> bool"where "wf_cfg G ≡ g_V0 G ⊆ set( g_V G)"
type_synonym node = nat
locale cfg_doms =
―‹Nodes are rPO numbers› fixes G :: "nat graph_rec" (structure)
―‹General properties› assumes wf_cfg: "wf_cfg G" assumes tail[simp]: "e = (u,v) ==> tail G e = u" assumes head[simp]: "e = (u,v) ==> head G e = v" assumes tail_in_verts[simp]: "e ∈ g_E G ==> tail G e ∈ set (g_V G)" assumes head_in_verts[simp]: "e ∈ g_E G ==> head G e ∈ set (g_V G)"
―‹Properties of a cfg where nodes are rPO numbers› assumes entry0: "g_V0 G = {0}" assumes dfst: "∀v ∈ set (g_V G) - {0}. ∃prev. (prev, v) ∈ g_E G ∧ prev < v" assumes reachable: "∀v ∈ set (g_V G). v ∈ (g_E G)* `` {0}" assumes verts: "g_V G = [0 ..< (length (g_V G))]"
―‹It is required that the entry node has an immediate successor which is not itself;
Otherwise, no need to compute dominators
It is required for proving the lemma: "wf\_dom start (unstables r step start)".› assumes succ_of_entry0: "∃s. (0,s) ∈ g_E G ∧ s ≠ 0"
begin
inductive path_entry :: "nat digraph ==> nat list ==> nat ==> bool"for E where
path_entry0: "path_entry E [] 0"
| path_entry_prepend: "[ (u,v)∈ E; path_entry E l u ]==> path_entry E (u#l) v"
lemma path_entry0_empty_conv: "path_entry E [] v ⟷ v = 0" by (auto intro: path_entry0 elim: path_entry.cases)
inductive_cases path_entry_uncons: "path_entry E (u'#l) w"
inductive_simps path_entry_cons_conv: "path_entry E (u'#l) w"
lemma single_path_entry: "path_entry E [p] w ==> p = 0" by (simp add: path_entry_cons_conv path_entry0_empty_conv)
lemma path_entry_append: "[ path_entry E l v; (v,w)∈E ]==> path_entry E (v#l) w" by (rule path_entry_prepend)
lemma entry_rtrancl_is_path: assumes"(0,v) ∈ E*" obtains p where"path_entry E p v" using assms by induct (auto intro:path_entry0 path_entry_prepend)
lemma path_entry_is_trancl: assumes"path_entry E l v" and"l ≠ []" shows"(0,v)∈E+" using assms apply induct apply auto [] apply (case_tac l) apply (auto simp add:path_entry0_empty_conv) done
lemma tail_is_vert: "(u,v) ∈ g_E G ==> u ∈ set (g_V G)" by (auto dest: tail_in_verts[of "(u,v)"])
lemma head_is_vert: "(u,v) ∈ g_E G ==> v ∈ set (g_V G)" by (auto dest: head_in_verts[of "(u,v)"])
lemma tail_is_vert2: "(u,v) ∈ (g_E G)+==> u ∈ set (g_V G)" by (induct rule:trancl.induct)(auto dest: tail_in_verts)
lemma head_is_vert2: "(u,v) ∈ (g_E G)+==> v ∈ set (g_V G)" by (induct rule:trancl.induct)(auto dest: head_in_verts)
lemma verts_set: "set (g_V G) = {0 ..< length (g_V G)}" proof- from verts have"set (g_V G) = set [0 ..< (length (g_V G))]"by simp alsohave"set [0 ..< (length (g_V G))] = {0 ..< (length (g_V G))}"by simp ultimatelyshow ?thesis by auto qed
lemma fin_verts: "finite (set (g_V G))" by (auto)
lemma zero_in_verts: "0 ∈ set (g_V G)" using wf_cfg entry0 by (unfold wf_cfg_def) auto
lemma verts_not_empty: "g_V G ≠ []" using zero_in_verts by auto
lemma len_verts_gt0: "length (g_V G) > 0" by (simp add:verts_not_empty)
lemma len_verts_gt1: "length (g_V G) > 1" proof- from succ_of_entry0 obtain s where"s ∈ set (g_V G)"and"s ≠ 0"using head_is_vert by auto with zero_in_verts have"{0,s} ⊆ set (g_V G)"and c: "card {0, s} > 1"by auto thenhave"card {0, s} ≤ card (set (g_V G))"by (auto simp add:card_mono) with c have"card (set (g_V G)) > 1"by simp thenshow ?thesis using card_length[of "g_V G"] by auto qed
lemma verts_ge_Suc0 : "¬ [0..<length (g_V G)] = [0]" proof assume"[0..<length (g_V G)] = [0]" thenhave"length [0..<length (g_V G)] = 1"by simp with len_verts_gt1 show False by auto qed
lemma distinct_verts1: "distinct [0..<length (g_V G)] " by simp
lemma distinct_verts2: "distinct (g_V G)" by (insert distinct_verts1 verts) simp
lemma single_entry: "is_singleton (g_V0 G)" by (simp add:entry0)
lemma path_entry_prepend_conv: "path_entry (g_E G) p n ==> p ≠ [] ==>∃v. path_entry (g_E G) (tl p) v ∧ (v, n) ∈ (g_E G)" proof (induct rule:path_entry.induct) case path_entry0 thenshow ?caseby auto next case (path_entry_prepend u v l) thenshow ?caseby auto qed
lemma path_verts: "path_entry (g_E G) p n ==> n ∈ set (g_V G)" proof (cases "p = []") case True assume"path_entry (g_E G) p n"and"p = []" thenshow ?thesis by (simp add:path_entry0_empty_conv zero_in_verts) next case False assume"path_entry (g_E G) p n"and"p ≠ []" thenhave"(0,n)∈(g_E G)+"by (auto simp add:path_entry_is_trancl) thenshow ?thesis using head_is_vert2 by simp qed
lemma path_in_verts: assumes"path_entry (g_E G) l v" shows"set l ⊆ set (g_V G)" using assms proof (induct rule:path_entry.induct) case path_entry0 thenshow ?caseby auto next case (path_entry_prepend u v l) thenshow ?caseusing path_verts by auto qed
lemma any_node_exits_path: assumes"v ∈ set (g_V G) " shows"∃p. path_entry (g_E G) p v" using assms proof (cases "v = 0") assume"v ∈ set (g_V G)"and"v = 0" have"path_entry (g_E G) [] 0"by (auto simp add:path_entry0) thenshow ?thesis using‹v = 0›by auto next assume"v ∈ set (g_V G)"and"v ≠ 0" with reachable have"v ∈ (g_E G)* `` {0}"by auto thenhave"(0,v) ∈ (g_E G)*"by (simp add:Image_iff) thenshow ?thesis by (auto intro:entry_rtrancl_is_path) qed
definition reachable :: "node ==> bool" where"reachable v ≡ v ∈ (g_E G)* `` {0}"
lemma path_entry_reachable: assumes"path_entry (g_E G) p n" shows"reachable n" using assms reachable by (fastforce intro:path_verts simp add:reachable_def)
lemma nin_nodes_reachable: "n ∉ set (g_V G) ==>¬ reachable n" proof(rule ccontr) assume"n ∉ set (g_V G)"and nn: " ¬¬ reachable n" from‹n ∉ set (g_V G)›have"n ≠ 0"using verts_set len_verts_gt0 entry0 by auto from nn have"reachable n"by auto thenhave"n ∈ (g_E G)* `` {0}"by (simp add: reachable_def) thenhave" (0, n) ∈ (g_E G)* "by (auto simp add:Image_def) with‹n ≠ 0›have"∃n'. (0,n') ∈ (g_E G)*∧ (n', n) ∈ (g_E G)"by (auto intro:rtranclE) thenobtain n' where"(0,n') ∈ (g_E G)* "and" (n', n) ∈ (g_E G)"by auto thenhave"n ∈ set (g_V G)"using head_is_vert by auto with‹n ∉ set (g_V G)›show False by auto qed
lemma reachable_path_entry: "reachable n ==>∃p. path_entry (g_E G) p n" proof- assume"reachable n" thenhave"(0,n) ∈ (g_E G)*"by (auto simp add:reachable_def Image_iff) thenhave"0 = n ∨ 0 ≠ n ∧ (0,n) ∈ (g_E G)+"by (auto simp add: rtrancl_eq_or_trancl) thenshow ?thesis proof assume"0 = n" have"path_entry (g_E G) [] 0"by (simp add:path_entry0) with‹0 = n›show ?thesis by auto next assume"0 ≠ n ∧ (0,n) ∈ (g_E G)+" thenhave"(0,n) ∈ (g_E G)+"by (auto simp add:rtranclpD) thenhave"n ∈ set (g_V G)"by (simp add:head_is_vert2) thenshow ?thesis by (rule any_node_exits_path) qed qed
lemma path_entry_unconc: assumes"path_entry (g_E G) (la@lb) w" obtains v where"path_entry (g_E G) lb v" using assms apply (induct "la@lb" w arbitrary:la lb rule: path_entry.induct) apply (fastforce intro:path_entry.intros) by (auto intro:path_entry.intros iff add: Cons_eq_append_conv)
lemma path_entry_append_conv: "path_entry (g_E G) (v#l) w ⟷ (path_entry (g_E G) l v ∧ (v,w) ∈ (g_E G))" proof assume"path_entry (g_E G) (v # l) w " thenshow"path_entry (g_E G) l v ∧ (v, w) ∈ g_E G" by (auto simp add:path_entry_cons_conv) next assume"path_entry (g_E G) l v ∧ (v, w) ∈ g_E G" thenshow"path_entry (g_E G) (v # l) w "by (fastforce intro: path_entry_append) qed
lemma takeWhileNot_path_entry: assumes"path_entry E p x" and"v ∈ set p" and"takeWhile ((≠) v) (rev p) = c" shows"path_entry E (rev c) v" using assms proof (induct rule: path_entry.induct) case path_entry0 thenshow ?caseby auto next case (path_entry_prepend u va l) thenshow ?case proof(cases "v ∈ set l") case True note v_in = this thenhave"takeWhile ((≠) v) (rev (u # l)) = takeWhile ((≠) v) (rev l)"by auto with path_entry_prepend.prems(2) have"takeWhile ((≠) v) (rev l) = c"by simp with v_in show ?thesis using path_entry_prepend.hyps(3) by auto next case False note v_nin = this with path_entry_prepend.prems(1) have v_u: "v = u"by auto thenhave take_eq: "takeWhile ((≠) v) (rev (u # l)) = takeWhile ((≠) v) ((rev l) @ [u])"by auto from v_nin have"∧x. x ∈ set (rev l) ==> ((≠) v) x"by auto thenhave"takeWhile ((≠) v) ((rev l) @ [u]) = (rev l) @ takeWhile ((≠) v) [u]" by (rule takeWhile_append2) simp with v_u take_eq have"takeWhile ((≠) v) (rev (u # l)) = (rev l)"by simp thenshow ?thesis using path_entry_prepend.prems(2) path_entry_prepend.hyps(2) v_u by auto qed qed
lemma path_entry_last: "path_entry (g_E G) p n ==> p ≠ [] ==> last p = 0" apply (induct rule: path_entry.induct) apply simp apply (simp add: path_entry_cons_conv neq_Nil_conv) apply (auto simp add:path_entry0_empty_conv) done
lemma path_entry_loop: assumes n_path: "path_entry (g_E G) p n" and n: "n ∈ set p " shows"∃p'. path_entry (g_E G) p' n ∧ n ∉ set p'" using assms proof - let ?c = "takeWhile ((≠) n) (rev ( p))" have"∀z ∈ set ?c. z ≠ n"by (auto dest: set_takeWhileD) thenhave n_nin: "n ∉ set (rev ?c)"by auto
from n_path obtain v where"path_entry (g_E G) ( p) v"using path_entry_prepend_conv by auto with n have"path_entry (g_E G) (rev ?c) n"by (auto intro:takeWhileNot_path_entry) with n_nin show ?thesis by fastforce qed
lemma path_entry_hd_edge: assumes"path_entry (g_E G) pa p " and"pa ≠ []" shows"(hd pa, p) ∈ (g_E G)" using assms by (induct rule: path_entry.induct) auto
lemma path_entry_edge: assumes"pa ≠ [] " and"path_entry (g_E G) pa p " shows"∃u∈set pa. (path_entry (g_E G) (rev (takeWhile ((≠) u) (rev pa))) u) ∧ (u,p) ∈ (g_E G)" using assms proof- from assms have1: "path_entry (g_E G) (rev (takeWhile ((≠) (hd pa)) (rev pa))) (hd pa)"by (auto intro:takeWhileNot_path_entry) from assms have2: "(hd pa, p)∈ (g_E G)"by (auto intro: path_entry_hd_edge) have"hd pa ∈ set pa"using assms(1) by auto with12show ?thesis by auto qed
definition is_tail :: "node ==> node × node ==> bool" where"is_tail v e = (v = tail G e)"
definition is_head :: "node ==> node × node ==> bool" where"is_head v e = (v = head G e)"
lemma succ_range: "∀v ∈ succs n. v < length (g_V G)" by (insert succ_in_G verts_set) auto
lemma path_entry_gt: assumes"∀p. path_entry E p n ⟶ d ∈ set p" and"∀p. path_entry E p n' ⟶ n ∈ set p" shows"∀p. path_entry E p n' ⟶ d ∈ set p" using assms proof (intro strip) fix p let ?npath = "takeWhile ((≠) n) (rev p)" have sub: "set ?npath ⊆ set p"apply (induct p) by (auto dest:set_takeWhileD)
assume ass: "path_entry E p n' " with assms(2) have n_in_p: "n ∈ set p"by auto thenhave"n ∈ set (rev p)"by auto with ass have"path_entry E (rev ?npath) n" using takeWhileNot_path_entry by auto with assms(1) have"d ∈ set ?npath"by fastforce with sub show"d ∈ set p"by auto qed
definition dominate :: "nat ==> nat ==> bool" where"dominate n1 n2 ≡ ∀pa. path_entry (g_E G) pa n2 ⟶ (n1 ∈ set pa ∨ n1 = n2)"
definition strict_dominate:: "nat ==> nat ==> bool"where "strict_dominate n1 n2 ≡ ∀pa. path_entry (g_E G) pa n2 ⟶ (n1 ∈ set pa ∧ n1 ≠ n2)"
lemma any_dominate_unreachable: "¬ reachable n ==> dominate d n" proof(unfold reachable_def dominate_def) assume ass: "n ∉ (g_E G)* `` {0}"
have"¬ (∃p. path_entry (g_E G) p n)" proof (rule ccontr) assume" ¬ (¬ (∃p. path_entry (g_E G) p n))" thenobtain p where p: "path_entry (g_E G) p n"by auto thenhave"n = 0 ∨ reachable n"by (auto intro:path_entry_reachable) thenshow False proof assume"n = 0" thenshow False using ass by auto next assume"reachable n" thenshow False using ass by (auto simp add:reachable_def) qed qed thenshow"∀pa. path_entry (g_E G) pa n ⟶ d ∈ set pa ∨ d = n"by auto qed
lemma any_sdominate_unreachable: "¬ reachable n ==> strict_dominate d n" proof(unfold reachable_def strict_dominate_def) assume ass:"n ∉ (g_E G)* `` {0} "
have"¬ (∃p. path_entry (g_E G) p n)" proof (rule ccontr) assume" ¬ (¬ (∃p. path_entry (g_E G) p n))" thenobtain p where p: "path_entry (g_E G) p n"by auto thenhave"n = 0 ∨ reachable n"by (auto intro:path_entry_reachable) thenshow False proof assume"n = 0" thenshow False using ass by auto next assume"reachable n" thenshow False using ass by (auto simp add:reachable_def) qed qed thenshow"∀pa. path_entry (g_E G) pa n ⟶ d ∈ set pa ∧ d ≠ n"by auto qed
lemma dom_reachable: "reachable n ==> dominate d n ==> reachable d" proof - assume reach_n: "reachable n" and dom_n: "dominate d n" from reach_n have"∃p. path_entry (g_E G) p n"by (rule reachable_path_entry) thenobtain p where p: "path_entry (g_E G) p n"by auto
show"reachable d" proof (cases "d ≠ n") case True with dom_n p have d_in: "d ∈ set p"by (auto simp add:dominate_def) let ?pa = "takeWhile ((≠) d) (rev p)" from d_in p have"path_entry (g_E G) (rev ?pa) d"using takeWhileNot_path_entry by auto thenshow ?thesis using path_entry_reachable by auto next case False with reach_n show ?thesis by auto qed qed
lemma dominate_refl: "dominate n n" by (simp add:dominate_def)
lemma entry0_dominates_all: "∀p ∈ set (g_V G). dominate 0 p" proof(intro strip) fix p assume"p ∈ set (g_V G)" show"dominate 0 p" proof (cases "p = 0") case True thenshow ?thesis by (auto simp add:dominate_def) next case False assume p_neq0: "p ≠ 0" have"∀pa. path_entry (g_E G) pa p ⟶ 0 ∈ set pa" proof (intro strip) fix pa assume path_p: "path_entry (g_E G) pa p" show"0 ∈ set pa" proof (cases "pa ≠ []") case True note pa_n_nil = this with path_p have last_pa: "last pa = 0"using path_entry_last by auto from pa_n_nil have"last pa ∈ set pa"by simp with last_pa show ?thesis by simp next case False with path_p have"p = 0"by (simp add:path_entry0_empty_conv) with p_neq0 show ?thesis by auto qed qed thenshow ?thesis by (auto simp add:dominate_def) qed qed
lemma"strict_dominate i j ==> j ∈ set (g_V G) ==> i ≠ j" using any_node_exits_path by (auto simp add:strict_dominate_def)
show"\<exists>pa.path_entry(g_EG)pan\<and>n\<notin>setpa" proof(cases"n=0") caseTrue thenshow?thesisusingpa0by(autosimpadd:non_strict_dominate_def) next caseFalsenoten_neq_0=this withp_nhave"p\<noteq>[]"usingpath_entry0_empty_convbyauto thenshow?thesisusingp_nby(autointro:path_entry_loop) qed qed
*) lemma non_sdominate_succ: "(i,j ) ∈ g_E G ==> k ≠ i ==> non_strict_dominate k i ==> non_strict_dominate k j" proof - assume i_j: "(i,j ) ∈ g_E G"and k_neq_i: "k ≠ i"and"non_strict_dominate k i" thenobtain pa where"path_entry (g_E G) pa i"and k_nin_pa: "k ∉ set pa"by (auto simp add:non_strict_dominate_def) with i_j have"path_entry (g_E G) (i#pa) j"by (auto simp add:path_entry_prepend) with k_neq_i k_nin_pa show ?thesis by (auto simp add:non_strict_dominate_def) qed
lemma any_node_non_sdom0: "non_strict_dominate k 0" by (auto intro:entry0_path simp add:non_strict_dominate_def)
lemma nonstrict_eq: "non_strict_dominate i j ==>¬ strict_dominate i j" by (auto simp add:non_strict_dominate_def strict_dominate_def)
lemma dominate_trans: assumes"dominate n1 n2" and"dominate n2 n3" shows"dominate n1 n3" using assms proof(cases "n1 = n2") case True thenshow ?thesis using assms(2) by auto next case False thenshow"dominate n1 n3" proof (cases "n1 = n3") case True thenshow ?thesis by (auto simp add:dominate_def) next case False show"dominate n1 n3" proof (cases "n2 = n3") case True thenshow ?thesis using assms(1) by auto next case False with‹n1 ≠ n2›‹n1 ≠ n3›show ?thesis proof (auto simp add: dominate_def) fix pa assume"n1 ≠ n2"and"n1 ≠ n3"and"n2 ≠ n3" from‹n1 ≠ n2› assms(1) have n1_n2_pa: "∀pa. path_entry (g_E G) pa n2 ⟶ n1 ∈ set pa" by (auto simp add:dominate_def) from‹n2 ≠ n3› assms(2) have"∀pa. path_entry (g_E G) pa n3 ⟶ n2 ∈ set pa" by (auto simp add:dominate_def) with n1_n2_pa have"∀pa. path_entry (g_E G) pa n3 ⟶ n1 ∈ set pa" by (rule path_entry_gt) thenshow"∧pa. path_entry (g_E G) pa n3 ==> n1 ∈ set pa"by auto qed qed qed qed
lemma len_takeWhile_lt: "x ∈ set xs ==> length (takeWhile ((≠) x) xs) < length xs" by (induct xs) auto
lemma len_takeWhile_comp: assumes"n1 ∈ set xs" and"n2 ∈ set xs" and"n1 ≠ n2" shows"length (takeWhile ((≠) n1) xs) ≠ length (takeWhile ((≠) n2) xs)" using assms by (induct xs) auto
lemma len_takeWhile_comp1: assumes"n1 ∈ set xs" and"n2 ∈ set xs" and"n1 ≠ n2" shows"length (takeWhile ((≠) n1) (rev (x # xs))) ≠ length (takeWhile ((≠) n2) (rev (x # xs)))" using assms len_takeWhile_comp[of "n1""rev xs""n2"] by fastforce
lemma len_takeWhile_comp2: assumes"n1 ∈ set xs" and"n2 ∉ set xs" shows"length (takeWhile ((≠) n1) (rev (x # xs))) ≠ length (takeWhile ((≠) n2) (rev (x # xs)))" using assms proof- let ?xs1 = "takeWhile ((≠) n1) (rev (x # xs))" let ?xs2 = "takeWhile ((≠) n2) (rev (x # xs))" from assms have len1: "length (takeWhile ((≠) n1) (rev xs)) < length (rev xs)" using len_takeWhile_lt[of _"rev xs"] by auto
from assms(1) have"?xs1 = takeWhile ((≠) n1) (rev xs)"by auto thenhave len2: "length ?xs1 < length (rev xs)"using len1 by auto
from assms(2) have"takeWhile ((≠) n2) (rev xs @ [x]) = (rev xs) @ takeWhile ((≠) n2) [x]" by (fastforce intro:takeWhile_append2) thenhave"?xs2 = (rev xs) @ takeWhile ((≠) n2) [x]"by simp thenshow ?thesis using len2 by auto qed
lemma len_compare1: assumes"n1 = x"and"n2 ≠ x" shows"length (takeWhile ((≠) n1) (rev (x # xs))) ≠ length (takeWhile ((≠) n2) (rev (x # xs)))" using assms proof(cases "n1 ∈ set xs ∧ n2 ∈ set xs") case True with assms show ?thesis using len_takeWhile_comp1 by fastforce next let ?xs1 = "takeWhile ((≠) n1) (rev (x # xs))" let ?xs2 = "takeWhile ((≠) n2) (rev (x # xs))"
case False thenhave"n1 ∈ set xs ∧ n2 ∉ set xs ∨ n1 ∉ set xs ∧ n2 ∈ set xs ∨ n1 ∉ set xs ∧ n2 ∉ set xs"by auto thenshow ?thesis proof assume"n1 ∈ set xs ∧ n2 ∉ set xs" thenshow ?thesis by (fastforce dest: len_takeWhile_comp2) next assume"n1 ∉ set xs ∧ n2 ∈ set xs ∨ n1 ∉ set xs ∧ n2 ∉ set xs" thenshow ?thesis proof assume"n1 ∉ set xs ∧ n2 ∈ set xs" thenhave n1: "n1 ∉ set xs"and n2: "n2 ∈ set xs"by auto have"length ?xs2 ≠ length ?xs1"using len_takeWhile_comp2[OF n2 n1] by auto thenshow ?thesis by simp next assume"n1 ∉ set xs ∧ n2 ∉ set xs" thenhave n1_nin: "n1 ∉ set xs"and n2_nin: "n2 ∉ set xs"by auto thenhave t1: "takeWhile ((≠) n1) (rev xs @ [x]) = (rev xs) @ takeWhile ((≠) n1) [x]" and"takeWhile ((≠) n2) (rev xs @ [x]) = (rev xs) @ takeWhile ((≠) n2) [x]" by (fastforce intro:takeWhile_append2)+ with‹n1 = x›‹n2 ≠ x›have t1': "takeWhile ((≠) n1) (rev xs @ [x]) = rev xs" and"takeWhile ((≠) n2) (rev xs @ [x]) = (rev xs) @ [x]"by auto thenhave"length (takeWhile ((≠) n2) (rev xs @ [x])) = length ((rev xs) @ [x])" using arg_cong[of "takeWhile ((≠) n2) (rev xs @ [x])""rev xs @ [x]""length"] by fastforce with t1' show ?thesis by auto qed qed qed
lemma len_takeWhile_set: assumes"length (takeWhile ((≠) n1) xs) > length (takeWhile ((≠) n2) xs)" and"n1 ≠ n2" and"n1 ∈ set xs" and"n2 ∈ set xs" shows"set (takeWhile ((≠) n2) xs) ⊆ set (takeWhile ((≠) n1) xs)" using assms proof (induct xs) case Nil thenshow ?caseby auto next case (Cons y ys) note ind_hyp = Cons(1) note len_n2_lt_n1_y_ys = Cons(2) note n1_n_n2 = Cons(3) note n1_in_y_ys = Cons(4) note n2_in_y_ys = Cons(5)
let ?ys1_take = "takeWhile ((≠) n1) ys" let ?ys2_take = "takeWhile ((≠) n2) ys"
show ?case proof(cases "n1 ∈ set ys") case True note n1_in_ys = this show ?thesis proof(cases "n2 ∈ set ys") case True note n2_in_ys = this show ?thesis proof (cases "n1 ≠ y") case True note n1_neq_y = this show ?thesis proof (cases "n2 ≠ y") case True note n2_neq_y = this from len_n2_lt_n1_y_ys have"length ?ys2_take < length ?ys1_take" using n1_n_n2 n1_in_ys n2_in_ys n1_neq_y n2_neq_y by (induct ys) auto from ind_hyp[OF this n1_n_n2 n1_in_ys n2_in_ys] have"set (takeWhile ((≠) n2) ys) ⊆ set (takeWhile ((≠) n1) ys)"by auto thenshow ?thesis using n1_neq_y n2_neq_y by (induct ys) auto next case False with n1_n_n2 show ?thesis by auto qed next case False with n1_n_n2 show ?thesis using len_n2_lt_n1_y_ys by auto qed next case False with n2_in_y_ys have"n2 = y"by auto thenshow ?thesis by auto qed next case False with n1_in_y_ys have"n1 = y"by auto with n1_n_n2 show ?thesis using len_n2_lt_n1_y_ys by auto qed qed
lemma reachable_dom_acyclic: assumes"reachable n2" and"dominate n1 n2" and"dominate n2 n1" shows"n1 = n2" using assms proof - from assms(1) assms(2) have"reachable n1"by (auto intro: dom_reachable) thenhave"∃pa. path_entry (g_E G) pa n1"by (auto intro: reachable_path_entry) thenobtain pa where pa: "path_entry (g_E G) pa n1"by auto
let ?n_take_n1 = "takeWhile ((≠) n1) (rev pa)" let ?n_take_n2 = "takeWhile ((≠) n2) (rev pa)"
show"n1 = n2" proof(rule ccontr) assume n1_neq_n2: "n1 ≠ n2" thenhave pa_n1_n2: "∀pa. path_entry (g_E G) pa n2 ⟶ n1 ∈ set pa" and pa_n2_n1: "∀pa. path_entry (g_E G) pa n1 ⟶ n2 ∈ set pa"using assms(2) assms(3) by (auto simp add:dominate_def) thenhave n1_n1_pa: "∀pa. path_entry (g_E G) pa n1 ⟶ n1 ∈ set pa"by (rule path_entry_gt) with pa pa_n2_n1 have n1_in_pa: "n1 ∈ set pa" and n2_in_pa: "n2 ∈ set pa"by auto with n1_neq_n2 have len_neq: "length ?n_take_n1 ≠ length ?n_take_n2" by (auto simp add: len_takeWhile_comp)
from pa n1_in_pa n2_in_pa have path1: "path_entry (g_E G) (rev ?n_take_n1) n1" and path2: "path_entry (g_E G) (rev ?n_take_n2) n2" using takeWhileNot_path_entry by auto
have n1_not_in: "n1 ∉ set ?n_take_n1"by (auto dest: set_takeWhileD[of _ _ "rev pa"]) have n2_not_in: "n2 ∉ set ?n_take_n2"by (auto dest: set_takeWhileD[of _ _ "rev pa"])
show False proof(cases "length ?n_take_n1 > length ?n_take_n2") case True thenhave"set ?n_take_n2 ⊆ set ?n_take_n1" using n1_in_pa n2_in_pa by (auto dest: len_takeWhile_set[of _ "rev pa"]) thenhave"n1 ∉ set ?n_take_n2 "using n1_not_in by auto with path2 show False using pa_n1_n2 by auto next case False with len_neq have"length ?n_take_n2 > length ?n_take_n1"by auto thenhave"set ?n_take_n1 ⊆ set ?n_take_n2" using n1_neq_n2 n2_in_pa n1_in_pa by (auto dest: len_takeWhile_set) thenhave"n2 ∉ set ?n_take_n1 "using n2_not_in by auto with path1 show False using pa_n2_n1 by auto qed qed qed
lemma sdom_neq: assumes"reachable n2" and"strict_dominate n1 n2" shows"n1 ≠ n2" using assms proof - from assms(1) have"∃p. path_entry (g_E G) p n2"by (rule reachable_path_entry) thenobtain p where"path_entry (g_E G) p n2"by auto with assms(2) show ?thesis by (auto simp add:strict_dominate_def) qed
lemma reachable_dom_acyclic2: assumes"reachable n2 " and"strict_dominate n1 n2" shows"¬ dominate n2 n1" using assms proof - from assms have n1_dom_n2: "dominate n1 n2"and n1_neq_n2: "n1 ≠ n2" by (auto simp add:sdom_dom sdom_neq) with assms(1) have"dominate n2 n1 ==> n1 = n2"using reachable_dom_acyclic by auto with n1_neq_n2 show ?thesis by auto qed
lemma strict_dominate_trans1: assumes"strict_dominate n1 n2" and"dominate n2 n3" shows"strict_dominate n1 n3" using assms proof (cases "reachable n2") case True note reach_n2 = this with assms(1) have n1_dom_n2: "dominate n1 n2"and n1_neq_n2: "n1 ≠ n2" by (auto simp add:sdom_dom sdom_neq) with assms(2) have n1_dom_n3: "dominate n1 n3"by (auto intro: dominate_trans) have n1_neq_n3: "n1 ≠ n3" proof (rule ccontr) assume"¬ n1 ≠ n3"thenhave"n1 = n3"by simp with assms(2) have n2_dom_n1: "dominate n2 n1"by simp with reach_n2 n1_dom_n2 have"n1 = n2"by (auto dest:reachable_dom_acyclic) with n1_neq_n2 show False by auto qed with n1_dom_n3 show ?thesis by (simp add:strict_dominate_def dominate_def) next case False note not_reach_n2 = this have"¬ reachable n3" proof (rule ccontr) assume"¬¬ reachable n3 " with assms(2) have"reachable n2"by (auto intro: dom_reachable) with not_reach_n2 show False by auto qed thenshow ?thesis by (auto intro:any_sdominate_unreachable) qed
lemma strict_dominate_trans2: assumes"dominate n1 n2" and"strict_dominate n2 n3" shows"strict_dominate n1 n3" using assms proof (cases "reachable n3") case True with assms(2) have n2_dom_n3: "dominate n2 n3"and n1_neq_n2: "n2 ≠ n3" by (auto simp add:sdom_dom sdom_neq) with assms(1) have n1_dom_n3: "dominate n1 n3"by (auto intro: dominate_trans) have n1_neq_n3: "n1 ≠ n3" proof (rule ccontr) assume"¬ n1 ≠ n3"thenhave"n1 = n3"by simp with assms(1) have"dominate n3 n2"by simp with‹reachable n3› n2_dom_n3 have"n2 = n3"by (auto dest:reachable_dom_acyclic) with n1_neq_n2 show False by auto qed with n1_dom_n3 show ?thesis by (simp add:strict_dominate_def dominate_def) next case False thenhave"¬ reachable n3"by simp thenshow ?thesis by (auto intro:any_sdominate_unreachable) qed
lemma sdominate_dominate_succs: assumes i_sdom_j: "strict_dominate i j" and j_in_succ_k: "j ∈ succs k" shows"dominate i k" proof (rule ccontr) assume ass:"¬ dominate i k" thenobtain p where path_k: "path_entry (g_E G) p k"and i_nin_p: "i ∉ set p"by (auto simp add:dominate_def) with j_in_succ_k i_sdom_j have i: "i = k ∨ i = j"by (auto intro:path_entry_append simp add:succs_def strict_dominate_def)
from j_in_succ_k have"reachable j"using succ_in_verts reachable by (auto simp add:reachable_def) with i_sdom_j have"i ≠ j"by (auto simp add: sdom_neq) with i have"i = k"by auto thenhave"dominate i k"by (auto simp add:dominate_refl) with ass show False by auto qed
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.