definition arc_to_ends :: "('a,'b) pre_digraph ==> 'b ==> 'a × 'a"where "arc_to_ends G e ≡ (tail G e, head G e)"
locale pre_digraph = fixes G :: "('a, 'b) pre_digraph" (structure)
locale wf_digraph = pre_digraph + assumes tail_in_verts[simp]: "e ∈ arcs G ==> tail G e ∈ verts G" assumes head_in_verts[simp]: "e ∈ arcs G ==> head G e ∈ verts G" begin
lemma wf_digraph: "wf_digraph G"by intro_locales
lemmas wellformed = tail_in_verts head_in_verts
end
definition arcs_ends :: "('a,'b) pre_digraph ==> ('a × 'a) set"where "arcs_ends G ≡ arc_to_ends G ` arcs G"
text‹
Matches "pseudo digraphs" from cite‹"bangjensen2009digraphs"›, except for
allowing the null graph. For a discussion of that topic,
see also cite‹"harary1974nullgraph"›. › locale fin_digraph = wf_digraph + assumes finite_verts[simp]: "finite (verts G)" and finite_arcs[simp]: "finite (arcs G)"
locale loopfree_digraph = wf_digraph + assumes no_loops: "e ∈ arcs G ==> tail G e ≠ head G e"
text‹
We model graphs as symmetric digraphs. This is fine for many purposes,
but not for all. For example, the path $a,b,a$ is considered to be a cycle
in a digraph (and hence in a symmetric digraph), but not in an undirected
graph. › locale pseudo_graph = fin_digraph + sym_digraph
locale graph = digraph + pseudo_graph
lemma (in wf_digraph) fin_digraphI[intro]: assumes"finite (verts G)" assumes"finite (arcs G)" shows"fin_digraph G" using assms by unfold_locales
lemma (in wf_digraph) sym_digraphI[intro]: assumes"symmetric G" shows"sym_digraph G" using assms by unfold_locales
lemma (in digraph) graphI[intro]: assumes"symmetric G" shows"graph G" using assms by unfold_locales
definition (in wf_digraph) arc :: "'b ==> 'a × 'a ==> bool"where "arc e uv ≡ e ∈ arcs G ∧ tail G e = fst uv ∧ head G e = snd uv"
lemma (in fin_digraph) fin_digraph: "fin_digraph G" by unfold_locales
lemma (in nomulti_digraph) nomulti_digraph: "nomulti_digraph G"by unfold_locales
lemma arcs_ends_conv: "arcs_ends G = (λe. (tail G e, head G e)) ` arcs G" by (auto simp: arc_to_ends_def arcs_ends_def)
lemma symmetric_conv: "symmetric G ⟷ (∀e1 ∈ arcs G. ∃e2 ∈ arcs G. tail G e1 = head G e2 ∧ head G e1 = tail G e2)" unfolding symmetric_def arcs_ends_conv sym_def by auto
lemma arcs_ends_symmetric: assumes"symmetric G" shows"(u,v) ∈ arcs_ends G ==> (v,u) ∈ arcs_ends G" using assms unfolding symmetric_def sym_def by auto
lemma (in nomulti_digraph) inj_on_arc_to_ends: "inj_on (arc_to_ends G) (arcs G)" by (rule inj_onI) (rule no_multi_arcs)
subsection‹Reachability›
abbreviation dominates :: "('a,'b) pre_digraph ==> 'a ==> 'a ==> bool" (‹_ →🍋 _› [100,100] 40) where "dominates G u v ≡ (u,v) ∈ arcs_ends G"
abbreviation reachable1 :: "('a,'b) pre_digraph ==> 'a ==> 'a ==> bool" (‹_ →+🍋 _› [100,100] 40) where "reachable1 G u v ≡ (u,v) ∈ (arcs_ends G)^+"
definition reachable :: "('a,'b) pre_digraph ==> 'a ==> 'a ==> bool" (‹_ →*🍋 _› [100,100] 40) where "reachable G u v ≡ (u,v) ∈ rtrancl_on (verts G) (arcs_ends G)"
lemma reachableE[elim]: assumes"u → v" obtains e where"e ∈ arcs G""tail G e = u""head G e = v" using assms by (auto simp add: arcs_ends_conv)
lemma (in loopfree_digraph) adj_not_same: assumes"a → a"shows"False" using assms by (rule reachableE) (auto dest: no_loops)
lemma reachable_in_vertsE: assumes"u →* v"obtains"u ∈ verts G""v ∈ verts G" using assms unfolding reachable_def by induct auto
lemma symmetric_reachable: assumes"symmetric G""v →* w"shows"w →* v" proof - have"sym (rtrancl_on (verts G) (arcs_ends G))" using assms by (auto simp add: symmetric_def dest: rtrancl_on_sym) thenshow ?thesis using assms unfolding reachable_def by (blast elim: symE) qed
lemma reachable_rtranclI: "u →* v ==> (u, v) ∈ (arcs_ends G)*" unfolding reachable_def by (rule rtrancl_on_rtranclI)
context wf_digraph begin
lemma adj_in_verts: assumes"u → v"shows"u ∈ verts G""v ∈ verts G" using assms unfolding arcs_ends_conv by auto
lemma dominatesI: assumes"arc_to_ends G a = (u,v)""a ∈ arcs G"shows"u → v" using assms by (auto simp: arcs_ends_def intro: rev_image_eqI)
lemma reachable_refl [intro!, Pure.intro!, simp]: "v ∈ verts G ==> v →* v" unfolding reachable_def by auto
lemma adj_reachable_trans[trans]: assumes"a → b""b →* c"shows"a →* c" using assms by (auto simp: reachable_def intro: converse_rtrancl_on_into_rtrancl_on adj_in_verts)
lemma reachable_adj_trans[trans]: assumes"a →* b""b → c"shows"a →* c" using assms by (auto simp: reachable_def intro: rtrancl_on_into_rtrancl_on adj_in_verts)
lemma reachable_adjI [intro, simp]: "u → v ==> u →* v" by (auto intro: adj_reachable_trans adj_in_verts)
lemma reachable_trans[trans]: assumes"u →*v""v →* w"shows"u →* w" using assms unfolding reachable_def by (rule rtrancl_on_trans)
lemma reachable_induct[consumes 1, case_names base step]: assumes major: "u →* v" and cases: "u ∈ verts G ==> P u" "∧x y. [u →* x; x → y; P x]==> P y" shows"P v" using assms unfolding reachable_def by (rule rtrancl_on_induct) auto
lemma converse_reachable_induct[consumes 1, case_names base step, induct pred: reachable]: assumes major: "u →* v" and cases: "v ∈ verts G ==> P v" "∧x y. [x → y; y →* v; P y]==> P x" shows"P u" using assms unfolding reachable_def by (rule converse_rtrancl_on_induct) auto
lemma (in pre_digraph) converse_reachable_cases: assumes"u →* v" obtains (base) "u = v""u ∈ verts G"
| (step) w where"u → w""w →* v" using assms unfolding reachable_def by (cases rule: converse_rtrancl_on_cases) auto
lemma reachable_in_verts: assumes"u →* v"shows"u ∈ verts G""v ∈ verts G" using assms by induct (simp_all add: adj_in_verts)
lemma reachable1_in_verts: assumes"u →+ v"shows"u ∈ verts G""v ∈ verts G" using assms by induct (simp_all add: adj_in_verts)
lemma reachable1_reachable[intro]: "v →+ w ==> v →* w" unfolding reachable_def by (rule rtrancl_consistent_rtrancl_on) (simp_all add: reachable1_in_verts adj_in_verts)
lemma reachable1_reachable_trans [trans]: "u →+ v ==> v →* w ==> u →+ w" by (metis trancl_trans reachable_neq_reachable1)
lemma reachable_reachable1_trans [trans]: "u →* v ==> v →+ w ==> u →+ w" by (metis trancl_trans reachable_neq_reachable1)
lemma reachable_conv: "u →* v ⟷ (u,v) ∈ (arcs_ends G)^* ∩ (verts G × verts G)" apply (auto intro: reachable_in_verts) apply (induct rule: rtrancl_induct) apply auto done
lemma reachable_conv': assumes"u ∈ verts G" shows"u →* v ⟷ (u,v) ∈ (arcs_ends G)*" (is"?L = ?R") proof assume"?R"thenshow"?L"using assms by induct auto qed (auto simp: reachable_conv)
end
lemma (in sym_digraph) symmetric_reachable': assumes"v →* w"shows"w →* v" using sym_arcs assms by (rule symmetric_reachable)
subsection‹Degrees of vertices›
definition in_arcs :: "('a, 'b) pre_digraph ==> 'a ==> 'b set"where "in_arcs G v ≡ {e ∈ arcs G. head G e = v}"
definition out_arcs :: "('a, 'b) pre_digraph ==> 'a ==> 'b set"where "out_arcs G v ≡ {e ∈ arcs G. tail G e = v}"
definition in_degree :: "('a, 'b) pre_digraph ==> 'a ==> nat"where "in_degree G v ≡ card (in_arcs G v)"
definition out_degree :: "('a, 'b) pre_digraph ==> 'a ==> nat"where "out_degree G v ≡ card (out_arcs G v)"
lemma (in fin_digraph) finite_in_arcs[intro]: "finite (in_arcs G v)" unfolding in_arcs_def by auto
lemma (in fin_digraph) finite_out_arcs[intro]: "finite (out_arcs G v)" unfolding out_arcs_def by auto
lemma in_in_arcs_conv[simp]: "e ∈ in_arcs G v ⟷ e ∈ arcs G ∧ head G e = v" unfolding in_arcs_def by auto
lemma in_out_arcs_conv[simp]: "e ∈ out_arcs G v ⟷ e ∈ arcs G ∧ tail G e = v" unfolding out_arcs_def by auto
lemma inout_arcs_arc_simps[simp]: assumes"e ∈ arcs G" shows"tail G e = u ==> out_arcs G u ∩ insert e E = insert e (out_arcs G u ∩ E)" "tail G e ≠ u ==> out_arcs G u ∩ insert e E = out_arcs G u ∩ E" "out_arcs G u ∩ {} = {}"(* XXX: should be unnecessary *) "head G e = u ==> in_arcs G u ∩ insert e E = insert e (in_arcs G u ∩ E)" "head G e ≠ u ==> in_arcs G u ∩ insert e E = in_arcs G u ∩ E" "in_arcs G u ∩ {} = {}"(* XXX: should be unnecessary *) using assms by auto
lemma in_arcs_int_arcs[simp]: "in_arcs G u ∩ arcs G = in_arcs G u"and
out_arcs_int_arcs[simp]: "out_arcs G u ∩ arcs G = out_arcs G u" by auto
lemma in_arcs_in_arcs: "x ∈ in_arcs G u ==> x ∈ arcs G" and out_arcs_in_arcs: "x ∈ out_arcs G u ==> x ∈ arcs G" by (auto simp: in_arcs_def out_arcs_def)
subsection‹Graph operations›
context pre_digraph begin
definition add_arc :: "'b ==> ('a,'b) pre_digraph"where "add_arc a = ( verts = verts G ∪ {tail G a, head G a}, arcs = insert a (arcs G), tail = tail G, head = head G )"
definition del_arc :: "'b ==> ('a,'b) pre_digraph"where "del_arc a = ( verts = verts G, arcs = arcs G - {a}, tail = tail G, head = head G)"
definition add_vert :: "'a ==> ('a,'b) pre_digraph"where "add_vert v = ( verts = insert v (verts G), arcs = arcs G, tail = tail G, head = head G )"
definition del_vert :: "'a ==> ('a,'b) pre_digraph"where "del_vert v = ( verts = verts G - {v}, arcs = {a ∈ arcs G. tail G a ≠ v ∧ head G a ≠ v}, tail = tail G, head = head G )"
lemma
verts_add_arc: "[ tail G a ∈ verts G; head G a ∈ verts G ]==> verts (add_arc a) = verts G"and
verts_add_arc_conv: "verts (add_arc a) = verts G ∪ {tail G a, head G a}"and
arcs_add_arc: "arcs (add_arc a) = insert a (arcs G)"and
tail_add_arc: "tail (add_arc a) = tail G"and
head_add_arc: "head (add_arc a) = head G" by (auto simp: add_arc_def)
lemma
verts_del_arc: "verts (del_arc a) = verts G"and
arcs_del_arc: "arcs (del_arc a) = arcs G - {a}"and
tail_del_arc: "tail (del_arc a) = tail G"and
head_del_arc: "head (del_arc a) = head G" by (auto simp: del_arc_def)
lemma
verts_del_vert: "verts (pre_digraph.del_vert G u) = verts G - {u}"and
arcs_del_vert: "arcs (pre_digraph.del_vert G u) = {a ∈ arcs G. tail G a ≠ u ∧ head G a ≠ u}"and
tail_del_vert: "tail (pre_digraph.del_vert G u) = tail G"and
head_del_vert: "head (pre_digraph.del_vert G u) = head G"and
ends_del_vert: "arc_to_ends (pre_digraph.del_vert G u) = arc_to_ends G" by (auto simp: pre_digraph.del_vert_def arc_to_ends_def)
lemma add_add_arc_collapse[simp]: "pre_digraph.add_arc (add_arc a) a = add_arc a" by (auto simp: pre_digraph.add_arc_def)
lemma add_del_arc_collapse[simp]: "pre_digraph.add_arc (del_arc a) a = add_arc a" by (auto simp: pre_digraph.verts_add_arc_conv pre_digraph.add_arc_simps)
lemma del_add_arc_collapse[simp]: "[ tail G a ∈ verts G; head G a ∈ verts G ]==> pre_digraph.del_arc (add_arc a) a = del_arc a" by (auto simp: pre_digraph.add_arc_simps pre_digraph.del_arc_simps)
lemma del_del_arc_collapse[simp]: "pre_digraph.del_arc (del_arc a) a = del_arc a" by (auto simp: pre_digraph.add_arc_simps pre_digraph.del_arc_simps)
lemma add_arc_commute: "pre_digraph.add_arc (add_arc b) a = pre_digraph.add_arc (add_arc a) b" by (auto simp: pre_digraph.add_arc_def)
lemma del_arc_commute: "pre_digraph.del_arc (del_arc b) a = pre_digraph.del_arc (del_arc a) b" by (auto simp: pre_digraph.del_arc_def)
lemma del_arc_in: "a ∉ arcs G ==> del_arc a = G" by (rule pre_digraph.equality) (auto simp: add_arc_def)
lemma in_arcs_add_arc_iff: "in_arcs (add_arc a) u = (if head G a = u then insert a (in_arcs G u) else in_arcs G u)" by auto
lemma out_arcs_add_arc_iff: "out_arcs (add_arc a) u = (if tail G a = u then insert a (out_arcs G u) else out_arcs G u)" by auto
lemma in_arcs_del_arc_iff: "in_arcs (del_arc a) u = (if head G a = u then in_arcs G u - {a} else in_arcs G u)" by auto
lemma out_arcs_del_arc_iff: "out_arcs (del_arc a) u = (if tail G a = u then out_arcs G u - {a} else out_arcs G u)" by auto
lemma (in wf_digraph) add_arc_in: "a ∈ arcs G ==> add_arc a = G" by (rule pre_digraph.equality) (auto simp: add_arc_def)
lemma wf_digraph_del_vert: "wf_digraph (del_vert u)" by standard (auto simp: del_vert_simps)
lemma wf_digraph_add_vert: "wf_digraph (add_vert u)" by standard (auto simp: add_vert_simps)
lemma del_vert_add_vert: assumes"u ∉ verts G" shows"pre_digraph.del_vert (add_vert u) u = G" using assms by (intro pre_digraph.equality) (auto simp: pre_digraph.del_vert_def add_vert_def)
end
context fin_digraph begin
lemma in_degree_add_arc_iff: "in_degree (add_arc a) u = (if head G a = u ∧ a ∉ arcs G then in_degree G u + 1 else in_degree G u)" proof - have"a ∉ arcs G ==> a ∉ in_arcs G u"by (auto simp: in_arcs_def) with finite_in_arcs show ?thesis unfolding in_degree_def by (auto simp: in_arcs_add_arc_iff intro: arg_cong[where f=card]) qed
lemma out_degree_add_arc_iff: "out_degree (add_arc a) u = (if tail G a = u ∧ a ∉ arcs G then out_degree G u + 1 else out_degree G u)" proof - have"a ∉ arcs G ==> a ∉ out_arcs G u"by (auto simp: out_arcs_def) with finite_out_arcs show ?thesis unfolding out_degree_def by (auto simp: out_arcs_add_arc_iff intro: arg_cong[where f=card]) qed
lemma in_degree_del_arc_iff: "in_degree (del_arc a) u = (if head G a = u ∧ a ∈ arcs G then in_degree G u - 1 else in_degree G u)" proof - have"a ∉ arcs G ==> a ∉ in_arcs G u"by (auto simp: in_arcs_def) with finite_in_arcs show ?thesis unfolding in_degree_def by (auto simp: in_arcs_del_arc_iff intro: arg_cong[where f=card]) qed
lemma out_degree_del_arc_iff: "out_degree (del_arc a) u = (if tail G a = u ∧ a ∈ arcs G then out_degree G u - 1 else out_degree G u)" proof - have"a ∉ arcs G ==> a ∉ out_arcs G u"by (auto simp: out_arcs_def) with finite_out_arcs show ?thesis unfolding out_degree_def by (auto simp: out_arcs_del_arc_iff intro: arg_cong[where f=card]) qed
lemma fin_digraph_del_vert: "fin_digraph (del_vert u)" by standard (auto simp: del_vert_simps)
lemma fin_digraph_del_arc: "fin_digraph (del_arc a)" by standard (auto simp: del_vert_simps)
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.