Theory Pair_Graph_Specs
theory Pair_Graph_Specs
imports Vwalk "Map_Addons" "Set_Addons"
begin
section ‹A Digraph Representation for Efficient Executable Functions›
text ‹We develop a locale modelling an abstract data type (ADT) which abstractly models a graph as an
adjacency map: i.e.\ every vertex is mapped to a ‹set› of adjacent vertices, and this latter
set is again modelled using the ADT of sets provided in Isabelle/HOL's distribution.
We then show that this ADT can be implemented using existing implementations of the ‹set› ADT.
›
locale Set_Choose = set: Set
where set = t_set for t_set ("[_]⇩s") +
fixes sel ::"'s ⇒ 'a"
assumes choose [simp]: "s ≠ empty ⟹ isin s (sel s)"
begin
context
includes set.automation
begin
subsection ‹Abstraction lemmas›
text ‹These are lemmas for automation. Their purpose is to remove any mention of the locale set ADT
constructs and replace it with Isabelle's native sets.›
lemma choose'[simp, intro,dest]:
"s ≠ empty ⟹ invar s ⟹ sel s ∈ t_set s"
by(auto simp flip: set.set_isin)
lemma choose''[intro]:
"invar s ⟹ s ≠ empty ⟹ t_set s ⊆ s' ⟹ sel s ∈ s'"
by(auto simp flip: set.set_isin)
lemma emptyD[dest]:
"s = empty ⟹ t_set s = {}"
"s ≠ empty ⟹ invar s ⟹ t_set s ≠ {}"
"empty = s ⟹ t_set s = {}"
"empty ≠ s ⟹ invar s ⟹ t_set s ≠ {}"
using set.set_empty
by auto
end
end
named_theorems Graph_Spec_Elims
named_theorems Graph_Spec_Intros
named_theorems Graph_Spec_Simps
locale Pair_Graph_Specs =
adjmap: Map
where update = update and invar = adjmap_inv +
vset: Set_Choose
where empty = vset_empty and delete = vset_delete and invar = vset_inv
for update :: "'v ⇒ 'vset ⇒ 'adjmap ⇒ 'adjmap" and adjmap_inv :: "'adjmap ⇒ bool" and
vset_empty :: "'vset" and vset_delete :: "'v ⇒ 'vset ⇒ 'vset" and
vset_inv
begin
notation vset_empty ("∅⇩V")
notation empty ("∅⇩G")
abbreviation isin' (infixl "∈⇩G" 50) where "isin' G v ≡ isin v G"
abbreviation not_isin' (infixl "∉⇩G" 50) where "not_isin' G v ≡ ¬ isin' G v"
definition "set_of_map (m::'adjmap) = {(u,v). case (lookup m u) of Some vs ⇒ v ∈⇩G vs}"
definition "graph_inv G = (adjmap_inv G ∧ (∀v vset. lookup G v = Some vset ⟶ vset_inv vset))"
definition "finite_graph G = (finite {v. (lookup G v) ≠ None})"
definition "finite_vsets = (∀vset. finite (t_set vset))"
definition neighb::"'adjmap ⇒ 'v ⇒ 'vset" where
"(neighb G v) = (case (lookup G v) of Some vset ⇒ vset | _ ⇒ vset_empty)"
lemmas [code] = neighb_def
notation "neighb" ("𝒩⇩G _ _" 100)
definition digraph_abs ("[_]⇩G") where "digraph_abs G = {(u,v). v ∈⇩G (𝒩⇩G G u)}"
definition "add_edge G u v =
(
case (lookup G u) of Some vset ⇒
let
vset = the (lookup G u);
vset' = insert v vset;
digraph' = update u vset' G
in
digraph'
| _ ⇒
let
vset' = insert v vset_empty;
digraph' = update u vset' G
in
digraph'
)"
definition "delete_edge G u v =
(
case (lookup G u) of Some vset ⇒
let
vset = the (lookup G u);
vset' = vset_delete v vset;
digraph' = update u vset' G
in
digraph'
| _ ⇒ G
)"
context
includes vset.set.automation and adjmap.automation
fixes G::'adjmap
begin
lemma graph_invE[elim]:
"graph_inv G ⟹ (⟦adjmap_inv G; (⋀v vset. lookup G v = Some vset ⟹ vset_inv vset)⟧ ⟹ P) ⟹ P"
by (auto simp: graph_inv_def)
lemma graph_invI[intro]:
"⟦adjmap_inv G; (⋀v vset. lookup G v = Some vset ⟹ vset_inv vset)⟧ ⟹ graph_inv G"
by (auto simp: graph_inv_def)
lemma finite_graphE[elim]:
"finite_graph G ⟹ (finite {v. (lookup G v) ≠ None} ⟹ P) ⟹ P"
by (auto simp: finite_graph_def)
lemma finite_graphI[intro]:
"finite {v. (lookup G v) ≠ None} ⟹ finite_graph G"
by (auto simp: finite_graph_def)
lemma finite_vsetsE[elim]:
"finite_vsets ⟹ ((⋀N. finite (t_set N)) ⟹ P) ⟹ P"
by (auto simp: finite_vsets_def)
lemma finite_vsetsI[intro]:
"(⋀N. finite (t_set N)) ⟹ finite_vsets"
by (auto simp: finite_vsets_def)
lemma neighbourhood_invars'[simp,dest]:
"graph_inv G ⟹ vset_inv (𝒩⇩G G v)"
by (auto simp add: graph_inv_def neighb_def split: option.splits)
lemma finite_graph[intro!]:
assumes "graph_inv G" "finite_graph G" "finite_vsets"
shows "finite (digraph_abs G)"
proof-
have "digraph_abs G ⊆ {v. lookup G v ≠ None} × (⋃ (t_set ` {N | N v. lookup G v = Some N}))"
using assms
by (fastforce simp: digraph_abs_def neighb_def graph_inv_def split: option.splits)
moreover have "finite {v. lookup G v ≠ None}"
using assms
by fastforce
moreover have "finite (⋃ (t_set ` {N | N v. lookup G v = Some N}))"
using assms
by (force elim!: finite_vsetsE finite_graphE
intro!: finite_imageI
rev_finite_subset
[where B = "(the o lookup G) ` {v. ∃y. lookup G v = Some y}"])
ultimately show ?thesis
by(fastforce intro!: finite_cartesian_product dest: finite_subset)+
qed
corollary finite_vertices[intro!]:
assumes "graph_inv G" "finite_graph G" "finite_vsets"
shows "finite (dVs (digraph_abs G))"
using finite_graph[OF assms]
by (simp add: finite_vertices_iff)
subsection ‹Abstraction lemmas›
text ‹These are lemmas for automation. Their purpose is to remove any mention of the neighbourhood
concept implemented using the locale constructs and replace it with abstract terms
on pair graphs.›
lemma are_connected_abs[simp]:
"graph_inv G ⟹ v ∈ t_set (𝒩⇩G G u) ⟷ (u,v) ∈ digraph_abs G"
by(auto simp: digraph_abs_def neighbourhood_def option.discI graph_inv_def
split: option.split)
lemma are_connected_absD[dest]:
"⟦v ∈ t_set (𝒩⇩G G u); graph_inv G⟧ ⟹ (u,v) ∈ digraph_abs G"
by (auto simp: are_connected_abs)
lemma are_connected_absI[intro]:
"⟦(u,v) ∈ digraph_abs G; graph_inv G⟧ ⟹ v ∈ t_set (𝒩⇩G G u)"
by (auto simp: are_connected_abs)
lemma neighbourhood_absD[dest!]:
"⟦t_set (𝒩⇩G G x) ≠ {}; graph_inv G⟧ ⟹ x ∈ dVs (digraph_abs G)"
by blast
lemma neighbourhood_abs[simp]:
"graph_inv G ⟹ t_set (𝒩⇩G G u) = neighbourhood (digraph_abs G) u"
by(auto simp: digraph_abs_def neighb_def Pair_Graph.neighbourhood_def option.discI graph_inv_def
split: option.split)
lemma adjmap_inv_insert[intro]: "graph_inv G ⟹ graph_inv (add_edge G u v)"
by (auto simp: add_edge_def graph_inv_def split: option.splits)
lemma digraph_abs_insert[simp]: "graph_inv G ⟹ digraph_abs (add_edge G u v) = Set.insert (u,v) (digraph_abs G)"
by (fastforce simp add: digraph_abs_def set_of_map_def neighb_def add_edge_def split: option.splits if_splits)
lemma adjmap_inv_delete[intro]: "graph_inv G ⟹ graph_inv (delete_edge G u v)"
by (auto simp: delete_edge_def graph_inv_def split: option.splits)
lemma digraph_abs_delete[simp]: "graph_inv G ⟹ digraph_abs (delete_edge G u v) = (digraph_abs G) - {(u,v)}"
by (fastforce simp add: digraph_abs_def set_of_map_def neighb_def delete_edge_def split: option.splits if_splits)
end
end text ‹@{const Pair_Graph_Specs}›
end