Theory Directed_Graph_Specs

section ‹Abstract Datatype for Weighted Directed Graphs›
theory Directed_Graph_Specs
imports Directed_Graph
begin

locale adt_wgraph =
  fixes α :: "'g  ('v) wgraph"
    and invar :: "'g  bool"
    and succ :: "'g  'v  (nat×'v) list"
    and empty_graph :: 'g
    and add_edge :: "'v×'v  nat  'g  'g"
  assumes succ_correct: "invar g  set (succ g u) = {(d,v). α g (u,v) = enat d}"
  assumes empty_graph_correct:
    "invar empty_graph"
    "α empty_graph = (λ_. )"
  assumes add_edge_correct:
    "invar g  α g e =   invar (add_edge e d g)"
    "invar g  α g e =   α (add_edge e d g) = (α g)(e:=enat d)"
begin
  
lemmas wgraph_specs = succ_correct empty_graph_correct add_edge_correct
  
end

locale adt_finite_wgraph = adt_wgraph where α=α for α :: "'g  ('v) wgraph" +
  assumes finite: "invar g  finite (WGraph.edges (α g))"


subsection ‹Constructing Weighted Graphs from Lists›  
lemma edges_empty[simp]: "WGraph.edges (λ_. ) = {}" 
  by (auto simp: WGraph.edges_def)
  
lemma edges_insert[simp]: 
  "WGraph.edges (g(e:=enat d)) = Set.insert e (WGraph.edges g)" 
  by (auto simp: WGraph.edges_def)

text ‹A list represents a graph if there are no multi-edges or duplicate edges›
definition "valid_graph_rep l  
  (u d d' v. (u,v,d)set l  (u,v,d')set l  d=d')
 distinct l
  "

text ‹Alternative characterization: all node pairs must be distinct›
lemma valid_graph_rep_code[code]: 
  "valid_graph_rep l  distinct (map (λ(u,v,_). (u,v)) l)"  
  by (auto simp: valid_graph_rep_def distinct_map inj_on_def)
  
lemma valid_graph_rep_simps[simp]:
  "valid_graph_rep []"
  "valid_graph_rep ((u,v,d) # l)  valid_graph_rep l  (d'. (u,v,d')set l)"
  by (auto simp: valid_graph_rep_def)

  
text ‹For a valid graph representation, there is exactly one graph that 
  corresponds to it›  
lemma valid_graph_rep_ex1: 
  "valid_graph_rep l  ∃! w. u v d. w (u,v) = enat d  (u,v,d)set l"  
  unfolding valid_graph_rep_code
  apply safe
  subgoal 
    apply (rule exI[where x="λ(u,v).
        if d. (u,v,d)set l then enat (SOME d. (u,v,d)set l) else "])
    by (auto intro: someI simp: distinct_map inj_on_def split: prod.splits; 
           blast)
  subgoal for w w'
    apply (simp add: fun_eq_iff)
    by (metis (mono_tags, opaque_lifting) not_enat_eq)
  done  

text ‹We define this graph using determinate choice›  
definition "wgraph_of_list l  THE w. u v d. w (u,v) = enat d  (u,v,d)set l"  

locale wgraph_from_list_algo = adt_wgraph 
begin

definition "from_list l  fold (λ(u,v,d). add_edge (u,v) d) l empty_graph"

definition "edges_undef l w  u v d. (u,v,d)set l  w (u,v) = "  
  
lemma edges_undef_simps[simp]:
  "edges_undef [] w"  
  "edges_undef l (λ_. )"
  "edges_undef ((u,v,d)#l) w  edges_undef l w  w (u,v) = "
  "edges_undef l (w((u,v) := enat d))  edges_undef l w  (d'. (u,v,d')set l)"  
  by (auto simp: edges_undef_def)

lemma from_list_correct_aux:
  assumes "valid_graph_rep l"
  assumes "edges_undef l (α g)"
  assumes "invar g"
  defines "g'  fold (λ(u,v,d). add_edge (u,v) d) l g"
  shows "invar g'"
    and "(u v d. α g' (u,v) = enat d  α g (u,v) = enat d  (u,v,d)set l)"
  using assms(1-3) unfolding g'_def
  apply (induction l arbitrary: g)
  by (auto simp: wgraph_specs split: if_splits)

lemma from_list_correct':
  assumes "valid_graph_rep l"
  shows "invar (from_list l)" 
    and "(u,v,d)set l  α (from_list l) (u,v) = enat d"
  unfolding from_list_def 
  using from_list_correct_aux[OF assms, where g=empty_graph]
  by (auto simp: wgraph_specs)
  
lemma from_list_correct:
  assumes "valid_graph_rep l"
  shows "invar (from_list l)" "α (from_list l) = wgraph_of_list l"
proof -
  from theI'[OF valid_graph_rep_ex1[OF assms], folded wgraph_of_list_def]
  have "(wgraph_of_list l (u, v) = enat d) = ((u, v, d)  set l)" for u v d 
    by blast

  then show "α (from_list l) = wgraph_of_list l" 
    using from_list_correct_aux[OF assms, where g=empty_graph]
    apply (clarsimp simp: fun_eq_iff wgraph_specs from_list_def)
    apply (metis (no_types) enat.exhaust)
    done
  
  show "invar (from_list l)"
    by (simp add: assms from_list_correct')
    
qed    
    
end



end