summaryrefslogtreecommitdiff
path: root/ipl/procs/graphpak.icn
diff options
context:
space:
mode:
Diffstat (limited to 'ipl/procs/graphpak.icn')
-rw-r--r--ipl/procs/graphpak.icn111
1 files changed, 111 insertions, 0 deletions
diff --git a/ipl/procs/graphpak.icn b/ipl/procs/graphpak.icn
new file mode 100644
index 0000000..7c62ec3
--- /dev/null
+++ b/ipl/procs/graphpak.icn
@@ -0,0 +1,111 @@
+############################################################################
+#
+# File: graphpak.icn
+#
+# Subject: Procedures for manipulating directed graphs
+#
+# Author: Ralph E. Griswold
+#
+# Date: May 2, 2001
+#
+############################################################################
+#
+# This file is in the public domain.
+#
+############################################################################
+#
+# The procedures here use sets to represent directed graphs. See
+# The Icon Programming Language, second edition, pp. 195-198.
+#
+# A value of type "graph" has two components: a list of nodes and
+# a two-way lookup table. The nodes in turn contain pointers to
+# other nodes. The two-way table maps a node to its name and
+# vice-versa.
+#
+# Graph specifications are give in files in which the first line
+# is a white-space separated list of node names and subsequent lines
+# give the arcs, as in
+#
+# Tucson Phoenix Bisbee Douglas Flagstaff
+# Tucson->Phoenix
+# Tucson->Bisbee
+# Bisbee->Bisbee
+# Bisbee->Douglas
+# Douglas->Phoenix
+# Douglas->Tucson
+#
+############################################################################
+
+record graph(nodes, lookup)
+
+# Construct a graph from the specification given in file f. Error checking
+# is minimal.
+
+procedure read_graph(f) #: read graph
+ local node, nodes, node_list, lookup, arc, from_name, to_name
+
+ nodes := [] # list of the graph nodes
+ lookup := table() # two-way table of names and nodes
+
+ node_list := read(f) | stop("*** empty specification file")
+
+ node_list ? { # process list of node names
+ while name := tab(upto('\t ') | 0) do {
+ node := set() # create a new node
+ put(nodes, node) # add node to the list
+ lookup[name] := node # name to node
+ lookup[node] := name # node to name
+ tab(many(' \t')) | break
+ }
+ }
+
+ while arc := read(f) do { # process arcs
+ arc ? {
+ from_name := tab(find("->")) | stop("*** bad arc specification")
+ move(2)
+ to_name := tab(0)
+ insert(\lookup[from_name], \lookup[to_name]) |
+ stop("*** non-existent node")
+ }
+ }
+
+
+ return graph(nodes, lookup) # now put the pieces together
+
+end
+
+# Write graph g to file f.
+
+procedure write_graph(g, f) #: write graph
+ local name_list, node
+
+ name_list := "" # initialize
+
+ every node := !g.nodes do # construct the list of names
+ name_list ||:= g.lookup[node] || " "
+
+ write(f, name_list[1:-1])
+
+ every node := !g.nodes do # write the arc specifications
+ every write(f, g.lookup[node], "->", g.lookup[!node])
+
+ return
+
+end
+
+# Transitive closure of node. Called as closure(node) without second argument
+
+procedure closure(node, close) #: transitive closure of graph
+ local n
+
+ /close := set() # initialize closure
+
+ insert(close, node) # add the node itself
+
+ every n := !node do # process all the arcs
+ # if not member, recurse
+ member(close, n) | closure(n, close)
+
+ return close
+
+end