src/Pure/General/graph.ML
author blanchet
Tue, 17 Feb 2009 14:01:54 +0100
changeset 29956 62f931b257b7
parent 29606 fedb8be05f24
child 30290 f49d70426690
permissions -rw-r--r--
Reintroduce set_interpreter for Collect and op :. I removed them by accident when removing old code that dealt with the "set" type. Incidentally, there is still some broken "set" code in Refute that should be fixed (see TODO in refute.ML).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/General/graph.ML
15759
wenzelm
parents: 15570
diff changeset
     2
    Author:     Markus Wenzel and Stefan Berghofer, TU Muenchen
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     3
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     4
Directed graphs.
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     5
*)
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     6
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     7
signature GRAPH =
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     8
sig
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
     9
  type key
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    10
  type 'a T
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
    11
  exception DUP of key
19029
8635700e2c9c share exception UNDEF with Table;
wenzelm
parents: 18970
diff changeset
    12
  exception SAME
8635700e2c9c share exception UNDEF with Table;
wenzelm
parents: 18970
diff changeset
    13
  exception UNDEF of key
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    14
  val empty: 'a T
28204
2d93b158ad99 added is_empty;
wenzelm
parents: 28183
diff changeset
    15
  val is_empty: 'a T -> bool
6659
7a056250899d removed get_nodes;
wenzelm
parents: 6152
diff changeset
    16
  val keys: 'a T -> key list
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
    17
  val dest: 'a T -> (key * key list) list
