Theory Dijkstra_Shortest_Path.GraphSpec
section "Graph Interface"
theory GraphSpec
imports Main Graph 
  Collections.Collections 
  
  
begin
  text ‹
    This theory defines an ICF-style interface for graphs.
›
  type_synonym ('V,'W,'G) graph_α = "'G ⇒ ('V,'W) graph"
  locale graph =
    fixes α :: "'G ⇒ ('V,'W) graph"
    fixes invar :: "'G ⇒ bool"
    assumes finite[simp, intro!]:
      "invar g ⟹ finite (nodes (α g))"
      "invar g ⟹ finite (edges (α g))"
    assumes valid: "invar g ⟹ valid_graph (α g)"
  type_synonym ('V,'W,'G) graph_empty = "unit ⇒ 'G"
  locale graph_empty = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes empty :: "unit ⇒ 'G"
    assumes empty_correct:
      "α (empty ()) = Graph.empty"
      "invar (empty ())"
  type_synonym ('V,'W,'G) graph_add_node = "'V ⇒ 'G ⇒ 'G"
  locale graph_add_node = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes add_node :: "'V ⇒ 'G ⇒ 'G"
    assumes add_node_correct:
      "invar g ⟹ invar (add_node v g)"
      "invar g ⟹ α (add_node v g) = Graph.add_node v (α g)"
  type_synonym ('V,'W,'G) graph_delete_node = "'V ⇒ 'G ⇒ 'G"
  locale graph_delete_node = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes delete_node :: "'V ⇒ 'G ⇒ 'G"
    assumes delete_node_correct:
      "invar g ⟹ invar (delete_node v g)"
      "invar g ⟹ α (delete_node v g) = Graph.delete_node v (α g)"
  type_synonym ('V,'W,'G) graph_add_edge = "'V ⇒'W ⇒ 'V ⇒ 'G ⇒ 'G"
  locale graph_add_edge = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes add_edge :: "'V ⇒ 'W ⇒ 'V ⇒ 'G ⇒ 'G"
    assumes add_edge_correct:
      "invar g ⟹ invar (add_edge v e v' g)"
      "invar g ⟹ α (add_edge v e v' g) = Graph.add_edge v e v' (α g)"
  type_synonym ('V,'W,'G) graph_delete_edge = "'V ⇒'W ⇒ 'V ⇒ 'G ⇒ 'G"
  locale graph_delete_edge = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes delete_edge :: "'V ⇒ 'W ⇒ 'V ⇒ 'G ⇒ 'G"
    assumes delete_edge_correct:
      "invar g ⟹ invar (delete_edge v e v' g)"
      "invar g ⟹ α (delete_edge v e v' g) = Graph.delete_edge v e v' (α g)"
  type_synonym ('V,'W,'σ,'G) graph_nodes_it = "'G ⇒ ('V,'σ) set_iterator"
  locale graph_nodes_it_defs =
    fixes nodes_list_it :: "'G ⇒ ('V,'V list) set_iterator"
  begin
    definition "nodes_it g ≡ it_to_it (nodes_list_it g)"
  end
  locale graph_nodes_it = graph α invar + graph_nodes_it_defs nodes_list_it 
    for α :: "'G ⇒ ('V,'W) graph" and invar and
    nodes_list_it :: "'G ⇒ ('V,'V list) set_iterator"
    +
    assumes nodes_list_it_correct:
      "invar g ⟹ set_iterator (nodes_list_it g) (Graph.nodes (α g))"
  begin
    lemma nodes_it_correct: 
      "invar g ⟹ set_iterator (nodes_it g) (Graph.nodes (α g))"
      unfolding nodes_it_def
      apply (rule it_to_it_correct)
      by (rule nodes_list_it_correct)
    lemma pi_nodes_it[icf_proper_iteratorI]: 
      "proper_it (nodes_it S) (nodes_it S)"
      unfolding nodes_it_def 
      by (intro icf_proper_iteratorI)
    lemma nodes_it_proper[proper_it]:
      "proper_it' nodes_it nodes_it"
      apply (rule proper_it'I)
      by (rule pi_nodes_it)
  end
  type_synonym ('V,'W,'σ,'G) graph_edges_it 
    = "'G ⇒ (('V×'W×'V),'σ) set_iterator"
  locale graph_edges_it_defs =
    fixes edges_list_it :: "('V,'W,('V×'W×'V) list,'G) graph_edges_it"
  begin
    definition "edges_it g ≡ it_to_it (edges_list_it g)"
  end
  locale graph_edges_it = graph α invar + graph_edges_it_defs edges_list_it
    for α :: "'G ⇒ ('V,'W) graph" and invar and
    edges_list_it :: "('V,'W,('V×'W×'V) list,'G) graph_edges_it" 
    +
    assumes edges_list_it_correct:
      "invar g ⟹ set_iterator (edges_list_it g) (Graph.edges (α g))"
  begin
    lemma edges_it_correct: 
      "invar g ⟹ set_iterator (edges_it g) (Graph.edges (α g))"
      unfolding edges_it_def
      apply (rule it_to_it_correct)
      by (rule edges_list_it_correct)
    lemma pi_edges_it[icf_proper_iteratorI]: 
      "proper_it (edges_it S) (edges_it S)"
      unfolding edges_it_def 
      by (intro icf_proper_iteratorI)
    lemma edges_it_proper[proper_it]:
      "proper_it' edges_it edges_it"
      apply (rule proper_it'I)
      by (rule pi_edges_it)
  end
  type_synonym ('V,'W,'σ,'G) graph_succ_it = 
    "'G ⇒ 'V ⇒ ('W×'V,'σ) set_iterator"
  locale graph_succ_it_defs =
    fixes succ_list_it :: "'G ⇒ 'V ⇒ ('W×'V,('W×'V) list) set_iterator"
  begin
    definition "succ_it g v ≡ it_to_it (succ_list_it g v)"
  end
  locale graph_succ_it = graph α invar + graph_succ_it_defs succ_list_it
    for α :: "'G ⇒ ('V,'W) graph" and invar and
    succ_list_it :: "'G ⇒ 'V ⇒ ('W×'V,('W×'V) list) set_iterator" +
    assumes succ_list_it_correct:
      "invar g ⟹ set_iterator (succ_list_it g v) (Graph.succ (α g) v)"
  begin
    lemma succ_it_correct: 
      "invar g ⟹ set_iterator (succ_it g v) (Graph.succ (α g) v)"
      unfolding succ_it_def
      apply (rule it_to_it_correct)
      by (rule succ_list_it_correct)
    lemma pi_succ_it[icf_proper_iteratorI]: 
      "proper_it (succ_it S v) (succ_it S v)"
      unfolding succ_it_def 
      by (intro icf_proper_iteratorI)
    lemma succ_it_proper[proper_it]:
      "proper_it' (λS. succ_it S v) (λS. succ_it S v)"
      apply (rule proper_it'I)
      by (rule pi_succ_it)
  end
  subsection "Adjacency Lists"
  type_synonym ('V,'W) adj_list = "'V list × ('V×'W×'V) list"
  definition adjl_α :: "('V,'W) adj_list ⇒ ('V,'W) graph" where
    "adjl_α l ≡ let (nl,el) = l in ⦇
      nodes = set nl ∪ fst`set el ∪ snd`snd`set el,
      edges = set el
    ⦈"
  
  lemma adjl_is_graph: "graph adjl_α (λ_. True)"
    apply (unfold_locales)
    unfolding adjl_α_def
    by force+
  type_synonym ('V,'W,'G) graph_from_list = "('V,'W) adj_list ⇒ 'G"
  locale graph_from_list = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes from_list :: "('V,'W) adj_list ⇒ 'G"
    assumes from_list_correct:
      "invar (from_list l)"
      "α (from_list l) = adjl_α l"
  type_synonym ('V,'W,'G) graph_to_list = "'G ⇒ ('V,'W) adj_list"
  locale graph_to_list = graph +
    constrains α :: "'G ⇒ ('V,'W) graph"
    fixes to_list :: "'G ⇒ ('V,'W) adj_list"
    assumes to_list_correct:
      "invar g ⟹ adjl_α (to_list g) = α g"
  subsection ‹Record Based Interface›