text‹We extend the Graph framework with inductively defined paths.
We adopt the convention of separating locale definitions into assumption-less base locales.›
theory Graph_path imports
FormalSSA_Misc
Dijkstra_Shortest_Path.GraphSpec
CAVA_Automata.Digraph_Basic begin
locale graph_pred_it_defs = fixes pred_list_it :: "'G ==> 'V ==> ('V×'W,('V×'W) list) set_iterator" begin definition"pred_it g v ≡ it_to_it (pred_list_it g v)" end
locale graph_pred_it = graph α invar + graph_pred_it_defs pred_list_it for α :: "'G ==> ('V,'W) graph"and invar and
pred_list_it :: "'G ==> 'V ==> ('V×'W,('V×'W) list) set_iterator" + assumes pred_list_it_correct: "invar g ==> set_iterator (pred_list_it g v) (pred (α g) v)" begin lemma pred_it_correct: "invar g ==> set_iterator (pred_it g v) (pred (α g) v)" unfolding pred_it_def apply (rule it_to_it_correct) by (rule pred_list_it_correct)
lemma pi_pred_it[icf_proper_iteratorI]: "proper_it (pred_it S v) (pred_it S v)" unfolding pred_it_def by (intro icf_proper_iteratorI)
lemma pred_it_proper[proper_it]: "proper_it' (λS. pred_it S v) (λS. pred_it S v)" apply (rule proper_it'I) by (rule pi_pred_it) end
definition inEdges :: "'g ==> 'node ==> ('node × 'edgeD × 'node) list" where"inEdges g n ≡ map (λ(f,d). (f,d,n)) (inEdges' g n)"
definition predecessors :: "'g ==> 'node ==> 'node list"where "predecessors g n ≡ map getFrom (inEdges g n)"
definition successors :: "'g ==> 'node ==> 'node list"where "successors g m ≡ [n . n ← αn g, m ∈ set (predecessors g n)]"
declare [[inductive_internals]] inductive path :: "'g ==> 'node list ==> bool" for g :: 'g where
empty_path[intro]: "[n ∈ set (αn g); invar g]==> path g [n]"
| Cons_path[intro]: "[path g ns; n' ∈ set (predecessors g (hd ns))]==> path g (n'#ns)"
definition path2 :: "'g ==> 'node ==> 'node list ==> 'node ==> bool" (‹_ ⊨ _-_→_› [51,0,0,51] 80) where "path2 g n ns m ≡ path g ns ∧ n = hd ns ∧ m = last ns"
abbreviation"α g ≡(nodes = set (αn g), edges = αe g)" end
lemma αn_distinct: "invar g ==> distinct (αn g)" by (frule ni.nodes_list_it_correct)
(metis foldri_cons_id iterate_to_list_correct iterate_to_list_def)
lemma inEdges_correct': assumes"invar g" shows"set (inEdges g n) = (λ(f,d). (f,d,n)) ` (pred (α g) n)" proof - from iterate_to_list_correct [OF pi.pred_list_it_correct [OF assms], of n] show ?thesis by (auto intro: rev_image_eqI simp: iterate_to_list_def pred_def inEdges_def) qed
lemma inEdges_correct [intro!, simp]: "invar g ==> set (inEdges g n) = {(_, _, t). t = n} ∩ αe g" by (auto simp: inEdges_correct' pred_def)
lemma in_set_αnI1 [intro]: "[invar g; x ∈ getFrom ` αe g]==> x ∈ set (αn g)" using αn_correct by blast lemma in_set_αnI2 [intro]: "[invar g; x ∈ getTo ` αe g]==> x ∈ set (αn g)" using αn_correct by blast
(*
localegraph_path_base=graph_inEdges_base\<alpha>einvarinEdges+graph_nodes_base\<alpha>einvar\<alpha>n for \<alpha>e::"'g\<Rightarrow>('node\<times>'edgeD\<times>'node)set"and \<alpha>n::"'g\<Rightarrow>'nodelist"and invar::"'g\<Rightarrow>bool"and inEdges::"'g\<Rightarrow>'node\<Rightarrow>('node\<times>'edgeD\<times>'node)list" begin
*)
(* end
localegraph_path=graph_path_base\<alpha>e\<alpha>ninvarinEdges+graph_inEdges\<alpha>einvarinEdges+graph_nodes\<alpha>einvar\<alpha>n for \<alpha>e::"'g\<Rightarrow>('node\<times>'edgeD\<times>'node)set"and \<alpha>n::"'g\<Rightarrow>'nodelist"and invar::"'g\<Rightarrow>bool"and inEdges::"'g\<Rightarrow>'node\<Rightarrow>('node\<times>'edgeD\<times>'node)list" begin
*)
lemma edge_to_node: assumes"invar g"and"e ∈ αe g" obtains"getFrom e ∈ set (αn g)"and"getTo e ∈ set (αn g)" using assms(2) αn_correct [OF ‹invar g›] by (cases e) (auto 43 intro: rev_image_eqI)
lemma inEdge_to_edge: assumes"e ∈ set (inEdges g n)"and"invar g" obtains eD n' where"(n',eD,n) ∈ αe g" using assms by auto
lemma edge_to_inEdge: assumes"(n,eD,m) ∈ αe g""invar g" obtains"(n,eD,m) ∈ set (inEdges g m)" using assms by auto
lemma edge_to_predecessors: assumes"(n,eD,m) ∈ αe g""invar g" obtains"n ∈ set (predecessors g m)" proof atomize_elim from assms have"(n,eD,m) ∈ set (inEdges g m)"by (rule edge_to_inEdge) thus"n ∈ set (predecessors g m)"unfolding predecessors_def by (metis get_edge_simps(1) image_eqI set_map) qed
lemma predecessor_is_node[elim]: "[n ∈ set (predecessors g n'); invar g]==> n ∈ set (αn g)" unfolding predecessors_def by (fastforce intro: rev_image_eqI simp: getTo_def getFrom_def)
lemma successor_is_node[elim]: "[n ∈ set (predecessors g n'); n ∈ set (αn g); invar g]==> n' ∈ set (αn g)" unfolding predecessors_def by (fastforce intro: rev_image_eqI)
lemma successors_predecessors[simp]: "n ∈ set (αn g) ==> n ∈ set (successors g m) ⟷ m ∈ set (predecessors g n)" by (auto simp:successors_def predecessors_def)
lemma path_not_Nil[simp, dest]: "path g ns ==> ns ≠ []" by (erule path.cases) auto
lemma path2_not_Nil[simp]: "g ⊨ n-ns→m ==> ns ≠ []" unfolding path2_def by auto
lemma path2_not_Nil2[simp]: "¬ g ⊨ n-[]→m" unfolding path2_def by auto
lemma empty_path2[intro]: "[n ∈ set (αn g); invar g]==> g ⊨ n-[n]→n" unfolding path2_def by auto
lemma Cons_path2[intro]: "[g ⊨ n-ns→m; n' ∈ set (predecessors g n)]==> g ⊨ n'-n'#ns→m" unfolding path2_def by auto
lemma path2_cases: assumes"g ⊨ n-ns→m" obtains (empty_path) "ns = [n]""m = n"
| (Cons_path) "g ⊨ hd (tl ns)-tl ns→m""n ∈ set (predecessors g (hd (tl ns)))" proof- from assms have1: "path g ns""hd ns = n""last ns = m"by (auto simp: path2_def) from this(1) show thesis proof cases case (empty_path n) with1show thesis by - (rule that(1), auto) next case (Cons_path ns n') with1show thesis by - (rule that(2), auto simp: path2_def) qed qed
lemma path2_induct[consumes 1, case_names empty_path Cons_path]: assumes"g ⊨ n-ns→m" assumes empty: "invar g ==> P m [m] m" assumes Cons: "∧ns n' n. g ⊨ n-ns→m ==> P n ns m ==> n' ∈ set (predecessors g n) ==> P n' (n' # ns) m" shows"P n ns m" using assms(1) unfolding path2_def apply- proof (erule conjE, induction arbitrary: n rule:path.induct) case empty_path with empty show ?caseby simp next case (Cons_path ns n' n'') hence[simp]: "n'' = n'"by simp from Cons_path Cons show ?caseunfolding path2_def by auto qed
lemma path_invar[intro]: "path g ns ==> invar g" by (induction rule:path.induct)
lemma path_in_αn[intro]: "[path g ns; n ∈ set ns]==> n ∈ set (αn g)" by (induct ns arbitrary: n rule:path.induct) auto
lemma path2_in_αn[elim]: "[g ⊨ n-ns→m; l ∈ set ns]==> l ∈ set (αn g)" unfolding path2_def by auto
lemma path2_hd_in_αn[elim]: "g ⊨ n-ns→m ==> n ∈ set (αn g)" unfolding path2_def by auto
lemma path2_tl_in_αn[elim]: "g ⊨ n-ns→m ==> m ∈ set (αn g)" unfolding path2_def by auto
lemma path2_forget_hd[simp]: "g ⊨ n-ns→m ==> g ⊨ hd ns-ns→m" unfolding path2_def by simp
lemma path2_forget_last[simp]: "g ⊨ n-ns→m ==> g ⊨ n-ns→last ns" unfolding path2_def by simp
lemma path_hd[dest]: "path g (n#ns) ==> path g [n]" by (rule empty_path, auto elim:path.cases)
lemma path_by_tail[intro]: "[path g (n#n'#ns); path g (n'#ns) ==> path g (n'#ms)]==> path g (n#n'#ms)" by (rule path.cases) auto
lemma αn_in_αnE [elim]: assumes"(n,e,m) ∈ αe g"and"invar g" obtains"n ∈ set (αn g)"and"m ∈ set (αn g)" using assms by (auto elim: edge_to_node)
lemma path_split: assumes"path g (ns@m#ns')" shows"path g (ns@[m])""path g(m#ns')" proof- from assms show"path g (ns@[m])" proof (induct ns) case (Cons n ns) thus ?caseby (cases ns) auto qed auto from assms show"path g (m#ns')" proof (induct ns) case (Cons n ns) thus ?caseby (auto elim:path.cases) qed auto qed
lemma path2_split: assumes"g ⊨ n-ns@n'#ns'→m" shows"g ⊨ n-ns@[n']→n'""g ⊨ n'-n'#ns'→m" using assms unfolding path2_def by (auto intro:path_split iff:hd_append)
lemma elem_set_implies_elem_tl_app_cons[simp]: "x ∈ set xs ==> x ∈ set (tl (ys@y#xs))" by (induction ys arbitrary: y; auto)
lemma path2_split_ex: assumes"g ⊨ n-ns→m""x ∈ set ns" obtains ns1 ns2where"g ⊨ n-ns1→x""g ⊨ x-ns2→m""ns = ns1@tl ns2""ns = butlast ns1@ns2" proof- from assms(2) obtain ns1 ns2where"ns = ns1@x#ns2"by atomize_elim (rule split_list) with assms[simplified this] show thesis by - (rule that, auto dest:path2_split(1) path2_split(2) intro: suffixI) qed
lemma path2_split_ex': assumes"g ⊨ n-ns→m""x ∈ set ns" obtains ns1 ns2where"g ⊨ n-ns1→x""g ⊨ x-ns2→m""ns = butlast ns1@ns2" using assms by (rule path2_split_ex)
lemma path_snoc: assumes"path g (ns@[n])""n ∈ set (predecessors g m)" shows"path g (ns@[n,m])" using assms(1) proof (induction ns) case Nil hence1: "n ∈ set (αn g)""invar g"by auto with assms(2) have"m ∈ set (αn g)"by auto with1have"path g [m]"by auto with assms(2) show ?caseby auto next case (Cons l ns) hence1: "path g (ns @ [n]) ∧ l ∈ set (predecessors g (hd (ns@[n])))"by -(cases g "(l # ns) @ [n]" rule:path.cases, auto) hence"path g (ns @ [n,m])"by (auto intro:Cons.IH) with1have"path g (l # ns @ [n,m])"by -(rule Cons_path, assumption, cases ns, auto) thus ?caseby simp qed
lemma path2_snoc[elim]: assumes"g ⊨ n-ns→m""m ∈ set (predecessors g m')" shows"g ⊨ n-ns@[m']→m'" proof- from assms(1) have1: "ns ≠ []"by auto
have"path g ((butlast ns) @ [last ns, m'])" using assms unfolding path2_def by -(rule path_snoc, auto) hence"path g ((butlast ns @ [last ns]) @ [m'])"by simp with1have"path g (ns @ [m'])"by simp thus ?thesis using assms unfolding path2_def by auto qed
lemma path_unsnoc: assumes"path g ns""length ns ≥ 2" obtains"path g (butlast ns) ∧ last (butlast ns) ∈ set (predecessors g (last ns))" using assms proof (atomize_elim, induction ns) case (Cons_path ns n) show ?case proof (cases "2 ≤ length ns") case True hence [simp]: "hd (butlast ns) = hd ns"by (cases ns, auto) have0: "n#butlast ns = butlast (n#ns)"using True by auto have1: "n ∈ set (predecessors g (hd (butlast ns)))"using Cons_path by simp from True have"path g (butlast ns)"using Cons_path by auto hence"path g (n#butlast ns)"using1by auto hence"path g (butlast (n#ns))"using0by simp moreover from Cons_path True have"last (butlast ns) ∈ set (predecessors g (last ns))"by simp hence"last (butlast (n # ns)) ∈ set (predecessors g (last (n # ns)))" using True by (cases ns, auto) ultimatelyshow ?thesis by auto next case False thus ?thesis proof (cases ns) case Nil thus ?thesis using Cons_path by -(rule ccontr, auto elim:path.cases) next case (Cons n' ns') hence [simp]: "ns = [n']"using False by (cases ns', auto) have"path g [n,n']"using Cons_path by auto thus ?thesis using Cons_path by auto qed qed qed auto
lemma path2_unsnoc: assumes"g ⊨ n-ns→m""length ns ≥ 2" obtains"g ⊨ n-butlast ns→last (butlast ns)""last (butlast ns) ∈ set (predecessors g m)" using assms unfolding path2_def by (metis append_butlast_last_id hd_append2 path_not_Nil path_unsnoc)
lemma path2_rev_induct[consumes 1, case_names empty snoc]: assumes"g ⊨ n-ns→m" assumes empty: "n ∈ set (αn g) ==> P n [n] n" assumes snoc: "∧ns m' m. g ⊨ n-ns→m' ==> P n ns m' ==> m' ∈ set (predecessors g m) ==> P n (ns@[m]) m" shows"P n ns m" using assms(1) proof (induction arbitrary:m rule:length_induct) case (1 ns) show ?case proof (cases "length ns ≥ 2") case False thus ?thesis proof (cases ns) case Nil thus ?thesis using1(2) by auto next case (Cons n' ns') with False have"ns' = []"by (cases ns', auto) with Cons 1(2) have"n' = n""m = n"unfolding path2_def by auto with Cons ‹ns' = []›1(2) show ?thesis by (auto intro:empty) qed next case True let ?ns' = "butlast ns" let ?m' = "last ?ns'" from1(2) have m: "m = last ns"unfolding path2_def by auto from True 1(2) obtain ns': "g ⊨ n-?ns'→?m'""?m' ∈ set (predecessors g m)"by -(rule path2_unsnoc) with True "1.IH"have"P n ?ns' ?m'"by auto with ns' have"P n (?ns'@[m]) m"by (auto intro!: snoc) with m 1(2) show ?thesis by auto qed qed
lemma path2_hd[elim, dest?]: "g ⊨ n-ns→m ==> n = hd ns" unfolding path2_def by simp
lemma path2_hd_in_ns[elim]: "g ⊨ n-ns→m ==> n ∈ set ns" unfolding path2_def by auto
lemma path2_last[elim, dest?]: "g ⊨ n-ns→m ==> m = last ns" unfolding path2_def by simp
lemma path2_last_in_ns[elim]: "g ⊨ n-ns→m ==> m ∈ set ns" unfolding path2_def by auto
lemma path_app[elim]: assumes"path g ns""path g ms""last ns = hd ms" shows"path g (ns@tl ms)" using assms by (induction ns rule:path.induct) auto
lemma path2_app[elim]: assumes"g ⊨ n-ns→m""g ⊨ m-ms→l" shows"g ⊨ n-ns@tl ms→l" proof- have"last (ns @ tl ms) = last ms"using assms unfolding path2_def proof (cases "tl ms") case Nil hence"ms = [m]"using assms(2) unfolding path2_def by (cases ms, auto) thus ?thesis using assms(1) unfolding path2_def by auto next case (Cons m' ms') from this[symmetric] have"ms = hd ms#m'#ms'"using assms(2) by auto thus ?thesis using assms unfolding path2_def by auto qed with assms show ?thesis unfolding path2_def by auto qed
lemma simple_path2_aux: assumes"g ⊨ n-ns→m" obtains ns' where"g ⊨ n-ns'→m""distinct ns'""set ns' ⊆ set ns""length ns' ≤ length ns" apply atomize_elim using assms proof (induction rule:path2_induct) case empty_path with assms show ?caseby - (rule exI[of _ "[m]"], auto) next case (Cons_path ns n n') thenobtain ns' where ns': "g ⊨ n'-ns'→m""distinct ns'""set ns' ⊆ set ns""length ns' ≤ length ns"by auto show ?case proof (cases "n ∈ set ns'") case False with ns' Cons_path(2) show ?thesis by -(rule exI[where x="n#ns'"], auto) next case True with ns' obtain ns'1 ns'2where split: "ns' = ns'1@n#ns'2""n ∉ set ns'2"by -(atomize_elim, rule split_list_last) with ns' have"g ⊨ n-n#ns'2→m"by -(rule path2_split, simp) with split ns' show ?thesis by -(rule exI[where x="n#ns'2"], auto) qed qed
lemma simple_path2: assumes"g ⊨ n-ns→m" obtains ns' where"g ⊨ n-ns'→m""distinct ns'""set ns' ⊆ set ns""length ns' ≤ length ns""n ∉ set (tl ns')""m ∉ set (butlast ns')" using assms apply (rule simple_path2_aux) by (metis append_butlast_last_id distinct.simps(2) distinct1_rotate hd_Cons_tl path2_hd path2_last path2_not_Nil rotate1.simps(2))
lemma simple_path2_unsnoc: assumes"g ⊨ n-ns→m""n ≠ m" obtains ns' where"g ⊨ n-ns'→last ns'""last ns' ∈ set (predecessors g m)""distinct ns'""set ns' ⊆ set ns""m ∉ set ns'" proof- obtain ns' where1: "g ⊨ n-ns'→m""distinct ns'""set ns' ⊆ set ns""m ∉ set (butlast ns')"by (rule simple_path2[OF assms(1)]) with assms(2) obtain2: "g ⊨ n-butlast ns'→last (butlast ns')""last (butlast ns') ∈ set (predecessors g m)"by - (rule path2_unsnoc, auto) show thesis proof (rule that[of "butlast ns'"]) from1(3) show"set (butlast ns') ⊆ set ns"by (metis in_set_butlastD subsetI subset_trans) qed (auto simp:12 distinct_butlast) qed
lemma path2_simple_loop: assumes"g ⊨ n-ns→n""n' ∈ set ns" obtains ns' where"g ⊨ n-ns'→n""n' ∈ set ns'""n ∉ set (tl (butlast ns'))""set ns' ⊆set ns" using assms proof (induction"length ns" arbitrary: ns rule: nat_less_induct) case1 let ?ns' = "tl (butlast ns)" show ?case proof (cases "n ∈ set ?ns'") case False with"1.prems"(2,3) show ?thesis by - (rule "1.prems"(1), auto) next case True hence2: "length ns > 1"by (cases ns, auto) with"1.prems"(2) obtain m where m: "g ⊨ n-butlast ns→m""m ∈ set (predecessors g n)"by - (rule path2_unsnoc, auto) with True obtain m' where m': "g ⊨ m'-?ns'→m""n ∈ set (predecessors g m')"by - (erule path2_cases, auto) with True obtain ns1 ns2where split: "g ⊨ m'-ns1→n""g ⊨ n-ns2→m""?ns' = ns1@tl ns2""?ns' = butlast ns1@ns2" by - (rule path2_split_ex) have"ns = butlast ns@[n]"using2"1.prems"(2) by (auto simp: path2_def) moreoverhave"butlast ns = n#tl (butlast ns)"using2 m(1) by (auto simp: path2_def) ultimatelyhave split': "ns = n#ns1@tl ns2@[n]""ns = n#butlast ns1@ns2@[n]"using split(3,4) by auto show ?thesis proof (cases "n' ∈ set (n#ns1)") case True show ?thesis proof (rule "1.hyps"[rule_format, of _ "n#ns1"]) show"length (n#ns1) < length ns"using split'(1) by auto show"n' ∈ set (n#ns1)"by (rule True) qed (auto intro: split(1) m'(2) intro!: "1.prems"(1) simp: split'(1)) next case False from False split'(1) "1.prems"(3) have5: "n' ∈ set (ns2@[n])"by auto show ?thesis proof (rule "1.hyps"[rule_format, of _ "ns2@[n]"]) show"length (ns2@[n]) < length ns"using split'(2) by auto show"n' ∈ set (ns2@[n])"by (rule 5) show"g ⊨ n-ns2@[n]→n"using split(2) m(2) by (rule path2_snoc) qed (auto intro!: "1.prems"(1) simp: split'(2)) qed qed qed
lemma path2_split_first_prop: assumes"g ⊨ n-ns→m""∃x∈set ns. P x" obtains m' ns' where"g ⊨ n-ns'→m'""P m'""∀x ∈ set (butlast ns'). ¬P x""prefix ns' ns" proof- obtain ns'' n' ns' where1: "ns = ns''@n'#ns'""P n'""∀x ∈ set ns''. ¬P x"by - (rule split_list_first_propE[OF assms(2)]) with assms(1) have"g ⊨ n-ns''@[n']→n'"by - (rule path2_split(1), auto) with1show thesis by - (rule that, auto) qed
lemma path2_split_last_prop: assumes"g ⊨ n-ns→m""∃x∈set ns. P x" obtains n' ns' where"g ⊨ n'-ns'→m""P n'""∀x ∈ set (tl ns'). ¬P x""suffix ns' ns" proof- obtain ns'' n' ns' where1: "ns = ns''@n'#ns'""P n'""∀x ∈ set ns'. ¬P x"by - (rule split_list_last_propE[OF assms(2)]) with assms(1) have"g ⊨ n'-n'#ns'→m"by - (rule path2_split(2), auto) with1show thesis by - (rule that, auto simp: Sublist.suffix_def) qed
text‹We fix an entry node per graph and use it to define node domination.›
locale graph_Entry_base = graph_path_base αe αn invar inEdges' for
αe :: "'g ==> ('node × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"
+ fixes Entry :: "'g ==> 'node" begin definition dominates :: "'g ==> 'node ==> 'node ==> bool"where "dominates g n m ≡ m ∈ set (αn g) ∧ (∀ns. g ⊨ Entry g-ns→m ⟶ n ∈ set ns)"
abbreviation"strict_dom g n m ≡ n ≠ m ∧ dominates g n m" end
locale graph_Entry = graph_Entry_base αe αn invar inEdges' Entry
+ graph_path αe αn invar inEdges' for
αe :: "'g ==> ('node × 'edgeD × 'node) set"and
αn :: "'g ==> 'node list"and
invar :: "'g ==> bool"and
inEdges' :: "'g ==> 'node ==> ('node × 'edgeD) list"and
Entry :: "'g ==> 'node"
+ assumes Entry_in_graph[simp]: "Entry g ∈ set (αn g)" assumes Entry_unreachable: "invar g ==> inEdges g (Entry g) = []" assumes Entry_reaches[intro]: "[n ∈ set (αn g); invar g]==>∃ns. g ⊨ Entry g-ns→n" begin lemma Entry_dominates[simp,intro]: "[invar g; n ∈ set (αn g)]==> dominates g (Entry g) n" unfolding dominates_def by auto
lemma Entry_iff_unreachable[simp]: assumes"invar g""n ∈ set (αn g)" shows"predecessors g n = [] ⟷ n = Entry g" proof (rule, rule ccontr) assume"predecessors g n = []""n ≠ Entry g" with Entry_reaches[OF assms(2,1)] show False by (auto elim:simple_path2_unsnoc) qed (auto simp:assms Entry_unreachable predecessors_def)
lemma Entry_loop: assumes"invar g""g ⊨ Entry g-ns→Entry g" shows"ns=[Entry g]" proof (cases "length ns ≥ 2") case True with assms have"last (butlast ns) ∈ set (predecessors g (Entry g))"by - (rule path2_unsnoc) with Entry_unreachable[OF assms(1)] have False by (simp add:predecessors_def) thus ?thesis .. next case False with assms show ?thesis by (metis Suc_leI hd_Cons_tl impossible_Cons le_less length_greater_0_conv numeral_2_eq_2 path2_hd path2_not_Nil) qed
lemma simple_Entry_path: assumes"invar g""n ∈ set (αn g)" obtains ns where"g ⊨ Entry g-ns→n"and"n ∉ set (butlast ns)" proof- from assms obtain ns where p: "g ⊨ Entry g-ns→n"by -(atomize_elim, rule Entry_reaches) with p obtain ns' where"g ⊨ Entry g-ns'→n""n ∉ set (butlast ns')"by -(rule path2_split_first_last, auto) thus ?thesis by (rule that) qed
lemma dominatesI [intro]: "[m ∈ set (αn g); ∧ns. [g ⊨ Entry g-ns→m]==> n ∈ set ns]==> dominates g n m" unfolding dominates_def by simp
lemma dominatesE: assumes"dominates g n m" obtains"m ∈ set (αn g)"and"∧ns. g ⊨ Entry g-ns→m ==> n ∈ set ns" using assms unfolding dominates_def by auto
lemma[simp]: "dominates g n m ==> m ∈ set (αn g)"by (rule dominatesE)
lemma[simp]: assumes"dominates g n m"and[simp]: "invar g" shows"n ∈ set (αn g)" proof- from assms obtain ns where"g ⊨ Entry g-ns→m"by atomize_elim (rule Entry_reaches, auto) with assms show ?thesis by (auto elim!:dominatesE) qed
lemma strict_domE[elim]: assumes"strict_dom g n m" obtains"m ∈ set (αn g)"and"∧ns. g ⊨ Entry g-ns→m ==> n ∈ set (butlast ns)" using assms by (metis dominates_def path2_def path_not_Nil rotate1.simps(2) set_ConsD set_rotate1 snoc_eq_iff_butlast)
lemma dominates_refl[intro!]: "[invar g; n ∈ set (αn g)]==> dominates g n n" by auto
lemma dominates_trans: assumes"invar g" assumes part1: "dominates g n n'" assumes part2: "dominates g n' n''" shows"dominates g n n''" proof from part2 show"n'' ∈ set (αn g)"by auto
fix ns :: "'node list" assume p: "g ⊨ Entry g-ns→n''" with part2 have"n' ∈ set ns"by - (erule dominatesE, auto) thenobtain as where prefix: "prefix (as@[n']) ns"by (auto intro:prefix_split_first) with p have"g ⊨ Entry g-(as@[n'])→n'"by auto with part1 have"n ∈ set (as@[n'])"unfolding dominates_def by auto with prefix show"n ∈ set ns"by auto qed
lemma dominates_antisymm: assumes"invar g" assumes dom1: "dominates g n n'" assumes dom2: "dominates g n' n" shows"n = n'" proof (rule ccontr) assume"n ≠ n'" from dom2 have"n ∈ set (αn g)"by auto with‹invar g›obtain ns where p: "g ⊨ Entry g-ns→n"and"n ∉ set (butlast ns)" by (rule simple_Entry_path) with dom2 have"n' ∈ set ns"by - (erule dominatesE, auto) thenobtain as where prefix: "prefix (as@[n']) ns"by (auto intro:prefix_split_first) with p have"g ⊨ Entry g-as@[n']→n'"by (rule path2_prefix) with dom1 have"n ∈ set (as@[n'])"unfolding dominates_def by auto with‹n ≠ n'›have"n ∈ set as"by auto with‹prefix (as@[n']) ns›have"n ∈ set (butlast ns)"by -(erule prefixE, auto iff:butlast_append) with‹n ∉ set (butlast ns)›show False.. qed
lemma dominates_unsnoc: assumes [simp]: "invar g"and"dominates g n m""m' ∈ set (predecessors g m)""n ≠ m" shows"dominates g n m'" proof show"m' ∈ set (αn g)"using assms by auto next fix ns assume"g ⊨ Entry g-ns→m'" with assms(3) have"g ⊨ Entry g-ns@[m]→m"by auto with assms(2,4) show"n ∈ set ns"by (auto elim!:dominatesE) qed
lemma dominates_unsnoc': assumes [simp]: "invar g"and"dominates g n m""g ⊨ m'-ms→m""∀x ∈ set (tl ms). x ≠ n" shows"dominates g n m'" using assms(3,4) proof (induction rule:path2_induct) case empty_path show ?caseby (rule assms(2)) next case (Cons_path ms m'' m') from Cons_path(4) have"dominates g n m'" by (simp add: Cons_path.IH in_set_tlD) moreoverfrom Cons_path(1) have"m' ∈ set ms"by auto hence"m' ≠ n"using Cons_path(4) by simp ultimatelyshow ?caseusing Cons_path(2) by - (rule dominates_unsnoc, auto) qed
lemma dominates_path: assumes"dominates g n m"and[simp]: "invar g" obtains ns where"g ⊨ n-ns→m" proof atomize_elim from assms obtain ns where ns: "g ⊨ Entry g-ns→m"by atomize_elim (rule Entry_reaches, auto) with assms have"n ∈ set ns"by - (erule dominatesE) with ns show"∃ns. g ⊨ n-ns→m"by - (rule path2_split_ex, auto) qed
lemma dominates_antitrans: assumes[simp]: "invar g"and"dominates g n1 m""dominates g n2 m" obtains (1) "dominates g n1 n2"
| (2) "dominates g n2 n1" proof (cases "dominates g n1 n2") case False show thesis proof (rule 2, rule dominatesI) show"n1∈ set (αn g)"using assms(2) by simp next fix ns assume asm: "g ⊨ Entry g-ns→n1" from assms(2) obtain ns2where"g ⊨ n1-ns2→m"by (rule dominates_path, simp) thenobtain ns2' where ns2': "g ⊨ n1-ns2'→m""n1∉ set (tl ns2')""set ns2' ⊆ set ns2"by(rule simple_path2) with asm have"g ⊨ Entry g-ns@tl ns2'→m"by auto with assms(3) have"n2∈ set (ns@tl ns2')"by - (erule dominatesE) moreoverhave"n2∉ set (tl ns2')" proof assume"n2∈ set (tl ns2')" with ns2'(1,2) obtain ns3where ns3: "g ⊨ n2-ns3→m""n1∉ set (tl ns3)" by - (erule path2_split_ex, auto simp: path2_not_Nil) have"dominates g n1 n2" proof show"n2∈ set (αn g)"using assms(3) by simp next fix ns' assume ns': "g ⊨ Entry g-ns'→n2" with ns3(1) have"g ⊨ Entry g-ns'@tl ns3→m"by auto with assms(2) have"n1∈ set (ns'@tl ns3)"by - (erule dominatesE) with ns3(2) show"n1∈ set ns'"by simp qed with False show False .. qed ultimatelyshow"n2∈ set ns"by simp qed qed
lemma dominates_extend: assumes"dominates g n m" assumes"g ⊨ m'-ms→m""n ∉ set (tl ms)" shows"dominates g n m'" proof (rule dominatesI) show"m' ∈ set (αn g)"using assms(2) by auto next fix ms' assume"g ⊨ Entry g-ms'→m'" with assms(2) have"g ⊨ Entry g-ms'@tl ms→m"by auto with assms(1) have"n ∈ set (ms'@tl ms)"by - (erule dominatesE) with assms(3) show"n ∈ set ms'"by auto qed
definition dominators :: "'g ==> 'node ==> 'node set"where "dominators g n ≡ {m ∈ set (αn g). dominates g m n}"
definition"isIdom g n m ⟷ strict_dom g m n ∧ (∀m' ∈ set (αn g). strict_dom g m' n⟶ dominates g m' m)" definition idom :: "'g ==> 'node ==> 'node"where "idom g n ≡ THE m. isIdom g n m"
lemma idom_ex: assumes[simp]: "invar g""n ∈ set (αn g)""n ≠ Entry g" shows"∃!m. isIdom g n m" proof (rule ex_ex1I) let ?A = "λm. {m' ∈ set (αn g). strict_dom g m' n ∧ strict_dom g m m'}"
have1: "∧A m. finite A ==> A = ?A m ==> strict_dom g m n ==>∃m'. isIdom g n m'" proof- fix A m show"finite A ==> A = ?A m ==> strict_dom g m n ==>∃m'. isIdom g n m'" proof (induction arbitrary:m rule:finite_psubset_induct) case (psubset A m) show ?case proof (cases "A = {}") case True
{ fix m' assume asm: "strict_dom g m' n"and [simp]: "m' ∈ set (αn g)" with True psubset.prems(1) have"¬(strict_dom g m m')"by auto hence"dominates g m' m"using dominates_antitrans[of g m' n m] asm psubset.prems(2) by fastforce
} thus ?thesis using psubset.prems(2) by - (rule exI[of _ m], auto simp:isIdom_def) next case False thenobtain m' where"m' ∈ A"by auto with psubset.prems(1) have m': "m' ∈ set (αn g)""strict_dom g m' n""strict_dom g m m'"by auto have"?A m' ⊂ ?A m" proof show"?A m' ≠ ?A m"using m' by auto show"?A m' ⊆ ?A m"using m' dominates_antisymm[of g m m'] dominates_trans[of g m] by auto qed thus ?thesis by (rule psubset.IH[of _ m', simplified psubset.prems(1)], simp_all add: m') qed qed qed show"∃m. isIdom g n m"by (rule 1[of "?A (Entry g)"], auto) next fix m m' assume"isIdom g n m""isIdom g n m'" thus"m = m'"by - (rule dominates_antisymm[of g], auto simp:isIdom_def) qed
lemma idom: "[invar g; n ∈ set (αn g) - {Entry g}]==> isIdom g n (idom g n)" unfolding idom_def by (rule theI', rule idom_ex, auto)
lemma dominates_mid: assumes"dominates g n x""dominates g x m""g ⊨ n-ns→m"and[simp]: "invar g" shows"x ∈ set ns" using assms proof (cases "n = x") case False from assms(1) obtain ns0where ns0: "g ⊨ Entry g-ns0→n""n ∉ set (butlast ns0)"by - (rule simple_Entry_path, auto) with assms(3) have"g ⊨ Entry g-butlast ns0@ns→m"by auto with assms(2) have"x ∈ set (butlast ns0@ns)"by (auto elim!:dominatesE) moreoverhave"x ∉ set (butlast ns0)" proof assume asm: "x ∈ set (butlast ns0)" with ns0obtain ns0' where ns0': "g ⊨ Entry g-ns0'→x""n ∉ set (butlast ns0')" by - (erule path2_split_ex, auto dest:in_set_butlastD simp: butlast_append split: if_split_asm) show False by (metis False assms(1) ns0' strict_domE) qed ultimatelyshow ?thesis by simp qed auto
definition shortestPath :: "'g ==> 'node ==> nat"where "shortestPath g n ≡ (LEAST l. ∃ns. length ns = l ∧ g ⊨ Entry g-ns→n)"
lemma shortestPath_ex: assumes"n ∈ set (αn g)""invar g" obtains ns where"g ⊨ Entry g-ns→n""distinct ns""length ns = shortestPath g n" proof- from assms obtain ns where"g ⊨ Entry g-ns→n"by - (atomize_elim, rule Entry_reaches) thenobtain sns where sns: "length sns = shortestPath g n""g ⊨ Entry g-sns→n" unfolding shortestPath_def by -(atomize_elim, rule LeastI, auto) thenobtain sns' where sns': "length sns' ≤ shortestPath g n""g ⊨ Entry g-sns'→n""distinct sns'"by - (rule simple_path2, auto) moreoverfrom sns'(2) have"shortestPath g n ≤ length sns'"unfolding shortestPath_def by - (rule Least_le, auto) ultimatelyshow thesis by -(rule that, auto) qed
lemma[simp]: "[n ∈ set (αn g); invar g]==> shortestPath g n ≠ 0" by (metis length_0_conv path2_not_Nil2 shortestPath_ex)
lemma shortestPath_upper_bound: assumes"n ∈ set (αn g)""invar g" shows"shortestPath g n ≤ length (αn g)" proof- from assms obtain ns where ns: "g ⊨ Entry g-ns→n""length ns = shortestPath g n""distinct ns"by (rule shortestPath_ex) hence"shortestPath g n = length ns"by simp alsohave"... = card (set ns)"using ns(3) by (rule distinct_card[symmetric]) alsohave"... ≤ card (set (αn g))"using ns(1) by - (rule card_mono, auto) alsohave"... ≤ length (αn g)"by (rule card_length) finallyshow ?thesis . qed
lemma shortestPath_predecessor: assumes"n ∈ set (αn g) - {Entry g}"and[simp]: "invar g" obtains n' where"Suc (shortestPath g n') = shortestPath g n""n' ∈ set (predecessors g n)" proof - from assms obtain sns where sns: "length sns = shortestPath g n""g ⊨ Entry g-sns→n" by - (rule shortestPath_ex, auto) let ?n' = "last (butlast sns)" from assms(1) sns(2) have1: "length sns ≥ 2"by auto hence prefix: "g ⊨ Entry g-butlast sns→last (butlast sns) ∧ last (butlast sns) ∈ set (predecessors g n)" using sns by -(rule path2_unsnoc, auto) hence"shortestPath g ?n' ≤ length (butlast sns)" unfolding shortestPath_def by -(rule Least_le, rule exI[where x = "butlast sns"], simp) with1 sns(1) have2: "shortestPath g ?n' < shortestPath g n"by auto
{ assume asm: "Suc (shortestPath g ?n') ≠ shortestPath g n" obtain sns' where sns': "g ⊨ Entry g-sns'→?n'""length sns' = shortestPath g ?n'" using prefix by - (rule shortestPath_ex, auto) hence[simp]: "g ⊨ Entry g-sns'@[n]→n"using prefix by auto from asm 2have"Suc (shortestPath g ?n') < shortestPath g n"by auto from this[unfolded shortestPath_def, THEN not_less_Least, folded shortestPath_def, simplified, THEN spec[of _ "sns'@[n]"]] have False using sns'(2) by auto
} with prefix show thesis by - (rule that, auto) qed
lemma successor_in_αn[simp]: assumes"predecessors g n ≠ []"and[simp]: "invar g" shows"n ∈ set (αn g)" proof- from assms(1) obtain m where"m ∈ set (predecessors g n)"by (cases "predecessors g n", auto) with assms(1) obtain m' e where"(m',e,n) ∈ αe g"using inEdges_correct[of g n, THEN arg_cong[where f="(`) getTo"]] by (auto simp: predecessors_def simp del: inEdges_correct) with assms(1) show ?thesis by (auto simp: predecessors_def) qed
lemma shortestPath_single_predecessor: assumes"predecessors g n = [m]"and[simp]: "invar g" shows"shortestPath g m < shortestPath g n" proof- from assms(1) have"n ∈ set (αn g) - {Entry g}" by (auto simp: predecessors_def Entry_unreachable) thus ?thesis by (rule shortestPath_predecessor, auto simp: assms(1)) qed
lemma strict_dom_shortestPath_order: assumes"strict_dom g n m""m ∈ set (αn g)""invar g" shows"shortestPath g n < shortestPath g m" proof- from assms(2,3) obtain sns where sns: "g ⊨ Entry g-sns→m""length sns = shortestPath g m" by (rule shortestPath_ex) with assms(1) sns(1) obtain sns' where sns': "g ⊨ Entry g-sns'→n""prefix sns' sns"by -(erule path2_prefix_ex, auto elim:dominatesE) hence"shortestPath g n ≤ length sns'" unfolding shortestPath_def by -(rule Least_le, auto) alsohave"length sns' < length sns" proof- from assms(1) sns(1) sns'(1) have"sns' ≠ sns"by -(drule path2_last, drule path2_last, auto) with sns'(2) have"strict_prefix sns' sns"by auto thus ?thesis by (rule prefix_length_less) qed finallyshow ?thesis by (simp add:sns(2)) qed
lemma dominates_shortestPath_order: assumes"dominates g n m""m ∈ set (αn g)""invar g" shows"shortestPath g n ≤ shortestPath g m" using assms by (cases "n = m", auto intro:strict_dom_shortestPath_order[THEN less_imp_le])
lemma strict_dom_trans: assumes[simp]: "invar g" assumes"strict_dom g n m""strict_dom g m m'" shows"strict_dom g n m'" proof (rule, rule notI) assume"n = m'" moreoverfrom assms(3) have"m' ∈ set (αn g)"by auto ultimatelyhave"dominates g m' n"by auto with assms(2) have"dominates g m' m"by - (rule dominates_trans, auto) with assms(3) show False by - (erule conjE, drule dominates_antisymm[OF assms(1)], auto) next from assms show"dominates g n m'"by - (rule dominates_trans, auto) qed
inductive EntryPath :: "'g ==> 'node list ==> bool"where
EntryPath_triv[simp]: "EntryPath g [n]"
| EntryPath_snoc[intro]: "EntryPath g ns ==> shortestPath g m = Suc (shortestPath g (last ns)) ==> EntryPath g (ns@[m])"
lemma[simp]: assumes"EntryPath g ns""prefix ns' ns""ns' ≠ []" shows"EntryPath g ns'" using assms proofinduction case (EntryPath_triv ns n) thus ?caseby (cases ns', auto) qed auto
lemma EntryPath_suffix: assumes"EntryPath g ns""suffix ns' ns""ns' ≠ []" shows"EntryPath g ns'" using assms proof (induction arbitrary: ns') case EntryPath_triv thus ?case by (metis EntryPath.EntryPath_triv append_Nil append_is_Nil_conv list.sel(3) Sublist.suffix_def tl_append2) next case (EntryPath_snoc g ns m) from EntryPath_snoc.prems obtain ns'' where [simp]: "ns' = ns''@[m]" by - (erule suffix_unsnoc, auto) show ?case proof (cases "ns'' = []") case True thus ?thesis by auto next case False from EntryPath_snoc.prems(1) have"suffix ns'' ns"by (auto simp: Sublist.suffix_def) with False have"last ns'' = last ns"by (auto simp: Sublist.suffix_def) moreoverfrom False have"EntryPath g ns''"using EntryPath_snoc.prems(1) by - (rule EntryPath_snoc.IH, auto simp: Sublist.suffix_def) ultimatelyshow ?thesis using EntryPath_snoc.hyps(2) by - (simp, rule EntryPath.EntryPath_snoc, simp_all) qed qed
lemma EntryPath_butlast_less_last: assumes"EntryPath g ns""z ∈ set (butlast ns)" shows"shortestPath g z < shortestPath g (last ns)" using assms proof (induction) case (EntryPath_snoc g ns m) thus ?caseby (cases "z ∈ set (butlast ns)", auto dest: not_in_butlast) qed simp
lemma EntryPath_distinct: assumes"EntryPath g ns" shows"distinct ns" using assms proof (induction) case (EntryPath_snoc g ns m) from this consider (non_distinct) "m ∈ set ns" | "distinct (ns @ [m])"by auto thus"distinct (ns @ [m])" proof (cases) case non_distinct have"EntryPath g (ns @ [m])"using EntryPath_snoc by (intro EntryPath.intros(2)) with non_distinct have"False" using EntryPath_butlast_less_last butlast_snoc last_snoc less_not_refl by force thus ?thesis by simp qed qed simp
lemma Entry_reachesE: assumes"n ∈ set (αn g)"and[simp]: "invar g" obtains ns where"g ⊨ Entry g-ns→n""EntryPath g ns" using assms(1) proof (induction"shortestPath g n" arbitrary:n) case0 hence False by simp thus ?case.. next case (Suc l) note Suc.prems(2)[simp] show ?case proof (cases "n = Entry g") case True thus ?thesis by - (rule Suc.prems(1), auto) next case False thenobtain n' where n': "shortestPath g n' = l""n' ∈ set (predecessors g n)" using Suc.hyps(2)[symmetric] by - (rule shortestPath_predecessor, auto) moreover { fix ns assume asm: "g ⊨ Entry g-ns→n'""EntryPath g ns" hence thesis using n' Suc.hyps(2) path2_last[OF asm(1)] by - (rule Suc.prems(1)[of "ns@[n]"], auto)
} ultimatelyshow thesis by - (rule Suc.hyps(1), auto) qed qed end
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-10)
¤
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.