28183
7d5103454520 export get_first from underlying table;
wenzelm
parents: 25538
diff changeset
    18
  val get_first: (key * ('a * (key list * key list)) -> 'b option) -> 'a T -> 'b option
19615
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
    19
  val fold: (key * ('a * (key list * key list)) -> 'b -> 'b) -> 'a T -> 'b -> 'b
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
    20
  val minimals: 'a T -> key list
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
    21
  val maximals: 'a T -> key list
21935
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
    22
  val subgraph: (key -> bool) -> 'a T -> 'a T
6142
wenzelm
parents: 6134
diff changeset
    23
  val map_nodes: ('a -> 'b) -> 'a T -> 'b T
19615
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
    24
  val fold_map_nodes: (key * 'a -> 'b -> 'c * 'b) -> 'a T -> 'b -> 'c T * 'b
15759
wenzelm
parents: 15570
diff changeset
    25
  val get_node: 'a T -> key -> 'a                                     (*exception UNDEF*)
6142
wenzelm
parents: 6134
diff changeset
    26
  val map_node: key -> ('a -> 'a) -> 'a T -> 'a T
17767
504acb86c9f5 added fold_nodes, map_node_yield
haftmann
parents: 17580
diff changeset
    27
  val map_node_yield: key -> ('a -> 'b * 'a) -> 'a T -> 'b * 'a T
6142
wenzelm
parents: 6134
diff changeset
    28
  val imm_preds: 'a T -> key -> key list
wenzelm
parents: 6134
diff changeset
    29
  val imm_succs: 'a T -> key -> key list
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    30
  val all_preds: 'a T -> key list -> key list
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    31
  val all_succs: 'a T -> key list -> key list
14161
73ad4884441f Added function strong_conn for computing the strongly connected components
berghofe
parents: 12451
diff changeset
    32
  val strong_conn: 'a T -> key list list
15759
wenzelm
parents: 15570
diff changeset
    33
  val new_node: key * 'a -> 'a T -> 'a T                              (*exception DUP*)
17179
28802c8a9816 canonical interface for 'default'
haftmann
parents: 17140
diff changeset
    34
  val default_node: key * 'a -> 'a T -> 'a T
15759
wenzelm
parents: 15570
diff changeset
    35
  val del_nodes: key list -> 'a T -> 'a T                             (*exception UNDEF*)
28333
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
    36
  val del_node: key -> 'a T -> 'a T                                   (*exception UNDEF*)
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
    37
  val is_edge: 'a T -> key * key -> bool
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    38
  val add_edge: key * key -> 'a T -> 'a T
6152
wenzelm
parents: 6142
diff changeset
    39
  val del_edge: key * key -> 'a T -> 'a T
23655
d2d1138e0ddc replaced exception TableFun/GraphFun.DUPS by TableFun/GraphFun.DUP;
wenzelm
parents: 21935
diff changeset
    40
  val merge: ('a * 'a -> bool) -> 'a T * 'a T -> 'a T                 (*exception DUP*)
19029
8635700e2c9c share exception UNDEF with Table;
wenzelm
parents: 18970
diff changeset
    41
  val join: (key -> 'a * 'a -> 'a) (*exception DUP/SAME*) ->
23655
d2d1138e0ddc replaced exception TableFun/GraphFun.DUPS by TableFun/GraphFun.DUP;
wenzelm
parents: 21935
diff changeset
    42
    'a T * 'a T -> 'a T                                               (*exception DUP*)
19580
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
    43
  val irreducible_paths: 'a T -> key * key -> key list list
20679
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
    44
  val all_paths: 'a T -> key * key -> key list list
6142
wenzelm
parents: 6134
diff changeset
    45
  exception CYCLES of key list list
15759
wenzelm
parents: 15570
diff changeset
    46
  val add_edge_acyclic: key * key -> 'a T -> 'a T                     (*exception CYCLES*)
wenzelm
parents: 15570
diff changeset
    47
  val add_deps_acyclic: key * key list -> 'a T -> 'a T                (*exception CYCLES*)
wenzelm
parents: 15570
diff changeset
    48
  val merge_acyclic: ('a * 'a -> bool) -> 'a T * 'a T -> 'a T         (*exception CYCLES*)
23964
d2df2797519b added topological_order;
wenzelm
parents: 23655
diff changeset
    49
  val topological_order: 'a T -> key list
15759
wenzelm
parents: 15570
diff changeset
    50
  val add_edge_trans_acyclic: key * key -> 'a T -> 'a T               (*exception CYCLES*)
wenzelm
parents: 15570
diff changeset
    51
  val merge_trans_acyclic: ('a * 'a -> bool) -> 'a T * 'a T -> 'a T   (*exception CYCLES*)
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    52
end;
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    53
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    54
functor GraphFun(Key: KEY): GRAPH =
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    55
struct
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    56
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    57
(* keys *)
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    58
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    59
type key = Key.key;
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    60
18970
d055a29ddd23 Library.is_equal;
wenzelm
parents: 18921
diff changeset
    61
val eq_key = is_equal o Key.ord;
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    62
18921
f47c46d7d654 canonical member/insert/merge;
wenzelm
parents: 18133
diff changeset
    63
val member_key = member eq_key;
15759
wenzelm
parents: 15570
diff changeset
    64
val remove_key = remove eq_key;
6152
wenzelm
parents: 6142
diff changeset
    65
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    66
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    67
(* tables and sets of keys *)
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    68
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    69
structure Table = TableFun(Key);
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    70
type keys = unit Table.table;
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    71
6142
wenzelm
parents: 6134
diff changeset
    72
val empty_keys = Table.empty: keys;
wenzelm
parents: 6134
diff changeset
    73
18921
f47c46d7d654 canonical member/insert/merge;
wenzelm
parents: 18133
diff changeset
    74
fun member_keys tab = Table.defined (tab: keys);
f47c46d7d654 canonical member/insert/merge;
wenzelm
parents: 18133
diff changeset
    75
fun insert_keys x tab = Table.insert (K true) (x, ()) (tab: keys);
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    76
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    77
6142
wenzelm
parents: 6134
diff changeset
    78
(* graphs *)
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    79
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    80
datatype 'a T = Graph of ('a * (key list * key list)) Table.table;
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    81
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
    82
exception DUP = Table.DUP;
19029
8635700e2c9c share exception UNDEF with Table;
wenzelm
parents: 18970
diff changeset
    83
exception UNDEF = Table.UNDEF;
8635700e2c9c share exception UNDEF with Table;
wenzelm
parents: 18970
diff changeset
    84
exception SAME = Table.SAME;
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    85
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    86
val empty = Graph Table.empty;
28204
2d93b158ad99 added is_empty;
wenzelm
parents: 28183
diff changeset
    87
fun is_empty (Graph tab) = Table.is_empty tab;
6659
7a056250899d removed get_nodes;
wenzelm
parents: 6152
diff changeset
    88
fun keys (Graph tab) = Table.keys tab;
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
    89
fun dest (Graph tab) = map (fn (x, (_, (_, succs))) => (x, succs)) (Table.dest tab);
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
    90
28183
7d5103454520 export get_first from underlying table;
wenzelm
parents: 25538
diff changeset
    91
fun get_first f (Graph tab) = Table.get_first f tab;
19615
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
    92
fun fold_graph f (Graph tab) = Table.fold f tab;
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
    93
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
    94
fun minimals G = fold_graph (fn (m, (_, ([], _))) => cons m | _ => I) G [];
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
    95
fun maximals G = fold_graph (fn (m, (_, (_, []))) => cons m | _ => I) G [];
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
    96
21935
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
    97
fun subgraph P G =
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
    98
  let
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
    99
    fun subg (k, (i, (preds, succs))) =
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
   100
      if P k then Table.update (k, (i, (filter P preds, filter P succs))) else I;
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
   101
  in Graph (fold_graph subg G Table.empty) end;
4e20a5397b57 renamed project to subgraph, improved presentation, avoided unnecessary evaluation of predicate;
wenzelm
parents: 21565
diff changeset
   102
6142
wenzelm
parents: 6134
diff changeset
   103
fun get_entry (Graph tab) x =
17412
e26cb20ef0cc TableFun/Symtab: curried lookup and update;
wenzelm
parents: 17221
diff changeset
   104
  (case Table.lookup tab x of
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15160
diff changeset
   105
    SOME entry => entry
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15160
diff changeset
   106
  | NONE => raise UNDEF x);
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   107
17412
e26cb20ef0cc TableFun/Symtab: curried lookup and update;
wenzelm
parents: 17221
diff changeset
   108
fun map_entry x f (G as Graph tab) = Graph (Table.update (x, f (get_entry G x)) tab);
19290
wenzelm
parents: 19029
diff changeset
   109
17767
504acb86c9f5 added fold_nodes, map_node_yield
haftmann
parents: 17580
diff changeset
   110
fun map_entry_yield x f (G as Graph tab) =
504acb86c9f5 added fold_nodes, map_node_yield
haftmann
parents: 17580
diff changeset
   111
  let val (a, node') = f (get_entry G x)
504acb86c9f5 added fold_nodes, map_node_yield
haftmann
parents: 17580
diff changeset
   112
  in (a, Graph (Table.update (x, node') tab)) end;
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   113
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   114
6142
wenzelm
parents: 6134
diff changeset
   115
(* nodes *)
wenzelm
parents: 6134
diff changeset
   116
wenzelm
parents: 6134
diff changeset
   117
fun map_nodes f (Graph tab) = Graph (Table.map (fn (i, ps) => (f i, ps)) tab);
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   118
19290
wenzelm
parents: 19029
diff changeset
   119
fun fold_map_nodes f (Graph tab) =
wenzelm
parents: 19029
diff changeset
   120
  apfst Graph o Table.fold_map (fn (k, (i, ps)) => f (k, i) #> apfst (rpair ps)) tab;
17580
78a286d696c1 added fold_map_graph
haftmann
parents: 17412
diff changeset
   121
6142
wenzelm
parents: 6134
diff changeset
   122
fun get_node G = #1 o get_entry G;
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   123
6142
wenzelm
parents: 6134
diff changeset
   124
fun map_node x f = map_entry x (fn (i, ps) => (f i, ps));
19290
wenzelm
parents: 19029
diff changeset
   125
17767
504acb86c9f5 added fold_nodes, map_node_yield
haftmann
parents: 17580
diff changeset
   126
fun map_node_yield x f = map_entry_yield x (fn (i, ps) =>
504acb86c9f5 added fold_nodes, map_node_yield
haftmann
parents: 17580
diff changeset
   127
  let val (a, i') = f i in (a, (i', ps)) end);
6142
wenzelm
parents: 6134
diff changeset
   128
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   129
6142
wenzelm
parents: 6134
diff changeset
   130
(* reachability *)
wenzelm
parents: 6134
diff changeset
   131
6659
7a056250899d removed get_nodes;
wenzelm
parents: 6152
diff changeset
   132
(*nodes reachable from xs -- topologically sorted for acyclic graphs*)
6142
wenzelm
parents: 6134
diff changeset
   133
fun reachable next xs =
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   134
  let
18006
535de280c812 reachable - abandoned foldl_map in favor of fold_map
haftmann
parents: 17912
diff changeset
   135
    fun reach x (rs, R) =
18921
f47c46d7d654 canonical member/insert/merge;
wenzelm
parents: 18133
diff changeset
   136
      if member_keys R x then (rs, R)
f47c46d7d654 canonical member/insert/merge;
wenzelm
parents: 18133
diff changeset
   137
      else apfst (cons x) (fold reach (next x) (rs, insert_keys x R))
23964
d2df2797519b added topological_order;
wenzelm
parents: 23655
diff changeset
   138
  in fold_map (fn x => fn X => reach x ([], X)) xs empty_keys end;
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   139
6142
wenzelm
parents: 6134
diff changeset
   140
(*immediate*)
wenzelm
parents: 6134
diff changeset
   141
fun imm_preds G = #1 o #2 o get_entry G;
wenzelm
parents: 6134
diff changeset
   142
fun imm_succs G = #2 o #2 o get_entry G;
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   143
6142
wenzelm
parents: 6134
diff changeset
   144
(*transitive*)
19482
9f11af8f7ef9 tuned basic list operators (flat, maps, map_filter);
wenzelm
parents: 19409
diff changeset
   145
fun all_preds G = flat o fst o reachable (imm_preds G);
9f11af8f7ef9 tuned basic list operators (flat, maps, map_filter);
wenzelm
parents: 19409
diff changeset
   146
fun all_succs G = flat o fst o reachable (imm_succs G);
14161
73ad4884441f Added function strong_conn for computing the strongly connected components
berghofe
parents: 12451
diff changeset
   147
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   148
(*strongly connected components; see: David King and John Launchbury,
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   149
  "Structuring Depth First Search Algorithms in Haskell"*)
18006
535de280c812 reachable - abandoned foldl_map in favor of fold_map
haftmann
parents: 17912
diff changeset
   150
fun strong_conn G = filter_out null (fst (reachable (imm_preds G)
19482
9f11af8f7ef9 tuned basic list operators (flat, maps, map_filter);
wenzelm
parents: 19409
diff changeset
   151
  (flat (rev (fst (reachable (imm_succs G) (keys G)))))));
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   152
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   153
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   154
(* nodes *)
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   155
6152
wenzelm
parents: 6142
diff changeset
   156
fun new_node (x, info) (Graph tab) =
17412
e26cb20ef0cc TableFun/Symtab: curried lookup and update;
wenzelm
parents: 17221
diff changeset
   157
  Graph (Table.update_new (x, (info, ([], []))) tab);
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   158
17179
28802c8a9816 canonical interface for 'default'
haftmann
parents: 17140
diff changeset
   159
fun default_node (x, info) (Graph tab) =
28802c8a9816 canonical interface for 'default'
haftmann
parents: 17140
diff changeset
   160
  Graph (Table.default (x, (info, ([], []))) tab);
17140
5be3a21ec949 added 'default' function
haftmann
parents: 16894
diff changeset
   161
6659
7a056250899d removed get_nodes;
wenzelm
parents: 6152
diff changeset
   162
fun del_nodes xs (Graph tab) =
15759
wenzelm
parents: 15570
diff changeset
   163
  Graph (tab
wenzelm
parents: 15570
diff changeset
   164
    |> fold Table.delete xs
wenzelm
parents: 15570
diff changeset
   165
    |> Table.map (fn (i, (preds, succs)) =>
wenzelm
parents: 15570
diff changeset
   166
      (i, (fold remove_key xs preds, fold remove_key xs succs))));
6659
7a056250899d removed get_nodes;
wenzelm
parents: 6152
diff changeset
   167
28333
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   168
fun del_node x (G as Graph tab) =
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   169
  let
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   170
    fun del_adjacent which y = Table.map_entry y (fn (i, ps) => (i, (which (remove_key x) ps)));
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   171
    val (preds, succs) = #2 (get_entry G x);
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   172
  in
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   173
    Graph (tab
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   174
      |> Table.delete x
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   175
      |> fold (del_adjacent apsnd) preds
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   176
      |> fold (del_adjacent apfst) succs)
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   177
  end;
507b64f4cd2a added del_node, which is more efficient for sparse graphs;
wenzelm
parents: 28204
diff changeset
   178
6152
wenzelm
parents: 6142
diff changeset
   179
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   180
(* edges *)
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   181
18921
f47c46d7d654 canonical member/insert/merge;
wenzelm
parents: 18133
diff changeset
   182
fun is_edge G (x, y) = member_key (imm_succs G x) y handle UNDEF _ => false;
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   183
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   184
fun add_edge (x, y) G =
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   185
  if is_edge G (x, y) then G
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   186
  else
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   187
    G |> map_entry y (fn (i, (preds, succs)) => (i, (x :: preds, succs)))
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   188
      |> map_entry x (fn (i, (preds, succs)) => (i, (preds, y :: succs)));
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   189
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   190
fun del_edge (x, y) G =
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   191
  if is_edge G (x, y) then
15759
wenzelm
parents: 15570
diff changeset
   192
    G |> map_entry y (fn (i, (preds, succs)) => (i, (remove_key x preds, succs)))
wenzelm
parents: 15570
diff changeset
   193
      |> map_entry x (fn (i, (preds, succs)) => (i, (preds, remove_key y succs)))
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   194
  else G;
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   195
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   196
fun diff_edges G1 G2 =
19482
9f11af8f7ef9 tuned basic list operators (flat, maps, map_filter);
wenzelm
parents: 19409
diff changeset
   197
  flat (dest G1 |> map (fn (x, ys) => ys |> map_filter (fn y =>
15531
08c8dad8e399 Deleted Library.option type.
skalberg
parents: 15160
diff changeset
   198
    if is_edge G2 (x, y) then NONE else SOME (x, y))));
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   199
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   200
fun edges G = diff_edges G empty;
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   201
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   202
18126
b74145e46e0d added join function
haftmann
parents: 18006
diff changeset
   203
(* join and merge *)
b74145e46e0d added join function
haftmann
parents: 18006
diff changeset
   204
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   205
fun no_edges (i, _) = (i, ([], []));
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   206
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   207
fun join f (Graph tab1, G2 as Graph tab2) =
19029
8635700e2c9c share exception UNDEF with Table;
wenzelm
parents: 18970
diff changeset
   208
  let fun join_node key ((i1, edges1), (i2, _)) = (f key (i1, i2), edges1)
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   209
  in fold add_edge (edges G2) (Graph (Table.join join_node (tab1, Table.map no_edges tab2))) end;
6152
wenzelm
parents: 6142
diff changeset
   210
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   211
fun gen_merge add eq (Graph tab1, G2 as Graph tab2) =
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   212
  let fun eq_node ((i1, _), (i2, _)) = eq (i1, i2)
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   213
  in fold add (edges G2) (Graph (Table.merge eq_node (tab1, Table.map no_edges tab2))) end;
6152
wenzelm
parents: 6142
diff changeset
   214
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   215
fun merge eq GG = gen_merge add_edge eq GG;
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   216
18133
1d403623dabc avoid code redundancy;
wenzelm
parents: 18126
diff changeset
   217
19580
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   218
(* irreducible paths -- Hasse diagram *)
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   219
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   220
fun irreducible_preds G X path z =
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   221
  let
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   222
    fun red x x' = is_edge G (x, x') andalso not (eq_key (x', z));
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   223
    fun irreds [] xs' = xs'
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   224
      | irreds (x :: xs) xs' =
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   225
          if not (member_keys X x) orelse eq_key (x, z) orelse member_key path x orelse
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   226
            exists (red x) xs orelse exists (red x) xs'
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   227
          then irreds xs xs'
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   228
          else irreds xs (x :: xs');
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   229
  in irreds (imm_preds G z) [] end;
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   230
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   231
fun irreducible_paths G (x, y) =
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   232
  let
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   233
    val (_, X) = reachable (imm_succs G) [x];
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   234
    fun paths path z =
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   235
      if eq_key (x, z) then cons (z :: path)
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   236
      else fold (paths (z :: path)) (irreducible_preds G X path z);
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   237
  in if eq_key (x, y) andalso not (is_edge G (x, x)) then [[]] else paths [] y [] end;
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   238
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   239
20736
934358468a1b tuned all_paths;
wenzelm
parents: 20679
diff changeset
   240
(* all paths *)
20679
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   241
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   242
fun all_paths G (x, y) =
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   243
  let
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   244
    val (_, X) = reachable (imm_succs G) [x];
20736
934358468a1b tuned all_paths;
wenzelm
parents: 20679
diff changeset
   245
    fun paths path z =
934358468a1b tuned all_paths;
wenzelm
parents: 20679
diff changeset
   246
      if not (null path) andalso eq_key (x, z) then [z :: path]
934358468a1b tuned all_paths;
wenzelm
parents: 20679
diff changeset
   247
      else if member_keys X z andalso not (member_key path z)
934358468a1b tuned all_paths;
wenzelm
parents: 20679
diff changeset
   248
      then maps (paths (z :: path)) (imm_preds G z)
20679
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   249
      else [];
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   250
  in paths [] y end;
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   251
c09af1bd255a Added function all_paths (formerly find_paths).
berghofe
parents: 19950
diff changeset
   252
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   253
(* maintain acyclic graphs *)
6142
wenzelm
parents: 6134
diff changeset
   254
wenzelm
parents: 6134
diff changeset
   255
exception CYCLES of key list list;
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   256
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   257
fun add_edge_acyclic (x, y) G =
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   258
  if is_edge G (x, y) then G
9347
1791a62b33e7 improved add_edges_cyclic;
wenzelm
parents: 9321
diff changeset
   259
  else
19580
c878a09fb849 replaced find_paths by irreducible_paths, i.e. produce paths within a Hasse diagram;
wenzelm
parents: 19482
diff changeset
   260
    (case irreducible_paths G (y, x) of
9347
1791a62b33e7 improved add_edges_cyclic;
wenzelm
parents: 9321
diff changeset
   261
      [] => add_edge (x, y) G
1791a62b33e7 improved add_edges_cyclic;
wenzelm
parents: 9321
diff changeset
   262
    | cycles => raise CYCLES (map (cons x) cycles));
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   263
15759
wenzelm
parents: 15570
diff changeset
   264
fun add_deps_acyclic (y, xs) = fold (fn x => add_edge_acyclic (x, y)) xs;
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   265
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   266
fun merge_acyclic eq GG = gen_merge add_edge_acyclic eq GG;
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   267
23964
d2df2797519b added topological_order;
wenzelm
parents: 23655
diff changeset
   268
fun topological_order G = minimals G |> all_succs G;
d2df2797519b added topological_order;
wenzelm
parents: 23655
diff changeset
   269
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   270
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   271
(* maintain transitive acyclic graphs *)
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   272
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   273
fun add_edge_trans_acyclic (x, y) G =
19290
wenzelm
parents: 19029
diff changeset
   274
  add_edge_acyclic (x, y) G
25538
58e8ba3b792b map_product and fold_product
haftmann
parents: 23964
diff changeset
   275
  |> fold_product (curry add_edge) (all_preds G [x]) (all_succs G [y]);
9321
e0dda4bde88c tuned exceptions;
wenzelm
parents: 8806
diff changeset
   276
14793
32d94d1e4842 added dest, minimals, maximals, is_edge, add_edge/merge_trans_acyclic;
wenzelm
parents: 14161
diff changeset
   277
fun merge_trans_acyclic eq (G1, G2) =
19290
wenzelm
parents: 19029
diff changeset
   278
  merge_acyclic eq (G1, G2)
wenzelm
parents: 19029
diff changeset
   279
  |> fold add_edge_trans_acyclic (diff_edges G1 G2)
wenzelm
parents: 19029
diff changeset
   280
  |> fold add_edge_trans_acyclic (diff_edges G2 G1);
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   281
19615
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
   282
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
   283
(*final declarations of this structure!*)
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
   284
val fold = fold_graph;
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
   285
6134
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   286
end;
ec6092b0599d added General/graph.ML: generic direct graphs;
wenzelm
parents:
diff changeset
   287
16810
2406588f99cb Graph: fast_string_ord;
wenzelm
parents: 16445
diff changeset
   288
structure Graph = GraphFun(type key = string val ord = fast_string_ord);
19615
e3ab6cd838a4 added fold;
wenzelm
parents: 19580
diff changeset
   289
structure IntGraph = GraphFun(type key = int val ord = int_ord);