graphbase
changeset 0:441ba945c077 tip
Automated check-in.
author | CTAN Mercurial User <ctanhg@scharrer-online.de> |
---|---|
date | Mon, 03 Oct 2011 23:29:42 +0200 |
parents | |
children | |
files | Makefile README abstract.pdf abstract.plaintex anna.dat assign_mona.w boilerplate.w book_components.w cities.texmap david.dat econ.dat econ_order.w football.w games.dat gb_basic.w gb_books.w gb_dijk.w gb_econ.w gb_flip.w gb_games.w gb_gates.w gb_graph.w gb_io.w gb_miles.w gb_mona.w gb_plane.w gb_raman.w gb_rand.w gb_roget.w gb_save.w gb_sort.w gb_words.w girth.w homer.dat huck.dat jean.dat ladders.w miles.dat miles_span.w mona.dat multiply.w queen.w queen_wrap.ch roget.dat roget_components.w sample.correct take_risc.w test.correct test.dat test_sample.w word_components.w words.dat |
diffstat | 52 files changed, 34556 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Makefile Mon Oct 03 23:29:42 2011 +0200 1.3 @@ -0,0 +1,113 @@ 1.4 +# 1.5 +# Makefile for the Stanford GraphBase 1.6 +# 1.7 + 1.8 +# Change DATADIR to the directory where the data files will go (425K bytes) 1.9 +DATADIR = /usr/local/lib 1.10 + 1.11 +# Uncomment the next line if your C uses <string.h> but not <strings.h> 1.12 +# SYS = -DSYSV 1.13 + 1.14 +# If you prefer optimization to debugging, change CFLAGS to something like -O 1.15 +CFLAGS = -g 1.16 + 1.17 +# Change MLIB, if necessary, to the code that loads the C math library 1.18 +MLIB = -lm 1.19 + 1.20 +install: 1.21 + - mkdir $(DATADIR) 1.22 + install -c -m 444 *.dat $(DATADIR) 1.23 + 1.24 +%.c: %.w 1.25 + ctangle $* 1.26 + 1.27 +%.o: %.c 1.28 + cc $(CFLAGS) -c $*.c 1.29 + 1.30 +IFGS = gb_io.o gb_flip.o gb_graph.o gb_sort.o 1.31 +IFG = gb_io.o gb_flip.o gb_graph.o 1.32 +IG = gb_io.o gb_graph.o 1.33 +FG = gb_flip.o gb_graph.o 1.34 + 1.35 +assign_mona: assign_mona.c $(IG) gb_mona.o 1.36 + cc $(CFLAGS) assign_mona.c $(IG) gb_mona.o -o assign_mona 1.37 + 1.38 +book_components: book_components.c $(IFGS) gb_books.o 1.39 + cc $(CFLAGS) book_components.c $(IFGS) gb_books.o -o book_components 1.40 + 1.41 +econ_order: econ_order.c $(IFG) gb_econ.o 1.42 + cc $(CFLAGS) econ_order.c $(IFG) gb_econ.o -o econ_order 1.43 + 1.44 +football: football.c $(IFGS) gb_games.o 1.45 + cc $(CFLAGS) football.c $(IFGS) gb_games.o -o football 1.46 + 1.47 +gb_graph.o: gb_graph.c 1.48 + cc $(CFLAGS) $(SYS) -c $*.c 1.49 + 1.50 +gb_io.o: gb_io.c 1.51 + echo "#define DATA_DIRECTORY \"$(DATADIR)/\"" >localdefs.h 1.52 + cc $(CFLAGS) $(SYS) -c $*.c 1.53 + rm localdefs.h 1.54 + 1.55 +gb_plane.o: gb_miles.o 1.56 + 1.57 +girth: girth.c $(FG) gb_raman.o 1.58 + cc $(CFLAGS) girth.c $(FG) gb_raman.o -o girth $(MLIB) 1.59 + 1.60 +miles_span: miles_span.c $(IFGS) gb_miles.o 1.61 + cc $(CFLAGS) miles_span.c $(IFGS) gb_miles.o -o miles_span 1.62 + 1.63 +multiply: multiply.c $(FG) gb_gates.o 1.64 + cc $(CFLAGS) multiply.c $(FG) gb_gates.o -o multiply 1.65 + 1.66 +queen: queen.c $(IG) gb_basic.o gb_save.o 1.67 + cc $(CFLAGS) queen.c $(IG) gb_basic.o gb_save.o -o queen 1.68 + 1.69 +queen_wrap.c: queen.w queen_wrap.ch 1.70 + ctangle queen_wrap.w queen_wrap.ch queen_wrap.c 1.71 + 1.72 +queen_wrap: queen_wrap.c $(IG) gb_basic.o gb_save.o 1.73 + cc $(CFLAGS) queen_wrap.c $(IG) gb_basic.o gb_save.o -o queen_wrap 1.74 + 1.75 +roget_components: roget_components.c $(IFG) gb_roget.o 1.76 + cc $(CFLAGS) roget_components.c $(IFG) gb_roget.o -o roget_components 1.77 + 1.78 +take_risc: take_risc.c $(FG) gb_gates.o 1.79 + cc $(CFLAGS) take_risc.c $(FG) gb_gates.o -o take_risc 1.80 + 1.81 +word_components: word_components.c $(IFGS) gb_words.o 1.82 + cc $(CFLAGS) word_components.c $(IFGS) gb_words.o -o word_components 1.83 + 1.84 +ladders: ladders.c $(IFGS) gb_words.o gb_dijk.o 1.85 + cc $(CFLAGS) ladders.c $(IFGS) gb_words.o gb_dijk.o -o ladders 1.86 + 1.87 +test_io: gb_io.o 1.88 + cc $(CFLAGS) test_io.c gb_io.o -o test_io 1.89 + 1.90 +test_graph: gb_graph.o 1.91 + cc $(CFLAGS) test_graph.c gb_graph.o -o test_graph 1.92 + 1.93 +test_flip: gb_flip.o 1.94 + cc $(CFLAGS) test_flip.c gb_flip.o -o test_flip 1.95 + 1.96 +test_sample: test_sample.c $(IFGS) gb_basic.o gb_books.o gb_econ.o \ 1.97 + gb_games.o gb_gates.o gb_miles.o gb_mona.o gb_plane.o gb_raman.o \ 1.98 + gb_rand.o gb_roget.o gb_save.o gb_words.o 1.99 + cc $(CFLAGS) test_sample.c $(IFGS) gb_basic.o gb_books.o gb_econ.o \ 1.100 + gb_games.o gb_gates.o gb_miles.o gb_mona.o gb_plane.o gb_raman.o \ 1.101 + gb_rand.o gb_roget.o gb_save.o gb_words.o -o test_sample 1.102 + 1.103 +test_all: test_io test_graph test_flip test_sample 1.104 + test_io 1.105 + test_graph 1.106 + test_flip 1.107 + test_sample > sample.out 1.108 + diff test.gb test.correct 1.109 + diff sample.out sample.correct 1.110 + rm test.gb sample.out test_io test_graph test_flip test_sample 1.111 + 1.112 +veryclean: 1.113 + rm -f *.o *.c *.h \ 1.114 + assign_mona book_components econ_order football \ 1.115 + girth ladders miles_span multiply roget_components \ 1.116 + take_risc word_components
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/README Mon Oct 03 23:29:42 2011 +0200 2.3 @@ -0,0 +1,90 @@ 2.4 +The Stanford GraphBase is copyright 1992 by Stanford University 2.5 + 2.6 +These files may be freely copied and distributed, provided that 2.7 +no changes whatsoever are made. All users are asked to help keep 2.8 +the Stanford GraphBase sources consistent and ``uncorrupted,'' 2.9 +identical everywhere in the world. Changes are permissible only 2.10 +if the changed file is given a new name, different from the names of 2.11 +existing files listed below, and only if the changed file is 2.12 +clearly identified as not being part of the Stanford GraphBase. 2.13 +The author has tried his best to produce correct and useful programs, 2.14 +in order to help promote computer science research, but no warranty 2.15 +of any kind should be assumed. 2.16 + 2.17 +FILES INCLUDED IN STANDARD GRAPHBASE DISTRIBUTION 2.18 + 2.19 +The standard Stanford GraphBase consists of the following files: 2.20 + 2.21 +1) Data files 2.22 + anna.dat Anna Karenina (used by gb_books) 2.23 + david.dat David Copperfield (used by gb_books) 2.24 + econ.dat US economic input and output (used by gb_econ) 2.25 + games.dat College football scores, 1990 (used by gb_games) 2.26 + homer.dat The Iliad (used by gb_books) 2.27 + huck.dat Huckleberry Finn (used by gb_books) 2.28 + jean.dat Les Miserables (used by gb_books) 2.29 + miles.dat Mileage between North American cities (used by gb_miles) 2.30 + mona.dat Mona Lisa pixels (used by gb_mona) 2.31 + roget.dat Cross references in Roget's Thesaurus (used by gb_roget) 2.32 + words.dat Five-letter words of English (used by (gb_words) 2.33 +2) CWEB program files 2.34 + a) Kernel routines 2.35 + gb_flip.w System-independent random number generator 2.36 + gb_graph.w Data structures for graphs 2.37 + gb_io.w Input/output routines 2.38 + gb_sort.w Sorting routine for linked lists 2.39 + b) Graph generating routines 2.40 + gb_basic.w Standard building blocks and graph operations 2.41 + gb_books.w Graphs based on world literature 2.42 + gb_econ.w Graphs based on US inter-industry flow 2.43 + gb_games.w Graphs based on college football games 2.44 + gb_gates.w Graphs based on combinational logic 2.45 + gb_miles.w Graphs based on highway distances 2.46 + gb_mona.w Graphs based on Leonardo's Mona Lisa 2.47 + gb_plane.w Planar graphs 2.48 + gb_raman.w Ramanujan graphs (expanders) 2.49 + gb_rand.w Random graphs 2.50 + gb_roget.w Graphs based on Roget's Thesaurus 2.51 + gb_words.w Graphs based on 5-letter words of English 2.52 + c) Demonstration routines 2.53 + assign_mona.w The assignment problem, using Mona Lisa 2.54 + book_components.w Biconnected components, using the plots of books 2.55 + econ_order.w Heuristic solution to an optimum permutation problem 2.56 + football.w Heuristic solution to a longest-path problem 2.57 + girth.w Empirical study of Ramanujan graphs 2.58 + ladders.w Shortest paths in word graphs 2.59 + miles_span.w Comparison of algorithms for minimum spanning tree 2.60 + multiply.w Using a parallel multiplication circuit 2.61 + queen.w Graphs based on queen moves 2.62 + roget_components.w Strong components of a directed graph 2.63 + take_risc.w Using a simple RISC computer circuit 2.64 + word_components.w Connected components of word graphs 2.65 + d) Miscellaneous routines 2.66 + boilerplate.w Legalese incorporated into all GraphBase programs 2.67 + gb_dijk.w Variants of Dijkstra's algorithm for shortest paths 2.68 + gb_save.w Converting graphs to ASCII files and vice versa 2.69 + test_sample.w Test routine for GraphBase installation 2.70 +3) Miscellaneous files 2.71 + Makefile Instructions to build everything with UNIX 2.72 + README What you're now reading 2.73 + abstract.plaintex Short explanation of what it's all about 2.74 + cities.texmap TeXable map of the 128 cities in miles.dat 2.75 + queen_wrap.ch Demonstration changefile 2.76 + sample.correct Correct primary output of test_sample 2.77 + test.correct Correct secondary output of test_sample 2.78 + test.dat Weird data used to test gb_io 2.79 + 2.80 +TO INSTALL THESE PROGRAMS 2.81 + 2.82 +First install CWEB (version 2.4 or greater), which can be found in 2.83 +various archives; the master files reside at labrea.stanford.edu. 2.84 +Then, on a UNIX-like system, edit the Makefile as instructed there, 2.85 +and "make install". 2.86 + 2.87 +Complete instructions will appear in a book by D. E. Knuth entitled 2.88 + The Stanford GraphBase: A Platform for Combinatorial Algorithms. 2.89 + 2.90 +Note: The system is presently in alpha-test state, meaning that everything 2.91 +appears to work on at least one system; but experience on a broad range 2.92 +of computers is lacking. Please communicate all suggested improvements to 2.93 +winkler@sunburn.stanford.edu, with subject line "GraphBase Alpha Test".
3.1 Binary file abstract.pdf has changed
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/abstract.plaintex Mon Oct 03 23:29:42 2011 +0200 4.3 @@ -0,0 +1,260 @@ 4.4 +% EXTENDED ABSTRACT DESCRIBING THE STANFORD GRAPHBASE --- PRELIMINARY DRAFT 4.5 +\magnification\magstep1 4.6 +\baselineskip12pt 4.7 +\parskip3pt 4.8 +\font\sc=cmcsc10 %use lower case as (Monthly) 4.9 + 4.10 +\def\happyface % new experimental version (DEK, November 88) 4.11 +{{\ooalign{\hfil\lower.06ex % a smiley face 4.12 + \hbox{$\scriptscriptstyle\smile$}\hfil\crcr 4.13 + \hfil\lower.7ex\hbox{\"{}}\hfil\crcr 4.14 + \mathhexbox20D}}} 4.15 +\def\display#1:#2:#3\par{\par\hangindent #1 \noindent 4.16 + \hbox to #1{\hfill #2 \hskip .1em}\ignorespaces#3\par} 4.17 +\def\disleft#1:#2:#3\par{\par\hangindent#1\noindent 4.18 + \hbox to #1{#2 \hfill \hskip .1em}\ignorespaces#3\par} 4.19 +\def\TeX{T\hbox{\hskip-.1667em\lower.424ex\hbox{E}\hskip-.125em X}} 4.20 +\def\biba{\par\parindent 40pt\hangindent 60pt} 4.21 + 4.22 +\centerline{\bf The Stanford GraphBase: A Platform for Combinatorial 4.23 +Algorithms} 4.24 + 4.25 +\bigskip 4.26 +A highly portable collection of programs and data will soon be 4.27 +available to researchers who study combinatorial algorithms and data 4.28 +structures. All files will be in the public domain, and usable with 4.29 +only one restriction: They must not be changed! A~``change file'' 4.30 +mechanism will allow local customization while the master files stay 4.31 +intact. 4.32 + 4.33 +The programs are intended to be interesting in themselves as examples 4.34 +of ``literate programming.'' Thus, the Stanford GraphBase can also be 4.35 +regarded as a collection of approximately 30 essays for programmers to enjoy 4.36 +reading, whether or not they are doing algorithmic research. The 4.37 +programs are written in {\tt CWEB}, a~combination of \TeX\ and~C that 4.38 +is easy to use by anyone who knows those languages and easy to read by 4.39 +anyone familiar with the rudiments of~C. (The {\tt CWEB} system is 4.40 +itself portable and in the public domain.) 4.41 + 4.42 +Four program modules constitute the {\it kernel\/} of the GraphBase: 4.43 + 4.44 +{ 4.45 + 4.46 +\biba 4.47 +{\sc gb\_$\,$flip} is a portable random number generator; 4.48 + 4.49 +\biba 4.50 +{\sc gb\_$\,$graph} defines standard data structures for graphs and 4.51 +includes routines for storage allocation; 4.52 + 4.53 +\biba 4.54 +{\sc gb\_$\,$io} reads data files and makes sure they are uncorrupted; 4.55 + 4.56 +\biba 4.57 +{\sc gb\_$\,$sort} is a portable sorting routine for 32-bit keys 4.58 +in linked lists of nodes. 4.59 + 4.60 +} 4.61 + 4.62 +\noindent 4.63 +All of the other programs rely on {\sc gb\_$\,$graph} and some subset 4.64 +of the other three parts of the kernel. 4.65 + 4.66 +A dozen or so {\it generator modules\/} construct graphs that are of 4.67 +special interest in algorithmic studies. For example {\tt 4.68 +gb\_$\,$basic} contains 12~subroutines to produce standard graphs, 4.69 +such as the graphs of queen moves on $d$-dimensional rectangular 4.70 +boards with ``wrap-around'' on selected coordinates. Another generator 4.71 +module, {\sc gb\_$\,$rand}, produces several varieties of 4.72 +random graphs. 4.73 + 4.74 +Each graph has a unique identifier that allows researchers all over 4.75 +the world to work with exactly the same graphs, even when those graphs 4.76 +are ``random.'' Repeatable experiments and standard benchmarks will 4.77 +therefore be possible and widely available. 4.78 + 4.79 +Most of the generator modules make use of {\it data sets}, which the 4.80 +author has been collecting for 20~years in an attempt to provide 4.81 +interesting and instructive examples for some forthcoming books on 4.82 +combinatorial algorithms ({\sl The Art of Computer Programming}, 4.83 +Volumes 4A, 4B, and~4C). For example, one of the data sets is {\tt 4.84 +words.dat}, a~collection of 5-letter words of English that the author 4.85 +believes is ``complete'' from his own reading experience. Each word is 4.86 +accompanied by frequency counts in various standard corpuses of text, 4.87 +so that the most common terms can be singled out if desired. {\sc 4.88 +gb\_$\,$words} makes a subset of words into a graph by saying that two 4.89 +words are adjacent when they agree in~4 out of~5 positions. Thus, we 4.90 +can get from {\tt words} to {\tt graph} in seven steps: 4.91 + 4.92 +\disleft 30pt:: 4.93 +{\tt words, wolds, golds, goads, grads, grade, grape, graph.} 4.94 + 4.95 +\noindent 4.96 +This is in fact the shortest such chain obtainable from {\tt 4.97 +words.dat}. 4.98 + 4.99 +A dozen or so {\it demonstration modules\/} are also provided, as 4.100 +illustrations of how the generated graphs can be used. For example, 4.101 +the {\tt LADDERS} module is an interactive program to construct chains 4.102 +of 5-letter words like the one just exhibited, using arbitrary subsets 4.103 +of the data. If we insist on restricting our choices to the 2000 most 4.104 +common words, instead of using the entire collection of about 5700, the 4.105 +shortest path from {\tt words} to {\tt graph} turns out to have 4.106 +length~20: 4.107 + 4.108 +\disleft 30pt:: 4.109 +{\tt words, lords, loads, leads, leaps, leapt, least,} 4.110 +\vskip-5pt 4.111 +\disleft 30pt:: 4.112 +{\tt lease, cease, chase, chose, chore, shore, shone,} 4.113 +\vskip-5pt 4.114 +\disleft 30pt:: 4.115 +{\tt phone, prone, prove, grove, grave, 4.116 +grape, graph.} 4.117 + 4.118 +Several variations on this theme have also been implemented: If we consider 4.119 +the distance between adjacent words to be alphabetic distance, for 4.120 +example, the shortest path from {\tt words} to {\tt graph} turns out 4.121 +to be 4.122 + 4.123 +\disleft 30pt:: 4.124 +{\tt words} (3) {\tt woods} (16) {\tt goods} (14) {\tt goads} (3) 4.125 +{\tt grads} (14) {\tt grape} (3) {\tt graph}, 4.126 + 4.127 +\noindent 4.128 +total length 65. 4.129 + 4.130 +The {\tt LADDERS} module makes use of another GraphBase module called 4.131 +{\sc gb\_$\,$dijk}, which carries out Dijkstra's algorithm for 4.132 +shortest paths and allows the user to plug in arbitrary 4.133 +implementations of priority queues so that the performance of 4.134 +different queuing methods can be compared. 4.135 + 4.136 +The graphs produced by {\sc gb\_$\,$words} are undirected. Other 4.137 +generator modules, like {\sc gb\_$\,$roget}, produce directed graphs. 4.138 +Roget's {\sl Thesaurus\/} of 1882 classified all concepts into 1022 4.139 +categories, which we can call the vertices of a graph; an arc goes 4.140 +from~$u$ to~$v$ when category~$u$ contains a cross reference to 4.141 +category~$v$ in Roget's book. A~demonstration module called {\sc 4.142 +roget\_$\,$components} determines the strong components of graphs 4.143 +generated by {\sc gb\_$\,$roget}. This program is an exposition of 4.144 +Tarjan's algorithm for strong components and topological sorting of 4.145 +directed graphs. 4.146 + 4.147 +Similarly, 4.148 +world literature leads to further interesting families of undirected 4.149 +graphs via 4.150 +the {\sc gb\_$\,$books} module. Five data sets {\tt anna.dat}, {\tt 4.151 +david.dat}, {\tt homer.dat}, {\tt huck.dat}, and {\tt jean.dat} give 4.152 +information about {\sl Anna Karenina}, {\sl David Copperfield}, {\sl 4.153 +The Iliad}, {\sl Huckleberry Finn}, and {\sl Les Mis\'erables\/}; as 4.154 +you might expect, the characters of each work become the vertices of a 4.155 +graph. Two vertices are adjacent if the corresponding characters 4.156 +encounter each other, in selected chapters of the book. 4.157 +A~demonstration program called 4.158 +{\sc book\_$\,$components} finds the blocks (i.e., biconnected 4.159 +components) of these graphs using the elegant algorithm of Hopcroft 4.160 +and Tarjan. 4.161 + 4.162 +Another module, {\sc gb\_$\,$games}, generates graphs based on college 4.163 +football scores. All the games from the 1990 season 4.164 + between America's leading 120 4.165 +teams are recorded in {\tt games.dat}; this data leads to ``cliquey'' 4.166 +graphs, because most of the teams belong to leagues and they play 4.167 +every other team in their league. The overall graph is, however, 4.168 +connected. A~demonstration module called {\sc football} finds long 4.169 +chains of scores, to prove for instance that Stanford might have trounced 4.170 +Harvard by more than 2000 points if the two teams had met---because 4.171 +Stanford beat Notre Dame by~5, and Notre Dame beat Air Force by~30, 4.172 +and Air Force beat Hawaii by~24, and \dots~, and Yale beat Harvard 4.173 +by~15. (Conversely, a~similar ``proof'' also ranks Harvard over 4.174 +Stanford by more than 2000 points.) No good algorithm is known for 4.175 +finding the optimum solution to problems like this, so the data 4.176 +provides an opportunity for researchers to exhibit better and better 4.177 +solutions with better and better techniques as algorithmic 4.178 +progress is made. 4.179 + 4.180 +The {\sc gb\_$\,$econ} module generates directed graphs based on the 4.181 +flow of money between industries in the US economy. A~variety of 4.182 +graphs can be obtained, as the economy can be divided into any number of 4.183 +sectors from~2 to~80 in this model. 4.184 + A~demonstration program {\sc econ\_$\,$order} 4.185 +attempts to rank the sectors in order from ``suppliers'' to 4.186 +``consumers,'' namely to permute rows and columns of a matrix so as to 4.187 +minimize the sum of entries above the diagonal. Again, no good 4.188 +algorithms for this problem are known; two heuristics are implemented 4.189 +for comparison, one ``greedy'' and the other ``cautious.'' Greed 4.190 +appears to be victorious, at least in the economic sphere. 4.191 + 4.192 +The highway mileage between 128 North American cities appears in {\tt 4.193 +miles.dat}, and the {\sc gb\_$\,$miles} module generates a variety of 4.194 +graphs from~it. Of special interest is a demonstration module called 4.195 +{\sc miles\_$\,$span}, which computes the minimum spanning trees of 4.196 +graphs output by {\sc gb\_$\,$miles}. Four algorithms for minimum 4.197 +spanning trees are implemented and compared, including some that are 4.198 +theoretically appealing but do not seem to fare so well in practice. 4.199 +An approach to comparison of algorithms called ``mem counting'' is 4.200 +shown in this demonstration to be an easily implemented 4.201 +machine-independent measure of efficiency that gives a reasonably fair 4.202 +comparison between competing techniques. 4.203 + 4.204 +A generator module called {\sc gb\_$\,$raman} produces ``Ramanujan 4.205 +graphs,'' which are important because of their role as expander 4.206 +graphs, useful for communication. A~demonstration module called {\sc 4.207 +girth} computes the shortest circuit and the diameter of Ramanujan 4.208 +graphs. 4.209 +Notice that some graphs, like those produced by {\sc gb\_$\,$basic} or 4.210 +{\sc gb\_$\,$raman}, have a rigid mathematical structure; others, like 4.211 +those produced by {\sc gb\_$\,$roget} or {\sc gb\_$\,$miles}, are more 4.212 +``organic'' in nature. It is interesting and important to test 4.213 +algorithms on both kinds of graphs, in order to see if there is any 4.214 +significant difference in performance. 4.215 + 4.216 +A generator module called {\sc gb\_$\,$gates} produces graphs of logic 4.217 +circuits. One family of graphs is equivalent to a simple {\sc risc} 4.218 +chip, a~programmable microcomputer with a variable number of registers 4.219 +and a variable number of bits per word. Using such a ``meta-network'' 4.220 +of gates, algorithms for design automation can be tested for a range 4.221 +of varying parameters. A~demonstration module {\sc take\_$\,$risc} 4.222 +simulates the execution of the chip on a sample program. Another 4.223 +meta-network of gates will perform parallel multiplication of $m$-bit 4.224 +numbers by $n$-bit numbers or by an $n$-bit constant; the {\sc 4.225 +multiply} module demonstrates this network. 4.226 + 4.227 +Planar graphs are generated by {\sc gb\_$\,$plane}, which includes 4.228 +among other things an implementation of the best currently known 4.229 +algorithm for Delaunay triangulation. 4.230 + 4.231 +Pixel data can lead to interesting bipartite graphs. Leonardo's {\sl 4.232 +Giaconda\/} is represented by {\tt mona.dat}, an array of pixels that 4.233 +is converted into graphs of different kinds by {\sc gb\_$\,$mona}. 4.234 +A~demonstration routine {\sc assign\_$\,$mona} solves the assignment 4.235 +problem by choosing one pixel in each row and in each column so that 4.236 +the total brightness of selected pixels is maximized. Although the 4.237 +assignment problem being solved here has no relevance whatever to art 4.238 +criticism or art appreciation, it does have great pedagogical value, 4.239 +because there is probably no better way to understand the 4.240 +characteristics of a large array of numbers than to perceive the array 4.241 +as an image. 4.242 + 4.243 +This lecture might well have been called ``Fun and games with the 4.244 +Stanford GraphBase,'' because the demonstration programs are great 4.245 +toys to play with. Indeed, the author firmly believes that the best 4.246 +serious work is also good fun, and we shouldn't apologize if we enjoy 4.247 +doing research. 4.248 + 4.249 +The Stanford GraphBase is now being beta-tested, and it should be 4.250 +released in 1993. A~book about it, containing in particular all the 4.251 +programs together with indexes and typographic aids to the reader, 4.252 +will also be published in 1993. A~module called {\sc gb\_$\,$save} 4.253 +converts GraphBase graphs to and from an ASCII format that 4.254 +readily interfaces with other systems for graph manipulation. 4.255 + 4.256 + 4.257 +\bigskip 4.258 +\rightline{\sl ---\vtop{\hbox{Donald E. Knuth} 4.259 +\hbox{Stanford University} 4.260 +\hbox{March 31, 1992}}} 4.261 + 4.262 +\bye 4.263 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/anna.dat Mon Oct 03 23:29:42 2011 +0200 5.3 @@ -0,0 +1,383 @@ 5.4 +* File "anna.dat" from the Stanford GraphBase (C) 1992 Stanford University 5.5 +* Anna Karenina, by Leo Nikolaevitch Tolstoy 5.6 +* This file may be freely copied but please do not change it in any way! 5.7 +* (Checksum parameters 378,911441608) 5.8 +AA Annushka, maid of AN 5.9 +AG Agafea Mihalovna, housekeeper of LE 5.10 +AL Alexey Alexandrovitch Karenin, minister of state 5.11 +AN Anna Arkadyevna Karenina, wife of AL 5.12 +AO Aliosha, son of DO and ST 5.13 +AP Anna Pavlovna, wife of PV 5.14 +BA Annie, baby of AN and VR 5.15 +BD Dmitri (Mitya), baby of LE and KI 5.16 +BE Madame Berthe, blind woman 5.17 +BL Count Bol, friend of KI in Moscow 5.18 +BN Bartnyansky, rich man in Petersburg 5.19 +BO Countess Bola, wife of BL 5.20 +BT Princess Betsy Tverskaya, cousin of VR 5.21 +CA Count Anitchkin, supervisor of ST 5.22 +CB Countess Bonina, dance partner of YK 5.23 +CD Colonel Demin, colleague of VR 5.24 +CN Countess Nordston, friend of KI 5.25 +CO Cord, English horse trainer 5.26 +CV Countess Vronskaya, mother of VR 5.27 +DO Princess Darya Alexandrovna Oblonskaya (Dolly), wife of ST 5.28 +ED Miss Edwards, English governor of SE 5.29 +EF Marya Efimovna, nurse of AL 5.30 +FC Fyodor 1, coachman of AA 5.31 +FR Fyodor Ryezunov, carpenter 5.32 +FY Fyodor 2, peasant 5.33 +GA Gagin, officer from Petersburg 5.34 +GO Golenishtchev, friend of VR 5.35 +GR Grisha, young son of ST and DO 5.36 +GV Grinevitch (Mihail Stanislavitch), board member 5.37 +HA Hannah, pupil of AN 5.38 +HO Miss Hoole, English governess to DO's children 5.39 +IG Ignat, coachman of LE 5.40 +IV Ivan 1, cowherd 5.41 +IW Ivan 2, coachmen of LE 5.42 +JL Jules Landau (Count Bezzubov), psychic 5.43 +KA Captain Kamerovsky, cavalry officer 5.44 +KE Prince Kedrov, member of VR's regiment 5.45 +KI Princess Ekaterina Alexandrovna Shtcherbatskaya (Kitty), wife of LE 5.46 +KO Sergei Ivanovitch Koznishev, half-brother of LE 5.47 +KP Kapitonitch, hall porter of AL 5.48 +KR Kritsky, friend of NI 5.49 +KT Professor Katavasov, natural scientist 5.50 +KU Prince Kuzovlev, fearful horseman 5.51 +KV Krivin, bald socialite 5.52 +KY Korney, valet of AL 5.53 +KZ Kouzma, elderly servant of LE 5.54 +LE Konstantin Dmitrievitch Levin, proprietor of Pokrovskoe 5.55 +LI Countess Lidia Ivanovna, Petersburg dogooder 5.56 +LK Lidi Korsunskaya, wife of YK 5.57 +LL Lily, youngest child of DO and ST 5.58 +LM Liza Merkalova, thin brunette admired by SM 5.59 +LP Lizaveta Petrovna, midwife 5.60 +LV Arseny Lvov, husband of NA 5.61 +MA Matvey, valet of ST 5.62 +MB Princess Marya Borissovna, KI's godmother 5.63 +MC Mihail, coachman 5.64 +MD Marya Dmitrievna, aunt of KI 5.65 +ME Mariette, governess of SE 5.66 +MH Mahotin, rival horseman to VR 5.67 +MI Mihailov, painter 5.68 +MJ Mihailitch, beekeeper 5.69 +MK Mishka, peasant lad 5.70 +ML Mademoiselle Linon, French governess of KI 5.71 +MM Masha 3, little daughter of ST and DO 5.72 +MN Marya Nikolaevna, companion of NI 5.73 +MO Metrov, Petersburg social scientist 5.74 +MP Mihael Petrovitch, landowner 5.75 +MQ Masha 2, maid of KI 5.76 +MR Mademoiselle Roland, French governess 5.77 +MS Madame Stahl, invalid philanthropist 5.78 +MT Masha Tchibisova, dancer 5.79 +MV Marya Vlasyevna, midwife 5.80 +MX Masha 1, young relative of BT 5.81 +MY Princess Myakaya, enfant terrible 5.82 +MZ Madame Sviazhskaya, wife of SV 5.83 +NA Princess Natalia Lvova, sister of DO and KI 5.84 +ND Nadinka, niece of LI 5.85 +NI Nikolay Levin, brother of LE 5.86 +NL Nikolinka, son of DO and ST 5.87 +NN Nikitin (Philip Ivanovitch), board member 5.88 +NS Nikolay Shtcherbatsky, cousin of KI 5.89 +NT Nastia, sister of MV 5.90 +NV Madame Nikolaevna, KI's maid of honor 5.91 +NY Nevyedovsky, malignant gentleman 5.92 +PA Parmenitch, old beekeeper 5.93 +PC Prince Tchetchensky, man with two families 5.94 +PD Pyotr Dmitrievitch, doctor 5.95 +PE Pestsov, eccentric enthusiast 5.96 +PH Matrona Marya Philimonovna, nurse 5.97 +PK Prince Kaluzhsky, Petersburg party guest 5.98 +PO Princess Oblonskaya, unmarried aunt of AN 5.99 +PP Prince Pyotr Oblonsky, man of sixty 5.100 +PR Prince Alexander Shtcherbatsky, father of DO and KI 5.101 +PS Princess Shtcherbatskaya, mother of DO and KI 5.102 +PT Lieutenant Petritsky, friend of VR 5.103 +PV Mihail Alexeyevitch Petrov, painter 5.104 +PX Pyotr, servant of AN 5.105 +PY Prohor Yermilin, mower 5.106 +RT Marya Yevgenyevna Rtishtcheva, lady of Moscow 5.107 +RY Mihail Ignatitch Ryabinin, merchant 5.108 +SA Sasha, wife of MI 5.109 +SE Sergey Alexeyevitch Karenin (Seryozha), son of AL and AN 5.110 +SH Baroness Shilton, friend of PT 5.111 +SI Vassily Lukitch Sitnikov, tutor of SE 5.112 +SL Mihail Vassilievitch Sludin, secretary of AL's department 5.113 +SM Stremov, opponent of AL 5.114 +SN Stepan Vassilievitch, landowner 5.115 +SO Princess Sorokina, young friend of CV 5.116 +SP General Serpuhovskoy, rival of VR 5.117 +SQ Snetkow, marshal of Kashinsky province 5.118 +SS Sappho Shtolz, blonde beauty 5.119 +ST Prince Stepan Arkadyevitch Oblonsky (Stiva), brother of AN 5.120 +SU Shuraev, peasant 5.121 +SV Nikolay Ivanovitch Sviazhsky, landowner 5.122 +SY Semyon, contractor to LE 5.123 +TA Tanya, oldest daughter of ST and DO 5.124 +TB Madame Trubetskaya, wedding guest 5.125 +TC Tchirikov, best man of LE 5.126 +TT Tit, mower 5.127 +TU Tushkevitch, croquet player 5.128 +TV Turovtsin, party guest 5.129 +VA Varya, wife of XV 5.130 +VE Venden, mustachioed clerk 5.131 +VF Vassily Fedorovitch, bailiff of LE 5.132 +VG Volgarinoff, Jew 5.133 +VI Pyotr Ilyitch Vinovsky, club friend of ST 5.134 +VK Varvara Andreevna (Varenka), adopted daughter of MS 5.135 +VO Ivan Petrovich Vorkuev, publisher 5.136 +VP Princess Varvara, aunt of ST 5.137 +VR Count Alexey Kirillovitch Vronsky, young officer 5.138 +VS Vaska, admirer of SS 5.139 +VV Vassenka Veslovsky, distant cousin of KI 5.140 +VY Voytov, horse purchaser 5.141 +XV Alexander Vronsky, brother of VR 5.142 +YG Yegor, servant in hotel 5.143 +YK Yegorushka Korsunsky, handsome dancer 5.144 +YS Young Shtcherbatsky, brother of KI 5.145 +YV Captain Yashvin, gambling friend of VR 5.146 + 5.147 +1.1:ST,DO 5.148 +1.2:ST,MR;ST,PH,MA;MA,DO 5.149 +1.3:ST,GR,TA;ST,MA 5.150 +1.4:DO,ST;ST,MA;DO,PH 5.151 +1.5:ST,NN,GV,LE 5.152 +1.6:NA,DO,KE,LE;NA,LV 5.153 +1.7:KO,LE 5.154 +1.8:KO,LE 5.155 +1.9:LE,NS,KI;LE,PS,ST,KI;LE,ML,KI 5.156 +1.10:LE,ST 5.157 +1.11:LE,ST 5.158 +1.12:PR,PS;PS,KI,VR 5.159 +1.13:LE,KI 5.160 +1.14:LE,KI,PS,CN,VR,PR 5.161 +1.15:KI,PS,PR 5.162 +1.16:VR 5.163 +1.17:VR,ST 5.164 +1.18:VR,ST,AN,CV 5.165 +1.19:AN,DO,GR,TA 5.166 +1.20:AN,DO,ST,KI;DO,KI,GR,TA 5.167 +1.21:AN,DO,ST,KI;AN,VR 5.168 +1.22:KI,PS,YK;CB,YK;LI,KV,ST,AN,VR;KI,YK,AN,VR 5.169 +1.23:KI,VR,PS,CN;KI,VR,AN;CN,YK;YK,KI;YK,AN 5.170 +1.24:LE,NI,MN,KR 5.171 +1.25:LE,NI,MN,KR 5.172 +1.26:LE,IG;LE,AG,KZ;LE,VF,SY 5.173 +1.27:LE,AG 5.174 +1.28:AN,DO,ST 5.175 +1.29:AN,ST;AN,AA 5.176 +1.30:VR,AN;AN,AL 5.177 +1.31:VR,AN,AL 5.178 +1.32:SE,AN;LI,AN 5.179 +1.33:AL,AN;AN,SE 5.180 +1.34:PT,SH,KA,VR 5.181 +2.1:KI,PS;PS,PR 5.182 +2.2:DO,PS,PR,KI 5.183 +2.3:DO,KI 5.184 +2.4:BT,AN,VR 5.185 +2.5:VR,BT;PT,KE,VE,VR 5.186 +2.6:BT,MY,VR 5.187 +2.7:BT,MY,VR,AN,AL;AN,LI 5.188 +2.8:AL 5.189 +2.9:AN,AL 5.190 +2.10:AN,AL,BT,VR 5.191 +2.11:VR,AN 5.192 +2.12:LE,NI;LE,AG 5.193 +2.13:LE,VF;LE,IG 5.194 +2.14:ST,LE,AG,KZ 5.195 +2.15:ST,LE 5.196 +2.16:ST,LE,RY 5.197 +2.17:ST,LE,AG 5.198 +2.18:VR 5.199 +2.19:VR,YV 5.200 +2.20:VR,PT,YV 5.201 +2.21:VR,CO 5.202 +2.22:VR,AN 5.203 +2.23:VR,AN 5.204 +2.24:VR,CO,MH;VR,XV;VR,ST;VR,KU 5.205 +2.25:VR,KU,MH;VR,YV 5.206 +2.26:AL,LI;AL,SL 5.207 +2.27:AN,AA;AN,AL,SL;AN,AL,SE 5.208 +2.28:AN,BT,AL;BT,ST 5.209 +2.29:AN,BT,AL 5.210 +2.30:PR,PS,KI,RT;KI,MS,VK;KI,NI,MN 5.211 +2.31:PS,KI,NI;NI,VK,MN;PS,KI,VK 5.212 +2.32:MS,VK;VK,PS,KI,RT 5.213 +2.33:KI,MS,VK;PS,KI;KI,PV,AP 5.214 +2.34:PR,PS,KI;PR,KI,BE;PR,KI,VK,MS;PR,KI,PV,AP 5.215 +2.35:PR,KI,RT,VK,PS 5.216 +3.1:KO,LE 5.217 +3.2:KO,LE,AG 5.218 +3.3:KO,LE;LE,VF 5.219 +3.4:KO,LE;LE,VF;LE,TT 5.220 +3.5:LE,MK,PY 5.221 +3.6:LE,KO,KZ 5.222 +3.7:ST,DO;DO,PH 5.223 +3.8:DO,PH,TA,HO;DO,AO,LL,TA;DO,HO,GR,TA,NL 5.224 +3.9:DO,LE,PH,LL 5.225 +3.10:DO,LE,TA;DO,TA,GR 5.226 +3.11:LE,PA 5.227 +3.12:LE,DO 5.228 +3.13:AL,AN 5.229 +3.14:AL 5.230 +3.15:AN,VR;AN,AA;AN,SE,ME 5.231 +3.16:AN,AA 5.232 +3.17:AN,BT,TU,MX 5.233 +3.18:AN,BT,SS,VS,PK,SM,LM;LM,AN,SM,TU 5.234 +3.19:VR,PT 5.235 +3.20:VR 5.236 +3.21:VR,PT,CD,SP,YV 5.237 +3.22:VR,AN 5.238 +3.23:AL,SM;AL,AN 5.239 +3.24:VF,LE 5.240 +3.25:LE 5.241 +3.26:LE,SV,MZ,NT 5.242 +3.27:LE,SV,MP,SN 5.243 +3.28:LE,SV 5.244 +3.29:LE,VF;LE,IV;LE,FR;LE,SU 5.245 +3.30:LE,VF;LE,AG 5.246 +3.31:LE,NI,AG 5.247 +3.32:LE,NI;LE,NS 5.248 +4.1:AL,AN;AN,VR 5.249 +4.2:AL,VR;VR,AN 5.250 +4.3:VR,AN;AN,LM 5.251 +4.4:AL,AN 5.252 +4.5:AL 5.253 +4.6:AL,SM;BT,MY;AL,ST,DO 5.254 +4.7:ST,MT;ST,LE;ST,CA 5.255 +4.8:AL,ST 5.256 +4.9:ST,KO,PE,PR,YS,TV,KI,AL,DO,LE,MA 5.257 +4.10:PE,KO,AL,ST,TV,PR,DO 5.258 +4.11:LE,KI,DO,TV 5.259 +4.12:PE,ST,AL,KO,TV;AL,DO,YS 5.260 +4.13:LE,PE,KO;LE,KI,YS;LE,KI,PR 5.261 +4.14:LE,ST;LE,DO;KE,KO,SV;LE,YG 5.262 +4.15:ML,LE;LE,KI,PR,PS 5.263 +4.16:PS,PR,KI,LE;KI,LE,ML;LE,KO;LE,SV;KI,CN 5.264 +4.17:AL,KP;AL,VR,AN;AN,BA 5.265 +4.18:VR,KP;VR,VA 5.266 +4.19:AL,BA;AL,SE,ED;AL,AN,BT 5.267 +4.20:AL,AN 5.268 +4.21:BT,ST;ST,AN 5.269 +4.22:ST,AL 5.270 +4.23:VR,VA;VR,BT;VR,AN 5.271 +5.1:PS,LE;LE,KO;LE,ST;LE,KI 5.272 +5.2:LE,KO,KT,TC;LE,KI,PS;KE,KO,SO,ST;LE,KZ 5.273 +5.3:KI,NA;LE,ST,KZ 5.274 +5.4:ST,DO,TC,LE,KI;LE,KI,CN;LE,KI,CA;KI,MD 5.275 +5.5:DO,NA;LK,YK;LK,TB;PR,NV;KO,DO;ST,NA;NA,CN;CN,DO 5.276 +5.6:LE,KI,PR,TC 5.277 +5.7:VR,AN,GO 5.278 +5.8:VR,AN 5.279 +5.9:VR,AN,GO 5.280 +5.10:MI,SA;MI,VR,GO,AN 5.281 +5.11:MI,VR,GO,AN 5.282 +5.12:MI,VR,GO,AN 5.283 +5.13:MI,VR,AN,GO 5.284 +5.14:LE,KI,AG,MQ 5.285 +5.15:KE,KI,KZ 5.286 +5.16:LE,KI,AG 5.287 +5.17:NI,LE,KI;LE,MN,KI 5.288 +5.18:NI,LE,KI,MN 5.289 +5.19:LE,KI 5.290 +5.20:NI,LE,KI,MN 5.291 +5.21:AL,BT,ST;AL,ED;AL,KY;AL,SL 5.292 +5.22:LI,AL,SE;AL,KY 5.293 +5.23:LI 5.294 +5.24:AL,LI 5.295 +5.25:AL,LI 5.296 +5.26:SE,KP;SE,SI;SE,ND 5.297 +5.27:SE,SI;SE,AL 5.298 +5.28:VR,CV,VA;VR,XV,AN;VR,BT,AN 5.299 +5.29:AN,KP;AN,SE 5.300 +5.30:KY,KP;KY,EF;EF,AN,SE,SI,AL 5.301 +5.31:AN,BA;AN,VR,YV 5.302 +5.32:AN,PO,VR,TU;AN,YV,VR,TU 5.303 +5.33:VR,YV;VR,SP;AN,VV,YV;VA,VR,CV,SO;XV,VR;AN,VR,SM 5.304 +6.1:DO,VK,KO,KI;KO,LE,KI,TV,VK;KI,PS 5.305 +6.2:AG,PS,KI,DO,LE 5.306 +6.3:KI,LE,PS 5.307 +6.4:VK,KO 5.308 +6.5:VK,GR,MM,KO,KI,LE 5.309 +6.6:VK,KO,KI,LE,PS,DO,AG;LE,GR,ST,VV;ST,TA;ST,DO;PS,VV;VV,VK;KO,ST 5.310 +6.7:KI,AG;LE,VV,ST,DO,KI;LE,PS,VK 5.311 +6.8:VV,ST,LE;LE,KI 5.312 +6.9:VV,ST,LE 5.313 +6.10:VV,ST,LE 5.314 +6.11:VV,ST,LE 5.315 +6.12:LE 5.316 +6.13:KI,MV;LE,ST,VV 5.317 +6.14:LE,VV,ST,KI,PS,MV,DO;HO,TA 5.318 +6.15:GR,MM;MM,DO,LE;LE,VV;LE,ST;DO,VK 5.319 +6.16:DO,LE 5.320 +6.17:VR,VV,AN,VP,SV,DO 5.321 +6.18:DO,AN,VV,VR 5.322 +6.19:DO,AA,AN;DO,AN,BA 5.323 +6.20:DO,AN,VP,VV,VR,SV,TU 5.324 +6.21:VR,DO 5.325 +6.22:AN,DO,VP,VR,SV,VV,TU 5.326 +6.23:AN,DO 5.327 +6.24:DO,AN;AN,AL 5.328 +6.25:AN,VR 5.329 +6.26:LE,KO;LE,KI 5.330 +6.27:LE,KO,SV,ST 5.331 +6.28:LE,KO;KE,SQ 5.332 +6.29:KO,ST,SV,VR;SV,LE,SN 5.333 +6.30:SV,LE,VR,ST,KO,NY 5.334 +6.31:NY,VR,SV,ST;AN,BA,VP 5.335 +6.32:AN,BA;AN,VP,VR 5.336 +7.1:LE,KI;KI,PR,MB,VR 5.337 +7.2:KE,KI;LE,KZ 5.338 +7.3:LE,KT,MO 5.339 +7.4:LE,LV,NA 5.340 +7.5:LE,NA;PE,LE;LE,BL 5.341 +7.6:LE,BO;LE,SV;LE,ST;LE,NA;LE,KI 5.342 +7.7:LE,PR;YV,VR,LE,ST,TV,GA,VI 5.343 +7.8:LE,ST,VR,GA;LE,PR;VR,YV 5.344 +7.9:LE,ST;AN,VO;LE,AN 5.345 +7.10:LE,AN,VO,ST,HA 5.346 +7.11:LE,ST;LE,KZ;LE,KI 5.347 +7.12:AN,VR 5.348 +7.13:LE,KI;LE,KZ;LE,LP 5.349 +7.14:LE,LP,PS,KI,PD,DO 5.350 +7.15:LE,PD,DO,LP,KI,PS,BD 5.351 +7.16:PR,KO,ST,LE;LE,KI,PS,BD 5.352 +7.17:ST,AL;ST,VG 5.353 +7.18:ST,AL 5.354 +7.19:ST,AL,SE;ST,AL,KY 5.355 +7.20:ST,PC;ST,BN;ST,PP;ST,BT,MY 5.356 +7.21:ST,BN;ST,LI,AL,JL 5.357 +7.22:ST,PP;ST,LI,AL,JL 5.358 +7.23:AN,VR,HA 5.359 +7.24:AN,VR 5.360 +7.25:AN,VR,AA;AN,VR,YV,VY 5.361 +7.26:AN,VR;VR,SO 5.362 +7.27:AN,BA;AN,AA;AN,MC;AN,PX 5.363 +7.28:AN,DO,KI 5.364 +7.29:AN,PX,AA 5.365 +7.30:AN,PX,FC 5.366 +7.31:AN,PX;AN,MC 5.367 +8.1:KO 5.368 +8.2:KO,KT,ST;ST,VR,CV 5.369 +8.3:KO,KT 5.370 +8.4:KO,CV 5.371 +8.5:KO,VR 5.372 +8.6:KO,KV,KI;KI,DO,PR;KI,AG,BD 5.373 +8.7:AG,KI,BD;PR,KT 5.374 +8.8:LE 5.375 +8.9:LE,KO 5.376 +8.10:LE 5.377 +8.11:LE,FY 5.378 +8.12:LE 5.379 +8.13:LE,DO 5.380 +8.14:LE,IW;GR,TA,KV,KO,DO,PR 5.381 +8.15:DO,LE,KT,KO,PR,MJ,GR 5.382 +8.16:LE,KT,KO,PR 5.383 +8.17:DO,LE,KV,GR,TA;KO,PR;LE,AG;LE,KI,BD 5.384 +8.18:LE,KT,KO,KI;LE,KI,BD 5.385 +8.19:LE,KI 5.386 +* End of file "anna.dat"
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/assign_mona.w Mon Oct 03 23:29:42 2011 +0200 6.3 @@ -0,0 +1,692 @@ 6.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 6.5 +\def\title{ASSIGN\_\thinspace MONA} 6.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 6.7 +\def\<#1>{$\langle${\rm#1}$\rangle$} 6.8 +\def\dash{\mathrel-\joinrel\joinrel\mathrel-} % adjacent vertices 6.9 +\def\ddash{=\joinrel\joinrel=} % matched vertices 6.10 + 6.11 +\prerequisite{GB\_\thinspace MONA} 6.12 +@* The assignment problem. 6.13 +This demonstration program takes a matrix 6.14 +constructed by the |gb_mona| module and chooses at most one number from 6.15 +each row and column in such a way as to maximize the sum of the numbers 6.16 +chosen. It also reports the number of ``mems'' (memory references) 6.17 +expended during its computations, so that the algorithm it uses 6.18 +can be compared with alternative procedures. 6.19 + 6.20 +The matrix has $m$ rows and $n$ columns. If $m\le n$, one number will 6.21 +be chosen in each row; if $m\ge n$, one number will be chosen in each column. 6.22 +The numbers in the matrix are brightness levels (i.e., pixel values) in 6.23 +a digitized version of the Mona Lisa. 6.24 + 6.25 +Of course the author does not pretend that the location of ``highlights'' in 6.26 +da Vinci's painting, one per row and one per column, has any application 6.27 +to art appreciation. However, this program does seem to have pedagogic value, 6.28 +because the relation between pixel values and shades of gray allows us 6.29 +to visualize the data underlying this special case of the 6.30 +assignment problem; ordinary matrices of numeric data are much harder 6.31 +to perceive. The non-random nature of pixels 6.32 +in a work of art may also have similarities to the ``organic'' properties 6.33 +of data in real-world applications. 6.34 + 6.35 +This program is optionally able to produce an encapsulated PostScript file 6.36 +from which the solution can be displayed graphically, with halftone shading. 6.37 + 6.38 +@ As explained in |gb_mona|, the subroutine call |mona(m,n,d,m0,m1,n0,n1,d0,d1, 6.39 +area)| constructs an $m\times n$ matrix of integers between $0$ and~$d$, 6.40 +inclusive, based on the brightness levels in a rectangular region of 6.41 +a digitized Mona Lisa, where |m0|, |m1|, |n0|, and |n1| define that 6.42 +region. The raw data is obtained as a sum of |(m1-m0)(n1-n0)| pixel 6.43 +values between $0$ and~$255$, then scaled in such a way that sums |<=d0| 6.44 +are mapped to zero, sums |>=d1| are mapped to~$d$, and intermediate sums are 6.45 +mapped linearly to intermediate values. Default values |m1=360|, |n1=250|, 6.46 +|m=m1-m0|, |n=n1-n0|, |d=255|, and |d1=255(m1-m0)(n1-n0)| are substituted if 6.47 +any of the parameters |m|, |n|, |d|, |m1|, |n1|, or |d1| are zero. 6.48 + 6.49 +The user can specify the nine parameters |(m,n,d,m0,m1,n0,n1,d0,d1)| 6.50 +on the command line, at least in a \UNIX\ implementation, thereby 6.51 +obtaining a variety of special effects; the relevant 6.52 +command-line options are \.{m=}\<number>, \.{m0=}\<number>, and so on, 6.53 +with no spaces before or after the \.= signs that separate parameter 6.54 +names from parameter values. Additional options are also provided: 6.55 +\.{-s} (use only Mona's $16\times32$ ``smile''); 6.56 +\.{-c} (complement black/white); \.{-p} (print the matrix and solution); 6.57 +\.{-P} (produce a PostScript file \.{mona.eps} for graphic output); 6.58 +\.{-h} (use a heuristic that applies only when $m=n$); and 6.59 +\.{-v} or \.{-V} (print verbose or Very verbose commentary about the 6.60 + algorithm's performance). 6.61 +@^UNIX dependencies@> 6.62 + 6.63 +Here is the overall layout of this \Cee\ program: 6.64 + 6.65 +@p 6.66 +#include "gb_graph.h" /* the GraphBase data structures */ 6.67 +#include "gb_mona.h" /* the |mona| routine */ 6.68 +@# 6.69 +@<Global variables@>@; 6.70 +main(argc,argv) 6.71 + int argc; /* the number of command-line arguments */ 6.72 + char *argv[]; /* an array of strings containing those arguments */ 6.73 +{@+@<Local variables@>; 6.74 + @<Scan the command line options@>; 6.75 + mtx=mona(m,n,d,m0,m1,n0,n1,d0,d1,working_storage); 6.76 + if (mtx==NULL) { 6.77 + fprintf(stderr,"Sorry, can't create the matrix! (error code %d)\n", 6.78 + panic_code); 6.79 + return -1; 6.80 + } 6.81 + printf("Assignment problem for %s%s\n",mona_id,(compl?", complemented":"")); 6.82 + sscanf(mona_id,"mona(%u,%u,%lu",&m,&n,&d); /* adjust for defaults */ 6.83 + if (m!=n) heur=0; 6.84 + if (printing) @<Display the input matrix@>; 6.85 + if (PostScript) @<Output the input matrix in PostScript format@>; 6.86 + mems=0; 6.87 + @<Solve the assignment problem@>; 6.88 + if (printing) @<Display the solution@>; 6.89 + if (PostScript) @<Output the solution in PostScript format@>; 6.90 + printf("Solved in %d mems%s.\n",mems, 6.91 + (heur?" with square-matrix heuristic":"")); 6.92 +} 6.93 + 6.94 +@ @f Vertex int /* |gb_graph| defines these data types */ 6.95 +@f Arc int 6.96 +@f Graph int 6.97 +@f Area int 6.98 + 6.99 +@<Glob...@>= 6.100 +Area working_storage; /* where to put the input data and auxiliary arrays */ 6.101 +long *mtx; /* input data for the assignment problem */ 6.102 +long mems; /* the number of memory references counted 6.103 + while solving the problem */ 6.104 + 6.105 +@ The following local variables are related to the command-line options: 6.106 + 6.107 +@<Local v...@>= 6.108 +unsigned m=0,n=0; /* number of rows and columns desired */ 6.109 +unsigned long d=0; /* number of pixel values desired, minus~1 */ 6.110 +unsigned m0=0,m1=0; /* input will be from rows $[|m0|\,.\,.\,|m1|)$ */ 6.111 +unsigned n0=0,n1=0; /* and from columns $[|n0|\,.\,.\,|n1|)$ */ 6.112 +unsigned long d0=0,d1=0; /* lower and upper threshold of raw pixel scores */ 6.113 +int compl=0; /* should the input values be complemented? */ 6.114 +int heur=0; /* should the square-matrix heuristic be used? */ 6.115 +int printing=0; /* should the input matrix and solution be printed? */ 6.116 +int PostScript=0; /* should an encapsulated PostScript file be produced? */ 6.117 + 6.118 +@ @<Scan the command line options@>= 6.119 +while (--argc) { 6.120 +@^UNIX dependencies@> 6.121 + if (sscanf(argv[argc],"m=%u",&m)==1) ; 6.122 + else if (sscanf(argv[argc],"n=%u",&n)==1) ; 6.123 + else if (sscanf(argv[argc],"d=%lu",&d)==1) ; 6.124 + else if (sscanf(argv[argc],"m0=%u",&m0)==1) ; 6.125 + else if (sscanf(argv[argc],"m1=%u",&m1)==1) ; 6.126 + else if (sscanf(argv[argc],"n0=%u",&n0)==1) ; 6.127 + else if (sscanf(argv[argc],"n1=%u",&n1)==1) ; 6.128 + else if (sscanf(argv[argc],"d0=%u",&d0)==1) ; 6.129 + else if (sscanf(argv[argc],"d1=%u",&d1)==1) ; 6.130 + else if (strcmp(argv[argc],"-s")==0) smile; /* sets |m0|, |m1|, |n0|, |n1| */ 6.131 + else if (strcmp(argv[argc],"-c")==0) compl=1; 6.132 + else if (strcmp(argv[argc],"-h")==0) heur=1; 6.133 + else if (strcmp(argv[argc],"-v")==0) verbose=1; 6.134 + else if (strcmp(argv[argc],"-V")==0) verbose=2; /* terrifically verbose */ 6.135 + else if (strcmp(argv[argc],"-p")==0) printing=1; 6.136 + else if (strcmp(argv[argc],"-P")==0) PostScript=1; 6.137 + else { 6.138 + fprintf(stderr, 6.139 + "Usage: %s [param=value] [-s] [-c] [-h] [-v] [-p] [-P]\n",argv[0]); 6.140 + return -2; 6.141 + } 6.142 +} 6.143 + 6.144 +@ @<Display the input matrix@>= 6.145 +for (k=0;k<m;k++) { 6.146 + for (l=0;l<n;l++) printf("% 4d",compl?d-*(mtx+k*n+l):*(mtx+k*n+l)); 6.147 + printf("\n"); 6.148 +} 6.149 + 6.150 +@ We obtain a crude but useful estimate of the computation time 6.151 +by counting mem units, as explained in the |miles_span| program. 6.152 + 6.153 +@d o mems++ 6.154 +@d oo mems+=2 6.155 +@d ooo mems+=3 6.156 + 6.157 +@* Algorithmic overview. The {\it assignment problem\/} is the classical 6.158 +problem of weighted bipartite matching, the problem of choosing 6.159 +a maximum-weight set of disjoint edges in a bipartite graph. We will consider 6.160 +only the case of complete bipartite graphs, when the weights are 6.161 +specified by an $m\times n$ matrix. 6.162 + 6.163 +An algorithm is most easily developed if we begin with the assumption 6.164 +that the matrix is square (i.e., that $m=n$), and if we change from 6.165 +maximization to minimization. Then the assignment problem is the task 6.166 +of finding a permutation $\pi[0]\ldots\pi[n-1]$ of $\{0,\ldots,n-1\}$ 6.167 +such that $\sum_{k=0}^{n-1} a_{k\pi[k]}$ is minimized, where 6.168 +$A=(a_{kl})$ is a given matrix of numbers $a_{kl}$ for $0\le k,l<n$. 6.169 +The algorithm below works for arbitrary real numbers $a_{kl}$, but we 6.170 +will assume in our implementation that the matrix entries are integers. 6.171 + 6.172 +One way to approach the assignment problem is to make three simple 6.173 +observations: (a)~Adding a constant to any row of the matrix does not 6.174 +change the solution $\pi[0]\ldots\pi[n-1]$. (b)~Adding a constant to 6.175 +any column of the matrix does not change the solution. (c)~If $a_{kl}\ge0$ 6.176 +for all $k$ and~$l$, and if $\pi[0]\ldots\pi[n-1]$ is a permutation 6.177 +with the property that $a_{k\pi[k]}=0$ for all~$k$, then $\pi[0]\ldots\pi[n-1]$ 6.178 +solves the assignment problem. 6.179 + 6.180 +The remarkable fact is that these three observations actually suffice. In 6.181 +other words, there is always a sequence of constants $(\sigma_0,\ldots,\sigma_ 6.182 +{n-1})$ and $(\tau_0,\ldots,\tau_{n-1})$ and a permutation $\pi[0]\ldots 6.183 +\pi[n-1]$ such that 6.184 +$$\vbox{\halign{$#$,\hfil&\quad for #\hfil\cr 6.185 +a_{kl}-\sigma_k+\tau_{\,l}\ge0& $0\le k<n$ and $0\le l<n$;\cr 6.186 +a_{k\pi[k]}-\sigma_k+\tau_{\pi[k]}=0& $0\le k<n$.\cr}}$$ 6.187 + 6.188 +@ To prove the remarkable fact just stated, we start by reviewing the 6.189 +theory of {\it unweighted\/} bipartite matching. Any $m\times n$ matrix 6.190 +$A=(a_{kl})$ befines a bipartite graph on the vertices $(r_0,\ldots,r_{m-1})$ 6.191 +and $(c_0,\ldots,c_{n-1})$ if we say that $r_k\dash c_l$ whenever 6.192 +$a_{kl}=0$; in other words, the edges of the bipartite graph are the zeroes 6.193 +of the matrix. Two zeroes of~$A$ are called {\it independent\/} if they appear 6.194 +in different rows and columns; this means that the corresponding edges have 6.195 +no vertices in common. A set of mutually independent zeroes of the matrix 6.196 +therefore corresponds to a set of mutually disjoint edges, also called a 6.197 +{\it matching\/} between rows and columns. 6.198 + 6.199 +The Hungarian mathematicians Egerv\'ary and K\"onig proved 6.200 +[{\sl Matematikai \'es Fizikai Lapok\/ \bf38} (1931), 16--28, 116--119] 6.201 +that the maximum number of independent zeroes in a matrix is equal to 6.202 +the minimum number of rows and/or columns that are needed to ``cover'' 6.203 +every zero. In other words, if we can find $p$ independent zeroes but 6.204 +not~$p+1$, then there is a way to choose $p$ lines in such a way that 6.205 +every zero of the matrix is included in at least one of the chosen lines, 6.206 +where a ``line'' is either a row or a column. 6.207 + 6.208 +Their proof was constructive, and it leads to a useful computer algorithm. 6.209 +Given a set of $p$ independent zeroes of a matrix, let us write 6.210 +$r_k\ddash c_l$ or $c_l\ddash r_k$ and say that $r_k$ is matched with $c_l$ 6.211 +if $a_{kl}$ is one of these $p$ special 6.212 +zeroes, while we continue to write $r_k\dash c_l$ or $c_l\dash r_k$ 6.213 +if $a_{kl}$ is one of the nonspecial zeroes. A given set of $p$ 6.214 +special zeroes defines a choice of $p$ lines in the following way: Column~$c$ 6.215 +is chosen if and only if it is reachable by a path of the form 6.216 +$$r_0\dash c_1\ddash r_1\dash c_2\ddash\cdots\dash c_q\ddash r_q\,,\eqno(*)$$ 6.217 +where $r_0$ is unmatched, $q\ge1$, and $c=c_q$. Row~$r$ is chosen if 6.218 +and only if it is matched with a column that is not chosen. Thus exactly 6.219 +$p$ lines are chosen. We can now prove that the chosen lines cover 6.220 +all the zeroes, unless there is a way to find $p+1$ independent zeroes. 6.221 + 6.222 +For if $c\ddash r$, either $c$ or $r$ has been chosen. And 6.223 +if $c\dash r$, one of the following cases must arise. (1)~If $r$ and~$c$ 6.224 +are both unmatched, we can increase~$p$ by matching them to each other. 6.225 +(2)~If $r$ is unmatched and $c\ddash r'$, then $c$ has been chosen, so 6.226 +the zero has been covered. (3)~If $r$ is matched to $c'\ne c$, then 6.227 +either $r$ has been chosen or $c'$ has been chosen. In the latter case 6.228 +there is a path of the form 6.229 +$$r_0\dash c_1\ddash r_1\dash c_2\ddash\cdots\ddash 6.230 + r_{q-1}\dash c'\ddash r\dash c\,,$$ 6.231 +where $r_0$ is unmatched and $q\ge1$. 6.232 +If $c$ is matched, it has therefore been chosen; otherwise we can increase $p$ 6.233 +by redefining the matching to include 6.234 +$$r_0\ddash c_1\dash r_1\ddash c_2\dash\cdots\dash 6.235 + r_{q-1}\ddash c'\dash r\ddash c\,.$$ 6.236 + 6.237 +@ Now suppose $A$ is a {\it nonnegative\/} matrix. 6.238 +Cover the zeroes of~$A$ with a minimum number of lines, $p$, using the 6.239 +algorithm of Egerv\'ary and K\"onig. If $p<n$, some elements are still 6.240 +uncovered, so those elements are positive; suppose the minimum uncovered 6.241 +value is $\delta>0$. We can subtract $\delta$ from each unchosen row 6.242 +and add $\delta$ to each chosen column; the net effect is to subtract~$\delta$ 6.243 +from all uncovered elements and to add~$\delta$ to all doubly-covered 6.244 +elements, while leaving all singly-covered elements unchanged. This 6.245 +transformation causes a new zero to appear, while preserving 6.246 +$p$ independent zeroes of the previous matrix (since they were each 6.247 +covered only once). If we repeat the Egerv\'ary-K\"onig construction 6.248 +with the same $p$ independent zeroes, we find that either $p$~is no 6.249 +longer maximum or at least one more column has been chosen. 6.250 +(The new zero $r\dash c$ occurs in a row~$r$ that was either unmatched 6.251 +or matched to a previously chosen column, because row~$r$ was not 6.252 +chosen.) Therefore if we repeat the process, we must eventually 6.253 +be able to increase $p$ until finally $p=n$. This will solve the 6.254 +assignment problem, proving the remarkable claim made earlier. 6.255 + 6.256 +@ If the given matrix $A$ has $m$ rows and $n>m$ columns, 6.257 +we can extend it artificially 6.258 +until it is square, by setting $a_{kl}=0$ for all $m\le k<n$ and 6.259 +$0\le l<n$. The construction above will then apply. But we need not 6.260 +waste time making such an extension, because it suffices to run the 6.261 +algorithm on the original $m\times n$ matrix until $m$ independent zeroes 6.262 +have been found. The reason is that the set of matched vertices always 6.263 +grows monotonically in the Egerv\'ary-K\"onig construction: If a 6.264 +column is matched at some stage, it will remain matched from that time on, 6.265 +although it may well change partners. The $n-m$ dummy rows at the bottom 6.266 +of~$A$ are always chosen to be part of the covering; so the dummy entries 6.267 +become nonzero only in the columns that are part of some covering. 6.268 +Such columns are part of some matching, so they are part of the 6.269 +final matching. Therefore at most $m$ columns of the dummy entries 6.270 +become nonzero during the procedure. We can always find $n-m$ independent 6.271 +zeroes in the $n-m$ dummy rows of the matrix, so we need not deal with the 6.272 +dummy elements explicitly. 6.273 + 6.274 +@ It has been convenient to describe the algorithm by saying that 6.275 +we add and subtract constants to and from the colums and rows of~$A$. 6.276 +But all those additions and subtractions can take a lot of time. So we will 6.277 +merely pretend to make the adjustments that the method calls for; we will 6.278 +represent them implicitly by two vectors $(\sigma_0,\ldots,\sigma_{m-1})$ 6.279 +and $(\tau_0,\ldots,\tau_{n-1})$. Then the current value of each matrix 6.280 +entry will be $a_{kl}-\sigma_k+\tau_{\,l}$, instead of $a_{kl}$. The 6.281 +``zeroes'' will be positions such that $a_{kl}=\sigma_k-\tau_{\,l}$. 6.282 + 6.283 +Initially we will set $\tau_{\,l}=0$ for $0\le l<n$ and $\sigma_k= 6.284 +\min\{a_{k0},\ldots,a_{k(n-1)}\}$ for $0\le k<m$. If $m=n$ we can also 6.285 +make sure that there's a zero in every column by subtracting 6.286 +$\min\{a_{0l},\ldots,a_{(n-1)l}\}$ from $a_{kl}$ for all $k$ and~$l$. 6.287 +(This initial adjustment can conveniently be made to the original 6.288 +matrix entries, instead of indirectly via the $\tau$'s.) Users can 6.289 +discover if such a transformation is worthwhile by trying the program 6.290 +both with and without the \.{-h} option. 6.291 + 6.292 +We have been saying a lot of things and proving a bunch of theorems, 6.293 +without writing any code. Let's get back into programming mode 6.294 +by writing the routine that is called into 6.295 +action when the \.{-h} option has been specified: 6.296 + 6.297 +@d aa(k,l) *(mtx+k*n+l) /* a macro to access the matrix elements */ 6.298 + 6.299 +@<Subtract column minima in order to start with lots of zeroes@>= 6.300 +{ 6.301 + for (l=0; l<n; l++) { 6.302 + o,s=aa(0,l); /* the |o| macro counts one mem */ 6.303 + for (k=1;k<n;k++) 6.304 + if (o,aa(k,l)<s) s=aa(k,l); 6.305 + if (s>0) 6.306 + for (k=0;k<n;k++) 6.307 + oo,aa(k,l)-=s; /* |oo| counts two mems */ 6.308 + } 6.309 + if (verbose) printf(" The heuristic has cost %d mems.\n",mems); 6.310 +} 6.311 + 6.312 +@ @<Local var...@>= 6.313 +register int k; /* the current row of interest */ 6.314 +register int l; /* the current column of interest */ 6.315 +register int j; /* another interesting column */ 6.316 +register long s; /* the current matrix element of interest */ 6.317 + 6.318 +@* Algorithmic details. 6.319 +The algorithm sketched above is quite simple, except that we did not 6.320 +discuss how to determine the chosen columns~$c_q$ that 6.321 +are reachable by paths of the stated form $(*)$. It is easy to find 6.322 +all such columns by constructing an unordered forest whose nodes are rows, 6.323 +beginning with all unmatched rows~$r_0$ and adding a row~$r$ 6.324 +for which $c\ddash r$ when $c$ is adjacent to a row already in the forest. 6.325 + 6.326 +Our data structure, which is based on suggestions of Papadimitriou and 6.327 +Steiglitz [{\sl Combinatorial Optimization\/} (Prentice-Hall, 1982), 6.328 +$\mathchar"278$11.1], will use several arrays. If row~$r$ is matched 6.329 +with column~$c$ we will have |matching_col[r]=c| and |matching_row[c]=r|; 6.330 +if row~$r$ is unmatched, |matching_col[r]| will be |-1|, and 6.331 +if column~$c$ is unmatched, |matching_row[c]| will be |-1|. 6.332 +If column~$c$ has a mate and is also reachable in a path of the form $(*)$, 6.333 +we will have $|parent_row|[c]=r'$ for some $r'$ in the forest. Otherwise 6.334 +column~$c$ is not chosen, and we will have |parent_row[c]=-1|. The rows 6.335 +in the current forest will be called |unchosen_row[0]| through 6.336 +|unchosen_row[t-1]|, where |t| is the current total number of nodes. 6.337 + 6.338 +The amount $\sigma_k$ subtracted from row $k$ is called |row_dec[k]|; the 6.339 +amount $\tau_{\,l}$ added to row~$l$ is called |col_inc[l]|. In order to 6.340 +compute the minimum uncovered element efficiently, we maintain a 6.341 +quantity called |slack[l]| representing the minimum uncovered element 6.342 +in each column. More precisely, if column~$l$ is not chosen, 6.343 +|slack[l]| is the minimum of $a_{kl} 6.344 +-\sigma_k+\tau_{\,l}$ for $k\in\{|unchosen_row|[0],\ldots, 6.345 +|unchosen_row|[q-1]\}$, where $q\le t$ is the number of rows in the 6.346 +forest that we have explored so far. We also remember |slack_row[l]|, 6.347 +the number of a row where the stated minimum occurs. 6.348 + 6.349 +Column $l$ is chosen if and only if |parent_row[l]>=0|. We will arrange 6.350 +things so that we also have |slack[l]=0| in every chosen column. 6.351 + 6.352 +@<Local var...@>= 6.353 +int* matching_col; /* the column matching a given row, or $-1$ */ 6.354 +int* matching_row; /* the row matching a given column, or $-1$ */ 6.355 +int* parent_row; /* ancestor of a given column's mate, or $-1$ */ 6.356 +int* unchosen_row; /* node in the forest */ 6.357 +int t; /* total number of nodes in the forest */ 6.358 +int q; /* total number of explored nodes in the forest */ 6.359 +long* row_dec; /* $\sigma_k$, the amount subtracted from a given row */ 6.360 +long* col_inc; /* $\tau_{\,l}$, the amount added to a given column */ 6.361 +long* slack; /* minimum uncovered entry seen in a given column */ 6.362 +int* slack_row; /* where the |slack| in a given column can be found */ 6.363 +int unmatched; /* this many rows have yet to be matched */ 6.364 + 6.365 +@ @<Allocate the intermediate data structures@>= 6.366 +matching_col=gb_alloc_type(m,@[int@],working_storage); 6.367 +matching_row=gb_alloc_type(n,@[int@],working_storage); 6.368 +parent_row=gb_alloc_type(n,@[int@],working_storage); 6.369 +unchosen_row=gb_alloc_type(m,@[int@],working_storage); 6.370 +row_dec=gb_alloc_type(m,@[long@],working_storage); 6.371 +col_inc=gb_alloc_type(n,@[long@],working_storage); 6.372 +slack=gb_alloc_type(n,@[long@],working_storage); 6.373 +slack_row=gb_alloc_type(n,@[int@],working_storage); 6.374 +if (gb_alloc_trouble) { 6.375 + fprintf(stderr,"Sorry, out of memory!\n"); return -3; 6.376 +} 6.377 + 6.378 +@ The algorithm operates in stages, where each stage terminates 6.379 +when we are able to increase the number of matched elements. 6.380 + 6.381 +The first stage is different from the others; it simply goes through 6.382 +the matrix and looks for zeroes, matching as many rows and columns 6.383 +as it can. This stage also initializes table entries that will be 6.384 +useful in later stages. 6.385 + 6.386 +@d INF 0x7fffffff /* infinity (or darn near) */ 6.387 + 6.388 +@<Do the initial stage@>= 6.389 +t=0; /* the forest starts out empty */ 6.390 +for (l=0; l<n; l++) { 6.391 + o,matching_row[l]=-1; 6.392 + o,parent_row[l]=-1; 6.393 + o,col_inc[l]=0; 6.394 + o,slack[l]=INF; 6.395 +} 6.396 +for (k=0; k<m; k++) { 6.397 + o,s=aa(k,0); /* get ready to calculate the minimum entry of row $k$ */ 6.398 + for (l=1; l<n; l++) if (o,aa(k,l)<s) s=aa(k,l); 6.399 + o,row_dec[k]=s; 6.400 + for (l=0; l<n; l++) 6.401 + if ((o,s==aa(k,l)) && (o,matching_row[l]<0)) { 6.402 + o,matching_col[k]=l; 6.403 + o,matching_row[l]=k; 6.404 + if (verbose>1) printf(" matching col %d==row %d\n",l,k); 6.405 + goto row_done; 6.406 + } 6.407 + o,matching_col[k]=-1; 6.408 + if (verbose>1) printf(" node %d: unmatched row %d\n",t,k); 6.409 + o,unchosen_row[t++]=k; 6.410 +row_done:; 6.411 +} 6.412 + 6.413 +@ If a subsequent stage has not succeeded in matching every row, 6.414 +we prepare for a new stage by reinitializing the forest as follows. 6.415 + 6.416 +@<Get ready for another stage@>= 6.417 +t=0; 6.418 +for (l=0; l<n; l++) { 6.419 + o,parent_row[l]=-1; 6.420 + o,slack[l]=INF; 6.421 +} 6.422 +for (k=0; k<m; k++) 6.423 + if (o,matching_col[k]<0) { 6.424 + if (verbose>1) printf(" node %d: unmatched row %d\n",t,k); 6.425 + o,unchosen_row[t++]=k; 6.426 + } 6.427 + 6.428 +@ Here, then, is the algorithm's overall control structure. 6.429 +There are at most $m$ stages, and each stage does $O(mn)$ operations, 6.430 +so the total running time is $O(m^2n)$. 6.431 + 6.432 +@<Do the Hungarian algorithm@>= 6.433 +@<Do the initial stage@>; 6.434 +if (t==0) goto done; 6.435 +unmatched=t; 6.436 +while(1) { 6.437 + if (verbose) printf(" After %d mems I've matched %d rows.\n",mems,m-t); 6.438 + q=0; 6.439 + while(1) { 6.440 + while (q<t) { 6.441 + @<Explore node |q| of the forest; 6.442 + if the matching can be increased, |goto breakthru|@>; 6.443 + q++; 6.444 + } 6.445 + @<Introduce a new zero into the matrix by modifying |row_dec| and |col_inc|; 6.446 + if the matching can be increased, |goto breakthru|@>; 6.447 + } 6.448 +breakthru: @<Update the matching by pairing row $k$ with column $l$@>; 6.449 + if(--unmatched==0) goto done; 6.450 + @<Get ready for another stage@>; 6.451 +} 6.452 +done: @<Doublecheck the solution@>; 6.453 + 6.454 +@ @<Explore node |q| of the forest; 6.455 + if the matching can be increased, |goto breakthru|@>= 6.456 +{ 6.457 + o,k=unchosen_row[q]; 6.458 + o,s=row_dec[k]; 6.459 + for (l=0; l<n; l++) 6.460 + if (o,slack[l]) {@+register long del; 6.461 + oo,del=aa(k,l)-s+col_inc[l]; 6.462 + if (del<slack[l]) { 6.463 + if (del==0) { /* we found a new zero */ 6.464 + if (o,matching_row[l]<0) goto breakthru; 6.465 + o,slack[l]=0; /* this column will now be chosen */ 6.466 + o,parent_row[l]=k; 6.467 + if (verbose>1) printf(" node %d: row %d==col %d--row %d\n", 6.468 + t,matching_row[l],l,k); 6.469 + oo,unchosen_row[t++]=matching_row[l]; 6.470 + } else { 6.471 + o,slack[l]=del; 6.472 + o,slack_row[l]=k; 6.473 + } 6.474 + } 6.475 + } 6.476 +} 6.477 + 6.478 +@ At this point, column $l$ is unmatched, and row $k$ is in 6.479 +the forest. By following parent links in the forest, 6.480 +we can rematch rows and columns so that a previously unmatched row~$r_0$ 6.481 +gets a mate. 6.482 + 6.483 +@<Update the matching by pairing row $k$ with column $l$@>= 6.484 +if (verbose) printf(" Breakthrough at node %d of %d!\n",q,t); 6.485 +while (1) { 6.486 + o,j=matching_col[k]; 6.487 + o,matching_col[k]=l; 6.488 + o,matching_row[l]=k; 6.489 + if (verbose>1) printf(" rematching col %d==row %d\n",l,k); 6.490 + if (j<0) break; 6.491 + o,k=parent_row[j]; 6.492 + l=j; 6.493 +} 6.494 + 6.495 +@ If we get to this point, we have explored the entire forest; none of 6.496 +the unchosen rows has led to a breakthrough. An unchosen column with 6.497 +smallest |slack| will allow us to make further progress. 6.498 + 6.499 +@<Introduce a new zero into the matrix by modifying |row_dec| and |col_inc|; 6.500 + if the matching can be increased, |goto breakthru|@>= 6.501 +s=INF; 6.502 +for (l=0; l<n; l++) 6.503 + if (o,slack[l] && slack[l]<s) 6.504 + s=slack[l]; 6.505 +for (q=0; q<t; q++) 6.506 + ooo,row_dec[unchosen_row[q]]+=s; 6.507 +for (l=0; l<n; l++) 6.508 + if (o,slack[l]) { /* column $l$ is not chosen */ 6.509 + o,slack[l]-=s; 6.510 + if (slack[l]==0) @<Look at a new zero, and |goto breakthru| with 6.511 + |col_inc| up to date if there's a breakthrough@>; 6.512 + } else oo,col_inc[l]+=s; 6.513 + 6.514 +@ There may be several columns tied for smallest slack. If any of them 6.515 +leads to a breakthough, we are very happy; but we must finish the loop on~|l| 6.516 +before going to |breakthru|, because the |col_inc| variables 6.517 +need to be maintained for the next stage. 6.518 + 6.519 +Within column |l|, there may be several rows that produce the same slack; 6.520 +we have remembered only one of them, |slack_row[l]|. Fortunately, one is 6.521 +sufficient for our purposes. We either have a breakthrough, or we choose 6.522 +column~|l|, regardless of which row or rows led us to consider that column. 6.523 + 6.524 +@<Look at a new zero, and |goto breakthru| with 6.525 + |col_inc| up to date if there's a breakthrough@>= 6.526 +{ 6.527 + o,k=slack_row[l]; 6.528 + if (verbose>1) 6.529 + printf(" Decreasing uncovered elements by %d produces zero at [%d,%d]\n", 6.530 + s,k,l); 6.531 + if (o,matching_row[l]<0) { 6.532 + for (j=l+1; j<n; j++) 6.533 + if (o,slack[j]==0) oo,col_inc[j]+=s; 6.534 + goto breakthru; 6.535 + } else { /* not a breakthrough, but the forest continues to grow */ 6.536 + o,parent_row[l]=k; 6.537 + if (verbose>1) printf(" node %d: row %d==col %d--row %d\n", 6.538 + t,matching_row[l],l,k); 6.539 + oo,unchosen_row[t++]=matching_row[l]; 6.540 + } 6.541 +} 6.542 + 6.543 +@ The code in the present section is redundant, unless cosmic 6.544 +radiation has cause the hardware to malfunction. But there is some 6.545 +reassurance whenever we find that mathematics still appears to be 6.546 +consistent, so the author could not resist writing these few unnecessary lines, 6.547 +which verify that the assignment problem has indeed been solved optimally. 6.548 +(We don't count the mems.) 6.549 + 6.550 +@<Doublecheck...@>= 6.551 +for (k=0;k<m;k++) 6.552 + for (l=0;l<n;l++) 6.553 + if (aa(k,l)<row_dec[k]-col_inc[l]) { 6.554 + fprintf(stderr,"Oops, I made a mistake!\n"); 6.555 + return -6; /* can't happen */ 6.556 + } 6.557 +for (k=0;k<m;k++) { 6.558 + l=matching_col[k]; 6.559 + if (l<0 || aa(k,l)!=row_dec[k]-col_inc[l]) { 6.560 + fprintf(stderr,"Oops, I blew it!\n"); return-66; /* can't happen */ 6.561 + } 6.562 +} 6.563 +k=0; 6.564 +for (l=0;l<n;l++) if (col_inc[l]) k++; 6.565 +if (k>m) { 6.566 + fprintf(stderr,"Oops, I adjusted too many columns!\n"); 6.567 + return-666; /* can't happen */ 6.568 +} 6.569 + 6.570 +@* Interfacing. 6.571 +A few nitty-gritty details still need to be handled: Our algorithm 6.572 +is not symmetric between rows and columns, and it works only for $m\le n$; 6.573 +so we will transpose the matrix when 6.574 +$m>n$. Furthermore, our algorithm minimizes, but we actually want 6.575 +it to maximize (except when |compl| is nonzero). 6.576 + 6.577 +Hence, we want to make the following transformations to the data before 6.578 +processing it with the algorithm developed above. 6.579 + 6.580 +@<Solve the assignment problem@>= 6.581 +if (m>n) @<Transpose the matrix@>@; 6.582 +else transposed=0; 6.583 +@<Allocate the intermediate data structures@>; 6.584 +if (compl==0) 6.585 + for (k=0; k<m; k++) for (l=0; l<n; l++) 6.586 + aa(k,l)=d-aa(k,l); 6.587 +if (heur) @<Subtract column minima...@>; 6.588 +@<Do the Hungarian algorithm@>; 6.589 + 6.590 +@ @<Transpose...@>= 6.591 +{ 6.592 + if (verbose>1) printf("Temporarily transposing rows and columns...\n"); 6.593 + tmtx=gb_alloc_type(m*n,@[long@],working_storage); 6.594 + if (tmtx==NULL) { 6.595 + fprintf(stderr,"Sorry, out of memory!\n"); return -4; 6.596 + } 6.597 + for (k=0; k<m; k++) for (l=0; l<n; l++) 6.598 + *(tmtx+l*m+k)=*(mtx+k*n+l); 6.599 + m=n;@+n=k; /* |k| holds the former value of |m| */ 6.600 + mtx=tmtx; 6.601 + transposed=1; 6.602 +} 6.603 + 6.604 +@ @<Local v...@>= 6.605 +long* tmtx; /* the transpose of |mtx| */ 6.606 +int transposed; /* has the data been transposed? */ 6.607 + 6.608 +@ @<Display the solution@>= 6.609 +{ 6.610 + printf("The following entries produce an optimum assignment:\n"); 6.611 + for (k=0; k<m; k++) 6.612 + printf(" [%d,%d]\n",@| 6.613 + transposed? matching_col[k]:k,@| 6.614 + transposed? k:matching_col[k]); 6.615 +} 6.616 + 6.617 +@* Encapsulated PostScript. 6.618 +A special output file called \.{mona.eps} is written if the user has 6.619 +selected the \.{-P} option. This file will contain a sequence of 6.620 +PostScript commands that can be used to generate an illustration 6.621 +within many kinds of documents. For example, if \TeX\ is being used 6.622 +with the \.{dvips} output driver from Radical Eye Software and the 6.623 +@.dvips@> 6.624 +associated \.{epsf.tex} macros, one can say 6.625 +$$\.{\\epsfxsize=10cm \\epsfbox\{mona.eps\}}$$ 6.626 +within a \TeX\ document and the illustration will be typeset in 6.627 +a box that is 10 centimeters wide. 6.628 + 6.629 +The conventions of PostScript allow the illustration to be scaled to 6.630 +any size. Best results are probably obtained if each pixel is at 6.631 +least one millimeter wide (about 1/25 inch) when printed. 6.632 + 6.633 +The illustration is formed by first 6.634 +``painting'' the input data as a rectangle of pixels, 6.635 +with up to 256 shades of gray. Then the solution pixels are 6.636 +framed in black, with a white trim just inside the black edges 6.637 +to help make the frame visible in already-dark places. The frames are 6.638 +created by painting over the original image; the 6.639 +center of each solution pixel retains its original color. 6.640 + 6.641 +Encapsulated PostScript files have a simple format that is recognized 6.642 +by many software packages and printing devices. We use a subset of 6.643 +PostScript that should be easy to convert to other languages if necessary. 6.644 + 6.645 +@<Output the input matrix in PostScript format@>= 6.646 +{ 6.647 + eps_file=fopen("mona.eps","w"); 6.648 + if (!eps_file) { 6.649 + fprintf("Sorry, I can't open the file `mona.eps'!\n"); 6.650 + PostScript=0; 6.651 + } else { 6.652 + fprintf(eps_file,"%%!PS-Adobe-3.0 EPSF-3.0\n"); /* 1.0 and 2.0 also OK */ 6.653 + fprintf(eps_file,"%%%%BoundingBox: -1 -1 %d %d\n",n+1,m+1); 6.654 + fprintf(eps_file,"/buffer %d string def\n",n); 6.655 + fprintf(eps_file,"%d %d 8 [%d 0 0 -%d 0 %d]\n",n,m,n,m,m); 6.656 + fprintf(eps_file,"{currentfile buffer readhexstring pop} bind\n"); 6.657 + fprintf(eps_file,"gsave %d %d scale image\n",n,m); 6.658 + for (k=0;k<m;k++) @<Output row |k| as a hexadecimal string@>; 6.659 + fprintf(eps_file,"grestore\n"); 6.660 + } 6.661 +} 6.662 + 6.663 +@ @<Glob...@>= 6.664 +FILE *eps_file; /* file for encapsulated PostScript output */ 6.665 + 6.666 +@ This program need not produce machine-independent output, so we may 6.667 +safely use floating-point arithmetic here. At most 64 characters 6.668 +(32 pixel-bytes) are output on each line. 6.669 + 6.670 +@<Output row |k|...@>= 6.671 +{@+register float conv=255.0/(float)d; register int x; 6.672 + for (l=0; l<n; l++) { 6.673 + x=(int)(conv*(float)(compl?d-aa(k,l):aa(k,l))); 6.674 + fprintf(eps_file,"%02x",x>255?255:x); 6.675 + if ((l&0x1f)==0x1f) fprintf(eps_file,"\n"); 6.676 + } 6.677 + if (n&0x1f) fprintf(eps_file,"\n"); 6.678 +} 6.679 + 6.680 +@ @<Output the solution in PostScript format@>= 6.681 +{ 6.682 + fprintf(eps_file, 6.683 + "/bx {moveto 0 1 rlineto 1 0 rlineto 0 -1 rlineto closepath\n"); 6.684 + fprintf(eps_file," gsave .3 setlinewidth 1 setgray clip stroke"); 6.685 + fprintf(eps_file," grestore stroke} bind def\n"); 6.686 + fprintf(eps_file," .1 setlinewidth\n"); 6.687 + for (k=0; k<m; k++) 6.688 + fprintf(eps_file," %d %d bx\n",@| 6.689 + transposed? k:matching_col[k],@| 6.690 + transposed? n-1-matching_col[k]:m-1-k); 6.691 + fclose(eps_file); 6.692 +} 6.693 + 6.694 +@* Index. As usual, we close with a list of identifier definitions and uses. 6.695 +
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/boilerplate.w Mon Oct 03 23:29:42 2011 +0200 7.3 @@ -0,0 +1,38 @@ 7.4 +% This material goes at the beginning of all Stanford GraphBase CWEB files 7.5 + 7.6 +\def\topofcontents{ 7.7 + \leftline{\sc\today\ at \hours}\bigskip\bigskip 7.8 + \centerline{\titlefont\title}} 7.9 + 7.10 +\font\ninett=cmtt9 7.11 +\def\botofcontents{\vskip 0pt plus 1filll 7.12 + \ninerm\baselineskip10pt 7.13 + \noindent\copyright\ 1992 Stanford University 7.14 + \bigskip\noindent 7.15 + This file may be freely copied and distributed, provided that 7.16 + no changes whatsoever are made. All users are asked to help keep 7.17 + the Stanford GraphBase files consistent and ``uncorrupted,'' 7.18 + identical everywhere in the world. Changes are permissible only 7.19 + if the modified file is given a new name, different from the names of 7.20 + existing files in the Stanford GraphBase, and only if the modified file is 7.21 + clearly identified as not being part of that GraphBase. 7.22 + (The {\ninett CWEB} system has a ``change file'' facility by 7.23 + which users can easily make minor alterations without modifying 7.24 + the master source files in any way. Everybody is supposed to use 7.25 + change files instead of changing the files.) 7.26 + The author has tried his best to produce correct and useful programs, 7.27 + in order to help promote computer science research, 7.28 + but no warranty of any kind should be assumed. 7.29 + \smallskip\noindent 7.30 + Preliminary work on the Stanford GraphBase project 7.31 + was supported in part by National Science 7.32 + Foundation grant CCR-86-10181.} 7.33 + 7.34 +\def\prerequisite#1{\def\startsection{\noindent 7.35 + Important: Before reading {\sc\title}, 7.36 + please read or at least skim the program for {\sc#1}.\bigskip 7.37 + \let\startsection=\stsec\stsec}} 7.38 +\def\prerequisites#1#2{\def\startsection{\noindent 7.39 + Important: Before reading {\sc\title}, please read 7.40 + or at least skim the programs for {\sc#1} and {\sc#2}.\bigskip 7.41 + \let\startsection=\stsec\stsec}}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/book_components.w Mon Oct 03 23:29:42 2011 +0200 8.3 @@ -0,0 +1,486 @@ 8.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 8.5 +\def\title{BOOK\_\kern.05emCOMPONENTS} 8.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 8.7 +\def\<#1>{$\langle${\rm#1}$\rangle$} 8.8 + 8.9 +\prerequisite{GB\_\thinspace BOOKS} 8.10 +@* Bicomponents. This demonstration program computes the 8.11 +biconnected components of GraphBase graphs derived from world literature, 8.12 +using a variant of Hopcroft and Tarjan's algorithm [R. E. Tarjan, ``Depth-first 8.13 +search and linear graph algorithms,'' {\sl SIAM Journal on Computing\/ 8.14 +\bf1} (1972), 146--160]. Articulation points and ordinary (connected) 8.15 +components are also obtained as byproducts of the computation. 8.16 + 8.17 +Two edges belong to the same biconnected component---or ``bicomponent'' 8.18 +for short---if and only if they are identical or both belong to a 8.19 +simple cycle. This defines an equivalence relation on edges. 8.20 +The bicomponents of a connected graph with more than one vertex form a 8.21 +free tree, if we say that two bicomponents are adjacent when they have 8.22 +a common vertex (i.e., when there is a vertex belonging to at least one edge 8.23 +in each of the bicomponents). Such a vertex is called an articulation 8.24 +point; there is a unique articulation point between any two adjacent 8.25 +bicomponents. If we choose one bicomponent to be the ``root'' of the 8.26 +free tree, the other bicomponents can be represented conveniently as 8.27 +lists of vertices, with the articulation point that leads toward the root 8.28 +listed last. This program displays the bicomponents in exactly that way. 8.29 + 8.30 +@ We permit command-line options in typical \UNIX\ style so that a variety of 8.31 +graphs can be studied: The user can say `\.{-t}\<title>', 8.32 +`\.{-n}\<number>', `\.{-x}\<number>', `\.{-f}\<number>', 8.33 +`\.{-l}\<number>', `\.{-i}\<number>', `\.{-o}\<number>', and/or 8.34 +`\.{-s}\<number>' to change the default values of the parameters in 8.35 +the graph generated by |book(t,n,x,f,l,i,o,s)|. 8.36 + 8.37 +When the bicomponents are listed, each character in the book is identified by 8.38 +a two-letter code, as found in the associated data file. 8.39 +An explanation of these codes will appear first if the \.{-v} or \.{-V} option 8.40 +is specified. The \.{-V} option prints a fuller explanation than~\.{-v}; it 8.41 +also shows each character's weighted number of appearances. 8.42 + 8.43 +@^UNIX dependencies@> 8.44 + 8.45 +@p 8.46 +#include "gb_graph.h" /* the GraphBase data structures */ 8.47 +#include "gb_books.h" /* the |book| routine */ 8.48 +#include "gb_io.h" /* the |imap_chr| routine */ 8.49 +@# 8.50 +@<Global variables@>; 8.51 +@<Subroutines@>; 8.52 +main(argc,argv) 8.53 + int argc; /* the number of command-line arguments */ 8.54 + char *argv[]; /* an array of strings containing those arguments */ 8.55 +{@+Graph *g; /* the graph we will work on */ 8.56 + register Vertex *v; /* the current vertex of interest */ 8.57 + char *t="anna"; /* the book to use */ 8.58 + unsigned n=0; /* the desired number of vertices (0 means infinity) */ 8.59 + unsigned x=0; /* the number of major characters to exclude */ 8.60 + unsigned f=0; /* the first chapter to include */ 8.61 + unsigned l=0; /* the last chapter to include (0 means infinity) */ 8.62 + long i=1; /* the weight for appearances in selected chapters */ 8.63 + long o=1; /* the weight for appearances in unselected chapters */ 8.64 + long s=0; /* the random number seed */ 8.65 + @<Scan the command line options@>; 8.66 + g=book(t,n,x,f,l,i,o,s); 8.67 + if (g==NULL) { 8.68 + fprintf(stderr,"Sorry, can't create the graph! (error code %d)\n", 8.69 + panic_code); 8.70 + return -1; 8.71 + } 8.72 + printf("Biconnectivity analysis of %s\n\n",g->id); 8.73 + if (verbose) @<Print the cast of selected characters@>; 8.74 + @<Perform the Hopcroft-Tarjan algorithm on |g|@>; 8.75 +} 8.76 + 8.77 +@ @<Scan the command line options@>= 8.78 +while (--argc) { 8.79 +@^UNIX dependencies@> 8.80 + if (strncmp(argv[argc],"-t",2)==0) t=argv[argc]+2; 8.81 + else if (sscanf(argv[argc],"-n%u",&n)==1) ; 8.82 + else if (sscanf(argv[argc],"-x%u",&x)==1) ; 8.83 + else if (sscanf(argv[argc],"-f%u",&f)==1) ; 8.84 + else if (sscanf(argv[argc],"-l%u",&l)==1) ; 8.85 + else if (sscanf(argv[argc],"-i%ld",&i)==1) ; 8.86 + else if (sscanf(argv[argc],"-o%ld",&o)==1) ; 8.87 + else if (sscanf(argv[argc],"-s%ld",&s)==1) ; 8.88 + else if (strcmp(argv[argc],"-v")==0) verbose=1; 8.89 + else if (strcmp(argv[argc],"-V")==0) verbose=2; 8.90 + else { 8.91 + fprintf(stderr,"Usage: %s [-ttitle][-xN][-fN][-lN][-iN][-oN][-sN][-v]\n", 8.92 + argv[0]); 8.93 + return -2; 8.94 + } 8.95 +} 8.96 + 8.97 +@ @f Vertex int /* |gb_graph| defines these data types */ 8.98 +@f Arc int 8.99 +@f Graph int 8.100 + 8.101 +@<Subroutines@>= 8.102 +char code_name[3][3]; 8.103 +char *vertex_name(v,i) /* return (as a string) the name of vertex |v| */ 8.104 + Vertex *v; 8.105 + int i; /* |i| should be 0, 1, or 2 to avoid clash in |code_name| array */ 8.106 +{ 8.107 + code_name[i][0]=imap_chr(v->short_code/36); 8.108 + code_name[i][1]=imap_chr(v->short_code%36); 8.109 + return code_name[i]; 8.110 +} 8.111 + 8.112 +@ @<Print the cast of selected characters@>= 8.113 +{ 8.114 + for (v=g->vertices;v<g->vertices+g->n;v++) { 8.115 + if (verbose==1) printf("%s=%s\n",vertex_name(v,0),v->name); 8.116 + else printf("%s=%s,%s [weight %d]\n",vertex_name(v,0),v->name,v->desc,@| 8.117 + i*v->in_count+o*v->out_count); 8.118 + } 8.119 + printf("\n"); 8.120 +} 8.121 + 8.122 +@*The algorithm. 8.123 +The Hopcroft-Tarjan algorithm is inherently recursive. We will 8.124 +implement the recursion explicitly via linked lists, instead of using 8.125 +\Cee's runtime stack, because some computer systems bog down in the 8.126 +presence of deeply nested recursion. 8.127 + 8.128 +Each vertex goes through three stages during the algorithm. First it is 8.129 +`unseen'; then it is `active'; finally it becomes `settled', when it 8.130 +has been assigned to a bicomponent. 8.131 + 8.132 +The data structures that represent the current state of the algorithm 8.133 +are implemented by using five of the utility fields in each vertex: 8.134 +|rank|, |parent|, |untagged|, |link|, and |min|. We will describe each of 8.135 +these in turn. 8.136 + 8.137 +@ First is the integer |rank| field, which is zero when a vertex is unseen. 8.138 +As soon as the vertex is first examined, it becomes active and its |rank| 8.139 +becomes and remains nonzero. Indeed, the |k|th vertex to become active 8.140 +will receive rank~|k|. 8.141 + 8.142 +It's convenient to think of the Hopcroft-Tarjan algorithm as a simple adventure 8.143 +game, in which we want to explore all rooms of a cave. Passageways between 8.144 +the rooms allow two-way travel. When we come 8.145 +into a room for the first time, we assign a new number to that room; 8.146 +this is its rank. Later on we may happen to come into the same room 8.147 +again, and we will notice that it has nonzero rank; then we'll be able 8.148 +to make a quick exit, saying ``we've already been here.'' (The extra 8.149 +complexities of computer games, like dragons that might need to be 8.150 +vanquished, do not arise.) 8.151 + 8.152 +@d rank z.i /* the |rank| of a vertex is stored in utility field |z| */ 8.153 + 8.154 +@<Glob...@>= 8.155 +int nn; /* the number of vertices that have been seen */ 8.156 + 8.157 +@ The active vertices will always form an oriented tree, whose arcs are 8.158 +a subset of the arcs in the original graph. A tree arc from |u| to~|v| 8.159 +will be represented by |v->parent==u|. Every active vertex has a 8.160 +parent, which is usually another active vertex; the only exception is 8.161 +the root of the tree, whose |parent| is a dummy vertex called |dummy|. 8.162 +The dummy vertex has rank zero. 8.163 + 8.164 +In the cave analogy, the `parent' of room |v| is the room we were in 8.165 +immediately before entering |v| the first time. By following parent 8.166 +pointers, we will be able to leave the cave whenever we want. 8.167 + 8.168 +@d parent y.v /* the |parent| of a vertex is stored in utility field |y| */ 8.169 + 8.170 +@<Glob...@>= 8.171 +Vertex dummy; /* imaginary parent of the root vertex */ 8.172 + 8.173 +@ All edges in the original undirected graph are explored systematically during 8.174 +a depth-first search. Whenever we look at an edge, we `tag' it so that 8.175 +we won't need to explore it again. In a cave, for example, we might 8.176 +mark each passageway between rooms once we've tried to go through it. 8.177 + 8.178 +In a GraphBase graph, undirected edges are represented as a pair of directed 8.179 +arcs. Each of these arcs will be examined and eventually tagged. 8.180 + 8.181 +The algorithm doesn't actually place a tag on its |Arc| records; instead, 8.182 +each vertex |v| has a pointer |v->untagged| that leads to all 8.183 +hitherto-unexplored arcs from~|v|. The arcs of the list that appear 8.184 +between |v->arcs| and |v->untagged| are the ones already examined. 8.185 + 8.186 +@d untagged x.a /* the |untagged| field points to an |Arc| record, or |NULL| */ 8.187 + 8.188 +@ The algorithm maintains a special stack, the |active_stack|, which contains 8.189 +all the currently active vertices. Each vertex has a |link| field that points 8.190 +to the vertex next lower on its stack, or to |NULL| if the vertex is 8.191 +at the bottom. The vertices on |active_stack| always appear in increasing 8.192 +order of rank from bottom to top. 8.193 + 8.194 +@d link w.v /* the |link| field of a vertex occupies utility field |w| */ 8.195 + 8.196 +@<Glob...@>= 8.197 +Vertex * active_stack; /* the top of the stack of active vertices */ 8.198 + 8.199 +@ Finally there's a |min| field, which is the tricky part that makes 8.200 +everything work. If vertex~|v| is unseen or settled, its |min| field is 8.201 +irrelevant. Otherwise |v->min| points to the active vertex~|u| 8.202 +of smallest rank having the property that 8.203 +there is a directed path from |v| to |u| consisting of 8.204 +zero or more `mature' tree arcs followed by a single non-tree arc. 8.205 + 8.206 +What is a tree arc, you ask. And what is a mature arc? Good questions. At the 8.207 +moment when arcs of the graph are tagged, we classify them either as tree 8.208 +arcs (if they correspond to a new |parent| link in the tree of active 8.209 +nodes) or non-tree arcs (otherwise). The tree arcs therefore correspond to 8.210 +passageways that have led us to new territory. A tree arc becomes mature 8.211 +when it is no longer on the path from the root to the current vertex being 8.212 +explored. We also say that a vertex becomes mature when it is 8.213 +no longer on that path. All arcs from a mature vertex have been tagged. 8.214 + 8.215 +We said before that every vertex is initially unseen, then active, and 8.216 +finally settled. With our new definitions, we see further that every arc starts 8.217 +out untagged, then it becomes either a non-tree arc or a tree arc. In the 8.218 +latter case it begins as an immature tree arc and eventually matures. 8.219 + 8.220 +The dummy vertex is considered to be active, and we assume that 8.221 +there is a non-tree arc from the root vertex back to |dummy|. Thus, 8.222 +there is a non-tree arc from |v| to |v->parent| for all~|v|, and |v->min| 8.223 +will always point to a vertex whose rank is less than or equal to 8.224 +|v->parent->rank|. It will turn out that |v->min| is always an ancestor 8.225 +of~|v|. 8.226 + 8.227 +Just believe these definitions, for now. All will become clear soon. 8.228 + 8.229 +@d min v.v /* the |min| field of a vertex occupies utility field |v| */ 8.230 + 8.231 +@ Depth-first search explores a graph by systematically visiting all 8.232 +vertices and seeing what they can lead to. In the Hopcroft-Tarjan algorithm, as 8.233 +we have said, the active vertices form an oriented tree. One of these 8.234 +vertices is called the current vertex. 8.235 + 8.236 +If the current vertex still has an arc that hasn't been tagged, we 8.237 +tag one such arc and there are two cases: Either the arc leads to 8.238 +an unseen vertex, or it doesn't. If it does, the arc becomes a tree 8.239 +arc; the previously unseen vertex becomes active, and it becomes the 8.240 +new current vertex. On the other hand if the arc leads to a vertex 8.241 +that has already been seen, the arc becomes a non-tree arc and the 8.242 +current vertex doesn't change. 8.243 + 8.244 +Finally there will come a time when the current vertex~|v| has no 8.245 +untagged arcs. At this point, the 8.246 +algorithm might decide that |v| and all its descendants 8.247 +form a bicomponent, together with |v->parent|. 8.248 + Indeed, this condition turns out to be true if and only if 8.249 +|v->min==v->parent|; a proof appears below. If so, |v| and all its descendants 8.250 +become settled, and they leave the tree. If not, the tree arc from 8.251 +|v|'s parent~|u| to~|v| becomes mature, so the value of |v->min| is 8.252 +used to update the value of |u->min|. In both cases |v| becomes mature, 8.253 +and the new current vertex will be the parent of~|v|. Notice that only the 8.254 +value of |u->min| needs to be updated, when the arc from |u| to~|v| 8.255 +matures; all other values |w->min| stay the same, because a newly 8.256 +mature arc has no mature predecessors. 8.257 + 8.258 +In the cave analogy, a room |v| and its descendants will become a 8.259 +bicomponent together with the room~|u| from which we entered~|v| 8.260 +when there's no outlet from the subcave starting at~|v| 8.261 +without coming back through |u| itself. Once such a bicomponent 8.262 +is identified, we close it off and don't explore that subcave any further. 8.263 + 8.264 +If |v| is the root of the tree, it always has |v->min==dummy|, so it 8.265 +will always define a new bicomponent at the moment it matures. Then 8.266 +the depth-first search will terminate, since |v|~has no real parent. 8.267 +But the Hopcroft-Tarjan algorithm will press on, trying to find a 8.268 +vertex~|u| that is still unseen. If such a vertex exists, a 8.269 +new depth-first search will begin with |u| as the root. This process 8.270 +keeps on going until at last all vertices are happily settled. 8.271 + 8.272 +The beauty of this algorithm is that it all works very efficiently 8.273 +when we organize it as follows: 8.274 + 8.275 +@<Perform the Hopcroft-Tarjan algorithm on |g|@>= 8.276 +@<Make all vertices unseen and all arcs untagged@>; 8.277 +for (vv=g->vertices; vv<g->vertices+g->n; vv++) 8.278 + if (vv->rank==0) /* |vv| is still unseen */ 8.279 + @<Perform a depth-first search with |vv| as the root, finding the 8.280 + bicomponents of all unseen vertices reachable from~|vv|@>; 8.281 + 8.282 +@ @<Glob...@>= 8.283 +Vertex *vv; /* sweeps over all vertices, making sure none is left unseen */ 8.284 + 8.285 +@ It's easy to get the data structures started, according to the 8.286 +conventions stipulated above. 8.287 + 8.288 +@<Make all vertices unseen...@>= 8.289 +for (v=g->vertices; v<g->vertices+g->n; v++) { 8.290 + v->rank=0; 8.291 + v->untagged=v->arcs; 8.292 +} 8.293 +nn=0; 8.294 +active_stack=NULL; 8.295 +dummy.rank=0; 8.296 + 8.297 +@ The task of starting a depth-first search isn't too bad either. Throughout 8.298 +this part of the algorithm, variable~|v| will point to the current vertex. 8.299 + 8.300 +@<Perform a depth-first search with |vv| as the root...@>= 8.301 +{ 8.302 + v=vv; 8.303 + v->parent=&dummy; 8.304 + @<Make vertex |v| active@>; 8.305 + do @<Explore one step from the current vertex~|v|, possibly moving 8.306 + to another current vertex and calling~it~|v|@>@; 8.307 + while (v!=&dummy); 8.308 +} 8.309 + 8.310 +@ @<Make vertex |v| active@>= 8.311 +v->rank=++nn; 8.312 +v->link=active_stack; 8.313 +active_stack=v; 8.314 +v->min=v->parent; 8.315 + 8.316 +@ Now things get interesting. But we're just doing what any well-organized 8.317 +spelunker would do when calmly exploring a cave. 8.318 +There are three main cases, 8.319 +depending on whether the current vertex stays where it is, moves 8.320 +to a new child, or backtracks to a parent. 8.321 + 8.322 +@<Explore one step from the current vertex~|v|, possibly moving 8.323 + to another current vertex and calling~it~|v|@>= 8.324 +{@+register Vertex *u; /* a vertex adjacent to |v| */ 8.325 + register Arc *a=v->untagged; /* |v|'s first remaining untagged arc, if any */ 8.326 + if (a) { 8.327 + u=a->tip; 8.328 + v->untagged = a->next; /* tag the arc from |v| to |u| */ 8.329 + if (u->rank) { /* we've seen |u| already */ 8.330 + if (u->rank < v->min->rank) 8.331 + v->min=u; /* non-tree arc, just update |v->min| */ 8.332 + } else { /* |u| is presently unseen */ 8.333 + u->parent = v; /* the arc from |v| to |u| is a new tree arc */ 8.334 + v = u; /* |u| will now be the current vertex */ 8.335 + @<Make vertex |v| active@>; 8.336 + } 8.337 + } else { /* all arcs from |v| are tagged, so |v| matures */ 8.338 + u=v->parent; /* prepare to backtrack in the tree */ 8.339 + if (v->min==u) @<Remove |v| and all its successors on the active stack 8.340 + from the tree, and report them as a bicomponent of the graph 8.341 + together with~|u|@>@; 8.342 + else /* the arc from |u| to |v| has just matured, 8.343 + making |v->min| visible from |u| */@, 8.344 + if (v->min->rank < u->min->rank) 8.345 + u->min=v->min; 8.346 + v=u; /* the former parent of |v| is the new current vertex |v| */ 8.347 + } 8.348 +} 8.349 + 8.350 +@ The elements of the active stack are always in order 8.351 +by rank, and all children of a vertex~|v| in the tree have rank higher 8.352 +than~|v|. The Hopcroft-Tarjan algorithm relies on a converse property: {\sl All 8.353 +active nodes whose rank exceeds that of the current vertex~|v| 8.354 +are descendants of~|v|.} (This holds because the algorithm has constructed 8.355 +the tree by assigning ranks in preorder, ``the order of succession to the 8.356 +throne''. First come |v|'s firstborn and descendants, then the nextborn, 8.357 +and so on.) Therefore the descendants of the current vertex always appear 8.358 +consecutively at the top of the stack. 8.359 + 8.360 +Suppose |v| is a mature, active vertex with |v->min==v->parent|, and 8.361 +let |u=v->parent|. We want to prove that |v| and its descendants, 8.362 +together with~|u| and all edges between these vertices, form a 8.363 +biconnected graph. Call this subgraph~|H|. The parent links 8.364 +define a subtree of~|H|, rooted at~|u|, and |v| is the only vertex 8.365 +having |u| as a parent (because all other vertices are descendants 8.366 +of~|v|). If |x| is any vertex of~|H| different from |u| and |v|, 8.367 +there is a path from |x| to |x->min| that does not touch~|x->parent|, 8.368 +and |x->min| is a proper ancestor of |x->parent|. This property 8.369 +is sufficient to establish the biconnectedness of~|H|. (A proof appears 8.370 +at the conclusion of this program.) Moreover, we cannot add any 8.371 +more vertices to~|H| without losing biconnectivity; if |w|~is another 8.372 +vertex, |w| has either been output already as a non-articulation point 8.373 +of a previous biconnected component, or we can prove that 8.374 +there is no path from |w| to~|v| that avoids the vertex~|u|. 8.375 + 8.376 +Therefore we are justified in settling |v| and its active descendants now. 8.377 +Removing them from the tree of active vertices does not remove any 8.378 +vertex from which there is a path to a vertex of rank less than 8.379 +|u->rank|; hence it does not affect the validity of the |w->min| value 8.380 +for any vertex~|w| that remains active. 8.381 + 8.382 +A slight technicality arises with respect to whether or not 8.383 +the parent of~|v|, vertex~|u|, is part of the present bicomponent. 8.384 +When |u| is the dummy vertex, we have already printed the final bicomponent 8.385 +of a connected component of the original graph, unless |v| was 8.386 +an isolated vertex. Otherwise |u| is an 8.387 +articulation point that will occur in subsequent bicomponents, 8.388 +unless this is the final bicomponent of a connected component. 8.389 +(This aspect of the algorithm is probably its most subtle point; 8.390 +consideration of an example or two should clarify everything.) 8.391 + 8.392 +We print out enough information for a reader to verify the 8.393 +biconnectedness of the claimed component easily. 8.394 + 8.395 +@<Remove |v| and all its successors on the active stack...@>= 8.396 +if (u==&dummy) { /* |active_stack| contains just |v| */ 8.397 + if (artic_pt) 8.398 + printf(" and %s (this ends a connected component of the graph)\n", 8.399 + vertex_name(artic_pt,0)); 8.400 + else printf("Isolated vertex %s\n",vertex_name(v,0)); 8.401 + active_stack=artic_pt=NULL; 8.402 +} else {@+register Vertex *t; /* runs through the vertices of the 8.403 + new bicomponent */ 8.404 + if (artic_pt) 8.405 + printf(" and articulation point %s\n",vertex_name(artic_pt,0)); 8.406 + t=active_stack; 8.407 + active_stack=v->link; 8.408 + printf("Bicomponent %s", vertex_name(v,0)); 8.409 + if (t==v) putchar('\n'); /* single vertex */ 8.410 + else { 8.411 + printf(" also includes:\n"); 8.412 + while (t!=v) { 8.413 + printf(" %s (from %s; ..to %s)\n", 8.414 + vertex_name(t,0), vertex_name(t->parent,1),vertex_name(t->min,2)); 8.415 + t=t->link; 8.416 + } 8.417 + } 8.418 + artic_pt=u; /* the printout will be finished later */ 8.419 +} 8.420 + 8.421 +@ Like all global variables, |artic_pt| is initially zero (|NULL|). 8.422 + 8.423 +@<Glob...@>= 8.424 +Vertex *artic_pt; /* articulation point to be printed if the current 8.425 + bicomponent isn't the last in its connected component */ 8.426 + 8.427 +@*Proofs. 8.428 +The program is done but we still should prove that it works. 8.429 +First we want to clarify the informal definition by verifying that 8.430 +the cycle relation between edges, as stated in the introduction, is indeed an 8.431 +equivalence relation. 8.432 + 8.433 +\def\dash{\mathrel-\joinrel\joinrel\mathrel-} 8.434 +Suppose $u\dash v$ and $w\dash x$ are edges of a simple cycle~$C$, while 8.435 +$w\dash x$ and $y\dash z$ are edges of a simple cycle~$D$. We want to show 8.436 +that there is a simple cycle containing the edges $u\dash v$ and $x\dash y$. 8.437 +There are vertices $a,b\in C$ such that $a\dash^\ast y\dash z\dash^\ast b$ 8.438 +is a subpath of~$D$ containing no other vertices of $C$ besides $a$ and~$b$. 8.439 +Join this subpath to the subpath in $C$ that runs from $b$ to~$a$ through 8.440 +the edge $u\dash v$. 8.441 + 8.442 +Therefore the stated relation between edges is transitive, and it is 8.443 +an equivalence relation. 8.444 +A graph is biconnected if it contains a single vertex, or if each of 8.445 +its vertices is adjacent to at least one other vertex and any two edges are 8.446 +equivalent. 8.447 + 8.448 +@ Next we prove the well known fact that a graph is biconnected if and 8.449 +only if it is connected and, for any three distinct vertices $x$, 8.450 +$y$,~$z$, it contains a path from $x$ to~$y$ that does not touch~$z$. 8.451 +Call the latter condition property~P. 8.452 + 8.453 +Suppose $G$ is biconnected, and let $x,y$ be distinct vertices of~$G$. 8.454 +Then there exist edges $u\dash x$ and $v\dash y$, which are either 8.455 +identical (hence $x$ and~$y$ are adjacent) or part of a simple cycle 8.456 +(hence there are two paths from $x$ to~$y$, having no other vertices in 8.457 +common). Thus $G$ has property~P. 8.458 + 8.459 +Suppose, conversely, that $G$ has property~P, and let $u\dash v, 8.460 +w\dash x$ be distinct edges of~$G$. We want to show that these edges 8.461 +belong to some simple cycle. The proof is by induction on 8.462 +$k=\min\bigl(d(u,w),d(u,x),\allowbreak d(v,w),d(v,x)\bigr)$, where $d$~denotes 8.463 +distance. If $k=0$, property~P gives the result directly. If $k>0$, 8.464 +we can assume by symmetry that $k=d(u,w)$; so there's a vertex $y$ 8.465 +with $u\dash y$ and $d(y,w)=k-1$. And we have $u\dash v$ equivalent to 8.466 +$u\dash y$ by property~P, $u\dash y$ equivalent to $w\dash x$ by induction, 8.467 +hence $u\dash v$ is equivalent to $w\dash x$ by transitivity. 8.468 + 8.469 +@ Finally, we prove that $G$ satisfies property~P if it has the 8.470 +following properties: (1)~There are two distinguished vertices $u$ 8.471 +and~$v$. (2)~Some of the edges of~$G$ form a subtree rooted at~$u$, 8.472 +and $v$ is the only vertex whose parent in this tree is~$u$. 8.473 +(3)~Every vertex~$x$ other than $u$ or $v$ has a path to its 8.474 +grandparent that does not go through its parent. 8.475 + 8.476 +If property P doesn't hold, there are distinct vertices $x,y,z$ such 8.477 +that every path from $x$ to~$y$ goes through~$z$. In particular, $z$ must be 8.478 +between $x$ and~$y$ in the unique path~$\pi$ that joins them in the subtree. 8.479 +It follows that $z\ne u$ is the parent of some node $z'$ in that path; hence 8.480 +$z'\ne u$ and $z'\ne v$. But we can 8.481 +avoid $z$ by going from $z'$ to the grandparent of $z'$, which is 8.482 +also part of path~$\pi$ unless $z$ is also the parent of another node 8.483 +$z''$ in~$\pi$. In the latter case, however, 8.484 +we can avoid $z$ by going from $z'$ to the grandparent of $z'$ and from there 8.485 +to $z''$, since $z'$ and $z''$ have the same grandparent. 8.486 + 8.487 +@* Index. We close with a list that shows where the identifiers of this 8.488 +program are defined and used. 8.489 +
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/cities.texmap Mon Oct 03 23:29:42 2011 +0200 9.3 @@ -0,0 +1,160 @@ 9.4 +% Plain TeX code to generate a map of the 128 cities in miles.dat 9.5 + 9.6 +% Parameters to the \\ macro are: 9.7 +% #1: city name to be typeset 9.8 +% #2,#3: (x,y) coordinates for lower left corner of label box 9.9 +% #4,#5: (x,y) coordinates for the dot 9.10 +% (#4,#5)=(12318-lng,1.5(lat-2672)), where (lat,lng) are the coords in miles.dat 9.11 + 9.12 +% Parameters to \| are similar, but the state code is separated out 9.13 +% and put on a second line, #3 ems from the right edge of the main line 9.14 +% e.g. City Name, ST .5(cityx,cityy,dotx,doty) 9.15 +% puts "ST" on the second line, .5em from the right 9.16 + 9.17 +\newdimen\unit \unit=.0012in 9.18 +\setbox0=\hbox{\fivesy\char15} 9.19 +\newbox\dotbox \setbox\dotbox=\hbox{\kern-.5\wd0\fivesy\char15} \wd\dotbox=0pt 9.20 +\newdimen\fudge \setbox0=\hbox{\fiverm p} \fudge=-\dp0 9.21 + \advance\fudge-.5\ht\dotbox \advance\fudge.5\dp\dotbox 9.22 +\newdimen\vertpos 9.23 +\def\\#1 (#2,#3,#4,#5){\vertpos=#5\unit \advance\vertpos\fudge 9.24 + \setbox0=\hbox{\kern#4\unit \raise\vertpos\copy\dotbox}\wd0=0pt \box0 9.25 + \setbox0=\hbox{\kern#2\unit \raise#3\unit\hbox{\fiverm#1}}\wd0=0pt \box0} 9.26 +\def\|#1, #2 #3(#4,#5,#6,#7){\vertpos=#7\unit \advance\vertpos\fudge 9.27 + \setbox0=\hbox{\kern#6\unit \raise\vertpos\copy\dotbox}\wd0=0pt \box0 9.28 + \setbox0=\hbox{\kern#4\unit \raise#5\unit 9.29 + \hbox{\fiverm#1,\llap{\lower55\unit\hbox{#2\kern#3em}}}}\wd0=0pt \box0} 9.30 + 9.31 +\vglue 2in 9.32 +\noindent 9.33 +\\Ravenna, OH (3707,2103,4188,2166) 9.34 +\\Reading, PA (4735,2050,4719,2041) 9.35 +\\Red Bluff, CA (-415,2034,88,2019) 9.36 +\\Regina, SA (1535,3575,1847,3555) 9.37 +\\Reno, NV (306,1940,331,1920) 9.38 +\\Rhinelander, WI (3222,2860,3370,2838) 9.39 +\\Richfield, UT (877,1737,1103,1807) 9.40 +\|Richmond, IN .5(3620,1901,3823,1966) 9.41 +\\Richmond, VA (4585,1572,4567,1623) 9.42 +\\Roanoke, VA (4136,1514,4318,1582) 9.43 +\\Rochester, MN (2696,2613,3066,2595) 9.44 +\\Rochester, NY (4032,2445,4551,2466) 9.45 +\\Rockford, IL (2953,2277,3402,2332) 9.46 +\\Rock Springs, WY (1014,2161,1389,2230) 9.47 +\\Rocky Mount, NC (4548,1323,4532,1383) 9.48 +\\Roswell, NM (1410,938,1859,1002) 9.49 +\\Rutland, VT (5044,2504,5015,2533) 9.50 +\\Sacramento, CA (168,1796,163,1780) 9.51 +\\Saginaw, MI (3533,2432,3918,2506) 9.52 +\\Saint Augustine, FL (3996,402,4180,475) 9.53 +\\Saint Cloud, MN (2349,2837,2895,2827) 9.54 +\\Saint Johnsbury, VT (4991,2677,5110,2655) 9.55 +\\Saint Joseph, MI (3659,2319,3664,2307) 9.56 +\\Saint Joseph, MO (2203,1964,2828,1957) 9.57 +\|Saint Louis, MO .5(3105,1715,3293,1785) 9.58 +\\Saint Paul, MN (2776,2750,3002,2734) 9.59 +\\Salem, OR (-362,2665,9,2733) 9.60 +\\Salida, CO (1404,1791,1712,1771) 9.61 +\\Salina, KS (2162,1793,2551,1818) 9.62 +\\Salinas, CA (-261,1426,147,1492) 9.63 +\\Salisbury, MD (4771,1690,4752,1747) 9.64 +\\Salt Lake City, UT (620,2036,1124,2106) 9.65 +\\San Angelo, TX (1699,683,2268,711) 9.66 +\\San Antonio, TX (1855,377,2462,405) 9.67 +\\San Bernardino, CA (605,1090,581,1108) 9.68 +\\San Diego, CA (340,827,597,898) 9.69 +\\Sandusky, OH (3537,2158,4041,2209) 9.70 +\\San Francisco, CA (-580,1605,70,1659) 9.71 +\\San Jos\'e, CA (147,1541,124,1593) 9.72 +\\Santa Ana, CA (-18,1004,525,1056) 9.73 +\\Santa Barbara, CA (-272,1175,342,1155) 9.74 +\\Santa Fe, NM (1224,1284,1717,1344) 9.75 +\\Santa Rosa, CA (-531,1729,40,1758) 9.76 +\\Sarasota, FL (3604,29,4059,93) 9.77 +\\Sault Sainte Marie, MI (3894,2969,3877,2965) 9.78 +\\Savannah, GA (4223,804,4203,804) 9.79 +\\Schenectady, NY (4942,2380,4917,2415) 9.80 +\\Scottsbluff, NB (1514,2292,1946,2272) 9.81 +\|Scranton, PA 1(4619,2245,4745,2203) 9.82 +\\Seattle, WA (-343,3143,79,3132) 9.83 +\\Sedalia, MO (2599,1720,2989,1798) 9.84 +\\Selma, AL (3630,786,3610,855) 9.85 +\\Seminole, OK (2416,1206,2644,1276) 9.86 +\\Sheridan, WY (1204,2733,1616,2712) 9.87 +\\Sherman, TX (2180,969,2651,1038) 9.88 +\\Shreveport, LA (2845,887,2937,868) 9.89 +\\Sioux City, IA (2185,2296,2673,2365) 9.90 +\\Sioux Falls, SD (2102,2535,2639,2523) 9.91 +\\South Bend, IN (3118,2210,3687,2244) 9.92 +\\Spokane, WA (579,3153,571,3142) 9.93 +\\Springfield, IL (2896,1977,3347,1962) 9.94 +\\Springfield, MA (5070,2256,5053,2307) 9.95 +\\Springfield, MO (2986,1507,2983,1575) 9.96 +\\Springfield, OH (3430,1990,3931,1980) 9.97 +\\Staunton, VA (4151,1644,4405,1714) 9.98 +\\Sterling, CO (1767,2105,1990,2085) 9.99 +\\Steubenville, OH (3646,2045,4250,2046) 9.100 +\\Stevens Point, WI (3288,2600,3355,2670) 9.101 +\\Stockton, CA (204,1658,183,1686) 9.102 +\\Stroudsburg, PA (4818,2111,4793,2140) 9.103 +\\Sumter, SC (4292,1007,4277,1080) 9.104 +\\Swainsboro, GA (4087,894,4078,882) 9.105 +\\Syracuse, NY (4300,2374,4697,2449) 9.106 +\\Tacoma, WA (-380,3019,69,3078) 9.107 +\\Tallahassee, FL (3334,502,3884,559) 9.108 +\\Tampa, FL (4070,202,4067,184) 9.109 +\\Terre Haute, IN (3008,1855,3571,1912) 9.110 +\\Texarkana, TX (2923,994,2907,1006) 9.111 +\\Toledo, OH (3743,2257,3958,2239) 9.112 +\\Topeka, KS (2380,1869,2745,1849) 9.113 +\\Toronto, ON (4065,2561,4374,2539) 9.114 +\\Traverse City, MI (3775,2682,3749,2706) 9.115 +\\Trenton, NJ (4859,1976,4835,2026) 9.116 +\\Trinidad, CO (1740,1501,1861,1567) 9.117 +\\Tucson, AZ (1018,755,1215,825) 9.118 +\\Tulsa, OK (2562,1436,2721,1416) 9.119 +\\Tupelo, MS (3037,1144,3441,1131) 9.120 +\\Tuscaloosa, AL (3560,986,3555,973) 9.121 +\\Twin Falls, ID (361,2393,865,2376) 9.122 +\\Tyler, TX (2417,816,2782,844) 9.123 +\|Uniontown, PA 1(4295,1986,4339,1977) 9.124 +\\Utica, NY (4807,2438,4789,2458) 9.125 +\\Valdosta, GA (3995,555,3984,616) 9.126 +\\Valley City, ND (2037,3050,2511,3030) 9.127 +\\Vancouver, BC (-257,3403,0,3382) 9.128 +\\Vicksburg, MS (2963,771,3224,844) 9.129 +\\Victoria, TX (2518,242,2611,313) 9.130 +\\Vincennes, IN (3575,1737,3559,1794) 9.131 +\\Waco, TX (2494,652,2598,724) 9.132 +\\Walla Walla, WA (370,2830,479,2902) 9.133 +\|Warren, PA .5(4285,2295,4398,2269) 9.134 +\\Washington, DC (4633,1807,4609,1825) 9.135 +\\Waterbury, CT (5027,2173,5007,2224) 9.136 +\\Waterloo, IA (2698,2383,3078,2367) 9.137 +\\Watertown, NY (4731,2571,4720,2589) 9.138 +\\Watertown, SD (2056,2701,2601,2727) 9.139 +\\Waukegan, IL (3180,2361,3529,2346) 9.140 +\\Wausau, WI (3363,2741,3348,2736) 9.141 +\\Waycross, GA (4087,675,4077,675) 9.142 +\\Weed, CA (-252,2225,73,2205) 9.143 +\\Wenatchee, WA (291,3040,280,3105) 9.144 +\\West Palm Beach, FL (4190,-70,4307,0) 9.145 +\|Wheeling, WV 1(3975,1935,4240,2002) 9.146 +\\Wichita, KS (2286,1575,2578,1645) 9.147 +\\Wichita Falls, TX (1909,1098,2463,1077) 9.148 +\|Williamson, WV .5(3650,1616,4084,1644) 9.149 +\|Williamsport, PA .5(4168,2192,4612,2179) 9.150 +\\Williston, ND (1471,3232,1950,3214) 9.151 +\\Wilmington, DE (4776,1899,4757,1954) 9.152 +\\Wilmington, NC (4521,1143,4520,1128) 9.153 +\|Winchester, VA 0(4135,1805,4496,1870) 9.154 +\\Winnipeg, MB (2347,3495,2597,3474) 9.155 +\\Winston-Salem, NC (3586,1354,4287,1407) 9.156 +\\Wisconsin Dells, WI (2769,2469,3335,2536) 9.157 +\\Worcester, MA (5140,2320,5132,2332) 9.158 +\\Yakima, WA (-11,2912,261,2982) 9.159 +\\Yankton, SD (2110,2410,2573,2424) 9.160 +\|Youngstown, OH 1(4262,2092,4247,2157) 9.161 + 9.162 +\nopagenumbers\bye 9.163 +
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/david.dat Mon Oct 03 23:29:42 2011 +0200 10.3 @@ -0,0 +1,157 @@ 10.4 +* File "david.dat" from the Stanford GraphBase (C) 1992 Stanford University 10.5 +* David Copperfield, by Charles Dickens 10.6 +* This file may be freely copied but please do not change it in any way! 10.7 +* (Checksum parameters 152,151276216) 10.8 +AD Adams, head boy in DS's school 10.9 +AS Annie Strong, beautiful young wife of DS 10.10 +AW Agnes Wickfield, daughter of WW 10.11 +BA Mr. Barkis, willin' carrier 10.12 +BC Beauty Crewler, sister of ST 10.13 +BM Baby Murdstone, baby boy of CC and ED 10.14 +BT Betsey Trotwood, DC's paternal great-aunt 10.15 +CC Clara Copperfield, mother of DC 10.16 +CD Mr. Chillip, doctor at DC's birth 10.17 +CH Captain Hopkins, debtor with sonorous voice 10.18 +CK Mr. Creakle, proprietor of Salem House school 10.19 +CL Clicket (the Orfling), servant of WM 10.20 +CM Jack Maldon, ne'er-do-well cousin of AS 10.21 +CP Clara Peggotty, nurse to DC 10.22 +CR Mrs. Crupp, landlady to DC 10.23 +CS Miss Clarissa Spenlow, aunt of DO 10.24 +DB Richard Babley (Mr. Dick), weak-minded prot\'eg\'e of BT 10.25 +DC David Copperfield, our hero 10.26 +DL Mr. Dolloby, buyer of used clothing 10.27 +DM Miss Emma Micawber, daughter of WM and EM 10.28 +DO Dora Spenlow, daughter of FS 10.29 +DP Dan Peggotty, brother of CP 10.30 +DS Dr. Strong, schoolmaster at Dover 10.31 +DW Miss Mowcher, dwarf hairdresser 10.32 +ED Edward Murdstone, second husband of CC 10.33 +EM Mrs. Emma Micawber, sanguine wife of WM 10.34 +FG Mr. Grainger, friend of JS 10.35 +FM Mr. Markham, friend of JS 10.36 +FS Mr. Francis Spenlow, attorney 10.37 +GP Mr. Gulpidge, something to do with the law business 10.38 +GR Gregory, foreman of wine packers at Murdstone and Grinby 10.39 +GU Mrs. Gulpidge, dinner guest of FS 10.40 +HA Mrs. Henry Spiker, `Hamlet's Aunt' 10.41 +HC Rev. Horace Crewler, father of ST 10.42 +HP Ham Peggotty, nephew to CP and DP 10.43 +HS Mr. Henry Spiker, solicitor 10.44 +JK Mr. Jorkins, `hard-hearted' partner of FS 10.45 +JM Jane Murdstone, sister of ED 10.46 +JR Joram, partner of OM 10.47 +JS James Steerforth, schoolmate of DC 10.48 +JT Janet, maid to BT 10.49 +JU Julia Mills, bosom friend of DO 10.50 +KI Miss Kitt, creature in pink 10.51 +LA Miss Larkins, DC's older woman crush 10.52 +LC Mr. Chestle, `elderly' gentleman who marries LA 10.53 +LE Emily Peggotty (Little Em'ly), niece of DP 10.54 +LF Mr. Larkins, father of LA 10.55 +LM Littimer, valet to JS 10.56 +LS Miss Lavinia Spenlow, aunt of DO 10.57 +MC Mrs. Creakle, wife of CK 10.58 +ME Martha Endell, `fallen woman' 10.59 +MF Mrs. Fibbotson, old housemate of MM 10.60 +MG Mrs. Gummidge (Old Mawther), widow of DP's partner 10.61 +MH Mrs. Crewler, wife of HC 10.62 +MJ Master Wilkins Micawber Jr., son of WM and EM 10.63 +ML Charley Mell, teacher at Salem House 10.64 +MM Mrs. Mell, mother of ML 10.65 +MO Minnie Omer, daughter and seamstress to OM 10.66 +MP Mealy Potatoes, laborer at Murdstone and Grinby 10.67 +MS Mrs. Steerforth, mother of JS 10.68 +MW Mick Walker, laborer at Murdstone and Grinby 10.69 +OC Miss Creakle, daughter of CK 10.70 +OM Mr. Omer, haberdasher and funeral furnisher 10.71 +OS Mrs. Markleham (The Old Soldier), mother of AS 10.72 +PA Mary Anne Paragon, first servant of DC and DO 10.73 +PN Mr. Passnidge, friend of ED 10.74 +QU Mr. Quinion, manager of Murdstone and Grinby 10.75 +RD Rosa Dartle, companion to MS 10.76 +RW Red Whisker, rival for DO 10.77 +SA Miss Shepherd, adorable little girl 10.78 +SC Sarah Crewler, crippled sister of ST 10.79 +SH Mr. Sharp, headmaster at Salem House 10.80 +ST Sophy Crewler, fianc\'ee of TT 10.81 +TI Mr. Tiffey, clerk to FS 10.82 +TP Tipp, carman at Murdstone and Grinby 10.83 +TR Mr. Trotwood, husband left by BT 10.84 +TT Tommy Traddles, student at Salem House 10.85 +TU Mr. Tungay, one-legged guard at Salem House 10.86 +TW Micawber Twins, children of WM and EM 10.87 +UH Uriah Heep, articled to lawyer WW 10.88 +UM Mrs. Heep, 'umble mother of UH 10.89 +WA Mrs. Waterbrook, wife of WB 10.90 +WB Mr. Waterbrook, agent for WW 10.91 +WI William 1, friendly and hungry waiter 10.92 +WL William 2, coachman 10.93 +WM Wilkins Micawber, debtor who waits 10.94 +WW Mr. Wickfield, attorney at Dover 10.95 + 10.96 +1:CC,BT;BT,CP;HP,CP;BT,CD;HP,BT;CC,DC 10.97 +2:CC,DC,CP;DC,CP;DC,CP,ED;CP,CC;DC,ED;DC,ED,QU,PN;BA,DC,CP 10.98 +3:CP,DC;CP,HP,DC;CP,HP,DC,LE,MG,DP;LE,DC;MG,CP;DC,CC,ED;BA,DC,CP 10.99 +4:CC,CP,DC,ED;JM,DC,CC,ED;CC,ED,JM;DC,CC,JM,ED;DC,ED;CP,DC;JM,DC;BA,DC 10.100 +5:BA,DC,CP;BA,DC;DC,WI;DC,ML,MM,MF;TU,ML,DC 10.101 +6:DC,ML,TU;DC,TU,CK,MC,OC;TT,DC;JS,DC 10.102 +7:TU,CK;CK,DC;TT,JS,DC;DC,JS;MM,JS,TT,DC,CK,TU;TU,DC;DP,HP,DC,JS 10.103 +8:BA,DC;DC,CC,BM,CP;DC,CC,CP;DC,ED,JM;DC,JM,CC,BM;DC,ED,JM,CC;DC,CC,BM 10.104 +9:DC,SH;CK,MC,DC;OM,MO,DC,JR;DC,CP,CC,BM;ED,CD,DC,JM;MG,ED,CD,DC,JR,MO 10.105 +10:JM,CP,DC;DC,HP,DP,CP,BA;BA,CP,DP,MG,LE,DC,HP;DP,HP,LE,DC,MG;QU,DC,ED,JM 10.106 +11:DC,MW,MP;QU,DC,WM;DC,WM,TW,MJ,DM,EM,CL;GR,TP,DC;EM,DC;CH,DC;DC,CP,WM 10.107 +12:DC,EM,WM;WM,QU,TP,DC;DC,WM,EM,MJ,DM,CL;CP,DC;DC,MP 10.108 +13:DC,DL;DC,JT,BT,DB 10.109 +14:BT,JT,JM,ED,DC;BT,DC,JM,ED;BT,DC,JM,ED,DB;DB,DC,BT 10.110 +15:DC,DB,BT,JT;DC,BT,UH;DC,BT,WW;DC,BT,WW,AW 10.111 +16:WW,DC,DS,AS;AD,DC;CM,WW,DC,AW,UH;JM,DC,AS,DS,OS,WW,AW 10.112 +17:DC,CP;BT,DB,TR;DS,DC,DB;UH,DC,UM,WM;DC,WM,EM 10.113 +18:DC,SA;DC,AW;AD,DC;DC,LA;DC,LF;LC,DC 10.114 +19:DC,BT,DB;DC,AW;DC,AW,DS,AS,OS,WW;WL,DC;JS,DC 10.115 +20:DC,JS;MS,JS,DC,RD;MS,DC 10.116 +21:DC,MS,JS,RD,LM;DC,MO,OM;DC,CP,BA;DC,CP,JS;DC,JS,HP,LE,DP,MG 10.117 +22:DC,JS,MG;DC,JS,HP,LE;ME,LE,HP;DC,JS,LM;DC,JS,DW;DC,HP,LE,CP,ME 10.118 +23:DC,JS,LM;DC,BT,JT;BT,TR;DC,BT,FS;DC,FS;DC,BT,CR;DC,BT,TI 10.119 +24:DC,MS,RD;DC,JS;DC,CR;DC,JS,FG,FM;DC,AW 10.120 +25:DC,AW;DC,AW,WA;DC,WB,WA,HS,HA,UH,AW,TT,GP,GU;DC,UH 10.121 +26:DC,AW,UH;DC,FS;DC,DO,JM;DC,CR;DC,TI 10.122 +27:DC,TT;DC,TT,WM;DC,TT,WM,EM;DC,WM 10.123 +28:DC,CR;DC,TT,WM,EM;DC,TT,WM,EM,LM;DC,JS 10.124 +29:DC,FS;DC,RD,MS,JS;DC,RD;DC,RD,JS;DC,JS,MS;DC,JS 10.125 +30:DC,OM;DC,OM,MO,JR;DC,DP,CP,LE,HP;DC,CP,DP,BA 10.126 +31:DC,CP;DC,CP,MG,DP;DC,CP,MG,DP,HP;DC,HP;LE,LM,JS 10.127 +32:DC,HP,DP,MG;DC,MO;DC,DW;DC,HP,DP,MG,CP;DC,DP,RD,MS 10.128 +33:DC,CP,FS,ED;JM,ED;DC,DO,JU,FS,RW,KI;TI,DC,CP 10.129 +34:DC,AW;CR,DC;CP,TT;DC,TT;DC,CP,BT,DB,CR;DC,CP,BT,DB 10.130 +35:DC,DB,BT,CP;DC,FS;DC,JK;DC,TI;WW,UH,AW,UM;DC,AW,BT,WW,UH 10.131 +36:DC,DS;DC,DS,AS,CM;DC,DB,TT;DC,TT,DM,MJ,EM,WM 10.132 +37:BT,CR;BT,CP,DC;DC,DO;DC,DO,JU;DC,JU 10.133 +38:DC,TT,DB,BT;DC,FS,JM;DC,JU;DC,TI;DC,TI,JK;JU,DO;DO,LS,CS 10.134 +39:DC,BT;DC,JT;DC,WM;DC,AW,WW,UH,UM 10.135 +40:DC,BT,DB;DC,BT;DC,ME;DC,DP;DC,DP,ME;LE,MG 10.136 +41:DC,LS,CS;DC,BT,DB,TT;TT,HC,MH,BC,SC,ST;TT,DC,LS,CS;DC,DO;BT,LS,CS,DO 10.137 +42:DC,AW,LS,CS,DO;DC,WW,UH,DS;DC,DS,OS,AS;DB,DS;DB,AS;DC,BT;WM,EM 10.138 +43:DC,TT;DC,DO,BT,LS,CS;DC,AW,DO,BT,CP,LS,CS,TT,ST;DC,DO,LS;DC,DO 10.139 +44:DC,DO;DC,DO,PA;DC,BT;DC,DO,TT 10.140 +45:DC,DS,OS;DS,OS,AS;DC,BT,AS,OS;DC,BT,OS,DS,AS,DB;DC,BT,DB 10.141 +46:DC,RD;DC,RD,LM;LM,LE;DC,RD,MS;DC,DP;DC,DP,ME 10.142 +47:DC,DP,ME;BT,TR;DC,BT 10.143 +48:DC,DO;DC,DO,TT;DC,DO,BT 10.144 +49:DC,WM;DC,TT;TT,EM;DC,TT,WM;DC,TT,WM,BT,DB 10.145 +50:DC,DP;DP,ME;DC,ME;RD,LE,DC;DP,LE,DC 10.146 +51:DC,DP,BT;DC,DO;DC,OM;DC,DP,CP,MG;DC,HP;DC,DP,MG 10.147 +52:DC,BT,DO;DC,TT,BT,DB,WM,UH;DC,TT,BT,DB,WM,UH,AW,UM;DC,BT,WM,EM,DM,TW,MJ 10.148 +53:DC,DO,BT;DC,DO;DC,BT,DO,AW;DC,AW 10.149 +54:DC,AW,BT,WM,EM;DC,TT,BT,AW;DC,BT;DC,BT,TR;DC,BT,WM 10.150 +55:DC,CP,DP;DC,BT;DC,LE;DC,HP,JS 10.151 +56:DC,RD,MS 10.152 +57:DC,WM,EM,TW,MJ,DM,TT,AW,BT,CP,DP;DC,CP,DP;DP,ME,DC;DC,CP,MG;LE,AW;DC,LE 10.153 +58:DC,AW 10.154 +59:DC,TT,ST;DC,TT;DC,CD;DC,BT,CP,DB;ED,JM 10.155 +60:DC,BT;DC,AW;DC,AW,WW 10.156 +61:DC,TT,ST;DC,TT;DC,CK,TT;DC,CK,TT,UH,LM;LM,DW 10.157 +62:DC,BT;DC,AW;DC,BT,AW,DB,CP;DC,AW,TT,ST,DS,AS 10.158 +63:DC,AW,DP;DP,LE,ME,MG,WM,EM,MJ,DM,ML;DC,AW,DP,BT,CP 10.159 +64:DC,AW,BT,CP,DB;RD,MS;JU,CM;DS,AS,OS;DC,TT,ST;TT,HC,MC,BC;DC,AW 10.160 +* End of file "david.dat"
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/econ.dat Mon Oct 03 23:29:42 2011 +0200 11.3 @@ -0,0 +1,891 @@ 11.4 +* File "econ.dat" from the Stanford GraphBase (C) 1992 Stanford University 11.5 +* Input/Output structure of the US economy, 1985 11.6 +* This file may be freely copied but please do not change it in any way! 11.7 +* (Checksum parameters 886,303998716) 11.8 +Industry: 11.9 +Goods: 11.10 +Natural resources: 11.11 +Organic resources: 11.12 +Living resources: 11.13 +Agriculture: 11.14 +Livestock and livestock products:1 11.15 +Agriculture, excluding livestock:2 11.16 +Forestry and fishery products:3 11.17 +Fossil fuels: 11.18 +Coal mining:7 11.19 +Petroleum and natural gas production:8 11.20 +Inorganic resources: 11.21 +Mining of metals: 11.22 +Mining of ferrous metals:5 11.23 +Mining of nonferrous metals:6 11.24 +Mining of minerals: 11.25 +Quarrying of stone and clay:9 11.26 +Mining of chemicals:10 11.27 +Manufacturing: 11.28 +Organic products: 11.29 +Products from agriculture: 11.30 +Food and tobacco products: 11.31 +Food, liquor, and candy:14 11.32 +Cigarettes, cigars, tobacco:15 11.33 +Inedible products from agriculture: 11.34 +Textiles and leather: 11.35 +Textile manufacturing: 11.36 +Yard goods: 11.37 +Spinning and weaving:16 11.38 +Specialized textile products:17 11.39 +Fabricated textiles: 11.40 +Apparel:18 11.41 +Household textiles:19 11.42 +Leather manufacturing: 11.43 +Leather tanning and finishing:33 11.44 +Leather products:34 11.45 +Wood and paper: 11.46 +Wood manufacturing: 11.47 +Lumber and basic wood products: 11.48 +Lumber and wood, except containers:20 11.49 +Wood containers:21 11.50 +Furniture: 11.51 +Household furniture:22 11.52 +Office furniture and fixtures:23 11.53 +Paper manufacturing: 11.54 +Paper products: 11.55 +Paper products, except containers:24 11.56 +Paperboard containers and boxes:25 11.57 +Printing and publishing:26 11.58 +Organic chemical products: 11.59 +Rubber and plastics: 11.60 +Rubber products:32 11.61 +Plastics and synthetic materials:28 11.62 +Petrochemicals: 11.63 +Petroleum refining and byproducts:31 11.64 +Paints and allied products:30 11.65 +Inorganic products: 11.66 +General inorganic products: 11.67 +Metal products: 11.68 +Primary metal manufacturing: 11.69 +Primary iron and steel manufacturing:37 11.70 +Primary nonferrous metals manufacturing:38 11.71 +Metal equipment: 11.72 +Tools and parts: 11.73 +Screw machine products and stampings:41 11.74 +Metal products, not screws or stampings:42 11.75 +Metal fixtures: 11.76 +Architectural metalwork:40 11.77 +Metal containers:39 11.78 +Mineral and chemical products: 11.79 +Inorganic chemical products: 11.80 +Drugs and toiletries:29 11.81 +Fertilizers, glues, explosives, etc.:27 11.82 +Mineral products: 11.83 +Stone and clay products:36 11.84 +Glass and glass products:35 11.85 +Specialized manufactured goods: 11.86 +Specialized static equipment: 11.87 +Precision instruments: 11.88 +Scientific and controlling instruments:62 11.89 +Optical and photographic equipment:63 11.90 +Sundries (jewelry, games, etc.):64 11.91 +Specialized dynamic equipment: 11.92 +Vehicles and ordnance: 11.93 +Vehicles: 11.94 +Aircraft and parts:60 11.95 +Land and water vehicles: 11.96 +Motor vehicles and equipment:59 11.97 +Ships, trains, cycles, motor homes:61 11.98 +Ordnance and accessories:13 11.99 +Machinery and equipment: 11.100 +Electrical machinery and parts: 11.101 +Electrical parts: 11.102 +Electrical components: 11.103 +Electronic components and accessories:57 11.104 +Batteries and other electric supplies:58 11.105 +Electric lighting and wiring equipment:55 11.106 +Electrical equipment: 11.107 +Electrical apparatus: 11.108 +Radio, TV, and communication equipment:56 11.109 +Electrical appliances: 11.110 +Household appliances:54 11.111 +Office, computing, and accounting machines:51 11.112 +Industrial machinery: 11.113 +Electrical machines for service industries:52 11.114 +Electrical apparatus for manufacturing:53 11.115 +Non-electrical machinery and parts: 11.116 +Machine components: 11.117 +General industrial machinery equipment:49 11.118 +Engines and components: 11.119 +Engine parts:50 11.120 +Engines and turbines:43 11.121 +Non-electrical machinery: 11.122 +Outdoor machinery: 11.123 +Farm and garden machinery:44 11.124 +Construction and mining machinery:45 11.125 +Machinery for manufacturing: 11.126 +Materials handling machinery and equipment:46 11.127 +Industrial robots: 11.128 +Metalworking machinery and equipment:47 11.129 +Special industry machinery and equipment:48 11.130 +Services: 11.131 +Indirect services: 11.132 +Infrastructure: 11.133 +Construction: 11.134 +New construction:11 11.135 +Repair and maintenance construction:12 11.136 +Facilities: 11.137 +Transportation and communication: 11.138 +Transportation and warehousing:65 11.139 +Communications: 11.140 +Communications, except radio and TV:66 11.141 +Radio and television broadcasting:67 11.142 +Utilities: 11.143 +Private utilities:68 11.144 +Public utilities: 11.145 +Federal government enterprises:78 11.146 +Local government enterprises:79 11.147 +Economic services: 11.148 +Wholesale and retail trade:69 11.149 +Financial services: 11.150 +Banking and insurance:70 11.151 +Real estate and rental:71 11.152 +Direct services: 11.153 +Commercial services: 11.154 +Business support services:73 11.155 +Agricultural support services:4 11.156 +Personal services: 11.157 +Health, education, and social services:77 11.158 +Non-institutional personal service: 11.159 +Personal support services: 11.160 +Hotels, beauty care, etc.:72 11.161 +Automobile repair and services:75 11.162 +Recreational services: 11.163 +Eating and drinking places:74 11.164 +Amusements:76 11.165 + 11.166 +8490,2182,42,467,,,,,, 11.167 +,,,59639,,84,58,3,4,7 11.168 +,,1,15,3,4,79,7,107, 11.169 +,23,,,,,,,5,2 11.170 +7,1,,,,,,3,, 11.171 +,2,,1,,,,,, 11.172 +,,,5,2,,,1,, 11.173 +,3,19,545,,73,120,5,, 11.174 + 11.175 +16775,2871,66,460,,,,3,, 11.176 +,,,22546,3354,774,18,18,29,7 11.177 +,,1,9,1,2,143,54,119,2 11.178 +2,10,,,,3,,,6,1 11.179 +3,1,,,,,,2,, 11.180 +,1,,,,,,,, 11.181 +,1,,25,7,,,392,88,2 11.182 +28,39,42,1202,,1114,187,1731,1, 11.183 + 11.184 +,,281,26,,,,,, 11.185 +,,,1465,,1,1,343,2,4601 11.186 +5,3,4,44,1,,47,3,21,29 11.187 +1,8,,,1,1,,,,10 11.188 +,7,,,,1,1,1,, 11.189 +,,,,,1,,,2, 11.190 +1,2,,7,,,,5,5, 11.191 +,,,1112,,,23,22,, 11.192 + 11.193 +3106,4127,1232,304,,1,11,1,1,2 11.194 +1025,1972,1,223,,2,,1,,110 11.195 +,1,,4,1,1,235,13,5,1 11.196 +5,1,,,1,3,1,1,,1 11.197 +,2,1,,,,,,, 11.198 +1,,2,,1,3,2,,2,2 11.199 +1,,2,1,14,2,,36,1631,9 11.200 +3140,111,23,3,,169,258,2,8, 11.201 + 11.202 +,,,,184,1,,,, 11.203 +,,2,1,,,,,,1 11.204 +,,,1,1,1,135,6,2,9 11.205 +2,,,,,6,2452,17,,7 11.206 +6,65,,1,1,1,5,1,3,1 11.207 +1,,1,,4,,1,8,9, 11.208 +,,1,,,,,3,, 11.209 +,,,,,,,,, 11.210 + 11.211 +,,,,22,240,,,, 11.212 +,,,2,,,,,, 11.213 +,,,5,,1,504,26,8,20 11.214 +9,4,,,4,8,72,1720,1,26 11.215 +1,14,,,,,5,1,3, 11.216 +,,2,,1,1,3,36,7,1 11.217 +,7,2,2,,,,,, 11.218 +,,,,,,,,,1 11.219 + 11.220 +17,4,,,11,13,4458,8,16,2 11.221 +,,12,154,9,37,7,7,4,11 11.222 +1,6,1,332,6,6,346,136,26,1 11.223 +31,46,1,1,2,354,2477,36,,10 11.224 +13,75,1,4,6,2,8,1,6,3 11.225 +3,4,5,6,8,8,6,5,66,8 11.226 +2,3,11,5,148,,,11672,59,2 11.227 +110,,2,79,14,9,32,1234,304,1 11.228 + 11.229 +,,,,,,,5725,50,2 11.230 +,,,13,,7,8,,3,1 11.231 +,,,19,3,3,10216,1144,117,158 11.232 +99602,263,,1,4,62,29,3,41,1 11.233 +1,6,,1,1,,6,4,7,1 11.234 +,1,,,,,6,2,, 11.235 +,5,14,4,220,,,33012,, 11.236 +,,,,,,,,17,3 11.237 + 11.238 +2,236,3,6,15,3,,,189,8 11.239 +1917,1728,,19,,,2,,1,3 11.240 +,,,234,1,2,316,20,33,38 11.241 +401,43,,,281,1742,148,22,,8 11.242 +1,14,,,,,3,1,2, 11.243 +2,,1,,3,3,3,1,5,1 11.244 +,3,2,35,,,,,, 11.245 +,,2,,,1,2,,, 11.246 + 11.247 +,1,,,,,,2,1,75 11.248 +,,,26,,,,,, 11.249 +,,,45,,2,1632,80,26,8 11.250 +41,12,2,,6,97,48,3,,1 11.251 +,4,,,,,1,3,1, 11.252 +,14,,,,,4,1,1, 11.253 +,3,7,2,2,,,8,, 11.254 +1,,,,,,,,4, 11.255 + 11.256 +,,,,,,,,, 11.257 +,,,,,,,,, 11.258 +,,,,,,,,, 11.259 +,,,,,,,,, 11.260 +,,,,,,,,, 11.261 +,,,,,,,,, 11.262 +,,,,,,,,, 11.263 +,,,,,,,,, 11.264 + 11.265 +207,497,355,123,19,9,146,4313,31,15 11.266 +594,211,68,867,14,113,34,102,29,177 11.267 +3,53,50,370,90,120,464,176,112,42 11.268 +758,244,4,12,65,316,614,179,46,276 11.269 +163,179,49,23,49,24,43,34,63,33 11.270 +406,41,97,47,37,139,196,34,209,148 11.271 +44,60,52,71,4790,5685,3,14571,2747,410 11.272 +24266,576,722,554,522,720,1298,584,3439,12 11.273 + 11.274 +,,18,,,,,,, 11.275 +23,1,1538,,,,,,, 11.276 +,,,,,,,,, 11.277 +,1,,,,59,20,,,13 11.278 +4,2,3,,,,2,6,,1 11.279 +,,4,,,104,2,,10,108 11.280 +21,1,1,1,2,,,1,5,2 11.281 +2,,120,,,,3,,,33 11.282 + 11.283 +11321,,104,255,,1,,7,1, 11.284 +10,3,1,50209,4,2,10,13,9,6 11.285 +,29,5,402,7,23,581,86,887,218 11.286 +47,43,453,19,1,26,6,5,5,8 11.287 +8,8,1,1,2,2,3,5,4,3 11.288 +11,4,5,3,1,8,12,3,5,8 11.289 +4,96,7,36,149,,1,379,583,15 11.290 +10,163,178,39923,3,568,4151,1630,1,1 11.291 + 11.292 +,,,,,,,,, 11.293 +,,,,3607,,,,, 11.294 +,,,1,,,,,, 11.295 +,,,,,,,,5, 11.296 +,,,,,,,,, 11.297 +,,,,,,,,, 11.298 +,,,,,,,,, 11.299 +,,,,,,,,, 11.300 + 11.301 +,15,,,,1,42,,1,4 11.302 +,,4,1,1,10645,2270,11372,4394,19 11.303 +,932,32,807,2,49,25,755,13,2 11.304 +3,957,,210,8,205,2,33,,5 11.305 +3,16,1,1,,1,5,13,4,1 11.306 +9,2,4,42,22,7,11,1,31,116 11.307 +12,370,7,394,4,,,3,1, 11.308 +1,212,39,1,,51,64,14,,4 11.309 + 11.310 +36,82,54,34,,,,,, 11.311 +1892,470,3,19,,234,769,147,1066,62 11.312 +,200,220,411,1,62,13,22,21,1 11.313 +25,938,,191,2,3,2,4,,4 11.314 +3,11,2,1,1,1,5,3,109,28 11.315 +5,2,7,2,2,4,6,5,315,3 11.316 +241,262,16,54,61,,,4,69, 11.317 +1,24,42,28,19,24,24,5,1,3 11.318 + 11.319 +,,,,,1,16,14,3,1 11.320 +38,11,15,17,2,39,105,9259,161,15 11.321 +,44,10,20,2,6,4,8,2, 11.322 +2,21,,20,6,8,12,4,1,6 11.323 +4,14,4,1,1,1,3,2,7,2 11.324 +6,2,5,2,2,37,42,1,20,15 11.325 +17,39,3,29,129,68,,21,118, 11.326 +10,526,74,,67,125,578,3,6,2 11.327 + 11.328 +,57,15,57,,,,,, 11.329 +87,72,2,73,,8,25,827,443,1 11.330 +,49,4,8,,2,36,4,4,2 11.331 +1,14,,1,2,1,8,5,,4 11.332 +54,7,6,2,3,2,5,1,4,2 11.333 +2,4,5,3,3,1,1,9,3364,108 11.334 +93,4,1,87,139,,,41,73,135 11.335 +8,636,25,97,,65,613,158,2,1 11.336 + 11.337 +11,12,,,5,22,112,,2,2 11.338 +20859,2899,31,39,3,5,16,1,30,14617 11.339 +177,1862,904,3542,11,26,113,25,15,1 11.340 +40,301,,42,139,211,96,118,16,120 11.341 +75,211,5,26,16,13,20,32,50,7 11.342 +24,57,38,74,37,51,23,5,218,41 11.343 +1138,59,8,494,39,,,128,986, 11.344 +7,128,30,25,,109,76,,,6 11.345 + 11.346 +4,173,2,15,,,,,, 11.347 +,,20,53,3,,,,,3 11.348 +3,8,4,2,,,,,, 11.349 +,5,,1,56,,7,14,,28 11.350 +20,3,,1,2,4,6,2,6,1 11.351 +,21,10,16,,21,1,,6,7 11.352 +,1,,5,,,,,21, 11.353 +,,,,,,,,,1 11.354 + 11.355 +,,,,,,,,, 11.356 +105,34,3,,,,,,, 11.357 +,32,2,,,,,,, 11.358 +,,,,,,,1,,1 11.359 +,1,,,,,,,, 11.360 +5,,3,,1,416,38,,1,16 11.361 +92,7,1,,,,,,, 11.362 +,2,,,,2,,,,6 11.363 + 11.364 +,,,,,,,,, 11.365 +783,187,1,,,,,,,1 11.366 +,,119,,,,,,, 11.367 +,1,,,,,3,1,,1 11.368 +4,1,1,,1,4,1,,1, 11.369 +1,1,1,34,1,,,2,528,28 11.370 +102,1,,,,,,,, 11.371 +,,,,,2,,,, 11.372 + 11.373 +159,66,2,14,,1,10,5,41,4 11.374 +958,500,10,3488,240,59,125,213,64,65 11.375 +,40,31,12052,8290,10266,837,426,432,21 11.376 +147,1073,,47,31,565,12,36,20,52 11.377 +112,75,23,4,4,12,15,14,70,8 11.378 +276,22,189,58,12,116,225,10,157,21 11.379 +17,318,578,435,139,73,1,135,4028,847 11.380 +133,252,7556,425,48,33,1911,95,15,19 11.381 + 11.382 +3,119,2,102,,,,3,4, 11.383 +9,4,39,6972,111,258,90,253,144,132 11.384 +34,164,179,1062,780,178,437,311,1051,83 11.385 +444,1040,10,81,510,174,60,91,41,190 11.386 +188,451,39,36,7,7,81,18,87,106 11.387 +252,145,130,246,227,201,211,102,143,18 11.388 +17,232,153,406,62,22,,18,1339,2 11.389 +1,80,216,979,1,1,157,35,,12 11.390 + 11.391 +19,30,1,10,1,1,10,20,8,2 11.392 +13,2,56,1863,195,22,19,83,37,35 11.393 +2,33,23,126,35,6089,193,31,198,65 11.394 +25,77,2,18,30,42,34,39,194,55 11.395 +40,71,13,10,17,14,32,26,34,29 11.396 +147,26,62,21,22,385,117,19,79,126 11.397 +35,103,40,77,551,336,3,313,3311,4261 11.398 +783,467,8369,223,33,124,8226,444,34,14 11.399 + 11.400 +189,6790,317,1732,63,126,499,592,118,69 11.401 +748,488,77,2403,27,807,580,112,106,919 11.402 +1,50,96,2225,504,1356,21439,12274,4730,2675 11.403 +4126,3656,116,56,726,910,1623,885,12,83 11.404 +168,915,6,10,16,8,135,194,45,12 11.405 +84,102,176,75,125,165,1070,427,388,73 11.406 +67,247,1527,435,223,18,1,1059,54,13 11.407 +361,215,1535,88,15,73,5200,11,177,26 11.408 + 11.409 +,,,,,,,1,3, 11.410 +,,42,81,1,5371,2944,1722,361,52 11.411 +4,88,31,1529,194,39,923,1563,179,632 11.412 +48,13586,,88,6,291,15,689,25,19 11.413 +70,162,2,4,3,6,41,18,32,6 11.414 +116,94,97,230,179,318,267,110,252,61 11.415 +166,236,167,654,,,,,, 11.416 +,,39,,,,,,,11 11.417 + 11.418 +197,,,3,,,,6,1,1 11.419 +94,45,2,1404,14,78,28,175,6,1 11.420 +,,,123,,2,483,162,3470,30 11.421 +625,31,35,18,,37,1,1,7,16 11.422 +14,16,,,,,1,1,2,2 11.423 +1,,,,,1,1,2,7, 11.424 +1,11,2,4,9,88,,32,193,10 11.425 +18,843,396,164,,6,8626,53,9, 11.426 + 11.427 +,,4,,,,,13,1, 11.428 +2897,2304,7,2,,3,5,,2,294 11.429 +,166,130,23,41,27,164,75,67,137 11.430 +10,59,,,25,76,28,44,253,157 11.431 +116,313,9,28,22,9,32,2,13,7 11.432 +82,59,70,140,42,52,10,26,651,80 11.433 +179,33,3,138,38,62,,2,, 11.434 +1,1,115,,642,1,22,2,,3 11.435 + 11.436 +1000,6006,344,652,66,76,729,395,234,47 11.437 +7670,3934,108,1474,56,271,117,282,50,654 11.438 +7,96,74,1862,254,335,2729,731,562,228 11.439 +10211,929,17,13,205,743,739,510,41,223 11.440 +89,253,83,21,43,59,124,84,199,69 11.441 +408,116,190,29,60,185,299,72,333,350 11.442 +135,196,156,190,17282,262,1,16722,9508,973 11.443 +967,693,2590,462,1635,332,3286,633,677,26 11.444 + 11.445 +375,490,11,90,37,52,242,28,68,8 11.446 +1332,1068,188,4014,424,431,525,331,527,410 11.447 +1,956,672,2053,61,510,907,888,2006,52 11.448 +260,4529,,465,83,236,117,396,28,416 11.449 +284,1311,82,299,294,122,151,218,306,42 11.450 +2099,462,535,878,469,2926,2642,471,7589,387 11.451 +396,1176,1315,934,1336,158,,176,1983,108 11.452 +505,661,1172,1687,193,159,3596,43,23,95 11.453 + 11.454 +,,,,,,,,, 11.455 +,,,,,3,1,260,162,2 11.456 +,61,5,2,,5,,,, 11.457 +,7,74,1188,,,,,, 11.458 +,2,,,,,1,,, 11.459 +,,,,,,,,, 11.460 +,1,,60,,,,,, 11.461 +,,6,,,,,1,, 11.462 + 11.463 +55,,,4,,,,2,, 11.464 +3,1,,5,,7,,7,2,9 11.465 +,,,1,1,2,7,1,1,1 11.466 +5,11,,474,5,,3,,, 11.467 +,1,,,,,,,,1 11.468 +2,,,,,2,1,,7,2 11.469 +,5,1,53,9,1,,9,147,19 11.470 +6,68,16,4,,23,40,30,1, 11.471 + 11.472 +8,,,3,,,,9,1, 11.473 +288,214,7,3940,,133,35,3,7,65 11.474 +,89,24,9,2,2,69,28,564,10 11.475 +49,572,,1,1118,38,9,23,1,414 11.476 +38,64,4,2,2,3,8,24,8,2 11.477 +39,19,33,103,453,101,522,21,1606,14 11.478 +184,141,223,23,20,4,,4,59,17 11.479 +5,198,58,219,383,1,317,2,1,6 11.480 + 11.481 +,149,2,19,3,24,132,17,40,1 11.482 +20842,5742,33,89,2,10,9,9,6,318 11.483 +2,73,52,142,13,21,165,47,27,86 11.484 +214,237,4,4,133,4489,450,167,7,93 11.485 +44,178,94,19,84,23,224,62,152,209 11.486 +144,108,178,99,54,103,442,32,502,117 11.487 +331,94,79,102,91,28,,94,122,5 11.488 +43,226,55,219,772,5,69,2,39,10 11.489 + 11.490 +8,10,,,47,84,126,466,43,15 11.491 +4855,1146,572,15,1,3,5,4,15,68 11.492 +3,300,1281,46,138,96,337,25,21,47 11.493 +44,625,,4,21,217,9272,475,2729,7095 11.494 +6600,4631,1234,868,1973,777,1446,833,2098,918 11.495 +473,1239,1360,1146,695,437,450,333,9978,1327 11.496 +1538,469,81,514,148,1,,38,15,2 11.497 +,3,45,,,,13,2,,105 11.498 + 11.499 +,,,,3,10,69,1,16,3 11.500 +3725,1033,457,8,,1,30,2,8,29 11.501 +,111,196,118,71,72,982,55,35,63 11.502 +17,169,,2,50,241,1100,14133,1548,3689 11.503 +1115,2276,461,109,97,153,402,295,660,442 11.504 +1115,1088,1454,582,729,1681,1896,1179,2604,2174 11.505 +505,672,429,906,90,110,,35,, 11.506 +,6,62,20,,6,,8,,85 11.507 + 11.508 +,,7,,,,,1,, 11.509 +,,,8858,1,,1,,1, 11.510 +,,,4,3,10,667,111,793,464 11.511 +402,8,,,,4,4,2,405,1 11.512 +16,12,,,,,1,1,1, 11.513 +,1,,,,,1,1,1, 11.514 +,15,3,2,,,,7,181, 11.515 +,,70,,,,,,, 11.516 + 11.517 +9,14,,,,,,46,21,5 11.518 +22247,7495,9,1,,,,,1,126 11.519 +,1,2,1,1,,7,1,13, 11.520 +2,68,,,1,13,5,5,,713 11.521 +4,24,157,4,246,99,94,127,163,3 11.522 +43,138,92,5,3,501,81,23,37,99 11.523 +1233,51,21,6,,,,4,28, 11.524 +177,,,,,,7,4,1,18 11.525 + 11.526 +36,,,1,10,17,257,,15,7 11.527 +144,62,124,636,,1,2,3,5,410 11.528 +1,87,207,14,3,6,37,4,177,18 11.529 +2,216,,17,29,22,212,138,8,1069 11.530 +1037,588,287,195,104,85,138,87,297,94 11.531 +1265,450,429,332,366,686,976,244,12408,601 11.532 +223,514,216,122,83,131,,101,2, 11.533 +2,27,106,387,2961,17,201,62,3,39 11.534 + 11.535 +140,239,31,42,43,41,179,499,69,7 11.536 +6757,3358,212,951,90,8,7,36,8,1148 11.537 +4,813,530,509,107,123,296,65,373,50 11.538 +324,422,,56,17,409,560,458,137,1374 11.539 +548,1717,189,116,198,139,184,245,319,238 11.540 +969,463,313,391,286,1004,1214,496,3671,554 11.541 +394,473,232,334,619,55,,240,477,23 11.542 +14,153,404,95,2016,27,249,17,4,48 11.543 + 11.544 +,,18,51,28,28,221,216,57,20 11.545 +,,57,,,,,,1,2 11.546 +,1,3,1,3,,14,,, 11.547 +10,25,,,,7,33,3,,28 11.548 +15,77,1443,871,566,116,14,109,155,53 11.549 +5,69,149,5,3,8,3,5,1617,17 11.550 +974,8,,5,274,215,,1501,1, 11.551 +6,,138,1,78,,,11,15,34 11.552 + 11.553 +385,882,19,75,,,,,, 11.554 +,,,30,,,,,,2 11.555 +,,,,1,,1,,, 11.556 +,,,,,,3,,,2 11.557 +1,3,2,356,11,1,1,1,1, 11.558 +,,,,,,,,1,1 11.559 +3,,,,19,,,77,19, 11.560 +90,,309,,2,4,,,39, 11.561 + 11.562 +,,,,48,61,805,113,140,22 11.563 +432,50,,,,,,,,5 11.564 +,,,,,,9,,, 11.565 +6,1,,,,134,3,,,3 11.566 +,9,11,2,566,11,1,1,7,1 11.567 +,,2,,,1,,,18, 11.568 +46,2,,,,,,7,, 11.569 +2,,261,,,,1,2,,5 11.570 + 11.571 +,,,,18,13,119,,45,4 11.572 +1221,475,2,3,1,32,,3,1,17 11.573 +,,1,,,,2,2,, 11.574 +,6,,,,5,12,12,,2 11.575 +1,1,,1,2,345,2,10,4,1 11.576 +1,,1,,,,,,23, 11.577 +4,1,,,8,,,10,134, 11.578 +2,,229,,,,,3,,3 11.579 + 11.580 +,,,3,2,3,5,35,7, 11.581 +57,19,124,46,3,15,8,14,7,113 11.582 +1,14,48,34,78,15,33,13,18,2 11.583 +10,206,1,7,51,33,370,499,50,220 11.584 +394,322,188,67,124,67,937,163,308,285 11.585 +316,173,188,62,102,246,252,109,482,618 11.586 +113,135,30,37,83,2,,37,73, 11.587 +3,,183,,13,1,,5,6,23 11.588 + 11.589 +,,,,,,,1,, 11.590 +,,1,156,,166,129,85,16,43 11.591 +1,10,1,295,101,322,595,53,10,2 11.592 +11,185,,3,72,6,56,23,,3 11.593 +3,20,,1,1,2,4,380,5, 11.594 +5,2,1,,,1,3,1,2, 11.595 +5,3,4,18,,,,,21, 11.596 +1,,341,92,,,,,,7 11.597 + 11.598 +21,28,9,11,40,30,442,340,72,12 11.599 +1367,221,184,123,21,1,2,6,3,46 11.600 +,13,76,155,2,9,349,180,141,6 11.601 +201,77,,1,14,98,700,430,7,384 11.602 +65,144,357,469,1082,556,383,567,2087,230 11.603 +113,614,139,101,15,377,54,113,1170,478 11.604 +637,58,82,65,526,92,,188,25,25 11.605 +19,,773,1,43,,,15,3,46 11.606 + 11.607 +57,89,2,9,5,16,119,203,33,5 11.608 +206,76,156,165,3,52,26,46,17,127 11.609 +3,29,51,96,42,33,80,37,31,11 11.610 +36,290,2,14,65,88,349,225,38,252 11.611 +1071,329,451,207,122,149,504,397,474,1382 11.612 +265,311,175,58,56,373,236,79,1860,759 11.613 +303,189,61,71,272,25,,223,424, 11.614 +33,40,181,297,780,6,20,24,81,34 11.615 + 11.616 +,,,1,,,,,, 11.617 +,,10,8,1,2,1,2,3,1 11.618 +,1,11,10,,31,12,2,5, 11.619 +2,16,,,1,2,12,2,,10 11.620 +12,27,3,1,3,5,7,5,19,4 11.621 +9408,3,46,6,7,335,375,12,7,31 11.622 +4,67,31,6,10,,,6,177,31 11.623 +14,788,546,10,2,10,35,9,,72 11.624 + 11.625 +,,,,,,,,, 11.626 +4047,1852,2,61,,,,,1,21 11.627 +,,2,1,,,86,4,3,1 11.628 +2,2,,,,1,6,6,1,96 11.629 +15,9,3,2,2,2,3,8,11,1 11.630 +3,992,5,262,3,13,1,7,1932,3 11.631 +117,4,,24,11,,,11,387, 11.632 +2,38,38,295,735,29,24,16,4,1 11.633 + 11.634 +12,13,,1,6,13,118,334,28,7 11.635 +2365,870,140,2,,,1,,2,30 11.636 +,2,47,7,1,5,56,2,10,1 11.637 +15,23,,,28,18,474,199,2,331 11.638 +66,206,146,80,186,244,356,480,780,73 11.639 +2382,1267,2076,705,250,692,351,221,368,135 11.640 +204,410,85,89,267,,,525,12,1 11.641 +53,21,269,,152,4,,1,162,53 11.642 + 11.643 +,,,,,,,1,, 11.644 +1052,544,1,,,,,43,, 11.645 +,,,,,,,,, 11.646 +,,,,9,,,,,2 11.647 +3,,1,,,,,,1, 11.648 +,3,1,140,,,,,2,1 11.649 +203,,,,24,,,30,36,53 11.650 +55,633,78,1,1,,28,9,14, 11.651 + 11.652 +6,6,1,6,,2,36,31,3,1 11.653 +5440,1911,12,25,,5,2,6,2,25 11.654 +,4,7,9,2,7,10,3,6,1 11.655 +14,106,,1,18,47,17,25,1,20 11.656 +45,15,5,32,4,3,34,4,9,4 11.657 +258,154,247,262,389,725,212,137,1163,11 11.658 +262,93,44,51,94,25,,268,104,42 11.659 +92,39,243,99,308,38,327,32,28,14 11.660 + 11.661 +,,,,,,1,5,, 11.662 +1446,464,1497,3,,,,1,,1 11.663 +,2,3,2,1,6,1,1,1, 11.664 +,8,,,1,1,5,7,,19 11.665 +12,16,20,1,4,3,6,11,9,2 11.666 +42,5,31,1,7,3314,86,3,798,2469 11.667 +201,24,9,11,76,2091,2,13,95,32 11.668 +1,35,71,3,82,6,81,11,2,84 11.669 + 11.670 +,,,,,,,,, 11.671 +,,528,,,14,3,1,3,2 11.672 +,8,9,18,,17,36,7,18,1 11.673 +,82,,1,3,9,12,58,,30 11.674 +25,74,20,1,8,7,30,69,93,15 11.675 +6515,8,953,12,329,15400,9168,743,465,1548 11.676 +23,1009,1678,127,74,727,28,16,18,96 11.677 +19,915,2002,,,,214,2,6,300 11.678 + 11.679 +94,448,7,49,,4,11,12,6,1 11.680 +308,96,12,12,,1,,4,1,15 11.681 +,,2,6,1,7,4,,6,1 11.682 +2,16,,,1,3,12,22,,8 11.683 +24,14,207,87,7,10,8,2,6,94 11.684 +42,5,23,4,312,42,19,680,3356,168 11.685 +79,26,21,10,84,15,,31,173,27 11.686 +90,12,147,15,609,4,554,14,10,6 11.687 + 11.688 +59,71,6,73,38,5,8,8,46,2 11.689 +315,137,52,18,1,2,,13,9,54 11.690 +,2,32,25,4,12,15,2,7,15 11.691 +136,39,,,1,88,101,58,2,75 11.692 +373,85,156,189,244,26,59,20,37,44 11.693 +32,58,74,35,39,99,9,132,48021,57 11.694 +739,34,4,13,438,251,,123,568,48 11.695 +39,19,196,28,10344,37,99,72,33,10 11.696 + 11.697 +,,,9,,,,,, 11.698 +,,2244,,1,,,,, 11.699 +,,4,,,9,,,, 11.700 +1,20,,,,2,9,2,,33 11.701 +22,29,74,3,14,10,14,21,29,52 11.702 +55,14,77,,12,209,31,,55,10609 11.703 +111,33,2,12,1991,,,31,, 11.704 +1,,2,,,,,,,78 11.705 + 11.706 +,,563,14,1,3,,,, 11.707 +4,,2,,,,,,1,3 11.708 +,,1,,,,,,, 11.709 +,,,,,,4,,,3 11.710 +1,1,3,1,2,,1,,2, 11.711 +,,4,,,,1,,47,1 11.712 +952,,,10,1412,12,,108,3,70 11.713 +15,7,397,1,15,256,15,22,35,1 11.714 + 11.715 +,,3,1,,2,16,41,2, 11.716 +1158,506,17,58,3,10,2,10,4,15 11.717 +1,8,6,37,5,7,99,28,57,2 11.718 +36,78,,3,26,13,94,40,2,78 11.719 +16,27,6,3,4,4,27,7,54,7 11.720 +62,255,43,386,7,135,27,13,360,458 11.721 +65,447,34,11,54,6,,173,121,7 11.722 +4,35,72,,18,,3687,5,3,9 11.723 + 11.724 +,,1,8,,,1,4,1, 11.725 +19,7,60,17,1,4,5,8,1,8 11.726 +,2,2,22,6,618,22,5,14,1 11.727 +7,21,,,6,14,11,4,3,11 11.728 +8,18,9,2,5,4,9,9,13,10 11.729 +56,9,26,3,16,199,66,9,25,290 11.730 +13,28,848,18,51,24,18,75,327,248 11.731 +91,566,2373,7,3,181,1201,21,7,12 11.732 + 11.733 +9,14,,7,3,1,6,7,5,1 11.734 +590,196,9,20,1,8,2,867,40,12 11.735 +,22,2,8,3,110,14,3,25,6 11.736 +2,32,,77,1,25,8,6,1,25 11.737 +5,18,1,1,8,5,5,3,5,3 11.738 +52,38,17,83,3,25,18,2,46,13 11.739 +34,30,6,1011,107,54,,91,742,326 11.740 +91,902,679,198,19,110,689,111,17,3 11.741 + 11.742 +1315,975,105,486,58,58,275,369,107,26 11.743 +6625,2280,388,6714,126,300,316,504,160,1073 11.744 +13,317,270,2273,768,1533,4136,1025,1127,400 11.745 +7634,1821,30,96,450,2781,1844,1593,293,751 11.746 +531,752,173,145,204,87,252,191,350,276 11.747 +1277,329,487,222,274,964,1218,407,1650,1238 11.748 +358,378,538,629,31372,555,16,4809,14477,2836 11.749 +774,461,6962,2493,2183,773,4995,3892,216,72 11.750 + 11.751 +207,312,11,15,2,4,26,94,13,2 11.752 +1401,693,118,659,12,160,30,510,54,84 11.753 +2,87,64,170,53,696,237,68,195,27 11.754 +234,213,2,33,43,126,71,91,12,173 11.755 +180,198,37,21,83,30,65,80,155,77 11.756 +427,77,132,40,45,463,324,43,106,334 11.757 +87,172,158,188,1914,1999,10,779,10089,5704 11.758 +1142,1176,7161,826,910,440,4101,250,44,21 11.759 + 11.760 +,,,,,,,,, 11.761 +,,,,,,,,, 11.762 +,,,,,,,,, 11.763 +,,,,,,,,,8 11.764 +,,,,,,,,, 11.765 +,,,,,,,,, 11.766 +,,,,,,12,,, 11.767 +3,,531,,,,,,, 11.768 + 11.769 +797,2774,80,372,408,296,840,1710,560,360 11.770 +1609,613,447,5913,88,1205,419,715,228,1274 11.771 +13,237,276,4204,374,792,7755,1849,841,145 11.772 +5131,2441,34,69,1278,2597,4220,2828,239,651 11.773 +658,1194,174,136,235,101,365,207,415,321 11.774 +928,295,517,311,252,962,1359,330,1767,986 11.775 +334,441,340,396,4173,1383,17,51703,20996,4133 11.776 +7732,4586,4196,4927,1588,1466,8982,759,3442,54 11.777 + 11.778 +2513,4120,392,1253,106,122,994,616,227,47 11.779 +26087,9600,475,17260,199,1371,624,2240,738,2509 11.780 +35,830,626,4088,440,2443,3873,1461,2114,496 11.781 +2718,2547,86,222,558,1221,2701,2948,477,1960 11.782 +1239,1787,578,711,1042,447,657,706,1127,406 11.783 +3086,1253,1600,864,843,3421,3198,800,7188,1384 11.784 +1377,1231,896,1525,5404,471,7,3136,10189,1044 11.785 +1609,1560,4898,8768,11095,513,6175,560,221,151 11.786 + 11.787 +1478,1518,76,260,19,53,271,560,102,102 11.788 +2501,633,120,1889,145,212,81,550,159,397 11.789 +12,318,296,363,66,650,938,178,551,80 11.790 +1337,498,7,129,122,380,317,379,76,297 11.791 +284,421,88,38,87,44,137,128,178,272 11.792 +962,92,364,139,202,516,710,251,683,1058 11.793 +147,216,382,324,3831,1353,16,2096,10827,65279 11.794 +14742,2034,4833,3799,520,646,3105,115,65,33 11.795 + 11.796 +1676,10760,139,1030,45,70,904,9422,228,40 11.797 +1012,396,183,1472,59,130,72,587,194,268 11.798 +6,179,176,408,137,1317,883,357,1173,85 11.799 +857,806,4,62,207,382,273,260,90,380 11.800 +206,359,58,62,71,68,169,108,210,223 11.801 +867,114,357,68,114,3645,664,195,345,459 11.802 +524,344,247,492,3650,2457,87,2100,36419,8924 11.803 +49610,4210,14526,6373,1963,2822,38336,1212,151,76 11.804 + 11.805 +132,154,16,42,3,7,34,70,49,8 11.806 +475,123,61,830,12,54,26,202,72,91 11.807 +3,59,48,261,30,453,236,92,182,44 11.808 +75,158,15,37,35,85,115,103,33,245 11.809 +73,123,26,12,25,17,45,36,66,59 11.810 +1199,63,145,53,89,559,537,106,136,872 11.811 +50,85,124,88,600,263,12,417,3351,1754 11.812 +212,1279,3770,969,220,474,2582,130,37,24 11.813 + 11.814 +374,2040,154,637,87,107,1084,1449,329,92 11.815 +46412,3386,1067,12160,1268,1448,418,1806,463,1036 11.816 +26,842,925,2144,380,4572,4129,1539,9796,499 11.817 +3114,2360,28,337,452,1305,1200,1125,224,1297 11.818 +1060,1524,323,203,446,240,573,417,838,1223 11.819 +3585,637,938,878,541,4241,2842,549,4116,3290 11.820 +680,1330,1552,1529,10966,4755,80,3737,82453,30351 11.821 +13701,5919,39370,8619,3355,5151,25392,1425,325,173 11.822 + 11.823 +14,20,43,120,4,10,41,425,27,13 11.824 +190,61,190,712,24,137,43,245,66,155 11.825 +5,87,76,185,75,1262,526,178,637,82 11.826 +342,406,3,43,62,206,122,155,56,218 11.827 +102,212,45,28,61,39,113,74,205,116 11.828 +779,92,185,71,92,650,673,99,211,1167 11.829 +89,249,297,163,2202,384,20,517,11535,2594 11.830 +1466,556,5472,278,197,552,3557,148,111,32 11.831 + 11.832 +249,297,46,276,37,64,210,239,50,22 11.833 +950,178,32,695,39,65,30,142,36,245 11.834 +3,100,95,218,75,288,141,132,110,33 11.835 +137,177,2,18,68,181,60,120,24,125 11.836 +135,130,46,10,20,33,72,26,73,88 11.837 +148,25,58,26,30,113,256,56,4928,146 11.838 +56,262,96,80,4511,259,1,545,11956,1009 11.839 +424,687,3752,317,429,682,2597,388,33,12 11.840 + 11.841 +,,,352,,,2,8,3,1 11.842 +2,1,1,7,2,,,4,,1 11.843 +,18,8,5,1,16,12,2,10,1 11.844 +3,6,,,2,1,1,3,1,11 11.845 +1,3,2,,1,2,2,,8,1 11.846 +4,,2,,1,14,39,31,28,32 11.847 +27,33,22,11,82,6,343,26,1565,5 11.848 +3,31,4806,1706,,6802,822,50,,1 11.849 + 11.850 +596,44,19,44,5,9,47,58,10,3 11.851 +10,5,14,155,11,48,4,44,66,80 11.852 +3,43,25,62,5,149,134,52,274,16 11.853 +118,173,1,4,11,39,14,37,12,42 11.854 +68,43,7,4,5,4,25,8,32,34 11.855 +60,23,17,17,12,115,125,9,207,124 11.856 +13,81,121,88,445,152,5,317,886,1294 11.857 +253,680,1936,366,59,323,6960,30,17,5 11.858 + 11.859 +10,15,8,81,3,8,15,23,8,7 11.860 +236,72,23,447,50,60,35,292,45,50 11.861 +2,45,50,100,33,1183,113,30,144,33 11.862 +113,95,3,58,29,61,72,52,5,73 11.863 +39,77,16,18,21,18,22,36,55,28 11.864 +117,15,58,58,28,369,131,16,224,239 11.865 +33,80,52,110,333,426,2,829,3763,7195 11.866 +1425,286,3667,291,55,104,2381,618,39,11 11.867 + 11.868 +,,4,33,1,3,5,11,11,2 11.869 +136,40,9,308,5,22,12,15,1,11 11.870 +,5,3,82,8,20,49,13,30, 11.871 +51,20,6,1,6,15,19,17,5,12 11.872 +10,24,3,2,4,2,7,3,7,5 11.873 +29,6,8,5,5,20,28,8,44,16 11.874 +4,12,9,10,212,107,2,57,515,80 11.875 +109,121,146,153,84,24,278,31,3,1 11.876 + 11.877 +1,7,4,5,13,75,39,513,14,12 11.878 +1,,14,4353,5,74,278,69,98,20 11.879 +,26,7,1071,23,45,895,134,560,70 11.880 +826,959,1,1,183,115,1184,2807,10,114 11.881 +45,162,76,72,114,23,140,67,65,16 11.882 +270,12,163,55,54,473,142,86,1360,81 11.883 +14,135,93,905,7080,2598,1,341,1649,2544 11.884 +34,96,1139,126,142,129,65,856,1,21 11.885 + 11.886 +20358,41531,3706,10213,1118,860,12999,94659,4147,920 11.887 +156635,67036,11870,74833,14205,8379,3231,19409,4403,17496 11.888 +180,5740,7022,24423,8988,33375,29925,9466,23680,3645 11.889 +34479,26857,776,2432,6524,17896,26394,13890,4852,16649 11.890 +14164,21872,7167,4945,9244,3139,12495,7637,11631,10223 11.891 +17064,7738,17112,5474,7580,24778,9758,7457,57221,34493 11.892 +12227,14622,9679,10959,132337,79652,966,147758,475550,165728 11.893 +517420,61039,322773,84779,48837,25330,256578,16653,5065,455017 11.894 +* End of file "econ.dat"
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/econ_order.w Mon Oct 03 23:29:42 2011 +0200 12.3 @@ -0,0 +1,289 @@ 12.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 12.5 +\def\title{ECON\_\thinspace ORDER} 12.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 12.7 +\def\<#1>{$\langle${\rm#1}$\rangle$} 12.8 + 12.9 +\prerequisite{GB\_\thinspace ECON} 12.10 +@* Near-triangular ordering. 12.11 +This demonstration program takes a matrix 12.12 +constructed by the |gb_econ| module and permutes the economic sectors 12.13 +so that the first sectors of the ordering tend to be producers of 12.14 +primary materials for other industries, while the last sectors 12.15 +tend to be final-product 12.16 +industries that deliver their output mostly to end users. 12.17 + 12.18 +More precisely, suppose the rows of the matrix represent the outputs 12.19 +of a sector and the columns represent the inputs. This program attempts 12.20 +to find a permutation of rows and columns that minimizes the sum of 12.21 +the elements below the main diagonal. (If this sum were zero, the 12.22 +matrix would be upper triangular; each supplier of a sector would precede 12.23 +it in the ordering, while each customer of that sector would follow it.) 12.24 + 12.25 +The general problem of finding a minimizing permutation is NP-complete; 12.26 +it includes, as a very special case, the {\sc FEEDBACK ARC SET} problem 12.27 +discussed in Karp's classic paper [{\sl Complexity of Computer 12.28 +Computations} (Plenum Press, 1972), 85--103]. 12.29 +Here we use a simple heuristic downhill method 12.30 +to find a permutation that is locally optimum, in the sense that 12.31 +the below-diagonal sum does not decrease if any individual 12.32 +sector is moved to another position while preserving the relative order 12.33 +of the other sectors. We start with a random permutation and repeatedly 12.34 +improve it, choosing the improvement that gives the least positive 12.35 +gain at each step. One of the main motives for the present implementation 12.36 +was to get further experience with this method of cautious descent, which 12.37 +was proposed by A. M. Gleason in {\sl AMS Proceedings of Symposia in Applied 12.38 +Mathematics\/ \bf10} (1958), 175--178. (See the comments below.) 12.39 + 12.40 +@ As explained in |gb_econ|, the subroutine call |econ(n,2,0,s)| 12.41 +constructs a graph whose |n<=79| vertices represent sectors of the 12.42 +U.S. economy, and whose arcs $u\to v$ are assigned numbers corresponding to the 12.43 +flow of products from sector~|u| to sector~|v|. When |n<79|, the 12.44 +|n| sectors are obtained from a basic set of 79 sectors by 12.45 +combining related commodities; if |s=0|, the combination is done in 12.46 +a way that tends to equalize the row sums, while if |s>0| the combination 12.47 +is done by choosing a random subtree of a given 79-leaf tree (where the 12.48 +``randomness'' is fully determined by the value of~|s|). 12.49 + 12.50 +This program uses two random number seeds, one for |econ| and one 12.51 +for choosing the random initial permutation. The former is called~|s| 12.52 +and the latter is called~|t|. A further parameter, |r|, governs the 12.53 +number of repetitions to be made, trying different starting permutations 12.54 +on the same matrix. When |r>1|, new solutions are displayed only when 12.55 +they improve on the previous best. 12.56 + 12.57 +By default, |n=79|, |r=1|, and |s=t=0|. The user can change these 12.58 +default parameters by specifying options 12.59 +on the command line, at least in a \UNIX\ implementation, thereby 12.60 +obtaining a variety of special effects; the relevant 12.61 +command-line options are \.{-n}\<number>, \.{-r}\<number>, 12.62 +\.{-s}\<number>, and/or \.{-t}\<number>. Additional options 12.63 +\.{-v} (verbose), \.{-V} (extreme verbosity), and \.{-g} 12.64 +(greedy or steepest descent instead of cautious descent) are also provided. 12.65 +@^UNIX dependencies@> 12.66 + 12.67 +Here is the overall layout of this \Cee\ program: 12.68 + 12.69 +@p 12.70 +#include "gb_graph.h" /* the GraphBase data structures */ 12.71 +#include "gb_flip.h" /* the random number generator */ 12.72 +#include "gb_econ.h" /* the |econ| routine */ 12.73 +@# 12.74 +@<Global variables@>@; 12.75 +main(argc,argv) 12.76 + int argc; /* the number of command-line arguments */ 12.77 + char *argv[]; /* an array of strings containing those arguments */ 12.78 +{@+unsigned n=79; /* the desired number of sectors */ 12.79 + long s=0; /* random |seed| for |econ| */ 12.80 + long t=0; /* random |seed| for initial permutation */ 12.81 + unsigned r=1; /* the number of repetitions */ 12.82 + long greedy=0; /* should we use steepest descent? */ 12.83 + register int j,k; /* all-purpose indices */ 12.84 + @<Scan the command line options@>; 12.85 + g=econ(n,2,0,s); 12.86 + if (g==NULL) { 12.87 + fprintf(stderr,"Sorry, can't create the matrix! (error code %d)\n", 12.88 + panic_code); 12.89 + return -1; 12.90 + } 12.91 + printf("Ordering the sectors of %s, using seed %ld:\n",g->id,t); 12.92 + printf(" (%s descent method)\n",greedy?"Steepest":"Cautious"); 12.93 + @<Put the graph data into matrix form@>; 12.94 + @<Print an obvious lower bound@>; 12.95 + gb_init_rand(t); 12.96 + while (r--) 12.97 + @<Find a locally optimum permutation and report the below-diagonal sum@>; 12.98 +} 12.99 + 12.100 +@ Besides the matrix $M$ of input/output coefficients, we will find it 12.101 +convenient to use the matrix $\Delta$, where $\Delta_{jk}=M_{jk}-M_{kj}$. 12.102 + 12.103 +@d INF 0x7fffffff /* infinity (or darn near) */ 12.104 +@f Vertex int /* |gb_graph| defines these data types */ 12.105 +@f Arc int 12.106 +@f Graph int 12.107 + 12.108 +@<Global...@>= 12.109 +Graph *g; /* the graph we will work on */ 12.110 +long mat[79][79]; /* the corresponding matrix */ 12.111 +long del[79][79]; /* skew-symmetric differences */ 12.112 +long best_score=INF; /* the smallest below-diagonal sum we've seen so far */ 12.113 + 12.114 +@ @<Scan the command line options@>= 12.115 +while (--argc) { 12.116 +@^UNIX dependencies@> 12.117 + if (sscanf(argv[argc],"-n%u",&n)==1) ; 12.118 + else if (sscanf(argv[argc],"-r%u",&r)==1) ; 12.119 + else if (sscanf(argv[argc],"-s%ld",&s)==1) ; 12.120 + else if (sscanf(argv[argc],"-t%ld",&t)==1) ; 12.121 + else if (strcmp(argv[argc],"-v")==0) verbose=1; 12.122 + else if (strcmp(argv[argc],"-V")==0) verbose=2; 12.123 + else if (strcmp(argv[argc],"-g")==0) greedy=1; 12.124 + else { 12.125 + fprintf(stderr,"Usage: %s [-nN][-rN][-sN][-tN][-g][-v][-V]\n",argv[0]); 12.126 + return -2; 12.127 + } 12.128 +} 12.129 + 12.130 +@ @<Put the graph data into matrix form@>= 12.131 +{@+register Vertex *v; 12.132 + register Arc *a; 12.133 + n=g->n; 12.134 + for (v=g->vertices;v<g->vertices+n;v++) 12.135 + for (a=v->arcs;a;a=a->next) 12.136 + mat[v-g->vertices][a->tip-g->vertices]=a->flow; 12.137 + for (j=0;j<n;j++) 12.138 + for (k=0;k<n;k++) 12.139 + del[j][k]=mat[j][k]-mat[k][j]; 12.140 +} 12.141 + 12.142 +@ The optimum permutation is a function only of the $\Delta$ matrix, because 12.143 +we can subtract any constant from both $M_{jk}$ and $M_{kj}$ without changing 12.144 +the basic problem. More sophisticated lower bounds than the trivial one 12.145 +computed here can be obtained by considering groups of three vertices 12.146 +instead of two. 12.147 + 12.148 +@<Print an obvious lower bound@>= 12.149 +{@+register long s=0; 12.150 + for (j=1;j<n;j++) 12.151 + for (k=0;k<j;k++) 12.152 + if (mat[j][k]<=mat[k][j]) s+=mat[j][k]; 12.153 + else s+=mat[k][j]; 12.154 + printf("(The amount of feed-forward must be at least %d.)\n",s); 12.155 +} 12.156 + 12.157 +@* Descent. 12.158 +At each stage in our search, |mapping| will be the current permutation; 12.159 +in other words, the sector in row and column~|k| will be 12.160 +|g->vertices+mapping[k]|. The current below-diagonal sum will be 12.161 +the value of |score|. We will not actually have to permute anything 12.162 +inside of |mat|. 12.163 + 12.164 +@d sec_name(k) (g->vertices+mapping[k])->name 12.165 + 12.166 +@<Glob...@>= 12.167 +int mapping[79]; /* current permutation */ 12.168 +long score; /* current sum of elements above main diagonal */ 12.169 +long steps; /* the number of iterations so far */ 12.170 + 12.171 +@ @<Find a locally optimum perm...@>= 12.172 +{ 12.173 + @<Initialize |mapping| to a random permutation@>; 12.174 + while(1) { 12.175 + @<Figure out the next move to make; |break| if at local optimum@>; 12.176 + if (verbose) printf("%8d after step %d\n",score,steps); 12.177 + else if (steps%1000==0 && steps>0) { 12.178 + putchar('.'); 12.179 + fflush(stdout); /* progress report */ 12.180 + } 12.181 + @<Take the next step@>; 12.182 + } 12.183 + printf("\n%s is %d, found after %d step%s.\n",@| 12.184 + best_score==INF?"Local minimum feed-forward":"Another local minimum",@| 12.185 + score,steps,steps==1?"":"s"); 12.186 + if (verbose || score<best_score) { 12.187 + printf("The corresponding economic order is:\n"); 12.188 + for (k=0;k<n;k++) printf(" %s\n",sec_name(k)); 12.189 + if (score<best_score) best_score=score; 12.190 + } 12.191 +} 12.192 + 12.193 +@ @<Initialize |mapping| to a random permutation@>= 12.194 +steps=score=0; 12.195 +for (k=0; k<n; k++) { 12.196 + j=gb_unif_rand(k+1); 12.197 + mapping[k]=mapping[j]; 12.198 + mapping[j]=k; 12.199 +} 12.200 +for (j=1; j<n; j++) for (k=0;k<j;k++) score+=mat[mapping[j]][mapping[k]]; 12.201 +if (verbose>1) { 12.202 + printf("\nInitial permutation:\n"); 12.203 + for (k=0;k<n;k++) printf(" %s\n",sec_name(k)); 12.204 +} 12.205 + 12.206 +@ If we move, say, |mapping[5]| to |mapping[3]| and shift the previous 12.207 +entries |mapping[3]| and |mapping[4]| right one, the score decreases by 12.208 +|del[mapping[5]][mapping[3]]+del[mapping[5]][mapping[4]]|. 12.209 + 12.210 +Similarly, if we move |mapping[5]| to |mapping[7]| and shift the previous 12.211 +entries |mapping[6]| and |mapping[7]| left one, the score decreases by 12.212 +|del[mapping[6]][mapping[5]]+del[mapping[7]][mapping[5]]|. 12.213 + 12.214 +The number of possible moves is $(n-1)^2$. Our job is to find the 12.215 +one that makes the score decrease, but by as little as possible (or, if 12.216 +|greedy!=0|, to make the score decrease as much as possible). 12.217 + 12.218 +@<Figure out the next move to make; |break| if at local optimum@>= 12.219 +best_d=greedy? 0: INF; 12.220 +best_k=-1; 12.221 +for (k=0;k<n;k++) {@+register int d=0; 12.222 + for (j=k-1;j>=0;j--) { 12.223 + d+=del[mapping[k]][mapping[j]]; 12.224 + @<Record the move from |k| to |j|, if |d| is better than |best_d|@>; 12.225 + } 12.226 + d=0; 12.227 + for (j=k+1;j<n;j++) { 12.228 + d+=del[mapping[j]][mapping[k]]; 12.229 + @<Record the move...@>; 12.230 + } 12.231 + } 12.232 +if (best_k<0) break; 12.233 + 12.234 +@ @<Record the move...@>= 12.235 +if (d>0 && (greedy? d>best_d: d<best_d)) { 12.236 + best_k=k; 12.237 + best_j=j; 12.238 + best_d=d; 12.239 +} 12.240 + 12.241 +@ @<Glob...@>= 12.242 +long best_d; /* best improvement seen so far on this step */ 12.243 +int best_k,best_j; /* moving |best_k| to |best_j| improves by |best_d| */ 12.244 + 12.245 +@ @<Take the next step@>= 12.246 +if (verbose>1) 12.247 + printf("Now move %s to the %s, past\n",sec_name(best_k), 12.248 + best_j<best_k? "left": "right"); 12.249 +j=best_k; 12.250 +k=mapping[j]; 12.251 +do@+{ 12.252 + if (best_j<best_k) mapping[j]=mapping[--j]; 12.253 + else mapping[j]=mapping[++j]; 12.254 + if (verbose>1) printf(" %s (%d)\n",sec_name(j),@| 12.255 + best_j<best_k?del[mapping[j],mapping[best_k]]: 12.256 + del[mapping[best_k],mapping[j]]); 12.257 +}@+while(j!=best_j); 12.258 +mapping[j]=k; 12.259 +score-=best_d; 12.260 +steps++; 12.261 + 12.262 +@* Comments. 12.263 +How well does cautious descent work? In this application, it 12.264 +is definitely too cautious. For example, after lots of computation with the 12.265 +default settings, it comes up 12.266 +with a pretty good value (457342), but only after taking 39418 steps! 12.267 +Then (if |r>1|) it tries again and stops with 461584 after 47634 steps. 12.268 +The greedy algorithm with the same starting permutations obtains the 12.269 +local minimum 457408 after only 93 steps, then 460411 after 83 steps. 12.270 +The greedy algorithm tends to find solutions that are a bit inferior, 12.271 +but it is so much faster that it allows us to run many 12.272 +more experiments. After 20 trials with the default settings it finds 12.273 +a permutation with only 456315 below the diagonal, 12.274 +and after about 250 more it reduces this upper bound to 456295. 12.275 + 12.276 +The method of stratified greed, which is illustrated in the |football| 12.277 +module, should do better; and it would be interesting to compare it 12.278 +to other methods like simulated annealing and genetic breeding. 12.279 +Comparisons should be made by seeing which method can come up with 12.280 +the best upper bound after calculating for a given number of mems 12.281 +(see |miles_span|). The upper bound obtained in any run is a random 12.282 +variable, so several independent trials of each method should be made. 12.283 + 12.284 +Question: Suppose we divide the vertices into two subsets and prescribe 12.285 +a fixed permutation on each subset. Is it NP-complete to find the 12.286 +optimum way to merge these two permutations---i.e., to find a 12.287 +permutation, extending the given ones, that has the smallest 12.288 +below-diagonal sum? 12.289 + 12.290 +@* Index. We close with a list that shows where the identifiers of this 12.291 +program are defined and used. 12.292 +
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/football.w Mon Oct 03 23:29:42 2011 +0200 13.3 @@ -0,0 +1,620 @@ 13.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 13.5 +\def\title{FOOTBALL} 13.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 13.7 + 13.8 +\prerequisite{GB\_\thinspace GAMES} 13.9 +@* Introduction. This demonstration program uses graphs 13.10 +constructed by the |gb_games| module to produce 13.11 +an interactive program called \.{football}, which finds preposterously 13.12 +long chains of scores to ``prove'' that one given team might outrank another 13.13 +by a huge margin. 13.14 + 13.15 +\def\<#1>{$\langle${\rm#1}$\rangle$} 13.16 +The program will prompt you for a starting team. If you simply type \<return>, 13.17 +it exits; otherwise you should enter a team name (e.g., `\.{Stanford}') 13.18 +before typing \<return>. 13.19 + 13.20 +Then the program will prompt you for another team. If you simply type 13.21 +\<return> at this point, it will go back and ask for a new starting team; 13.22 +otherwise you should specify another name (e.g., `\.{Harvard}'). 13.23 + 13.24 +Then the program will find and display a chain from the starting team 13.25 +to the other one. For example, you might see 13.26 +$$\vbox{\halign{\tt#\hfil\cr 13.27 + Sep 06: Stanford Cardinal 17, Colorado Buffaloes 21 (-4)\cr 13.28 + Nov 17: Colorado Buffaloes 64, Kansas State Wildcats 3 (+57)\cr 13.29 + Sep 29: Kansas State Wildcats 38, New Mexico Lobos 6 (+89)\cr 13.30 + Sep 22: New Mexico Lobos 32, Texas Tech Red Raiders 34 (+87)\cr 13.31 + Nov 17: Texas Tech Red Raiders 62, Southern Methodist Mustangs 7 (+142)\cr 13.32 + Sep 08: Southern Methodist Mustangs 44, Vanderbilt Commodores 7 (+179)\cr 13.33 +\omit\qquad\vdots\cr 13.34 + Nov 10: Cornell Big Red 41, Columbia Lions 0 (+2148)\cr 13.35 + Sep 15: Columbia Lions 6, Harvard Crimson 9 (+2145)\cr}}$$ 13.36 +This chain isn't necessarily optimal, it's just this 13.37 +particular program's best guess; algorithms that 13.38 +find better chains should be fun to invent. 13.39 + 13.40 +Actually this program has two variants. If you invoke it by saying simply 13.41 +`\.{football}', you get chains found by a simple ``greedy algorithm.'' 13.42 +But if you invoke it by saying `\.{football} \<number>' (assuming \UNIX\ 13.43 +command-line conventions), the program works harder. Higher values of 13.44 +\<number> do more calculation and tend to find better chains. For 13.45 +example, the simple greedy algorithm favors Stanford over Harvard by 13.46 +only 781; \.{football}~\.{10} raises this to 1939; the 13.47 +example above corresponds to \.{football}~\.{1000}. 13.48 + 13.49 +@ We use the data types \&{Area}, \&{Vertex}, \&{Arc}, and \&{Graph} 13.50 +defined in |gb_graph|. 13.51 + 13.52 +@f Area int 13.53 +@f Vertex int 13.54 +@f Arc int 13.55 +@f Graph int 13.56 + 13.57 +@ Here is the general layout of this program, as seen by the \Cee\ compiler: 13.58 +@^UNIX dependencies@> 13.59 + 13.60 +@p 13.61 +#include "gb_graph.h" /* the standard GraphBase data structures */ 13.62 +#include "gb_games.h" /* the routine that sets up the graph of scores */ 13.63 +#include "gb_flip.h" /* random number generator */ 13.64 +@# 13.65 +@<Type declarations@>@; 13.66 +@<Global variables@>@; 13.67 +@<Subroutines@>@; 13.68 +main(argc,argv) 13.69 + int argc; /* the number of command-line arguments */ 13.70 + char *argv[]; /* an array of strings containing those arguments */ 13.71 +{ 13.72 + @<Scan the command line options@>; 13.73 + @<Set up the graph@>; 13.74 + while(1) { 13.75 + @<Prompt for starting team and goal team; |break| if none given@>; 13.76 + @<Find a chain from |start| to |goal|, and print it@>; 13.77 + } 13.78 +} 13.79 + 13.80 +@ Let's deal with \UNIX-dependent stuff first. The rest of this program 13.81 +should work without change on any operating system. 13.82 +@^UNIX dependencies@> 13.83 + 13.84 +@<Scan the command line options@>= 13.85 +if (argc==3 && strcmp(argv[2],"-v")==0) verbose=argc=2; /* secret option */ 13.86 +if (argc==1) width=0; 13.87 +else if (argc==2 && sscanf(argv[1],"%d",&width)==1) { 13.88 + if (width<0) width=-width; /* a \UNIX\ user might have used a hyphen */ 13.89 +} else { 13.90 + fprintf(stderr,"Usage: %s [searchwidth]\n",argv[0]); 13.91 + return -2; 13.92 +} 13.93 + 13.94 +@ @<Glob...@>= 13.95 +int width; /* number of cases examined per stratum */ 13.96 +Graph *g; /* the graph containing score information */ 13.97 +Vertex *u,*v; /* vertices of current interest */ 13.98 +Arc *a; /* arc of current interest */ 13.99 +Vertex *start,*goal; /* teams specified by the user */ 13.100 +int mm; /* counter used only in |verbose| mode */ 13.101 + 13.102 +@ An arc from |u| to |v| in the graph generated by |games| has a |len| field 13.103 +equal to the number of points scored by |u| against |v|. 13.104 +For our purposes we want also a |del| field, which gives the difference 13.105 +between the number of points scored by |u| and the number of points 13.106 +scored by~|v| in that game. 13.107 + 13.108 +@d del a.i /* |del| info appears in utility field |a| of an |Arc| record */ 13.109 + 13.110 +@<Set up the graph@>= 13.111 +g=games(0,0,0,0,0,0,0,0); 13.112 + /* this default graph has the data for the entire 1990 season */ 13.113 +if (g==NULL) { 13.114 + fprintf(stderr,"Sorry, can't create the graph! (error code %d)\n", 13.115 + panic_code); 13.116 + return -1; 13.117 +} 13.118 +for (v=g->vertices;v<g->vertices+g->n;v++) 13.119 + for (a=v->arcs;a;a=a->next) 13.120 + if (a->tip>v) { /* arc |a+1| is the mate of arc |a| iff |a->tip>v| */ 13.121 + a->del=a->len-(a+1)->len; 13.122 + (a+1)->del=-a->del; 13.123 + } 13.124 + 13.125 +@* Terminal interaction. While we're getting trivialities out of the way, 13.126 +we might as well take care of the simple dialog that transpires 13.127 +between this program and the user. 13.128 + 13.129 +@<Prompt for...@>= 13.130 +putchar('\n'); /* make a blank line for visual punctuation */ 13.131 +restart: /* if we avoid this label, the |break| command will be broken */ 13.132 +if ((start=prompt_for_team("Starting"))==NULL) break; 13.133 +if ((goal=prompt_for_team(" Other"))==NULL) goto restart; 13.134 +if (start==goal) { 13.135 + printf(" (Um, please give me the names of two DISTINCT teams.)\n"); 13.136 + goto restart; 13.137 +} 13.138 + 13.139 +@ The user must spell team names exactly as they appear in the file 13.140 +\.{games.dat}. Thus, for example, `\.{Berkeley}' and `\.{Cal}' don't 13.141 +work; it has to be `\.{California}'. Similarly, a person must type 13.142 +`\.{Pennsylvania}' instead of `\.{Penn}', `\.{Nevada-Las} \.{Vegas}' 13.143 +instead of `\.{UNLV}'. A backslash is necessary in `\.{Texas} \.{A\\\&M}'. 13.144 + 13.145 +@<Sub...@>= 13.146 +Vertex *prompt_for_team(s) 13.147 + char *s; /* string used in prompt message */ 13.148 +{@+register char *q; /* current position in |buffer| */ 13.149 + register Vertex *v; /* current vertex being examined in sequential search */ 13.150 + char buffer[30]; /* a line of input */ 13.151 + while (1) { 13.152 + printf("%s team: ",s); 13.153 + fflush(stdout); /* make sure the user sees the prompt */ 13.154 + fgets(buffer,30,stdin); 13.155 + if (buffer[0]=='\n') return NULL; /* the user just hit \<return> */ 13.156 + buffer[29]='\n'; 13.157 + for (q=buffer;*q!='\n';q++) ; /* scan to end of input */ 13.158 + *q='\0'; 13.159 + for (v=g->vertices;v<g->vertices+g->n;v++) 13.160 + if (strcmp(buffer,v->name)==0) return v; /* aha, we found it */ 13.161 + printf(" (Sorry, I don't know any team by that name.)\n"); 13.162 + printf(" (One team I do know is %s...)\n", 13.163 + (g->vertices+gb_unif_rand(g->n))->name); 13.164 + } 13.165 +} 13.166 + 13.167 +@*Greed. The main task of this program is to find the longest possible 13.168 +simple path from |start| to |goal|, using |del| as the length of each 13.169 +arc in the path. This is an NP-complete problem, and the number of 13.170 +possibilities is pretty huge, so the present program is content to 13.171 +use heuristics that are reasonably easy to compute. (Researchers are hereby 13.172 +challenged to come up with better heuristics. Does simulated annealing 13.173 +give good results? How about genetic algorithms?) 13.174 + 13.175 +Perhaps the first approach that comes to mind is a simple ``greedy'' approach 13.176 +in which each step takes the largest possible |del| that doesn't prevent 13.177 +us from eventually getting to |goal|. So that's the method we will 13.178 +implement first. 13.179 + 13.180 +@ @<Find a chain from |start| to |goal|, and print it@>= 13.181 +@<Initialize the allocation of auxiliary memory@>; 13.182 +if (width==0) @<Use a simple-minded 13.183 + greedy algorithm to find a chain from |start| to |goal|@>@; 13.184 +else @<Use a stratified heuristic to find a chain from |start| to |goal|@>; 13.185 +@<Print the solution corresponding to |cur_node|@>; 13.186 +@<Recycle the auxiliary memory used@>; 13.187 + 13.188 +@ We might as well use data structures that are more general than we need, 13.189 +in anticipation of a more complex heuristic that will be implemented later. 13.190 +The set of all possible solutions can be viewed as a backtrack tree 13.191 +in which the branches from each node are the games that can possibly 13.192 +follow that node. We will examine a small part of that gigantic tree. 13.193 + 13.194 +@<Type declarations@>= 13.195 +typedef struct node_struct { 13.196 + Arc *a; /* game from the current team to the next team */ 13.197 + int len; /* accumulated length from |start| to here */ 13.198 + struct node_struct *prev; /* node that gave us the current team */ 13.199 + struct node_struct *next; 13.200 + /* list pointer to node in same stratum (see below) */ 13.201 +} node; 13.202 + 13.203 +@ @<Glob...@>= 13.204 +Area node_storage; /* working storage for heuristic calculations */ 13.205 +node *next_node; /* where the next node is slated to go */ 13.206 +node *bad_node; /* end of current allocation block */ 13.207 +node *cur_node; /* current node of particular interest */ 13.208 + 13.209 +@ @<Initialize the allocation of auxiliary memory@>= 13.210 +next_node=bad_node=NULL; 13.211 + 13.212 +@ @<Subroutines@>= 13.213 +node *new_node(x,d) 13.214 + node *x; /* an old node that the new node will call |prev| */ 13.215 + int d; /* incremental change to |len| */ 13.216 +{ 13.217 + if (next_node==bad_node) { 13.218 + next_node=gb_alloc_type(1000,@[node@],node_storage); 13.219 + if (next_node==NULL) return NULL; /* we're out of space */ 13.220 + bad_node=next_node+1000; 13.221 + } 13.222 + next_node->prev=x; 13.223 + next_node->len=(x?x->len:0)+d; 13.224 + return next_node++; 13.225 +} 13.226 + 13.227 +@ @<Recycle the auxiliary memory used@>= 13.228 +gb_free(node_storage); 13.229 + 13.230 +@ When we're done, |cur_node->a->tip| will be the |goal| vertex, and 13.231 +we can get back to the |start| vertex by following |prev| links 13.232 +from |cur_node|. It looks better to print the answers from |start| to 13.233 +|goal|, so maybe we should have changed our algorithm to go the 13.234 +other way. 13.235 + 13.236 +But let's not worry over trifles. It's easy to change 13.237 +the order of a linked list. The secret is simply to think of the list 13.238 +as a stack, from which we pop all the elements off to another stack; 13.239 +the new stack has the elements in reverse order. 13.240 + 13.241 +@<Print the solution corresponding to |cur_node|@>= 13.242 +next_node=NULL; /* now we'll use |next_node| as top of temporary stack */ 13.243 +do@+{@+register node*t; 13.244 + t=cur_node; 13.245 + cur_node=t->prev; /* pop */ 13.246 + t->prev=next_node; 13.247 + next_node=t; /* push */ 13.248 +}@+while (cur_node); 13.249 +for (v=start;v!=goal;v=u,next_node=next_node->prev) { 13.250 + a=next_node->a; 13.251 + u=a->tip; 13.252 + @<Print the score of game |a| between |v| and |u|@>; 13.253 + printf(" (%+d)\n",next_node->len); 13.254 +} 13.255 + 13.256 +@ @<Print the score of game |a| between |v| and |u|@>= 13.257 +{@+register int d=a->date; /* date of the game, 0 means Aug 26 */ 13.258 + if (d<=5) printf(" Aug %02d",d+26); 13.259 + else if (d<=35) printf(" Sep %02d",d-5); 13.260 + else if (d<=66) printf(" Oct %02d",d-35); 13.261 + else if (d<=96) printf(" Nov %02d",d-66); 13.262 + else if (d<=127) printf(" Dec %02d",d-96); 13.263 + else printf(" Jan 01"); /* |d=128| */ 13.264 + printf(": %s %s %d, %s %s %d",v->name,v->nickname,a->len, 13.265 + u->name,u->nickname,a->len-a->del); 13.266 +} 13.267 + 13.268 +@ We can't just move from |v| to any adjacent vertex; we can only 13.269 +go to a vertex from which |goal| can be reached without touching |v| 13.270 +or any other vertex already used on the path from |start|. 13.271 + 13.272 +Furthermore, if the locally best move from |v| is directly to |goal|, 13.273 +we don't want to make that move unless it's our last chance; we can 13.274 +probably do better by making the chain longer. Otherwise, for example, 13.275 +a chain between a team and its worst opponent would consist of 13.276 +only a single game. 13.277 + 13.278 +To keep track of untouchable vertices, we use a utility field 13.279 +called |blocked| in each vertex record. Another utility field, 13.280 +|valid|, will be set to a validation code in each vertex that 13.281 +still leads to the goal. 13.282 + 13.283 +@d blocked u.i 13.284 +@d valid v.v 13.285 + 13.286 +@<Use a simple-minded greedy algorithm to find a chain from |start| to |goal|@>= 13.287 +{ 13.288 + for (v=g->vertices;v<g->vertices+g->n;v++) v->blocked=0,v->valid=NULL; 13.289 + cur_node=NULL; 13.290 + for (v=start;v!=goal;v=cur_node->a->tip) {@+register int d=-10000; 13.291 + register Arc *best_arc; /* arc that achieves |del=d| */ 13.292 + register Arc *last_arc; /* arc that goes directly to |goal| */ 13.293 + v->blocked=1; 13.294 + cur_node=new_node(cur_node,0); 13.295 + if (cur_node==NULL) { 13.296 + fprintf(stderr,"Oops, there isn't enough memory!\n");@+return -2; 13.297 + } 13.298 + @<Set |u->valid=v| for all |u| to which |v| might now move@>; 13.299 + for (a=v->arcs;a;a=a->next) 13.300 + if (a->del>d && a->tip->valid==v) 13.301 + if (a->tip==goal) last_arc=a; 13.302 + else best_arc=a,d=a->del; 13.303 + cur_node->a=(d==-10000?last_arc:best_arc); 13.304 + /* use |last_arc| as a last resort */ 13.305 + cur_node->len+=cur_node->a->del; 13.306 + } 13.307 +} 13.308 + 13.309 +@ A standard marking algorithm supplies the final missing link in 13.310 +our algorithm. 13.311 + 13.312 +@d link w.v 13.313 + 13.314 +@<Set |u->valid=v| for all |u| to which |v| might now move@>= 13.315 +u=goal; /* |u| will be the top of a stack of nodes to be explored */ 13.316 +u->link=NULL; 13.317 +u->valid=v; 13.318 +do { 13.319 + for (a=u->arcs,u=u->link;a;a=a->next) 13.320 + if (a->tip->blocked==0 && a->tip->valid!=v) { 13.321 + a->tip->valid=v; /* mark |a->tip| reachable from |goal| */ 13.322 + a->tip->link=u; 13.323 + u=a->tip; /* push it on the stack, so that its successors 13.324 + will be marked too */ 13.325 + } 13.326 +} while (u); 13.327 + 13.328 +@*Stratified greed. 13.329 +One approach to better chains is the following algorithm, motivated by 13.330 +similar ideas of Pang Chen [Ph.D. thesis, Stanford University, 1989]: 13.331 +Suppose the nodes of a (possibly huge) backtrack tree are classified into 13.332 +a (fairly small) number of strata, by a function $h$ with the property 13.333 +that $h({\rm child})<h({\rm parent})$. Suppose further that we wish to 13.334 +find a node $x$ that maximizes a given function~$f(x)$, where it is 13.335 +reasonable to believe that $f$(child) will be relatively large among 13.336 +nodes in a child's stratum only if $f$(parent) is relatively large in 13.337 +the parent's stratum. Then it makes sense to restrict backtracking to, 13.338 +say, the top $w$ nodes of each stratum, ranked by their $f$ values. 13.339 + 13.340 +The greedy algorithm already described is a special case of this general 13.341 +approach, with $w=1$ and with $h(x)=-($length of chain leading to~$x)$. 13.342 +The refined algorithm we are about the describe uses a general value of $w$ 13.343 +and a somewhat more relevant stratification function: Given a node~$x$ 13.344 +of the backtrack tree for longest paths, corresponding to a path from 13.345 +|start| to a certain vertex~$u=u(x)$, we will let $h(x)$ be the number of 13.346 +vertices that lie between |u| and |goal| (in the sense that the simple 13.347 +path from |start| to~|u| can be extended until it passes through such 13.348 +a vertex and then all the way to~|goal|). 13.349 + 13.350 +Here is the top level of the stratified greedy algorithm. We maintain 13.351 +a linked list of nodes for each stratum, i.e., for each possible value 13.352 +of~$h$. The number of nodes required is bounded by $w$ times the 13.353 +number of strata. 13.354 + 13.355 +@<Use a strat...@>= 13.356 +{ 13.357 + @<Make |list[0]| through |list[n-1]| empty@>; 13.358 + cur_node=NULL; /* |NULL| represents the root of the backtrack tree */ 13.359 + m=g->n-1; /* the highest stratum not yet fully explored */ 13.360 + do@+{ 13.361 + @<Place each child~|x| of |cur_node| into |list[h(x)]|, retaining 13.362 + at most |width| nodes of maximum |len| on each list@>; 13.363 + while (list[m]==NULL) m--,mm=0; 13.364 + cur_node=list[m]; 13.365 + list[m]=cur_node->next; /* remove a node from highest remaining stratum */ 13.366 + if (verbose) @<Print ``verbose'' info about |cur_node|@>; 13.367 + }@+while (m>0); /* exactly one node should be in |list[0]| (see below) */ 13.368 +} 13.369 + 13.370 +@ The calculation of $h(x)$ is somewhat delicate, and we will defer it 13.371 +for a moment. The list manipulation is, however, easy, so we can finish it 13.372 +quickly while it's fresh in our minds. 13.373 + 13.374 +@d MAX_N 120 /* the number of teams in \.{games.dat} */ 13.375 + 13.376 +@<Glob...@>= 13.377 +node *list[MAX_N]; /* the best nodes known in given strata */ 13.378 +int size[MAX_N]; /* the number of elements in a given |list| */ 13.379 +int m,h; /* current lists of interest */ 13.380 +node *x; /* a child of |cur_node| */ 13.381 + 13.382 +@ @<Make |list[0]|...@>= 13.383 +for (m=0;m<g->n;m++) { 13.384 + list[m]=NULL; 13.385 + size[m]=0; 13.386 +} 13.387 + 13.388 +@ The lists are maintained in order by |len|, with the largest |len| value 13.389 +at the end so that we can easily delete the smallest. 13.390 + 13.391 +When |h=0|, we retain only one node instead of~|width| different nodes, 13.392 +because we are interested in only one solution. 13.393 + 13.394 +@<Place node~|x| into |list[h]|, retaining 13.395 + at most |width| nodes of maximum |len|@>= 13.396 +if ((h>0 && size[h]==width) || (h==0 && size[0]>0)) { 13.397 + if (x->len<=list[h]->len) goto done; /* drop node |x| */ 13.398 + list[h]=list[h]->next; /* drop one node from |list[h]| */ 13.399 +} else size[h]++; 13.400 +{@+register node *p,*q; /* node in list and its predecessor */ 13.401 + for (p=list[h],q=NULL; p; q=p,p=p->next) 13.402 + if (x->len<=p->len) break; 13.403 + x->next=p; 13.404 + if (q) q->next=x; 13.405 + else list[h]=x; 13.406 +} 13.407 +done:; 13.408 + 13.409 +@ @<Print ``verbose'' info...@>= 13.410 +{ 13.411 + cur_node->next=(node*)((++mm<<8)+m); /* pack an ID for this node */ 13.412 + printf("[%d,%d]=[%d,%d]&%s (%+d)\n",m,mm,@| 13.413 + cur_node->prev?((unsigned)cur_node->prev->next)&0xff:0,@| 13.414 + cur_node->prev?((unsigned)cur_node->prev->next)>>8:0,@| 13.415 + cur_node->a->tip->name, cur_node->len); 13.416 +} 13.417 + 13.418 +@ Incidentally, it is plausible to conjecture that the stratified algorithm 13.419 +always beats the simple greedy algorithm; but that conjecture is false. 13.420 +For example, the greedy algorithm is able to rank Harvard over Stanford 13.421 +by 1529, while the stratified algorithm achieves only 1527 when 13.422 +|width=1|. On the other hand, the greedy algorithm often fails 13.423 +miserably; when comparing two Ivy League teams, it doesn't find a 13.424 +way to break out of the Ivy and Patriot Leagues. 13.425 + 13.426 +@*Bicomponents revisited. 13.427 +How difficult is it to compute the function $h$? Given a connected graph~$G$ 13.428 +with two distinguished vertices $u$ and~$v$, we wish to count the number 13.429 +of vertices that might appear on a simple path from $u$ to~$v$. 13.430 +(This is {\it not\/} the same as the number of vertices reachable from both 13.431 +$u$ and~$v$. For example, consider a ``claw'' graph with four vertices 13.432 +$\{u,v,w,x\}$ and with edges only from $x$ to the other three vertices; 13.433 +in this graph $w$ is reachable from $u$ and~$v$ but it is not on any simple 13.434 +path between them.) 13.435 + 13.436 +The best way to solve this problem is probably to compute the bicomponents 13.437 +of~$G$, or least to compute some of them. Another demo program, 13.438 +|book_components|, explains the relevant theory in some detail, and 13.439 +we will assume familiarity with that algorithm in the present 13.440 +discussion. 13.441 + 13.442 +Let us imagine extending $G$ to a slightly larger graph $G^+$ by 13.443 +adding a dummy vertex~$o$ that is adjacent only to $v$. Suppose we determine 13.444 +the bicomponents of $G^+$ by depth-first search starting at~$o$. 13.445 +These bicomponents form a tree rooted at the bicomponent that contains 13.446 +just $o$ and~$v$. The number of vertices on paths between $u$ and~$v$, 13.447 +not counting $v$ itself, is then the number of vertices in the bicomponent 13.448 +containing~$u$ and in any other bicomponents between that one and the root. 13.449 + 13.450 +Strictly speaking, each articulation point belongs 13.451 +to two or more bicomponents. But we will assign each articulation point 13.452 +to its bicomponent that is nearest the root of the tree; then the vertices 13.453 +of each bicomponent are precisely the vertices output in bursts by the 13.454 +depth-first procedure. The bicomponents we wish to enumerate are $B_1$, $B_2$, 13.455 +\dots,~$B_k$, where $B_1$ is the bicomponent containing~$u$ and 13.456 +$B_{j+1}$ is the bicomponent containing the articulation point associated 13.457 +with~$B_j$; we stop at~$B_k$ when its associated articulation point is~$v$. 13.458 +(Often $k=1$.) 13.459 + 13.460 +The ``children'' of a given graph~$G$ are obtained by removing vertex~$u$ 13.461 +and by considering paths from $u'$ to~$v$, where $u'$ is a vertex 13.462 +formerly adjacent to~$u$; thus $u'$ is either in~$B_1$ or it is $B_1$'s 13.463 +associated articulation point. Removing $u$ will, in general, split 13.464 +$B_1$ into a tree of smaller bicomponents, but $B_2,\ldots,B_k$ will be 13.465 +unaffected. The implementation below does not take full advantage of this 13.466 +observation, because the amount of memory required to avoid recomputation 13.467 +would probably be prohibitive. 13.468 + 13.469 +@ The following program is copied almost verbatim from |book_components|. 13.470 +Instead of repeating the commentary that appears there, we will mention 13.471 +only the significant differences. One difference is that we start 13.472 +the depth-first search at a definite place, the |goal|. 13.473 + 13.474 +@<Place each child~|x| of |cur_node| into |list[h(x)]|, retaining 13.475 + at most |width| nodes of maximum |len| on each list@>= 13.476 +@<Make all vertices unseen and all arcs untagged, except for vertices 13.477 + that have already been used in steps leading up to |cur_node|@>; 13.478 +@<Perform a depth-first search with |goal| as the root, finding 13.479 + bicomponents and determining the number of vertices accessible 13.480 + between any given vertex and |goal|@>; 13.481 +for (a=(cur_node? cur_node->a->tip: start)->arcs; a; a=a->next) 13.482 + if ((u=a->tip)->untagged==NULL) { /* |goal| is reachable from |u| */ 13.483 + x=new_node(cur_node,a->del); 13.484 + if (x==NULL) { 13.485 + fprintf(stderr,"Oops, there isn't enough memory!\n");@+return -3; 13.486 + } 13.487 + x->a=a; 13.488 + @<Set |h| to the number of vertices on paths between |u| and |goal|@>; 13.489 + @<Place node...@>; 13.490 + } 13.491 + 13.492 +@ Setting the |rank| field of a vertex to infinity, before beginning 13.493 +a depth-first search, is tantamount to removing that vertex from 13.494 +the graph, because it tells the algorithm not to look further at 13.495 +such a vertex. 13.496 + 13.497 +@d rank z.i /* when was this vertex first seen? */ 13.498 +@d parent u.v /* who told me about this vertex? */ 13.499 +@d untagged x.a /* what is its first untagged arc? */ 13.500 +@d min v.v /* how low in the tree can we jump from its mature descendants? */ 13.501 + 13.502 +@<Make all vertices unseen and all arcs untagged, except for vertices 13.503 + that have already been used in steps leading up to |cur_node|@>= 13.504 +for (v=g->vertices; v<g->vertices+g->n; v++) { 13.505 + v->rank=0; 13.506 + v->untagged=v->arcs; 13.507 +} 13.508 +for (x=cur_node;x;x=x->prev) 13.509 + x->a->tip->rank=g->n; /* ``infinite'' rank (or close enough) */ 13.510 +start->rank=g->n; 13.511 +nn=0; 13.512 +active_stack=settled_stack=NULL; 13.513 + 13.514 +@ @<Glob...@>= 13.515 +Vertex * active_stack; /* the top of the stack of active vertices */ 13.516 +Vertex *settled_stack; /* the top of the stack of bicomponents found */ 13.517 +int nn; /* the number of vertices that have been seen */ 13.518 +Vertex dummy; /* imaginary parent of |goal|; its |rank| is zero */ 13.519 + 13.520 +@ The |settled_stack| will contain a list of all bicomponents in 13.521 +the opposite order from which they are discovered. This is the order 13.522 +we need for computing the |h| function in each bicomponent later. 13.523 + 13.524 +@<Perform a depth-first search...@>= 13.525 +{ 13.526 + v=goal; 13.527 + v->parent=&dummy; 13.528 + @<Make vertex |v| active@>; 13.529 + do @<Explore one step from the current vertex~|v|, possibly moving 13.530 + to another current vertex and calling~it~|v|@>@; 13.531 + while (v!=&dummy); 13.532 + @<Use |settled_stack| to put the mutual reachability count for 13.533 + each vertex |u| in |u->parent->rank|@>; 13.534 +} 13.535 + 13.536 +@ @<Make vertex |v| active@>= 13.537 +v->rank=++nn; 13.538 +v->link=active_stack; 13.539 +active_stack=v; 13.540 +v->min=v->parent; 13.541 + 13.542 +@ @<Explore one step from the current vertex~|v|, possibly moving 13.543 + to another current vertex and calling~it~|v|@>= 13.544 +{@+register Vertex *u; /* a vertex adjacent to |v| */ 13.545 + register Arc *a=v->untagged; /* |v|'s first remaining untagged arc, if any */ 13.546 + if (a) { 13.547 + u=a->tip; 13.548 + v->untagged = a->next; /* tag the arc from |v| to |u| */ 13.549 + if (u->rank) { /* we've seen |u| already */ 13.550 + if (u->rank < v->min->rank) 13.551 + v->min=u; /* non-tree arc, just update |v->min| */ 13.552 + } else { /* |u| is presently unseen */ 13.553 + u->parent = v; /* the arc from |v| to |u| is a new tree arc */ 13.554 + v = u; /* |u| will now be the current vertex */ 13.555 + @<Make vertex |v| active@>; 13.556 + } 13.557 + } else { /* all arcs from |v| are tagged, so |v| matures */ 13.558 + u=v->parent; /* prepare to backtrack in the tree */ 13.559 + if (v->min==u) @<Remove |v| and all its successors on the active stack 13.560 + from the tree, and report them as a bicomponent of the graph 13.561 + together with~|u|@>@; 13.562 + else /* the arc from |u| to |v| has just matured, 13.563 + making |v->min| visible from |u| */@, 13.564 + if (v->min->rank < u->min->rank) 13.565 + u->min=v->min; 13.566 + v=u; /* the former parent of |v| is the new current vertex |v| */ 13.567 + } 13.568 +} 13.569 + 13.570 +@ When a bicomponent is found, we reset the |parent| field of each vertex 13.571 +so that, afterwards, two vertices will belong to the same bicomponent 13.572 +if and only if they have the same |parent|. (This trick was not used 13.573 +in |book_components|, but it does appear in the similar algorithm of 13.574 +|roget_components|.) The new parent, |v|, will represent that bicomponent 13.575 +in subsequent computation; we put it onto |settled_stack|. 13.576 +We also reset |v->rank| to be the bicomponent's size, plus a constant 13.577 +large enough to keep the algorithm from getting confused. (Vertex~|u| 13.578 +may still have untagged arcs leading into this bicomponent; we need to 13.579 +keep the ranks at least as big as the rank of |u->min|.) Notice that 13.580 +|v->min| is |u|, the articulation point associated with this bicomponent. 13.581 +Later the |rank| field will 13.582 +contain the sum of all counts between here and the root. 13.583 + 13.584 +We don't have to do anything when |v==goal|; the trivial root bicomponent 13.585 +always comes out last. 13.586 + 13.587 +@<Remove |v| and all its successors on the active stack...@>= 13.588 +{@+if (v!=goal) {@+register Vertex *t; /* runs through the vertices of the 13.589 + new bicomponent */ 13.590 + int c=0; /* the number of vertices removed */ 13.591 + t=active_stack; 13.592 + while (t!=v) { 13.593 + c++; 13.594 + t->parent=v; 13.595 + t=t->link; 13.596 + } 13.597 + active_stack=v->link; 13.598 + v->parent=v; 13.599 + v->rank=c+g->n; /* the true component size is |c+1| */ 13.600 + v->link=settled_stack; 13.601 + settled_stack=v; 13.602 + } 13.603 +} 13.604 + 13.605 +@ So here's how we sum the ranks. When we get to this step, the |settled| 13.606 +stack contains all bicomponent representatives except |goal| itself. 13.607 + 13.608 +@<Use |settled_stack| to put the mutual reachability count for 13.609 + each vertex |u| in |u->parent->rank|@>= 13.610 +while (settled_stack) { 13.611 + v=settled_stack; 13.612 + settled_stack=v->link; 13.613 + v->rank+=v->min->parent->rank+1-g->n; 13.614 +} /* note that |goal->parent->rank=0| */ 13.615 + 13.616 +@ And here's the last piece of the puzzle. 13.617 + 13.618 +@<Set |h| to the number of vertices on paths between |u| and |goal|@>= 13.619 +h=u->parent->rank; 13.620 + 13.621 +@* Index. Finally, here's a list that shows where the identifiers of this 13.622 +program are defined and used. 13.623 +
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/games.dat Mon Oct 03 23:29:42 2011 +0200 14.3 @@ -0,0 +1,792 @@ 14.4 +* File "games.dat" from the Stanford GraphBase (C) 1992 Stanford University 14.5 +* College football teams and scores, 1990 14.6 +* This file may be freely copied but please do not change it in any way! 14.7 +* (Checksum parameters 787,644169130) 14.8 +USAF Air Force(Falcons)Western Athletic;,;5, 14.9 +AKRON Akron(Zips)Independent;,;, 14.10 +BAMA Alabama(Crimson Tide)Southeastern;104,;13,1 14.11 +AZ Arizona(Wildcats)Pacific Ten;370,48;, 14.12 +AZ-ST Arizona State(Sun Devils)Pacific Ten;113,8;, 14.13 +ARK Arkansas(Razorbacks)Southwest;647,79;, 14.14 +ARMY Army(Cadets)Independent;,;, 14.15 +AUBN Auburn(Tigers)Southeastern;1385,619;288,39 14.16 +BALL Ball State(Cardinals)Mid-American;,;, 14.17 +BAYL Baylor(Bears)Southwest;,;, 14.18 +BOST Boston College(Eagles)Independent;,;, 14.19 +BOWLG Bowling Green(Falcons)Mid-American;,;, 14.20 +BYU Brigham Young(Cougars)Western Athletic;1171,430;246,41 14.21 +BROWN Brown(Bears)Ivy;,;, 14.22 +BUCK Bucknell(Bisons)Patriot;,;, 14.23 +CAL California(Golden Bears)Pacific Ten;,;37, 14.24 +CMICH Central Michigan(Chippewas)Mid-American;,;, 14.25 +CINCI Cincinnati(Bearcats)Independent;,;, 14.26 +CLEM Clemson(Tigers)Atlantic Coast;471,21;950,420 14.27 +COLG Colgate(Red Raiders)Patriot;,;, 14.28 +COLO Colorado(Buffaloes)Big Eight;1041,305;1475,846 14.29 +CO-ST Colorado State(Rams)Western Athletic;9,;67, 14.30 +COLUM Columbia(Lions)Ivy;,;, 14.31 +CORN Cornell(Big Red)Ivy;,;, 14.32 +DART Dartmouth(Big Green)Ivy;,;, 14.33 +DUKE Duke(Blue Devils)Atlantic Coast;,;, 14.34 +ECAR East Carolina(Pirates)Independent;,;, 14.35 +EMICH Eastern Michigan(Hurons)Mid-American;,;, 14.36 +FLA Florida(Gators)Southeastern;163,18;863, 14.37 +FL-ST Florida State(Seminoles)Independent;1367,647;1303,677 14.38 +FORD Fordham(Rams)Patriot;,;, 14.39 +FRES Fresno State(Bulldogs)Big West;51,12;, 14.40 +FULL Fullerton State(Titans)Big West;,;, 14.41 +GA Georgia(Bulldogs)Southeastern;7,;, 14.42 +GTECH Georgia Tech(Yellow Jackets)Atlantic Coast;37,7;1441,847 14.43 +HARV Harvard(Crimson)Ivy;,;, 14.44 +HI Hawaii(Rainbow Warriors)Western Athletic;,;2, 14.45 +HOLY Holy Cross(Crusaders)Patriot;,;, 14.46 +HOUST Houston(Cougars)Southwest;395,;940, 14.47 +ILL Illinois(Fighting Illini)Big Ten;365,25;146,6 14.48 +IND Indiana(Fightin' Hoosiers)Big Ten;,;, 14.49 +IOWA Iowa(Hawkeyes)Big Ten;,;371,57 14.50 +IA-ST Iowa State(Cyclones)Big Eight;,;, 14.51 +KAS Kansas(Jayhawks)Big Eight;,;, 14.52 +KS-ST Kansas State(Wildcats)Big Eight;,;, 14.53 +KENTS Kent State(Golden Flashes)Mid-American;,;, 14.54 +KY Kentucky(Wildcats)Southeastern;,;, 14.55 +LAFAY Lafayette(Leopards)Patriot;,;, 14.56 +LHIGH Lehigh(Engineers)Patriot;,;, 14.57 +LBSU Long Beach State(Forty-Niners)Big West;,;, 14.58 +LSU Louisiana State(Fighting Tigers)Southeastern;25,;, 14.59 +LTECH Louisiana Tech(Bulldogs)Independent;,;, 14.60 +LOUVL Louisville(Cardinals)Independent;5,;775,245 14.61 +MD Maryland(Terps)Atlantic Coast;42,2;, 14.62 +MEMPH Memphis State(Tigers)Independent;,;, 14.63 +MIFL Miami, Florida(Hurricanes)Independent;1013,290;1388,763 14.64 +MIOH Miami, Ohio(Redskins)Mid-American;,;, 14.65 +MICH Michigan(Wolverines)Big Ten;1230,462;1025,426 14.66 +MI-ST Michigan State(Spartans)Big Ten;382,15;610,120 14.67 +MINN Minnesota(Golden Gophers)Big Ten;,;, 14.68 +MISS Mississippi(Rebels)Southeastern;3,;253,7 14.69 +MS-ST Mississippi State(Bulldogs)Southeastern;,;, 14.70 +MO Missouri(Tigers)Big Eight;,;, 14.71 +NAVY Navy(Midshipmen)Independent;,;, 14.72 +NEB Nebraska(Cornhuskers)Big Eight;1047,421;185,41 14.73 +UNLV Nevada-Las Vegas(Rebels)Big West;,;, 14.74 +NMEX New Mexico(Lobos)Western Athletic;,;, 14.75 +NM-ST New Mexico State(Aggies)Big West;,;, 14.76 +NCAR North Carolina(Tar Heels)Atlantic Coast;,;4, 14.77 +NC-ST North Carolina State(Wolfpack)Atlantic Coast;,;30, 14.78 +NIL Northern Illinois(Huskies)Independent;,;, 14.79 +NW Northwestern(Wildcats)Big Ten;,;, 14.80 +NDAME Notre Dame(Fighting Irish)Independent;1451,666;1179,548 14.81 +OSU Ohio State(Buckeyes)Big Ten;467,114;7,1 14.82 +OU Ohio University(Bobcats)Mid-American;,;, 14.83 +OK Oklahoma(Sooners)Big Eight;662,;452, 14.84 +OK-ST Oklahoma State(Cowboys)Big Eight;,;, 14.85 +OR Oregon(Ducks)Pacific Ten;36,2;6,1 14.86 +OR-ST Oregon State(Beavers)Pacific Ten;,;, 14.87 +PAC Pacific(Tigers)Big West;,;, 14.88 +PA-ST Penn State(Nittany Lions)Independent;25,;907,301 14.89 +PENN Pennsylvania(Red \& Blue)Ivy;,;, 14.90 +PITT Pittsburgh(Panthers)Independent;673,140;, 14.91 +PRIN Princeton(Tigers)Ivy;,;, 14.92 +PURD Purdue(Boilermakers)Big Ten;1,;, 14.93 +RICE Rice(Owls)Southwest;,;, 14.94 +RUTG Rutgers(Scarlet Knights)Independent;1,;, 14.95 +SDSU San Diego State(Aztecs)Western Athletic;,;, 14.96 +SJSU San Jose State(Spartans)Big West;,;138,16 14.97 +SCAR South Carolina(Fighting Gamecocks)Independent;40,2;, 14.98 +USC Southern California(Trojans)Pacific Ten;1126,479;266,9 14.99 +SMU Southern Methodist(Mustangs)Southwest;,;, 14.100 +SMISS Southern Mississippi(Golden Eagles)Independent;31,2;48,1 14.101 +SWLA Southwestern Louisiana(Ragin' Cajuns)Independent;,;, 14.102 +STAN Stanford(Cardinal)Pacific Ten;4,;, 14.103 +SYR Syracuse(Orangemen)Independent;2,;121,12 14.104 +TEMP Temple(Owls)Independent;,;, 14.105 +TENN Tennessee(Volunteers)Southeastern;1108,441;993,449 14.106 +TEX Texas(Longhorns)Southwest;214,25;887,268 14.107 +TA&M Texas A\&M(Aggies)Southwest;802,188;627,204 14.108 +TCU Texas Christian(Horned Frogs)Southwest;,;, 14.109 +UTEP Texas-El Paso(Miners)Western Athletic;,;, 14.110 +TTECH Texas Tech(Red Raiders)Southwest;,;, 14.111 +TOL Toledo(Rockets)Mid-American;,;, 14.112 +TUL Tulane(Green Wave)Independent;,;, 14.113 +TULSA Tulsa(Golden Hurricane)Independent;,;, 14.114 +UCLA UCLA(Bruins)Pacific Ten;38,;6, 14.115 +UTAH Utah(Utes)Western Athletic;,;, 14.116 +UT-ST Utah State(Aggies)Big West;,;, 14.117 +VAND Vanderbilt(Commodores)Southeastern;,;, 14.118 +VA Virginia(Cavaliers)Atlantic Coast;1005,272;188,65 14.119 +VTECH Virginia Tech(Gobblers)Independent;,;5,5 14.120 +WAKEF Wake Forest(Demon Deacons)Atlantic Coast;,;, 14.121 +WASH Washington(Huskies)Pacific Ten;345,20;1246,664 14.122 +WA-ST Washington State(Cougars)Pacific Ten;,;, 14.123 +WVA West Virginia(Mountaineers)Independent;10,;, 14.124 +WMICH Western Michigan(Broncos)Mid-American;,;, 14.125 +WIS Wisconsin(Badgers)Big Ten;,;, 14.126 +WYO Wyoming(Cowboys)Western Athletic;16,;7, 14.127 +YALE Yale(Bulldogs)Ivy;,;, 14.128 +>A26 14.129 +COLO31,TENN31 14.130 +>A31 14.131 +USC34,SYR16 14.132 +>S1 14.133 +CO-ST35@USAF33 14.134 +LBSU0@CLEM59 14.135 +LTECH17@ECAR27 14.136 +EMICH10@FRES41 14.137 +TA&M28@HI13 14.138 +VA59@KAS10 14.139 +CMICH17@KY20 14.140 +VTECH13@MD20 14.141 +BAYL0@NEB13 14.142 +NMEX29@NM-ST12 14.143 +MIOH0@NCAR34 14.144 +TULSA3@OK-ST10 14.145 +OU3@PITT35 14.146 +WAKEF17@RICE33 14.147 +LOUVL10@SJSU10 14.148 +DUKE10@SCAR21 14.149 +PAC7@TENN55 14.150 +WA-ST21@TCU3 14.151 +BYU30@UTEP10 14.152 +SWLA48@TUL6 14.153 +UTAH19@UT-ST0 14.154 +KENTS24@WVA35 14.155 +TEMP23@WYO38 14.156 +>S2 14.157 +BOWLG34@CINCI20 14.158 +>S6 14.159 +STAN17@COLO21 14.160 +>S8 14.161 +HI3@USAF27 14.162 +SMISS27@BAMA24 14.163 +ILL16@AZ28 14.164 +BAYL13@AZ-ST28 14.165 +FULL17@AUBN38 14.166 +MIFL21@BYU28 14.167 +CINCI34@CMICH0 14.168 +WMICH27@EMICH24 14.169 +OK-ST7@FLA50 14.170 +ECAR24@FL-ST45 14.171 +NMEX17@FRES24 14.172 +NC-ST13@GTECH21 14.173 +UNLV9@HOUST37 14.174 +OR-ST12@KAS38 14.175 +AKRON10@KENTS38 14.176 +FORD3@LHIGH35 14.177 +GA13@LSU18 14.178 +TOL14@MIOH20 14.179 +UTAH35@MINN29 14.180 +MEMPH21@MISS23 14.181 +TENN40@MS-ST7 14.182 +TCU20@MO19 14.183 +NIL14@NEB60 14.184 +TTECH10@OSU17 14.185 +SDSU21@OR42 14.186 +TEX17@PA-ST13 14.187 +BOST6@PITT29 14.188 +TUL21@RICE10 14.189 +KY8@RUTG24 14.190 +NCAR5@SCAR27 14.191 +VAND7@SMU44 14.192 +TEMP9@SYR19 14.193 +NM-ST27@UTEP24 14.194 +OK34@UCLA14 14.195 +LBSU13@UT-ST27 14.196 +CLEM7@VA20 14.197 +BOWLG21@VTECH7 14.198 +SJSU17@WASH17 14.199 +WYO34@WA-ST13 14.200 +MD14@WVA10 14.201 +CAL28@WIS12 14.202 +>S13 14.203 +HOUST51@TTECH35 14.204 +>S15 14.205 +CMICH14@AKRON14 14.206 +FLA17@BAMA13 14.207 +CO-ST20@AZ-ST31 14.208 +TULSA3@ARK28 14.209 +HOLY7@ARMY24 14.210 +OSU31@BOST10 14.211 +WA-ST36@BYU50 14.212 +YALE27@BROWN21 14.213 +MIFL52@CAL24 14.214 +HARV9@COLUM6 14.215 +PRIN14@CORN17 14.216 +PENN16@DART6 14.217 +VTECH24@ECAR23 14.218 +OU18@EMICH45 14.219 +SMISS17@GA18 14.220 +COLO22@ILL23 14.221 +CINCI10@IOWA63 14.222 +NM-ST7@KS-ST52 14.223 +IND45@KY24 14.224 +BUCK24@LAFAY14 14.225 +MIOH7@LSU35 14.226 +KAS16@LOUVL28 14.227 +CLEM18@MD17 14.228 +IA-ST16@MINN20 14.229 +AUBN24@MISS10 14.230 +FULL13@MS-ST27 14.231 +UT-ST10@MO45 14.232 +AZ25@NMEX10 14.233 +WAKEF15@NC-ST20 14.234 +DUKE27@NW24 14.235 +MICH24@NDAME28 14.236 +PITT28@OK52 14.237 +UNLV19@OR-ST20 14.238 +SJSU28@PAC14 14.239 +WASH20@PURD14 14.240 +COLG17@RUTG28 14.241 +LBSU20@SDSU38 14.242 +PA-ST14@USC19 14.243 +MI-ST23@SYR23 14.244 +UTEP0@TENN56 14.245 +SWLA14@TA&M63 14.246 +NIL14@TOL23 14.247 +SMU7@TUL43 14.248 +STAN31@UCLA32 14.249 +FRES31@UTAH7 14.250 +NAVY14@VA56 14.251 +LTECH21@WMICH27 14.252 +BALL7@WIS24 14.253 +>S22 14.254 +FULL17@AKRON48 14.255 +OR17@AZ22 14.256 +MISS21@ARK17 14.257 +TOL28@BALL16 14.258 +SDSU34@BYU62 14.259 +COLUM16@BUCK41 14.260 +BOWLG0@CMICH17 14.261 +MIOH16@CINCI12 14.262 +CORN24@COLG59 14.263 +UTEP20@CO-ST38 14.264 +LHIGH14@DART33 14.265 +VA59@DUKE0 14.266 +NM-ST3@FRES42 14.267 +BAMA16@GA17 14.268 +MO7@IND58 14.269 +IA-ST35@IOWA45 14.270 +PAC7@LBSU28 14.271 +NC-ST12@MD13 14.272 +UCLA15@MICH38 14.273 +NDAME20@MI-ST19 14.274 +SMISS10@MS-ST13 14.275 +MINN0@NEB56 14.276 +SJSU47@UNLV13 14.277 +TTECH34@NMEX32 14.278 +KY13@NCAR16 14.279 +KS-ST35@NIL42 14.280 +TULSA10@OK52 14.281 +RUTG0@PA-ST28 14.282 +HOLY17@PENN3 14.283 +FORD14@PRIN23 14.284 +NW14@RICE31 14.285 +ECAR20@SWLA10 14.286 +OR-ST3@STAN37 14.287 +PITT20@SYR20 14.288 +COLO29@TEX22 14.289 +OK-ST21@TCU31 14.290 +FL-ST31@TUL13 14.291 +HI19@UTAH7 14.292 +LSU21@VAND24 14.293 +SCAR35@VTECH24 14.294 +USC0@WASH31 14.295 +CAL31@WA-ST41 14.296 +LOUVL9@WVA7 14.297 +KENTS10@WMICH37 14.298 +TEMP24@WIS18 14.299 +USAF12@WYO24 14.300 +LAFAY17@YALE18 14.301 +>S29 14.302 +VAND28@BAMA59 14.303 +CAL20@AZ25 14.304 +CO-ST52@ARK31 14.305 +TENN26@AUBN26 14.306 +BOWLG6@BALL16 14.307 +FORD35@BROWN28 14.308 +MIOH7@CMICH31 14.309 +DUKE7@CLEM26 14.310 +PRIN13@COLG39 14.311 +WASH14@COLO20 14.312 +BUCK42@CORN21 14.313 +MS-ST21@FLA34 14.314 +VTECH28@FL-ST39 14.315 +FULL3@FRES38 14.316 +ECAR15@GA19 14.317 +SCAR6@GTECH27 14.318 +HARV14@HOLY35 14.319 +RICE22@HOUST24 14.320 +EMICH6@IND37 14.321 +WMICH20@IA-ST34 14.322 +NMEX6@KS-ST38 14.323 +CINCI27@KENTS24 14.324 +PENN13@LAFAY20 14.325 +COLUM9@LHIGH42 14.326 +TA&M8@LSU17 14.327 +SWLA10@LTECH24 14.328 +IOWA21@MIFL48 14.329 +MD17@MICH45 14.330 +TUL21@MISS31 14.331 +AZ-ST9@MO30 14.332 +BOST28@NAVY17 14.333 +OR-ST7@NEB31 14.334 +NC-ST12@NCAR9 14.335 +NIL7@NW24 14.336 +PURD11@NDAME37 14.337 +USC35@OSU26 14.338 +TOL27@OU20 14.339 +KAS17@OK31 14.340 +BYU16@OR32 14.341 +UNLV37@PAC28 14.342 +WVA38@PITT24 14.343 +MI-ST34@RUTG10 14.344 +USAF18@SDSU48 14.345 +TCU42@SMU21 14.346 +LOUVL13@SMISS25 14.347 +SJSU29@STAN23 14.348 +BAYL21@TTECH15 14.349 +MEMPH22@TULSA10 14.350 +WYO28@UTAH10 14.351 +ARMY14@WAKEF52 14.352 +UCLA30@WA-ST20 14.353 +>O6 14.354 +NAVY7@USAF24 14.355 +WMICH24@AKRON20 14.356 +WASH42@AZ-ST14 14.357 +TCU54@ARK26 14.358 +DUKE17@ARMY16 14.359 +LTECH14@AUBN16 14.360 +HOUST31@BAYL15 14.361 +RUTG14@BOST19 14.362 +OU10@BOWLG10 14.363 +SJSU34@CAL35 14.364 +GA3@CLEM34 14.365 +UTAH13@CO-ST22 14.366 +LAFAY41@COLUM34 14.367 +SMISS16@ECAR7 14.368 +LSU8@FLA34 14.369 +CORN20@HARV17 14.370 +DART10@HOLY21 14.371 +KAS34@IA-ST34 14.372 +NEB45@KS-ST8 14.373 +CMICH42@KENTS0 14.374 +NM-ST27@LBSU31 14.375 +TULSA14@LOUVL38 14.376 +GTECH31@MD3 14.377 +TUL14@MEMPH21 14.378 +FL-ST22@MIFL31 14.379 +BALL10@MIOH24 14.380 +IOWA12@MI-ST7 14.381 +KY29@MISS35 14.382 +COLO33@MO31 14.383 +FULL10@UNLV29 14.384 +UTEP28@NMEX48 14.385 +FRES18@NIL73 14.386 +IND42@NW0 14.387 +STAN36@NDAME31 14.388 +ILL31@OSU20 14.389 +OK31@OK-ST17 14.390 +UT-ST7@OR52 14.391 +TEMP10@PA-ST48 14.392 +LHIGH22@PENN16 14.393 +BROWN23@PRIN27 14.394 +MINN19@PURD7 14.395 +TEX26@RICE10 14.396 +WA-ST17@USC30 14.397 +BAMA25@SWLA6 14.398 +TTECH24@TA&M28 14.399 +EMICH23@TOL37 14.400 +AZ28@UCLA21 14.401 +SYR49@VAND14 14.402 +WVA21@VTECH26 14.403 +NCAR31@WAKEF24 14.404 +MICH41@WIS3 14.405 +SDSU51@WYO52 14.406 +COLG30@YALE7 14.407 +>O13 14.408 +CAL31@AZ-ST24 14.409 +TTECH49@ARK44 14.410 +VAND6@AUBN56 14.411 +KENTS0@BALL31 14.412 +SMU17@BAYL52 14.413 +ARMY20@BOST41 14.414 +CO-ST9@BYU52 14.415 +HOLY55@BROWN0 14.416 +PRIN9@BUCK14 14.417 +WMICH13@CMICH20 14.418 +IA-ST12@COLO28 14.419 +YALE17@DART27 14.420 +UT-ST24@FRES24 14.421 +PAC67@FULL37 14.422 +MISS28@GA12 14.423 +CLEM19@GTECH21 14.424 +FORD13@HARV19 14.425 +TA&M31@HOUST36 14.426 +PURD0@ILL34 14.427 +OSU27@IND27 14.428 +WIS10@IOWA30 14.429 +OK-ST17@KS-ST23 14.430 +MS-ST15@KY17 14.431 +CORN38@LAFAY16 14.432 +MEMPH17@LOUVL19 14.433 +WAKEF13@MD41 14.434 +KAS0@MIFL34 14.435 +MI-ST28@MICH27 14.436 +NW25@MINN35 14.437 +AKRON13@NAVY17 14.438 +MO21@NEB69 14.439 +UNLV24@NM-ST20 14.440 +USAF27@NDAME57 14.441 +MIOH40@OU18 14.442 +TEX14,OK13 14.443 +AZ21@OR-ST35 14.444 +SYR21@PA-ST27 14.445 +COLUM6@PENN21 14.446 +RUTG21@PITT45 14.447 +LBSU29@SJSU46 14.448 +ECAR7@SCAR37 14.449 +USC37@STAN22 14.450 +FLA3@TENN45 14.451 +RICE28@TCU38 14.452 +HI10@UTEP12 14.453 +BOWLG13@TOL19 14.454 +SMISS14@TUL14 14.455 +LTECH35@TULSA21 14.456 +SDSU31@UCLA45 14.457 +NC-ST0@VA31 14.458 +OR17@WASH38 14.459 +CINCI20@WVA28 14.460 +NMEX22@WYO25 14.461 +>O20 14.462 +LAFAY0@ARMY56 14.463 +FL-ST17@AUBN20 14.464 +PA-ST40@BOST21 14.465 +EMICH15@BOWLG25 14.466 +PENN17@BROWN24 14.467 +UCLA31@CAL38 14.468 +TOL12@CMICH13 14.469 +NMEX7@CO-ST47 14.470 +DART11@CORN6 14.471 +MD23@DUKE20 14.472 +CINCI32@ECAR56 14.473 +AKRON0@FLA59 14.474 +COLG31@FORD7 14.475 +LBSU16@FRES28 14.476 +VAND28@GA39 14.477 +FULL21@HI45 14.478 +LHIGH22@HOLY34 14.479 +MI-ST13@ILL15 14.480 +COLO41@KAS10 14.481 +OU15@KENTS44 14.482 +KY20@LSU30 14.483 +IOWA24@MICH23 14.484 +IND0@MINN12 14.485 +KS-ST10@MO31 14.486 +OK-ST3@NEB31 14.487 +GTECH13@NCAR13 14.488 +CLEM24@NC-ST17 14.489 +WIS34@NW44 14.490 +MIFL20@NDAME29 14.491 +IA-ST33@OK31 14.492 +AZ-ST7@OR27 14.493 +WA-ST55@OR-ST24 14.494 +NM-ST24@PAC62 14.495 +LOUVL27@PITT20 14.496 +HARV23@PRIN20 14.497 +OSU42@PURD2 14.498 +TTECH21@RICE42 14.499 +UT-ST27@SJSU34 14.500 +AZ35@USC26 14.501 +HOUST44@SMU17 14.502 +MEMPH7@SMISS23 14.503 +WASH52@STAN16 14.504 +RUTG0@SYR42 14.505 +VTECH28@TEMP31 14.506 +BAMA9@TENN6 14.507 +ARK17@TEX49 14.508 +BAYL20@TA&M20 14.509 +MS-ST38@TUL17 14.510 +SWLA25@TULSA13 14.511 +UTEP23@UTAH37 14.512 +VA49@WAKEF14 14.513 +BALL13@WMICH14 14.514 +COLUM7@YALE31 14.515 +>O27 14.516 +UTAH21@USAF52 14.517 +PA-ST9@BAMA0 14.518 +WA-ST34@AZ42 14.519 +USC13@AZ-ST6 14.520 +SYR26@ARMY14 14.521 +MIOH10@BOWLG10 14.522 +NMEX31@BYU55 14.523 +COLG28@BUCK27 14.524 +OK23@COLO32 14.525 +PRIN15@COLUM17 14.526 +BROWN7@CORN34 14.527 +HARV0@DART17 14.528 +CMICH16@EMICH12 14.529 +LSU3@FL-ST42 14.530 +DUKE31@GTECH48 14.531 +PAC24@HI35 14.532 +LAFAY3@HOLY34 14.533 +ARK28@HOUST62 14.534 +MICH45@IND19 14.535 +NW14@IOWA56 14.536 +NEB45@IA-ST13 14.537 +KS-ST24@KAS27 14.538 +GA24@KY26 14.539 +FULL35@LBSU37 14.540 +SWLA6@MEMPH20 14.541 +PURD33@MI-ST55 14.542 +AUBN17@MS-ST16 14.543 +TULSA35@NM-ST10 14.544 +MD10@NCAR34 14.545 +SCAR29@NC-ST38 14.546 +MINN23@OSU52 14.547 +WMICH31@OU23 14.548 +MO28@OK-ST48 14.549 +STAN0@OR31 14.550 +YALE27@PENN10 14.551 +NDAME31@PITT22 14.552 +AKRON17@RUTG20 14.553 +ECAR27@TEMP30 14.554 +SMU3@TEX52 14.555 +RICE15@TA&M41 14.556 +BAYL27@TCU21 14.557 +WYO17@UTEP10 14.558 +MIFL45@TTECH10 14.559 +KENTS14@TOL28 14.560 +CINCI7@TUL49 14.561 +OR-ST17@UCLA26 14.562 +UNLV6@UT-ST31 14.563 +MISS14@VAND13 14.564 +SMISS16@VTECH20 14.565 +CLEM24@WAKEF6 14.566 +CAL7@WASH46 14.567 +BOST27@WVA14 14.568 +ILL21@WIS3 14.569 +>N3 14.570 +BYU54@USAF7 14.571 +NIL31@AKRON28 14.572 +OR-ST9@AZ-ST34 14.573 +RICE19@ARK11 14.574 +RUTG31@ARMY35 14.575 +SYR35@BOST6 14.576 +BALL13@CMICH3 14.577 +LOUVL41@CINCI16 14.578 +NCAR3@CLEM20 14.579 +WYO8@CO-ST31 14.580 +COLUM20@DART34 14.581 +WAKEF20@DUKE57 14.582 +AUBN7@FLA48 14.583 +LAFAY59@FORD14 14.584 +BROWN37@HARV52 14.585 +NMEX16@HI43 14.586 +BUCK14@HOLY43 14.587 +TCU35@HOUST56 14.588 +IOWA54@ILL28 14.589 +IA-ST14@KS-ST28 14.590 +BOWLG20@KENTS16 14.591 +COLG7@LHIGH52 14.592 +MISS19@LSU10 14.593 +ECAR24@MEMPH17 14.594 +PITT0@MIFL45 14.595 +EMICH14@MIOH34 14.596 +IND20@MI-ST45 14.597 +BAMA22@MS-ST0 14.598 +OK55@MO10 14.599 +NDAME52@NAVY31 14.600 +COLO27@NEB12 14.601 +FRES45@UNLV18 14.602 +NW7@OSU48 14.603 +KAS31@OK-ST30 14.604 +UCLA24@OR28 14.605 +PENN20@PRIN34 14.606 +MICH38@PURD13 14.607 +UTAH14@SDSU66 14.608 +FULL6@SJSU44 14.609 +FL-ST41@SCAR10 14.610 +CAL31@USC31 14.611 +TA&M38@SMU17 14.612 +SMISS14@SWLA13 14.613 +WA-ST13@STAN31 14.614 +TEMP20@TENN41 14.615 +TEX41@TTECH22 14.616 +NM-ST10@UT-ST55 14.617 +GTECH41@VA38 14.618 +NC-ST16@VTECH20 14.619 +AZ10@WASH54 14.620 +PA-ST31@WVA19 14.621 +TOL37@WMICH9 14.622 +MINN21@WIS3 14.623 +CORN41@YALE31 14.624 +>N10 14.625 +LSU3@BAMA24 14.626 +STAN23@AZ10 14.627 +USAF15@ARMY3 14.628 +SMISS13@AUBN12 14.629 +ARK3@BAYL34 14.630 +WMICH19@BOWLG13 14.631 +DART29@BROWN0 14.632 +OR3@CAL28 14.633 +LAFAY7@COLG36 14.634 +OK-ST22@COLO41 14.635 +TULSA13@CO-ST31 14.636 +CORN41@COLUM0 14.637 +NIL20@ECAR24 14.638 +BALL20@EMICH13 14.639 +GA7@FLA38 14.640 +CINCI21@FL-ST70 14.641 +HOLY48@FORD0 14.642 +PAC17@FRES48 14.643 +UT-ST45@FULL17 14.644 +VTECH3@GTECH6 14.645 +WIS7@IND20 14.646 +OSU27@IOWA26 14.647 +MO25@IA-ST27 14.648 +NEB41@KAS9 14.649 +VAND21@KY28 14.650 +BUCK30@LHIGH27 14.651 +AKRON15@LTECH36 14.652 +BOST10@LOUVL17 14.653 +MS-ST27@MEMPH23 14.654 +KENTS10@MIOH31 14.655 +ILL17@MICH22 14.656 +MI-ST28@MINN16 14.657 +UTAH29@NMEX27 14.658 +SJSU56@NM-ST20 14.659 +VA24@NCAR10 14.660 +DUKE0@NC-ST16 14.661 +PURD33@NW13 14.662 +CMICH52@OU7 14.663 +KS-ST7@OK34 14.664 +USC56@OR-ST7 14.665 +MD10@PA-ST24 14.666 +HARV20@PENN24 14.667 +TEMP28@PITT18 14.668 +SMU28@RICE30 14.669 +WVA28@RUTG3 14.670 +HI38@SDSU44 14.671 +TUL26@SYR24 14.672 +NDAME34@TENN29 14.673 +HOUST24@TEX45 14.674 +TTECH40@TCU28 14.675 +NAVY14@TOL10 14.676 +UCLA25@WASH22 14.677 +AZ-ST51@WA-ST26 14.678 +BYU45@WYO14 14.679 +PRIN7@YALE34 14.680 +>N17 14.681 +CINCI7@BAMA45 14.682 +TA&M20@ARK16 14.683 +GA10@AUBN33 14.684 +OU6@BALL23 14.685 +FORD7@BUCK44 14.686 +STAN27@CAL25 14.687 +SCAR15@CLEM24 14.688 +HOLY35@COLG6 14.689 +KS-ST3@COLO64 14.690 +BROWN17@COLUM0 14.691 +PENN15@CORN21 14.692 +NCAR24@DUKE22 14.693 +YALE34@HARV19 14.694 +WYO17@HI38 14.695 +ILL24@IND10 14.696 +PURD9@IOWA38 14.697 +OK-ST25@IA-ST17 14.698 +MO31@KAS21 14.699 +EMICH24@KENTS25 14.700 +FLA47@KY15 14.701 +LHIGH35@LAFAY14 14.702 +UNLV20@LBSU29 14.703 +CO-ST30@LTECH31 14.704 +FL-ST35,MEMPH3 14.705 +BOST12@MIFL42 14.706 +MINN18@MICH35 14.707 +LSU22@MS-ST34 14.708 +SDSU40@NMEX34 14.709 +FULL9@NM-ST43 14.710 +MI-ST29@NW22 14.711 +PA-ST24@NDAME21 14.712 +OR6@OR-ST3 14.713 +DART23@PRIN6 14.714 +BAYL17@RICE16 14.715 +FRES7@SJSU42 14.716 +NIL20@SWLA24 14.717 +RUTG22@TEMP29 14.718 +MISS13@TENN22 14.719 +TEX38@TCU10 14.720 +USAF14@UTEP13 14.721 +SMU7@TTECH62 14.722 +USC45@UCLA42 14.723 +BYU42@UTAH22 14.724 +PAC45@UT-ST51 14.725 +ARMY42@VAND38 14.726 +MD35@VA30 14.727 +GTECH42@WAKEF7 14.728 +WASH55@WA-ST10 14.729 +SYR31@WVA7 14.730 +MIOH17@WMICH31 14.731 +OSU35@WIS10 14.732 +>N22 14.733 +WVA10@SCAR29 14.734 +>N23 14.735 +NEB10@OK45 14.736 +>N24 14.737 +AZ-ST17@AZ21 14.738 +TEX23@BAYL13 14.739 +TEMP29@BOST10 14.740 +UT-ST10@BYU45 14.741 +CO-ST30@HI27 14.742 +NW23@ILL28 14.743 +TUL13@LSU16 14.744 +SYR7@MIFL33 14.745 +WIS9@MI-ST14 14.746 +IOWA24@MINN31 14.747 +MS-ST9@MISS21 14.748 +MICH16@OSU13 14.749 +PITT17@PA-ST22 14.750 +IND28@PURD14 14.751 +UTEP31@SDSU58 14.752 +NDAME10@USC6 14.753 +ARK42@SMU29 14.754 +KY28@TENN42 14.755 +TCU10@TA&M56 14.756 +WAKEF56@VAND28 14.757 +VA13@VTECH38 14.758 +>D1 14.759 +HOUST62,AZ-ST45 14.760 +BAMA16,AUBN7 14.761 +FLA30@FL-ST45 14.762 +GTECH40@GA23 14.763 +BYU28@HI59 14.764 +MIFL30@SDSU28 14.765 +TA&M27@TEX28 14.766 +TENN49@VAND20 14.767 +>D8 14.768 +NAVY20@ARMY30 14.769 +SJSU48,CMICH24 14.770 +>D15 14.771 +LTECH34,MD34 14.772 +>D25 14.773 +SYR28,AZ0 14.774 +>D27 14.775 +USAF23,OSU11 14.776 +>D28 14.777 +FL-ST24,PA-ST17 14.778 +NC-ST31,SMISS27 14.779 +>D29 14.780 +TA&M65,BYU14 14.781 +AUBN27,IND23 14.782 +CO-ST32,OR31 14.783 +>D31 14.784 +MI-ST17,USC16 14.785 +CAL17,WYO15 14.786 +>J1 14.787 +LOUVL34,BAMA7 14.788 +CLEM30,ILL0 14.789 +WASH46,IOWA34 14.790 +MICH35,MISS3 14.791 +GTECH45,NEB21 14.792 +COLO10,NDAME9 14.793 +MIFL46,TEX3 14.794 +TENN23,VA22 14.795 +* End of file "games.dat"
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/gb_basic.w Mon Oct 03 23:29:42 2011 +0200 15.3 @@ -0,0 +1,2415 @@ 15.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 15.5 +\def\title{GB\_\thinspace BASIC} 15.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 15.7 + 15.8 +\prerequisite{GB\_\thinspace GRAPH} 15.9 +@* Introduction. This GraphBase module contains six subroutines that generate 15.10 +standard graphs of various types, together with six routines that combine or 15.11 +transform existing graphs. 15.12 + 15.13 +Simple examples of the use of these routines can be found in the 15.14 +demonstration programs |queen| and |queen_wrap|. 15.15 + 15.16 +@f Graph int /* |gb_graph| defines the |Graph| type and a few others */ 15.17 +@f Vertex int 15.18 +@f Arc int 15.19 +@f Area int 15.20 + 15.21 +@<gb_basic.h@>= 15.22 +extern Graph *board(); /* moves on generalized chessboards */ 15.23 +extern Graph *simplex(); /* generalized triangular configurations */ 15.24 +extern Graph *subsets(); /* patterns of subset intersection */ 15.25 +extern Graph *perms(); /* permutations of a multiset */ 15.26 +extern Graph *parts(); /* partitions of an integer */ 15.27 +extern Graph *binary(); /* binary trees */ 15.28 +@# 15.29 +extern Graph *complement(); /* the complement of a graph */ 15.30 +extern Graph *gunion(); /* the union of two graphs */ 15.31 +extern Graph *intersection(); /* the intersection of two graphs */ 15.32 +extern Graph *lines(); /* the line graph of a graph */ 15.33 +extern Graph *product(); /* the product of two graphs */ 15.34 +extern Graph *induced(); /* a graph induced from another */ 15.35 + 15.36 +@ The \Cee\ file \.{gb\_basic.c} has the following overall shape: 15.37 + 15.38 +@p 15.39 +#include "gb_graph.h" /* we use the |gb_graph| data structures */ 15.40 +@# 15.41 +@<Private variables@>@; 15.42 +@<Basic subroutines@>@; 15.43 +@<Applications of basic subroutines@>@; 15.44 + 15.45 +@ Several of the programs below allocate arrays that will be freed again 15.46 +before the routine is finished. 15.47 + 15.48 +@<Private variables@>= 15.49 +static Area working_storage; 15.50 + 15.51 +@ If a graph-generating subroutine encounters a problem, it returns |NULL| 15.52 +(that is, \.{NULL}), after putting a code number into the external variable 15.53 +|panic_code|. This code number identifies the type of failure. 15.54 +Otherwise the routine returns a pointer to the newly created graph, which 15.55 +will be represented with the data structures explained in |gb_graph|. 15.56 +(The external variable |@!panic_code| is itself defined in |gb_graph|.) 15.57 + 15.58 +@d panic(c) 15.59 + {@+panic_code=c; 15.60 + gb_free(working_storage); 15.61 + gb_alloc_trouble=0; 15.62 + return NULL; 15.63 + } 15.64 + 15.65 +@ The names of vertices are sometimes formed from the names of other 15.66 +vertices, or from potentially long sequences of numbers. We assemble 15.67 +them in the |buffer| array, which is sufficiently long that the 15.68 +vast majority of applications will be unconstrained by size limitations. 15.69 +The programs do always make sure that |BUF_SIZE| is not exceeded, but 15.70 +they assume that it is rather large. 15.71 + 15.72 +@d BUF_SIZE 4096 15.73 + 15.74 +@<Private v...@>= 15.75 +static char buffer[BUF_SIZE]; 15.76 + 15.77 +@*Grids and game boards. The subroutine call 15.78 +`|board(n1,n2,n3,n4,piece,wrap,directed)|' 15.79 +constructs a graph based on the moves of generalized chesspieces on a 15.80 +generalized rectangular board. Each vertex of the graph corresponds to a 15.81 +position on the board. Each arc of the graph corresponds to a move from 15.82 +one position to another. 15.83 + 15.84 +The first parameters, |n1| through |n4|, specify the size of the board. 15.85 +If, for example, a two-dimensional board with $n_1$ rows and $n_2$ columns 15.86 +is desired, you set $|n1|=n_1$, $|n2|=n_2$, and $|n3|=0$; the resulting 15.87 +graph will have $n_1n_2$ vertices. If you want a three-dimensional 15.88 +board with $n_3$ layers, set $|n3|=n_3$ and $n_4=0$. If you want 15.89 +a four-dimensional board, put the number of 4th coordinates in~|n4|. 15.90 +If you want a $d$-dimensional board with $2^d$ positions, set |n1=2| 15.91 +and |n2=-d|. 15.92 + 15.93 +In general, the |board| subroutine determines the dimensions by scanning the 15.94 +sequence |(n1,n2,n3,n4,0)=@t$(n_1,n_2,n_3,n_4,0)$@>| from left to right 15.95 +until coming to the first nonpositive parameter $n_{k+1}$. If $k=0$ 15.96 +(i.e., if |n1<=0|), the default size $8\times8$ will be used; this is 15.97 +an ordinary chessboard with 8~rows and 8~columns. Otherwise if $n_{k+1}=0$, 15.98 +the board will have $k$~dimensions $n_1$, \dots,~$n_k$. Otherwise 15.99 +we must have $n_{k+1}<0$; in this case the board will have $d=\vert n_{k+1} 15.100 +\vert$ dimensions, chosen as the first $d$ elements of the infinite 15.101 +periodic sequence $(n_1,\ldots,n_k,n_1,\ldots,n_k,n_1,\ldots\,)$. 15.102 +For example, the specification |(n1,n2,n3,n4)=(2,3,5,-7)| is about as 15.103 +tricky as you can get. It produces a seven-dimensional board with 15.104 +dimensions $(n_1,\ldots,n_7)=(2,3,5,2,3,5,2)$, hence a graph with 15.105 +$2\cdot3\cdot5\cdot2\cdot3\cdot5\cdot2=1800$ vertices. 15.106 + 15.107 +The |piece| parameter specifies the legal moves of a generalized chesspiece. 15.108 +If |piece>0|, a move from position~|u| to position~|v| is considered legal 15.109 +if and only if the Euclidean distance between points |u| and~|v| is 15.110 +equal to $\sqrt{\vphantom1\smash{|piece|}}$. 15.111 +For example, if |piece=1| and if we have a 15.112 +two-dimensional board, the legal moves from $(x,y)$ are to $(x,y\pm1)$ and 15.113 +$(x\pm1,y)$; these are the moves of a so-called wazir, the only moves that 15.114 +a king and a rook can both make. If |piece=2|, the legal moves from $(x,y)$ 15.115 +are to $(x\pm1,y\pm1)$; these are the four moves that a king and a bishop 15.116 +can both make. (A piece that can make only these moves was called a ``fers'' 15.117 +in ancient Muslim chess.) If |piece=5|, the legal moves are those of a 15.118 +knight, from $(x,y)$ to $(x\pm1,y\pm2)$ or to $(x\pm2,y\pm1)$. If |piece=3|, 15.119 +there are no legal moves on a two-dimensional board, but moves from 15.120 +$(x,y,z)$ to $(x\pm1,y\pm1,z\pm1)$ would be legal in three dimensions. 15.121 +If |piece=0|, it is changed to the default value |piece=1|. 15.122 + 15.123 +If the value of |piece| is negative, arbitrary multiples of the basic moves 15.124 +for $\vert|piece|\vert$ are permitted. For example, |piece=-1| defines the 15.125 +moves of a rook, from $(x,y)$ to $(x\pm a,y)$ or to $(x,y\pm a)$ for all 15.126 +$a>0$; |piece=-2| defines the moves of a bishop, from $(x,y)$ to 15.127 +$(x\pm a,y\pm a)$. The literature of ``fairy chess'' assigns standard names 15.128 +to the following |piece| values: $\rm wazir=1$, $\rm fers=2$, $\rm dabbaba=4$, 15.129 +$\rm knight=5$, $\rm alfil=8$, $\rm camel=10$, $\rm zebra=13$, $\rm giraffe 15.130 +=17$, $\rm fiveleaper=25$, $\hbox{root-50-leaper}=50$, etc.; $\rm rook=-1$, 15.131 +$\rm bishop=-2$, $\rm unicorn=-3$, $\rm dabbabarider=-4$, $\rm nightrider=-5$, 15.132 +$\rm alfilrider=-8$, $\rm camelrider=-10$, etc. 15.133 + 15.134 +To generate a board with the moves of a king, you can use the |gunion| 15.135 +subroutine below to take the union of boards with |piece=1| and 15.136 +|piece=2|. Similarly, you can get queen moves by taking the union of 15.137 +boards with |piece=-1| and |piece=-2|. 15.138 + 15.139 +If |piece>0|, all arcs of the graph will have length~1. If |piece<0|, the 15.140 +length of each arc will be the number of multiples of a basic move that 15.141 +produced the arc. 15.142 + 15.143 +@ If the |wrap| parameter is nonzero, it specifies a subset of coordinates 15.144 +in which values are computed modulo the corresponding size. 15.145 +For example, the coordinates $(x,y)$ for vertices on a two-dimensional 15.146 +board are restricted to the range $0\le x<n_1$, $0\le y<n_2$; when 15.147 +|wrap=0|, a move from $(x,y)$ to $(x+\delta_1,y+\delta_2)$ is 15.148 +therefore legal only if $0\le x+\delta_1<n_1$ and $0\le 15.149 +y+\delta_2<n_2$. But when |wrap=1|, the $x$~coordinates are allowed to 15.150 +``wrap around''; the move would then be made to $((x+\delta_1)\bmod 15.151 +n_1,y+\delta_2)$, provided that $0\le y+\delta_2<n_2$. Setting 15.152 +|wrap=1| effectively makes the board into a cylinder instead of a 15.153 +rectangle. Similarly, the $y$~coordinates are allowed to wrap around 15.154 +when |wrap=2|. Both $x$ and $y$ coordinates are treated modulo their 15.155 +corresponding sizes when |wrap=3|; the board is then effectively a 15.156 +torus. In general, coordinates $k_1$, $k_2$, \dots~ will wrap around 15.157 +when $|wrap|=2^{k_1-1}+2^{k_2-1}+\cdots\,$. Setting |wrap=-1| causes all 15.158 +coordinates to be computed modulo their size. 15.159 + 15.160 +The graph constructed by |board| will be undirected unless |directed!=0|. 15.161 +Directed |board| graphs will be acyclic when |wrap=0|, but they may 15.162 +have cycles when |wrap!=0|. Precise rules defining the directed arcs 15.163 +are given below. 15.164 + 15.165 +Several important special cases are worth noting: To get the complete graph 15.166 +on |n| vertices, you can say |board(n,0,0,0,-1,0,0)|. To get the 15.167 +transitive tournament on |n| vertices, i.e., the directed graph 15.168 +with arcs from |u| to |v| when |u<v|, you can say |board(n,0,0,0,-1,0,1)|. 15.169 +To get the empty graph on |n| vertices, you can say |board(n,0,0,0,2,0,0)|. 15.170 +To get a circuit (undirected) or a cycle (directed) of length~|n|, 15.171 +you can say |board(n,0,0,0,1,1,0)| and |board(n,0,0,0,1,1,1)|, 15.172 +respectively. 15.173 + 15.174 +@(gb_basic.h@>= 15.175 +#define complete(n) @[board(n,0,0,0,-1,0,0)@] 15.176 +#define transitive(n) @[board(n,0,0,0,-1,0,1)@] 15.177 +#define empty(n) @[board(n,0,0,0,2,0,0)@] 15.178 +#define circuit(n) @[board(n,0,0,0,1,1,0)@] 15.179 +#define cycle(n) @[board(n,0,0,0,1,1,1)@] 15.180 + 15.181 + 15.182 +@ @<Basic subroutines@>= 15.183 +Graph *board(n1,n2,n3,n4,piece,wrap,directed) 15.184 + int n1,n2,n3,n4; /* size of board desired */ 15.185 + int piece; /* type of moves desired */ 15.186 + long wrap; /* mask for coordinate positions that wrap around */ 15.187 + int directed; /* should the graph be directed? */ 15.188 +{@+@<Vanilla local variables@>@; 15.189 + long n; /* total number of vertices */ 15.190 + int p; /* $\vert|piece|\vert$ */ 15.191 + int l; /* length of current arc */ 15.192 + @<Normalize the board-size parameters@>; 15.193 + @<Set up a graph with |n| vertices@>; 15.194 + @<Insert arcs or edges for all legal moves@>; 15.195 + if (gb_alloc_trouble) { 15.196 + gb_recycle(new_graph); 15.197 + panic(alloc_fault); /* alas, we ran out of memory somewhere back there */ 15.198 + } 15.199 + return new_graph; 15.200 +} 15.201 + 15.202 +@ Most of the subroutines in |gb_basic| use the following local 15.203 +variables. 15.204 + 15.205 +@<Vanilla local variables@>= 15.206 +Graph *new_graph; /* the graph being constructed */ 15.207 +register int i,j,k; /* all-purpose indices */ 15.208 +register int d; /* the number of dimensions */ 15.209 +register Vertex *v; /* the current vertex of interest */ 15.210 +register long s; /* accumulator */ 15.211 + 15.212 +@ Several arrays will facilitate the calculations that |board| needs to make: 15.213 +The number of distinct values in coordinate position~$k$ will be |nn[k]|; 15.214 +this coordinate position will wrap around if and only if |wr[k]!=0|. 15.215 +The current moves under consideration will be from $(x_1,\ldots,x_d)$ 15.216 +to $(x_1+\delta_1,\ldots, x_k+\delta_k)$, where $\delta_k$ is stored 15.217 +in |del[k]|. An auxiliary array |sig| holds the sums 15.218 +$\sigma_k=\delta_1^2+\cdots+\delta_{k-1}^2$. Additional arrays |xx| 15.219 +and |yy| hold coordinates of vertices before and after a move is made. 15.220 + 15.221 +Some of these arrays are also used for other purposes by other programs 15.222 +besides |board|; we will meet those programs later. 15.223 + 15.224 +We limit the number of dimensions to 91 or less. This is hardly a limitation, 15.225 +since the number of vertices would be astronomical even if the dimensionality 15.226 +were only half this big. But some of our later programs will be able 15.227 +to make good use of 40 or 50 dimensions and perhaps more; the number 91 15.228 +is an upper limit imposed by the number of standard printable characters 15.229 +(see the convention for vertex names in the |perms| routine). 15.230 + 15.231 +@d MAX_D 91 15.232 + 15.233 +@<Private...@>= 15.234 +static int nn[MAX_D+1]; /* component sizes */ 15.235 +static int wr[MAX_D+1]; /* does this component wrap around? */ 15.236 +static int del[MAX_D+1]; /* displacements for the current move */ 15.237 +static int sig[MAX_D+2]; /* partial sums of squares of displacements */ 15.238 +static int xx[MAX_D+1], yy[MAX_D+1]; /* coordinate values */ 15.239 + 15.240 +@ @<Normalize the board-size parameters@>= 15.241 +if (piece==0) piece=1; 15.242 +if (n1<=0) {@+n1=n2=8;@+n3=0;@+} 15.243 +nn[1]=n1; 15.244 +if (n2<=0) {@+k=2;@+d=-n2;@+n3=n4=0;@+} 15.245 +else { 15.246 + nn[2]=n2; 15.247 + if (n3<=0) {@+k=3;@+d=-n3;@+n4=0;@+} 15.248 + else { 15.249 + nn[3]=n3; 15.250 + if (n4<=0) {@+k=4;@+d=-n4;@+} 15.251 + else {@+nn[4]=n4;@+d=4;@+goto done;@+} 15.252 + } 15.253 +} 15.254 +if (d==0) {@+d=k-1;@+goto done;@+} 15.255 +@<Compute component sizes periodically for |d| dimensions@>; 15.256 +done: /* now |nn[1]| through |nn[d]| are set up */ 15.257 + 15.258 +@ At this point, |nn[1]| through |nn[k-1]| are the component sizes 15.259 +that should be replicated periodically. In unusual cases, the number 15.260 +of dimensions might not be as large as the number of specifications. 15.261 + 15.262 +@<Compute component sizes periodically...@>= 15.263 +if (d>MAX_D) panic(bad_specs); /* too many dimensions */ 15.264 +for (j=1; k<=d; j++,k++) nn[k]=nn[j]; 15.265 + 15.266 +@ We want to make the subroutine idiot-proof, so we use floating-point 15.267 +arithmetic to make sure that boards with more than a billion cells have 15.268 +not been specified. 15.269 + 15.270 +@d MAX_NNN 1000000000.0 15.271 + 15.272 +@<Set up a graph with |n| vertices@>= 15.273 +{@+float nnn; /* approximate size */ 15.274 + for (n=1,nnn=1.0,j=1; j<=d; j++) { 15.275 + nnn *= (float)nn[j]; 15.276 + if (nnn>MAX_NNN) panic(very_bad_specs); /* way too big */ 15.277 + n *= nn[j]; /* this multiplication cannot cause integer overflow */ 15.278 + } 15.279 + new_graph=gb_new_graph(n); 15.280 + if (new_graph==NULL) 15.281 + panic(no_room); /* out of memory before we're even started */ 15.282 + sprintf(new_graph->id,"board(%d,%d,%d,%d,%d,%ld,%d)", 15.283 + n1,n2,n3,n4,piece,wrap,directed?1:0); 15.284 + strcpy(new_graph->format,"ZZZIIIZZZZZZZZ"); 15.285 + @<Give names to the vertices@>; 15.286 +} 15.287 + 15.288 +@ The symbolic name of a board position like $(3,1)$ will be the string 15.289 +`\.{3.1}'. The first three coordinates are also stored as integers, in 15.290 +utility fields |x.i|, |y.i|, and |z.i|, because immediate access to 15.291 +those values will be helpful in certain applications. (The coordinates can, 15.292 +of course, always be recovered in a slower fashion from the vertex name, 15.293 +via |sscanf|.) 15.294 + 15.295 +The process of assigning coordinate values and names is equivalent to 15.296 +adding unity in a mixed-radix number system. Vertex $(x_1,\ldots,x_d)$ 15.297 +will be in position $x_1n_2\ldots n_d+\cdots+x_{d-1}n_d+x_d$ relative 15.298 +to the first vertex of the new graph; therefore it is also possible to 15.299 +deduce the coordinates of a vertex from its address. 15.300 + 15.301 +@<Give names...@>= 15.302 +{@+register char *p; /* string pointer */ 15.303 + nn[0]=xx[0]=xx[1]=xx[2]=xx[3]=0; 15.304 + for (k=4;k<=d;k++) xx[k]=0; 15.305 + for (v=new_graph->vertices;;v++) { 15.306 + p=buffer; 15.307 + for (k=1;k<=d;k++) { 15.308 + sprintf(p,".%d",xx[k]); 15.309 + while (*p) p++; 15.310 + } 15.311 + v->name=gb_save_string(&buffer[1]); /* omit |buffer[0]|, which is |'.'| */ 15.312 + v->x.i=xx[1];@+v->y.i=xx[2];@+v->z.i=xx[3]; 15.313 + for (k=d;xx[k]+1==nn[k];k--) xx[k]=0; 15.314 + if (k==0) break; /* a ``carry'' has occurred all the way to the left */ 15.315 + xx[k]++; /* increase coordinate |k| */ 15.316 + } 15.317 +} 15.318 + 15.319 +@ Now we come to a slightly tricky part of the routine, the move generator. 15.320 +Let $p=\vert|piece|\vert$. The outer loop of this procedure runs through all 15.321 +solutions of the equation $\delta_1^2+\cdots+\delta_d^2=p$, where the 15.322 +$\delta$'s are nonnegative integers. Within that loop, we attach signs 15.323 +to the $\delta$'s, but always leaving $\delta_k$ positive if $\delta_1= 15.324 +\cdots=\delta_{k-1}=0$. For every such vector~$\delta$, we generate moves 15.325 +from |v| to $v+\delta$ for every vertex |v|. When |directed=0|, 15.326 +we use |gb_new_edge| instead of |gb_new_arc|, so that the reverse arc 15.327 +from $v+\delta$ to~|v| is also generated. 15.328 + 15.329 +@<Insert arcs or edges for all legal moves@>= 15.330 +@<Initialize the |wr|, |sig|, and |del| tables@>; 15.331 +p=piece; 15.332 +if (p<0) p=-p; 15.333 +while (1) { 15.334 + @<Advance to the next nonnegative |del| vector, or |break| if done@>; 15.335 + while (1) { 15.336 + @<Generate moves for the current |del| vector@>; 15.337 + @<Advance to the next signed |del| vector, or restore |del| 15.338 + to nonnegative values and |break|@>; 15.339 + } 15.340 +} 15.341 + 15.342 +@ The \Cee\ language does not define |>>| unambiguously. If |w| is negative, 15.343 +the assignment `|w>>=1|' here should keep |w| negative. 15.344 +(However, this technicality doesn't matter except in highly unusual cases 15.345 +when there are more than 32 dimensions.) 15.346 +@^system dependencies@> 15.347 + 15.348 +@<Initialize the |wr|, |sig|, and |del| tables@>= 15.349 +{@+register long w=wrap; 15.350 + for (k=1;k<=d;k++,w>>=1) { 15.351 + wr[k]=w&1; 15.352 + del[k]=sig[k]=0; 15.353 + } 15.354 + sig[0]=del[0]=sig[d+1]=0; 15.355 +} 15.356 + 15.357 +@ @<Advance to the next nonnegative |del|...@>= 15.358 +for (k=d;sig[k]+(del[k]+1)*(del[k]+1)>p;k--) del[k]=0; 15.359 +if (k==0) break; 15.360 +del[k]++; 15.361 +sig[k+1]=sig[k]+del[k]*del[k]; 15.362 +for (k++;k<=d;k++) sig[k+1]=sig[k]; 15.363 +if (sig[d+1]<p) continue; 15.364 + 15.365 +@ @<Advance to the next signed |del| vector, or restore |del| 15.366 + to nonnegative values and |break|@>= 15.367 +for (k=d;del[k]<=0;k--) del[k]=-del[k]; 15.368 +if (sig[k]==0) break; /* all but |del[k]| were negative or zero */ 15.369 +del[k]=-del[k]; /* some entry preceding |del[k]| is positive */ 15.370 + 15.371 +@ We use the mixed-radix addition technique again when generating moves. 15.372 + 15.373 +@<Generate moves for the current |del| vector@>= 15.374 +for (k=1;k<=d;k++) xx[k]=0; 15.375 +for (v=new_graph->vertices;;v++) { 15.376 + @<Generate moves from |v| corresponding to |del|@>; 15.377 + for (k=d;xx[k]+1==nn[k];k--) xx[k]=0; 15.378 + if (k==0) break; /* a ``carry'' has occurred all the way to the left */ 15.379 + xx[k]++; /* increase coordinate |k| */ 15.380 +} 15.381 + 15.382 +@ The legal moves when |piece| is negative are derived as follows, in 15.383 +the presence of possible wraparound: Starting at $(x_1,\ldots,x_d)$, we 15.384 +move to $(x_1+\delta_1,\ldots,x_d+\delta_d)$, $(x_1+2\delta_1,\ldots, 15.385 +x_d+2\delta_d)$,~\dots, until either coming to a position with a nonwrapped 15.386 +coordinate out of range or coming back to the original point. 15.387 + 15.388 +A subtle technicality should be noted: When coordinates are wrapped and 15.389 +|piece>0|, self-loops are possible---for example, in |board(1,0,0,0,1,1,1)|. 15.390 +But self-loops never arise when |piece<0|. 15.391 + 15.392 +@<Generate moves from |v|...@>= 15.393 +for (k=1;k<=d;k++) yy[k]=xx[k]+del[k]; 15.394 +for (l=1;;l++) { 15.395 + @<Correct for wraparound, or |goto no_more| if off the board@>; 15.396 + if (piece<0) @<Go to |no_more| if |yy=xx|@>; 15.397 + @<Record a legal move from |xx| to |yy|@>; 15.398 + if (piece>0) goto no_more; 15.399 + for (k=1;k<=d;k++) yy[k]+=del[k]; 15.400 +} 15.401 +no_more: 15.402 + 15.403 +@ @<Go to |no_more|...@>= 15.404 +{ 15.405 + for (k=1;k<=d;k++) if (yy[k]!=xx[k]) goto unequal; 15.406 + goto no_more; 15.407 + unequal:; 15.408 +} 15.409 + 15.410 +@ @<Correct for wraparound, or |goto no_more| if off the board@>= 15.411 +for (k=1;k<=d;k++) { 15.412 + if (yy[k]<0) { 15.413 + if (!wr[k]) goto no_more; 15.414 + do yy[k]+=nn[k];@+ while (yy[k]<0); 15.415 + } else if (yy[k]>=nn[k]) { 15.416 + if (!wr[k]) goto no_more; 15.417 + do yy[k]-=nn[k];@+ while (yy[k]>=nn[k]); 15.418 + } 15.419 +} 15.420 + 15.421 +@ @<Record a legal move from |xx| to |yy|@>= 15.422 +for (k=2,j=yy[1];k<=d;k++) j=nn[k]*j+yy[k]; 15.423 +if (directed) gb_new_arc(v,new_graph->vertices+j,l); 15.424 +else gb_new_edge(v,new_graph->vertices+j,l); 15.425 + 15.426 +@* Generalized triangular boards. The subroutine call 15.427 +`|simplex(n,n0,n1,n2,n3,n4,directed)|' creates a graph based on 15.428 +generalized triangular or tetrahedral configurations. Such graphs are 15.429 +similar in spirit to the game boards created by |board|, but they 15.430 +pertain to nonrectangular grids like those in ``Chinese checkers.'' As 15.431 +with |board| in the case |piece=1|, the vertices represent board positions, 15.432 +and the arcs run from board positions to their nearest neighbors. Each arc has 15.433 +length~1.{\tolerance=1000\par} 15.434 + 15.435 +More formallly, the vertices can be defined as sequences of nonnegative 15.436 +integers $(x_0,x_1,\ldots,x_d)$ whose sum is~|n|, where two sequences 15.437 +are considered adjacent if and only if they differ by $\pm1$ in exactly 15.438 +two components---equivalently, if the Euclidean distance between them 15.439 +is~$\sqrt2$. When $d=2$, for example, the vertices can be visualized 15.440 +as a triangular array 15.441 +$$\vcenter{\halign{&\hbox to 2em{\hss$#$\hss}\cr 15.442 +&&&(0,0,3)\cr 15.443 +&&(0,1,2)&&(1,0,2)\cr 15.444 +&(0,2,1)&&(1,1,1)&&(2,0,1)\cr 15.445 +(0,3,0)&&(1,2,0)&&(2,1,0)&&(3,0,0)\cr}}$$ 15.446 +containing $(n+1)(n+2)/2$ elements, illustrated here when $n=3$; each vertex of 15.447 +the array has up to 6 neighbors. When $d=3$ the vertices form a tetrahedral 15.448 +array, a stack of triangular layers, and they can have as many as 12 15.449 +neighbors. In general, a vertex in a $d$-simplicial array will have up to 15.450 +$d(d+1)$ neighbors. 15.451 + 15.452 +If the |directed| parameter is nonzero, arcs run only form vertices to neighbors 15.453 +that are lexicographically greater---for example, downward or to the right 15.454 +in the triangular array shown. The directed graph is therefore acyclic, 15.455 +and a vertex of a $d$-simplicial array has out-degree at most $d(d+1)/2$. 15.456 + 15.457 +@ The first parameter, |n|, specifies the sum of the coordinates 15.458 +$(x_0,x_1,\ldots,x_d)$. The following parameters |n0| through |n4| specify 15.459 +upper bounds on those coordinates, and they also specify the dimensionality~|d|. 15.460 + 15.461 +If, for example, |n0|, |n1|, and |n2| are positive while |n3=0|, the 15.462 +value of~|d| will be~2 and the coordinates will be constrained to 15.463 +satisfy $0\le x_0\le|n0|$, $0\le x_1\le|n1|$, $0\le x_2\le|n2|$. These 15.464 +upper bounds essentially lop off the corners of the triangular array. 15.465 +We obtain a hexagonal board with $6m$ boundary cells by asking for 15.466 +|simplex(3m,2m,2m,2m,0,0,0)|. We obtain the diamond-shaped board used 15.467 +in the game of Hex [Martin Gardner, {\sl The Scientific American 15.468 +Book of Mathematical Puzzles {\char`\&} Diversions\/} (Simon {\char`\&} 15.469 +Schuster, 1959), Chapter~8] by calling |simplex(20,10,20,10,0,0,0)|. 15.470 + 15.471 +In general, |simplex| determines |d| and upper bounds $(n_0,n_1,\ldots,n_d)$ 15.472 +in the following way: Let the first nonpositive entry of the sequence 15.473 +|(n0,n1,n2,n3,n4,0)|$\null=(n_0,n_1,n_2,n_3,n_4,0)$ be~$n_k$. If $k>0$ 15.474 +and $n_k=0$, the value of~$d$ will be $k-1$ and the coordinates will be 15.475 +bounded by the given numbers $(n_0,\ldots,n_d)$. If $k>0$ and $n_k<0$, 15.476 +the value of~$d$ will be $\vert n_k\vert$ and the coordinates will be 15.477 +bounded by the first $d+1$ elements of the infinite periodic sequence 15.478 +$(n_0,\ldots,n_{k-1},n_0,\ldots,n_{k-1},n_0,\ldots\,)$. If $k=0$ and 15.479 +$n_0<0$, the value of~$d$ will be $\vert n_0\vert$ and the coordinates 15.480 +will be unbounded; equivalently, we may set $n_0=\cdots=n_d=n$. In 15.481 +this case the number of vertices will be $n+d\choose d$. Finally, 15.482 +if $k=0$ and $n_0=0$, we have the default case of a triangular array 15.483 +with $3n$ boundary cells, exactly as if $n_0=-2$. 15.484 + 15.485 +For example, the specification |n0=3|, |n1=-5| will produce all vertices 15.486 +$(x_0,x_1,\ldots,x_5)$ such that $x_0+x_1+\cdots+x_5=n$ and $0\le x_j\le3$. 15.487 +The specification |n0=1|, |n1=-d| will essentially produce all $n$-element 15.488 +subsets of the $(d+1)$-element set $\{0,1,\ldots,d\}$, because we can 15.489 +regard an element~$k$ as being present in the set if $x_k=1$, absent 15.490 +if $x_k=0$. In that case two subsets are adjacent if and only if 15.491 +they have exactly $n-1$ elements in common. 15.492 + 15.493 +@ @<Basic subroutines@>= 15.494 +Graph *simplex(n,n0,n1,n2,n3,n4,directed) 15.495 + unsigned n; /* the constant sum of all coordinates */ 15.496 + int n0,n1,n2,n3,n4; /* constraints on coordinates */ 15.497 + int directed; /* should the graph be directed? */ 15.498 +{@+@<Vanilla local variables@>@; 15.499 + @<Normalize the simplex parameters@>; 15.500 + @<Create a graph with one vertex for each point@>; 15.501 + @<Name the points and create the arcs or edges@>; 15.502 + if (gb_alloc_trouble) { 15.503 + gb_recycle(new_graph); 15.504 + panic(alloc_fault); /* darn, we ran out of memory somewhere back there */ 15.505 + } 15.506 + return new_graph; 15.507 +} 15.508 + 15.509 +@ @<Normalize the simplex parameters@>= 15.510 +if (n0==0) n0=-2; 15.511 +if (n0<0) {@+k=2;@+nn[0]=n;@+d=-n0;@+n1=n2=n3=n4=0;@+} 15.512 +else { 15.513 + if (n0>n) n0=n; 15.514 + nn[0]=n0; 15.515 + if (n1<=0) {@+k=2;@+d=-n1;@+n2=n3=n4=0;@+} 15.516 + else { 15.517 + if (n1>n) n1=n; 15.518 + nn[1]=n1; 15.519 + if (n2<=0) {@+k=3;@+d=-n2;@+n3=n4=0;@+} 15.520 + else { 15.521 + if (n2>n) n2=n; 15.522 + nn[2]=n2; 15.523 + if (n3<=0) {@+k=4;@+d=-n3;@+n4=0;@+} 15.524 + else { 15.525 + if (n3>n) n3=n; 15.526 + nn[3]=n3; 15.527 + if (n4<=0) {@+k=5;@+d=-n4;@+} 15.528 + else {@+if (n4>n) n4=n; 15.529 + nn[4]=n4;@+d=4;@+goto done;@+} 15.530 + } 15.531 + } 15.532 + } 15.533 +} 15.534 +if (d==0) {@+d=k-2;@+goto done;@+} 15.535 +nn[k-1]=nn[0]; 15.536 +@<Compute component sizes periodically...@>; 15.537 +done: /* now |nn[0]| through |nn[d]| are set up */ 15.538 + 15.539 +@ @<Create a graph with one vertex for each point@>= 15.540 +@<Determine the number of feasible $(x_0,\ldots,x_d)$, and allocate the graph@>; 15.541 +sprintf(new_graph->id,"simplex(%u,%d,%d,%d,%d,%d,%d)", 15.542 + n,n0,n1,n2,n3,n4,directed?1:0); 15.543 +strcpy(new_graph->format,"VVZIIIZZZZZZZZ"); /* hash table will be used */ 15.544 + 15.545 +@ We determine the number of vertices by determining the coefficient of~$z^n$ 15.546 +in the power series 15.547 +$$(1+z+\cdots+z^{n_0})(1+z+\cdots+z^{n_1})\ldots(1+z+\cdots+z^{n_d}).$$ 15.548 + 15.549 +@<Determine the number of feasible $(x_0,\ldots,x_d)$...@>= 15.550 +{@+long nverts; /* the number of vertices */ 15.551 + register long *coef=gb_alloc_type(n+1,@[long@],working_storage); 15.552 + if (gb_alloc_trouble) panic(no_room+1); /* can't allocate |coef| array */ 15.553 + for (k=0;k<=nn[0];k++) coef[k]=1; 15.554 + /* now |coef| represents the coefficients of $1+z+\cdots+z^{n_0}$ */ 15.555 + for (j=1;j<=d;j++) 15.556 + @<Multiply the power series coefficients by $1+z+\cdots+z^{n_j}$@>; 15.557 + nverts=coef[n]; 15.558 + gb_free(working_storage); /* recycle the |coef| array */ 15.559 + new_graph=gb_new_graph(nverts); 15.560 + if (new_graph==NULL) 15.561 + panic(no_room); /* out of memory before we're even started */ 15.562 +} 15.563 + 15.564 +@ There's a neat way to multiply by $1+z+\cdots+z^{n_j}$: We multiply 15.565 +first by $1-z^{n_j+1}$, then sum the coefficients. 15.566 + 15.567 +We want to detect impossibly large specifications without risking 15.568 +integer overflow. It is easy to do this because multiplication is being 15.569 +done via addition. 15.570 + 15.571 +@<Multiply the power series coefficients by $1+z+\cdots+z^{n_j}$@>= 15.572 +{ 15.573 + for (k=n,i=n-nn[j]-1;i>=0;k--,i--) coef[k]-=coef[i]; 15.574 + s=1; 15.575 + for (k=1;k<=n;k++) { 15.576 + s+=coef[k]; 15.577 + if (s>1000000000) panic(very_bad_specs); /* way too big */ 15.578 + coef[k]=s; 15.579 + } 15.580 +} 15.581 + 15.582 +@ As we generate the vertices, it proves convenient to precompute an 15.583 +array containing the numbers $y_j=n_j+\cdots+n_d$, representing the 15.584 +largest possible sum of $x_j+\cdots+x_d$. We also want to maintain 15.585 +the numbers $\sigma_j=n-(x_0+\cdots+x_{j-1})=x_j+\cdots+x_d$. The 15.586 +conditions 15.587 +$$0\le x_j\le n_j, \qquad \sigma_j-y_{j+1}\le x_j\le \sigma_j$$ 15.588 +are ``necessary and sufficient,'' in the sense that we can find at least 15.589 +one way to complete a partial solution $(x_0,\ldots,x_k)$ to a full 15.590 +solution $(x_0,\ldots,x_d)$ if and only if the conditions hold for 15.591 +all $j\le k$. 15.592 + 15.593 +There is at least one solution if and only if $n\le y_0$. 15.594 + 15.595 +We enter the name string into a hash table, using the |hash_in| 15.596 +routine of |gb_graph|, because there is no simple way to compute the 15.597 +location of a vertex from its coordinates. 15.598 + 15.599 +@<Name the points and create the arcs or edges@>= 15.600 +v=new_graph->vertices; 15.601 +yy[d+1]=0;@+sig[0]=n; 15.602 +for (k=d;k>=0;k--) yy[k]=yy[k+1]+nn[k]; 15.603 +if (yy[0]>=n) { 15.604 + k=0;@+xx[0]=(yy[1]>=n? 0: n-yy[1]); 15.605 + while (1) { 15.606 + @<Complete the partial solution $(x_0,\ldots,x_k)$@>; 15.607 + @<Assign a symbolic name for $(x_0,\ldots,x_d)$ to vertex~|v|@>; 15.608 + hash_in(v); /* enter |v->name| into the hash table 15.609 + (via utility fields |u,v|) */ 15.610 + @<Create arcs or edges from previous points to~|v|@>; 15.611 + v++; 15.612 + @<Advance to the next partial solution $(x_0,\ldots,x_k)$, where |k| is 15.613 + as large as possible; |goto last| if there are no more solutions@>; 15.614 + } 15.615 +} 15.616 +last:@+if (v!=new_graph->vertices+new_graph->n) 15.617 + panic(impossible); /* can't happen */ 15.618 + 15.619 +@ @<Complete the partial solution $(x_0,\ldots,x_k)$@>= 15.620 +for (s=sig[k]-xx[k],k++;k<=d;s-=xx[k],k++) { 15.621 + sig[k]=s; 15.622 + if (s<=yy[k+1]) xx[k]=0; 15.623 + else xx[k]=s-yy[k+1]; 15.624 +} 15.625 +if (s!=0) panic(impossible+1) /* can't happen */ 15.626 + 15.627 +@ Here we seek the largest $k$ such that $x_k$ can be increased without 15.628 +violating the necessary and sufficient conditions stated earlier. 15.629 + 15.630 +@<Advance to the next partial solution $(x_0,\ldots,x_k)$...@>= 15.631 +for (k=d-1;;k--) { 15.632 + if (xx[k]<sig[k] && xx[k]<nn[k]) break; 15.633 + if (k==0) goto last; 15.634 +} 15.635 +xx[k]++; 15.636 + 15.637 +@ As in the |board| routine, we represent the sequence of coordinates 15.638 +$(2,0,1)$ by the string `\.{2.0.1}'. 15.639 +The string won't exceed |BUF_SIZE|, because the ratio |BUF_SIZE/MAX_D| is 15.640 +plenty big. 15.641 + 15.642 +The first three coordinate values, $(x_0,x_1,x_2)$, are placed into 15.643 +utility fields |x|, |y|, and |z|, so that they can be accessed immediately 15.644 +if an application needs them. 15.645 + 15.646 +@<Assign a symbolic name for $(x_0,\ldots,x_d)$ to vertex~|v|@>= 15.647 +{@+register char *p=buffer; /* string pointer */ 15.648 + for (k=0;k<=d;k++) { 15.649 + sprintf(p,".%d",xx[k]); 15.650 + while (*p) p++; 15.651 + } 15.652 + v->name=gb_save_string(&buffer[1]); /* omit |buffer[0]|, which is |'.'| */ 15.653 + v->x.i=xx[0];@+v->y.i=xx[1];@+v->z.i=xx[2]; 15.654 +} 15.655 + 15.656 +@ Since we are generating the vertices in lexicographic order of their 15.657 +coordinates, it is easy to identify all adjacent vertices that 15.658 +precede the current setting of $(x_0,x_1,\ldots,x_d)$. We locate them 15.659 +via their symbolic names. 15.660 + 15.661 +@<Create arcs or edges from previous points to~|v|@>= 15.662 +for (j=0;j<d;j++) 15.663 + if (xx[j]) {@+register Vertex *u; /* previous vertex adjacent to |v| */ 15.664 + xx[j]--; 15.665 + for (k=j+1;k<=d;k++) 15.666 + if (xx[k]<nn[k]) {@+register char *p=buffer; /* string pointer */ 15.667 + xx[k]++; 15.668 + for (i=0;i<=d;i++) { 15.669 + sprintf(p,".%d",xx[i]); 15.670 + while (*p) p++; 15.671 + } 15.672 + u=hash_out(&buffer[1]); 15.673 + if (u==NULL) panic(impossible+2); /* can't happen */ 15.674 + if (directed) gb_new_arc(u,v,1); 15.675 + else gb_new_edge(u,v,1); 15.676 + xx[k]--; 15.677 + } 15.678 + xx[j]++; 15.679 + } 15.680 + 15.681 +@* Subset graphs. The subroutine call 15.682 +`|subsets(n,n0,n1,n2,n3,n4,size_bits,directed)|' 15.683 +creates a graph having the same vertices as 15.684 +|simplex(n,n0,n1,n2,n3,n4,directed)| but with a quite different notion 15.685 +of adjacency. In this we interpret a solution $(x_0,x_1,\ldots,x_d)$ to 15.686 +the conditions $x_0+x_1+\cdots+x_d=n$ and $0\le x_j\le n_j$ not as a 15.687 +position on a game board but as a submultiset of the multiset 15.688 +$\{n_0\cdot0,n_1\cdot 1,\ldots,n_d\cdot d\}$, having $x_j$ elements 15.689 +equal to~$j$. (If each $n_j=1$, the multiset is a set; this is an 15.690 +important special case.) Two vertices are adjacent if and only if 15.691 +their intersection has a cardinality that matches one of the bits in 15.692 +|size_bits|, which is an unsigned integer. Each arc has length~1. 15.693 + 15.694 +For example, suppose $n=3$ and |(n0,n1,n2,n3)=(2,2,2,0)|. Then the vertices 15.695 +are the 3-element submultisets of $\{0,0,1,1,2,2\}$, namely 15.696 +$$\{0,0,1\},\quad \{0,0,2\},\quad \{0,1,2\},\quad 15.697 +\{0,2,2\},\quad \{1,1,2\},\quad \{1,2,2\},$$ 15.698 +which are represented by the respective vectors 15.699 +$$(2,1,0),\quad (2,0,1),\quad (1,1,1),\quad 15.700 +(1,0,2),\quad (0,2,1),\quad (0,1,2).$$ 15.701 +The intersection of multisets represented by $(x_0,x_1,\ldots,x_d)$ and 15.702 +$(y_0,y_1,\ldots,y_d)$ is $$\bigl(\min(x_0,y_0),\min(x_1,y_1),\ldots, 15.703 +\min(x_d,y_d)\bigr);$$ each element occurs as often as it occurs 15.704 +in both multisets being intersected. If now |size_bits=3|, the 15.705 +multisets will be considered adjacent whenever their 15.706 +intersection contains exactly 0 or~1 elements, because $3=2^0+2^1$. 15.707 +The vertices adjacent to $\{0,0,1\}$ will, for example, be 15.708 +$\{0,2,2\}$ and $\{1,2,2\}$. In this case, every pair of submultisets 15.709 +has a nonempty intersection, so the same graph would be obtained 15.710 +if |size_bits=2|. 15.711 + 15.712 +If |directed| is nonzero, the graph will have directed arcs, from |u| 15.713 +to~|v| only if $u\le v$. Notice that the graph will have self-loops if 15.714 +and only if the binary representation of |size_bits| contains the term 15.715 +$2^n$, in which case there will be a loop from every vertex to itself. 15.716 +(In an undirected graph, such loops are represented by two arcs.) 15.717 + 15.718 +We define a macro |disjoint_subsets(n,k)| for the case 15.719 +of $n\choose k$ vertices, adjacent if and only if they represent 15.720 +disjoint $k$-subsets of an $n$-set. 15.721 +One important special case is the Petersen graph, whose vertices 15.722 +are the 2-element subsets of $\{0,1,2,3,4\}$, adjacent when they 15.723 +are disjoint. This graph is remarkable because it contains 10 vertices, 15.724 +each of degree~3, but it has no circuits of length less than~5. 15.725 + 15.726 +@(gb_basic.h@>= 15.727 +#define disjoint_subsets(n,k) @[subsets(k,1,1-n,0,0,0,1,0)@] 15.728 +#define petersen() @[disjoint_subsets(5,2)@] 15.729 + 15.730 +@ @<Basic subroutines@>= 15.731 +Graph *subsets(n,n0,n1,n2,n3,n4,size_bits,directed) 15.732 + unsigned n; /* the number of elements in the multiset */ 15.733 + int n0,n1,n2,n3,n4; /* multiplicities of elements */ 15.734 + unsigned long size_bits; /* intersection sizes that trigger arcs */ 15.735 + int directed; /* should the graph be directed? */ 15.736 +{@+@<Vanilla local variables@>@; 15.737 + @<Normalize the simplex parameters@>; 15.738 + @<Create a graph with one vertex for each subset@>; 15.739 + @<Name the subsets and create the arcs or edges@>; 15.740 + if (gb_alloc_trouble) { 15.741 + gb_recycle(new_graph); 15.742 + panic(alloc_fault); /* rats, we ran out of memory somewhere back there */ 15.743 + } 15.744 + return new_graph; 15.745 +} 15.746 + 15.747 +@ @<Create a graph with one vertex for each subset@>= 15.748 +@<Determine the number of feasible $(x_0,\ldots,x_d)$, and allocate the graph@>; 15.749 +sprintf(new_graph->id,"subsets(%u,%d,%d,%d,%d,%d,0x%lx,%d)", 15.750 + n,n0,n1,n2,n3,n4,size_bits,directed?1:0); 15.751 +strcpy(new_graph->format,"ZZZIIIZZZZZZZZ"); /* hash table will not be used */ 15.752 + 15.753 +@ We generate the vertices with exactly the logic used in |simplex|. 15.754 + 15.755 +@<Name the subsets and create the arcs or edges@>= 15.756 +v=new_graph->vertices; 15.757 +yy[d+1]=0;@+sig[0]=n; 15.758 +for (k=d;k>=0;k--) yy[k]=yy[k+1]+nn[k]; 15.759 +if (yy[0]>=n) { 15.760 + k=0;@+xx[0]=(yy[1]>=n? 0: n-yy[1]); 15.761 + while (1) { 15.762 + @<Complete the partial solution $(x_0,\ldots,x_k)$@>; 15.763 + @<Assign a symbolic name for $(x_0,\ldots,x_d)$ to vertex~|v|@>; 15.764 + @<Create arcs or edges from previous subsets to~|v|@>; 15.765 + v++; 15.766 + @<Advance to the next partial solution $(x_0,\ldots,x_k)$, where |k| is 15.767 + as large as possible; |goto last| if there are no more solutions@>; 15.768 + } 15.769 +} 15.770 +last:@+if (v!=new_graph->vertices+new_graph->n) 15.771 + panic(impossible); /* can't happen */ 15.772 + 15.773 +@ The only difference is that we generate the arcs or edges by brute 15.774 +force, examining each pair of vertices to see if they are adjacent or not. 15.775 + 15.776 +The code here is character-set dependent: It assumes that `\..' and null 15.777 +have a character code less than `\.0', as in ASCII. It also assumes 15.778 +that characters occupy exactly eight bits. 15.779 +@^system dependencies@> 15.780 + 15.781 +@d UL_BITS 8*sizeof(unsigned long) /* the number of bits in |size_bits| */ 15.782 + 15.783 +@<Create arcs or edges from previous subsets to~|v|@>= 15.784 +{@+register Vertex *u; 15.785 + for (u=new_graph->vertices;u<=v;u++) {@+register char *p=u->name; 15.786 + int ss=0; /* the number of elements common to |u| and |v| */ 15.787 + for (j=0;j<=d;j++,p++) { 15.788 + for (s=(*p++)-'0';*p>='0';p++) s=10*s+*p-'0'; /* |sscanf(p,"%d",&s)| */ 15.789 +@^character-set dependencies@> 15.790 + if (xx[j]<s) ss+=xx[j]; 15.791 + else ss+=s; 15.792 + } 15.793 + if ((size_bits&(((unsigned long)1)<<ss))&& ss<UL_BITS) { 15.794 + if (directed) gb_new_arc(u,v,1); 15.795 + else gb_new_edge(u,v,1); 15.796 + } 15.797 + } 15.798 +} 15.799 + 15.800 +@* Permutation graphs. The subroutine call 15.801 +`|perms(n0,n1,n2,n3,n4,max_inv,directed)|' 15.802 +creates a graph whose vertices represent the permutations of a 15.803 +multiset, having at most |max_inv| inversions. Two permutations are adjacent 15.804 +in the graph if one is obtained from the other by interchanging two 15.805 +adjacent elements. Each arc has length~1. 15.806 + 15.807 +For example, the multiset $\{0,0,1,2\}$ has twelve permutations: 15.808 +$$\vcenter{\halign{#&&\quad#\cr 15.809 +0012,&0021,&0102,&0120,&0201,&0210,\cr 15.810 +1002,&1020,&1200,&2001,&2010,&2100.\cr}}$$ 15.811 +The first of these, 0012, has two neighbors, 0021 and 0102. 15.812 + 15.813 +The number of inversions is the number of pairs of elements $xy$ such 15.814 +that $x>y$ and $x$ precedes $y$ from left to right, counting 15.815 +multiplicity. For example, 2010 has four inversions, corresponding to 15.816 +$xy\in\{20,21,20,10\}$. When two permutations are adjacent, one of 15.817 +them has exactly one more inversion than the other. It is not 15.818 +difficult to verify that the number of inversions of a permutation is 15.819 +equal to the distance in the graph from that permutation to the 15.820 +lexicographically first permutation. 15.821 + 15.822 +Parameters |n0| through |n4| specify the composition of the multiset, 15.823 +just as in the |subsets| routine. 15.824 +Roughly speaking, there are |n0| elements equal to~0, |n1| elements 15.825 +equal to~1, and so on. The multiset $\{0,0,1,2,3,3\}$ would, for example, 15.826 +be represented by |(n0,n1,n2,n3,n4)=(2,1,1,2,0)|. 15.827 + 15.828 +Of course, we sometimes want to have multisets with more than five distinct 15.829 +elements; when there are $d+1$ distinct elements, the multiset should have 15.830 +$n_k$ elements equal to~$k$ and $n=n_0+n_1+\cdots+n_d$ elements in all. 15.831 +The value of $d$ can be specified by making |n0=-d| (in which case 15.832 +each multiplicity $n_k$ is taken to be~1); or by making |n0>0| and |n1=-d| 15.833 +(in which case each multiplicity $n_k$ is taken to be equal to~|n0|); or 15.834 +|n0>0|, |n1>0|, |n2=-d| (in which case the multiplicities are alternately 15.835 +$(|n0|,|n1|,|n0|,|n1|,|n0|,\ldots\,)$); or |n0>0|, |n1>0|, |n2>0|, |n3=-d|, 15.836 +(in which case the multiplicities are the first~|d+1| elements of the 15.837 +periodic sequence $(|n0|,|n1|,|n2|,|n0|,|n1|,\ldots\,)$); or all 15.838 +but |n4| are positive, while |n4=-d| (in which case the multiplicities again 15.839 +are periodic). 15.840 + 15.841 +An example like |(n0,n1,n2,n3,n4)=(1,2,3,4,-8)| is about as tricky 15.842 +as you can get. It specifies the multiset $\{0,1,1,2,2,2,3,3,3,3,4,5,5, 15.843 +6,6,6,7,7,7,7,8\}$. 15.844 + 15.845 +If any of the multiplicity parameters is negative or zero, the 15.846 +remaining multiplicities are ignored. For example, if |n2<=0|, the 15.847 +subroutine does not look at |n3| or~|n4|. 15.848 + 15.849 +You probably don't want to try |perms(n0,0,0,0,0,max_inv,directed)| 15.850 +when |n0>0|, because a multiset with |n0| identical elements has only 15.851 +one permutation. 15.852 + 15.853 +The special case when you want all $n!$ permutations of an $n$-element set 15.854 +can be obtained by calling |all_perms(n,directed)|. 15.855 + 15.856 +@(gb_basic.h@>= 15.857 +#define all_perms(n,directed) @[perms(1-n,0,0,0,0,0,directed)@] 15.858 + 15.859 +@ If |max_inv=0|, all permutations will be considered, regardless of 15.860 +the number of inversions. In that case the total number of vertices in 15.861 +the graph will be the multinomial coefficient $${n\choose 15.862 +n_0,n_1,\ldots,n_d}\,,\qquad n=n_0+n_1+\cdots+n_d.$$ The maximum 15.863 +number of inversions in general is the number of inversions of the 15.864 +lexicographically last permutation, namely ${n\choose2}-{n_0\choose2}- 15.865 +{n_1\choose2}-\cdots-{n_d\choose2}=\sum_{0\le j<k\le d}n_jn_k$. 15.866 + 15.867 +If |directed| is nonzero, the graph will contain only arcs that are directed 15.868 +from permutations to their neighbors having exactly one more inversion. 15.869 + 15.870 +@ The program for |perms| is very similar in structure to the program 15.871 +for |simplex| already considered. 15.872 + 15.873 +@<Basic subroutines@>= 15.874 +Graph *perms(n0,n1,n2,n3,n4,max_inv,directed) 15.875 + int n0,n1,n2,n3,n4; /* composition of the multiset */ 15.876 + unsigned long max_inv; /* maximum number of inversions */ 15.877 + int directed; /* should the graph be directed? */ 15.878 +{@+@<Vanilla local variables@>@; 15.879 + register int n; /* total number of elements in multiset */ 15.880 + @<Normalize the permutation parameters@>; 15.881 + @<Create a graph with one vertex for each permutation@>; 15.882 + @<Name the permutations and create the arcs or edges@>; 15.883 + if (gb_alloc_trouble) { 15.884 + gb_recycle(new_graph); 15.885 + panic(alloc_fault); /* shucks, we ran out of memory somewhere back there */ 15.886 + } 15.887 + return new_graph; 15.888 +} 15.889 + 15.890 +@ @<Normalize the permutation parameters@>= 15.891 +if (n0==0) {@+n0=1;@+n1=0;@+} /* convert the empty set into $\{0\}$ */ 15.892 +else if (n0<0) {@+n1=n0;@+n0=1;@+} 15.893 +n=BUF_SIZE; /* this allows us to borrow code from |simplex|, already written */ 15.894 +@<Normalize the simplex parameters@>; 15.895 +@<Determine |n| and the maximum possible number of inversions@>; 15.896 + 15.897 +@ Here we want to set |max_inv| to the maximum possible number of 15.898 +inversions, if it is zero or if it exceeds that number. 15.899 + 15.900 +@<Determine |n| and the maximum possible number of inversions@>= 15.901 +{@+register long ss; /* max inversions known to be possible */ 15.902 + for (k=0,s=ss=0;k<=d;ss+=s*nn[k],s+=nn[k],k++) 15.903 + if (nn[k]>=BUF_SIZE) panic(bad_specs); 15.904 + /* too many elements in the multiset */ 15.905 + if (s>=BUF_SIZE) panic(bad_specs+1); /* too many elements in the multiset */ 15.906 + n=s; 15.907 + if (max_inv==0 || max_inv>ss) max_inv=ss; 15.908 +} 15.909 + 15.910 +@ To determine the number of vertices, we sum the first |max_inv+1| 15.911 +coefficients of a power series in which the coefficient of~$z^j$ 15.912 +is the number of permutations having $j$ inversions. It is known 15.913 +[{\sl Sorting and Searching}, exercise 5.1.2--16] that this power series 15.914 +is the ``$z$-multinomial coefficient'' 15.915 +$${n\choose n_0,\ldots,n_d}_z={n!_z\over n_0!_z\ldots n_d!_z}\,, 15.916 +\qquad\hbox{where}\qquad m!_z=\prod_{k=1}^m{1-z^k\over 1-z}\,.$$ 15.917 + 15.918 +@<Create a graph with one vertex for each permutation@>= 15.919 +{@+long nverts; /* the number of vertices */ 15.920 + register long *coef=gb_alloc_type(max_inv+1,@[long@],working_storage); 15.921 + if (gb_alloc_trouble) panic(no_room+1); /* can't allocate |coef| array */ 15.922 + coef[0]=1; 15.923 + for (j=1,s=nn[0];j<=d;s+=nn[j],j++) 15.924 + @<Multiply the power series coefficients by 15.925 + $\prod_{1\le k\le n_j}(1-z^{s+k})/(1-z^k)$@>; 15.926 + for (k=1,nverts=1;k<=max_inv;k++) { 15.927 + nverts+=coef[k]; 15.928 + if (nverts>1000000000) panic(very_bad_specs); /* way too big */ 15.929 + } 15.930 + gb_free(working_storage); /* recycle the |coef| array */ 15.931 + new_graph=gb_new_graph(nverts); 15.932 + if (new_graph==NULL) 15.933 + panic(no_room); /* out of memory before we're even started */ 15.934 + sprintf(new_graph->id,"perms(%d,%d,%d,%d,%d,%lu,%d)", 15.935 + n0,n1,n2,n3,n4,max_inv,directed?1:0); 15.936 + strcpy(new_graph->format,"VVZZZZZZZZZZZZ"); /* hash table will be used */ 15.937 +} 15.938 + 15.939 +@ After multiplication by $(1-z^{k+s})/(1-z^k)$, the coefficients of the 15.940 +power series will be nonnegative, because they are the coefficients of 15.941 +a $z$-multinomial coefficient. 15.942 + 15.943 +@<Multiply the power series coefficients by 15.944 + $\prod_{1\le k\le n_j}(1-z^{s+k})/(1-z^k)$@>= 15.945 +for (k=1;k<=nn[j];k++) {@+register int ii; 15.946 + for (i=max_inv,ii=i-k-s;ii>=0;ii--,i--) coef[i]-=coef[ii]; 15.947 + for (i=k,ii=0;i<=max_inv;i++,ii++) { 15.948 + coef[i]+=coef[ii]; 15.949 + if (coef[i]>1000000000) panic(very_bad_specs+1); /* way too big */ 15.950 + } 15.951 +} 15.952 + 15.953 +@ As we generate the permutations, we maintain a table $(y_1,\ldots,y_n)$, 15.954 +where $y_k$ is the number of 15.955 +inversions whose first element is the $k$th element of the multiset. 15.956 +For example, if the multiset is $\{0,0,1,2\}$ and the current permutation is 15.957 +$(2,0,1,0)$, the inversion table is $(y_1,y_2,y_3,y_4)=(0,0,1,3)$. Clearly 15.958 +$0\le y_k<k$, and $y_k\le y_{k-1}$ when the $k$th element of the multiset 15.959 +is the same as the $(k-1)$st element. These conditions are necessary 15.960 +and sufficient to define a valid inversion table. We will generate 15.961 +permutations in lexicographic order of their inversion tables. 15.962 + 15.963 +For convenience, we set up another array~|z|, which holds the 15.964 +initial inversion-free permutation. 15.965 + 15.966 +@<Name the permutations and create the arcs or edges@>= 15.967 +{@+register int *xtab,*ytab,*ztab; /* permutations and their inversions */ 15.968 + int m=0; /* current number of inversions */ 15.969 + @<Initialize |xtab|, |ytab|, and |ztab|@>; 15.970 + v=new_graph->vertices; 15.971 + while (1) { 15.972 + @<Assign a symbolic name for $(x_1,\ldots,x_n)$ to vertex~|v|@>; 15.973 + @<Create arcs or edges from previous permutations to~|v|@>; 15.974 + v++; 15.975 + @<Advance to the next perm; |goto last| if there are no more solutions@>; 15.976 + } 15.977 + last:@+if (v!=new_graph->vertices+new_graph->n) 15.978 + panic(impossible); /* can't happen */ 15.979 + gb_free(working_storage); 15.980 +} 15.981 + 15.982 +@ @<Initialize |xtab|, |ytab|, and |ztab|@>= 15.983 +xtab=gb_alloc_type(3*n+3,@[int@],working_storage); 15.984 +if (gb_alloc_trouble) { /* can't allocate |xtab| */ 15.985 + gb_recycle(new_graph);@+panic(no_room+2);@+} 15.986 +ytab=xtab+(n+1); 15.987 +ztab=ytab+(n+1); 15.988 +for (j=0,k=1,s=nn[0];;k++) { 15.989 + xtab[k]=ztab[k]=j; /* |ytab[k]=0| */ 15.990 + if (k==s) { 15.991 + if (++j>d) break; 15.992 + else s+=nn[j]; 15.993 + } 15.994 +} 15.995 + 15.996 +@ Here is the heart of the permutation logic. We find the largest~$k$ 15.997 +such that $y_k$ can legitimately be increased by~1. When we encounter 15.998 +a~$k$ for which $y_k$ cannot be increased, we set $y_k=0$ and adjust 15.999 +the $x$'s accordingly. If no $y_k$ can be increased, we are done. 15.1000 + 15.1001 +@<Advance to the next perm...@>= 15.1002 +for (k=n;k;k--) { 15.1003 + if (m<max_inv && ytab[k]<k-1) 15.1004 + if (ytab[k]<ytab[k-1] || ztab[k]>ztab[k-1]) goto move; 15.1005 + if (ytab[k]) { 15.1006 + for (j=k-ytab[k];j<k;j++) xtab[j]=xtab[j+1]; 15.1007 + m-=ytab[k]; 15.1008 + ytab[k]=0; 15.1009 + xtab[k]=ztab[k]; 15.1010 + } 15.1011 +} 15.1012 +goto last; 15.1013 +move: j=k-ytab[k]; /* the current location of the $k$th element, $z_k$ */ 15.1014 +xtab[j]=xtab[j-1];@+xtab[j-1]=ztab[k]; 15.1015 +ytab[k]++;@+m++; 15.1016 + 15.1017 +@ A permutation is encoded as a sequence of nonblank characters, 15.1018 +using an abbreviated copy of the |imap| code from |gb_io| and omitting 15.1019 +the characters that need to be quoted within strings. If the 15.1020 +number of distinct elements in the multiset is at most~62, only digits 15.1021 +and letters will appear in the vertex name. 15.1022 + 15.1023 +@<Private variables@>= 15.1024 +static char *short_imap="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ 15.1025 +abcdefghijklmnopqrstuvwxyz_^~&@@,;.:?!%#$+-*/|<=>()[]{}`'"; 15.1026 + 15.1027 +@ @<Assign a symbolic name for $(x_1,\ldots,x_n)...@>= 15.1028 +{@+register char *p; register int *q; 15.1029 + for (p=&buffer[n-1],q=&xtab[n];q>xtab;p--,q--) *p=short_imap[*q]; 15.1030 + v->name=gb_save_string(buffer); 15.1031 + hash_in(v); /* enter |v->name| into the hash table 15.1032 + (via utility fields |u,v|) */ 15.1033 +} 15.1034 + 15.1035 +@ Since we are generating the vertices in lexicographic order of their 15.1036 +inversions, it is easy to identify all adjacent vertices that 15.1037 +precede the current setting of $(x_1,\ldots,x_n)$. We locate them 15.1038 +via their symbolic names. 15.1039 + 15.1040 +@<Create arcs or edges from previous permutations to~|v|@>= 15.1041 +for (j=1;j<n;j++) 15.1042 + if (xtab[j]>xtab[j+1]) {@+register Vertex *u; 15.1043 + /* previous vertex adjacent to |v| */ 15.1044 + buffer[j-1]=short_imap[xtab[j+1]];@+buffer[j]=short_imap[xtab[j]]; 15.1045 + u=hash_out(buffer); 15.1046 + if (u==NULL) panic(impossible+2); /* can't happen */ 15.1047 + if (directed) gb_new_arc(u,v,1); 15.1048 + else gb_new_edge(u,v,1); 15.1049 + buffer[j-1]=short_imap[xtab[j]];@+buffer[j]=short_imap[xtab[j+1]]; 15.1050 + } 15.1051 + 15.1052 +@* Partition graphs. The subroutine call 15.1053 +`|parts(n,max_parts,max_size,directed)|' 15.1054 +creates a graph whose vertices represent the different ways to partition 15.1055 +the integer~|n| into at most |max_parts| parts, where each part is at most 15.1056 +|max_size|. Two partitions are adjacent in the graph if 15.1057 +one can be obtained from the other by combining two parts. 15.1058 +Each arc has length~1. 15.1059 + 15.1060 +For example, the partitions of~5 are 15.1061 +$$5,\quad 4+1,\quad 3+2,\quad 3+1+1,\quad 2+2+1,\quad 2+1+1+1,\quad 1+1+1+1+1.$$ 15.1062 +Here 5 is adjacent to $4+1$ and to $3+2$; $4+1$ is adjacent also to 15.1063 +$3+1+1$ and to $2+2+1$; $3+2$ is adjacent also to $3+1+1$ and to $2+2+1$; etc. 15.1064 +If |max_size| is 3, the partitions 5 and $4+1$ would not be included in 15.1065 +the graph. If |max_parts| is 3, the partitions $2+1+1+1$ and $1+1+1+1+1$ 15.1066 +would not be included. 15.1067 + 15.1068 +If |max_parts| or |max_size| are zero, they are reset to be equal to~|n|, 15.1069 +so that they make no restriction on the partitions. 15.1070 + 15.1071 +If |directed| is nonzero, the graph will contain only directed arcs from 15.1072 +partitions to their neighbors having exactly one more part. 15.1073 + 15.1074 +The special case when we want to generate all $p(n)$ partitions of the 15.1075 +integer~$n$ can be obtained by calling |all_parts(n,directed)|. 15.1076 + 15.1077 +@(gb_basic.h@>= 15.1078 +#define all_parts(n,directed) @[parts(n,0,0,directed)@] 15.1079 + 15.1080 +@ The program for |parts| is very similar in structure to the program 15.1081 +for |perms| already considered. 15.1082 + 15.1083 +@<Basic subroutines@>= 15.1084 +Graph *parts(n,max_parts,max_size,directed) 15.1085 + unsigned n; /* the number being partitioned */ 15.1086 + unsigned max_parts; /* maximum number of parts */ 15.1087 + unsigned max_size; /* maximum size of each part */ 15.1088 + int directed; /* should the graph be directed? */ 15.1089 +{@+@<Vanilla local variables@>@; 15.1090 + if (max_parts==0 || max_parts>n) max_parts=n; 15.1091 + if (max_size==0 || max_size>n) max_size=n; 15.1092 + if (max_parts>MAX_D) panic(bad_specs); /* too many parts allowed */ 15.1093 + @<Create a graph with one vertex for each partition@>; 15.1094 + @<Name the partitions and create the arcs or edges@>; 15.1095 + if (gb_alloc_trouble) { 15.1096 + gb_recycle(new_graph); 15.1097 + panic(alloc_fault); 15.1098 + /* doggone it, we ran out of memory somewhere back there */ 15.1099 + } 15.1100 + return new_graph; 15.1101 +} 15.1102 + 15.1103 +@ The number of vertices is the coefficient of $z^n$ 15.1104 +in the $z$-binomial coefficient ${m+p\choose m}_z$, where $m=|max_parts|$ 15.1105 +and $p=|max_size|$. This coefficient is calculated as in the |perms| routine. 15.1106 + 15.1107 +@<Create a graph with one vertex for each partition@>= 15.1108 +{@+long nverts; /* the number of vertices */ 15.1109 + register long *coef=gb_alloc_type(n+1,@[long@],working_storage); 15.1110 + if (gb_alloc_trouble) panic(no_room+1); /* can't allocate |coef| array */ 15.1111 + coef[0]=1; 15.1112 + for (k=1;k<=max_parts;k++) { 15.1113 + for (j=n,i=n-k-max_size;i>=0;i--,j--) coef[j]-=coef[i]; 15.1114 + for (j=k,i=0;j<=n;i++,j++) { 15.1115 + coef[j]+=coef[i]; 15.1116 + if (coef[j]>1000000000) panic(very_bad_specs); /* way too big */ 15.1117 + } 15.1118 + } 15.1119 + nverts=coef[n]; 15.1120 + gb_free(working_storage); /* recycle the |coef| array */ 15.1121 + new_graph=gb_new_graph(nverts); 15.1122 + if (new_graph==NULL) 15.1123 + panic(no_room); /* out of memory before we're even started */ 15.1124 + sprintf(new_graph->id,"parts(%u,%u,%u,%d)", 15.1125 + n,max_parts,max_size,directed?1:0); 15.1126 + strcpy(new_graph->format,"VVZZZZZZZZZZZZ"); /* hash table will be used */ 15.1127 +} 15.1128 + 15.1129 +@ As we generate the partitions, we maintain 15.1130 +the numbers $\sigma_j=n-(x_1+\cdots+x_{j-1})=x_j+x_{j+1}+\cdots\,$, 15.1131 +somewhat as we did in the |simplex| routine. We set $x_0=|max_size|$, 15.1132 +and $y_j=|max_parts|+1-j$; then the conditions 15.1133 +$$\sigma_j/y_j\le x_j\le \sigma_j,\qquad x_j\le x_{j-1}$$ 15.1134 +characterize the legal values of~$x_j$, given $(x_1,\ldots,x_{j-1})$. 15.1135 + 15.1136 +@<Name the partitions and create the arcs or edges@>= 15.1137 +v=new_graph->vertices; 15.1138 +xx[0]=max_size;@+sig[1]=n; 15.1139 +for (k=max_parts,s=1;k>0;k--,s++) yy[k]=s; 15.1140 +if (max_size*max_parts>=n) { 15.1141 + k=1;@+xx[1]=(n-1)/max_parts+1; /* $\lceil n/|max_parts|\rceil$ */ 15.1142 + while (1) { 15.1143 + @<Complete the partial solution $(x_1,\ldots,x_k)$@>; 15.1144 + @<Assign the name $x_1+\cdots+x_d$ to vertex~|v|@>; 15.1145 + @<Create arcs or edges from |v| to previous partitions@>; 15.1146 + v++; 15.1147 + @<Advance to the next partial solution $(x_1,\ldots,x_k)$, where |k| is 15.1148 + as large as possible; |goto last| if there are no more solutions@>; 15.1149 + } 15.1150 +} 15.1151 +last:@+if (v!=new_graph->vertices+new_graph->n) 15.1152 + panic(impossible); /* can't happen */ 15.1153 + 15.1154 +@ @<Complete the partial solution $(x_1,\ldots,x_k)$@>= 15.1155 +for (s=sig[k]-xx[k],k++;s;k++) { 15.1156 + sig[k]=s; 15.1157 + xx[k]=(s-1)/yy[k]+1; 15.1158 + s-=xx[k]; 15.1159 +} 15.1160 +d=k-1; /* the smallest part is $x_d$ */ 15.1161 + 15.1162 +@ Here we seek the largest $k$ such that $x_k$ can be increased without 15.1163 +violating the necessary and sufficient conditions stated earlier. 15.1164 + 15.1165 +@<Advance to the next partial solution $(x_1,\ldots,x_k)$...@>= 15.1166 +if (d==1) goto last; 15.1167 +for (k=d-1;;k--) { 15.1168 + if (xx[k]<sig[k] && xx[k]<xx[k-1]) break; 15.1169 + if (k==1) goto last; 15.1170 +} 15.1171 +xx[k]++; 15.1172 + 15.1173 +@ @<Assign the name $x_1+...@>= 15.1174 +{@+register char *p=buffer; /* string pointer */ 15.1175 + for (k=1;k<=d;k++) { 15.1176 + sprintf(p,"+%d",xx[k]); 15.1177 + while (*p) p++; 15.1178 + } 15.1179 + v->name=gb_save_string(&buffer[1]); /* omit |buffer[0]|, which is |'+'| */ 15.1180 + hash_in(v); /* enter |v->name| into the hash table 15.1181 + (via utility fields |u,v|) */ 15.1182 +} 15.1183 + 15.1184 +@ Since we are generating the partitions in lexicographic order of their 15.1185 +parts, it is reasonably easy to identify all adjacent vertices that 15.1186 +precede the current setting of $(x_1,\ldots,x_d)$, by splitting 15.1187 +$x_j$ into two parts when $x_j\ne x_{j+1}$. We locate previous partitions 15.1188 +via their symbolic names. 15.1189 + 15.1190 +@<Create arcs or edges from |v| to previous partitions@>= 15.1191 +if (d<max_parts) { 15.1192 + xx[d+1]=0; 15.1193 + for (j=1;j<=d;j++) { 15.1194 + if (xx[j]!=xx[j+1]) {@+int a,b; 15.1195 + for (b=xx[j]/2,a=xx[j]-b;b;a++,b--) 15.1196 + @<Generate a subpartition $(n_1,\ldots,n_{d+1})$ by 15.1197 + splitting $x_j$ into $a+b$, and make that subpartition 15.1198 + adjacent to~|v|@>; 15.1199 + } 15.1200 + nn[j]=xx[j]; 15.1201 + } 15.1202 +} 15.1203 + 15.1204 +@ The values of $(x_1,\ldots,x_{j-1})$ have already been copied into 15.1205 +$(n_1,\ldots,n_{j-1})$. Our job is to copy the smaller parts 15.1206 +$(x_{j+1},\ldots,x_d)$ while 15.1207 +inserting $a$ and $b$ in their proper places, knowing that $a\ge b$. 15.1208 + 15.1209 +@<Generate a subpartition $(n_1,\ldots,n_{d+1})$...@>= 15.1210 +{@+register Vertex *u; /* previous vertex adjacent to |v| */ 15.1211 + register char *p=buffer; 15.1212 + for (k=j+1;xx[k]>a;k++) nn[k-1]=xx[k]; 15.1213 + nn[k-1]=a; 15.1214 + for (;xx[k]>b;k++) nn[k]=xx[k]; 15.1215 + nn[k]=b; 15.1216 + for (;k<=d;k++) nn[k+1]=xx[k]; 15.1217 + for (k=1;k<=d+1;k++) { 15.1218 + sprintf(p,"+%d",nn[k]); 15.1219 + while (*p) p++; 15.1220 + } 15.1221 + u=hash_out(&buffer[1]); 15.1222 + if (u==NULL) panic(impossible+2); /* can't happen */ 15.1223 + if (directed) gb_new_arc(v,u,1); 15.1224 + else gb_new_edge(v,u,1); 15.1225 +} 15.1226 + 15.1227 +@* Binary tree graphs. The subroutine call 15.1228 +`|binary(n,max_height,directed)|' 15.1229 +creates a graph whose vertices represent the binary trees with $n$ internal 15.1230 +nodes and with all leaves at distance at most |max_height| from the root. 15.1231 +Two binary trees are adjacent in the graph if 15.1232 +one can be obtained from the other by a single application of the 15.1233 +associative law for binary operations, i.e., by replacing some subtree 15.1234 +of the form $(\alpha\cdot\beta)\cdot\gamma$ by the subtree $\alpha\cdot 15.1235 +(\beta\cdot\gamma)$. (This transformation on binary trees is often 15.1236 +called a ``rotation.'') If the |directed| parameter is nonzero, the 15.1237 +directed arcs go from a tree containing $(\alpha\cdot\beta)\cdot\gamma$ 15.1238 +to a tree containing $\alpha\cdot(\beta\cdot\gamma)$ in its place; otherwise 15.1239 +the graph is undirected. Each arc has length~1. 15.1240 + 15.1241 +For example, the binary trees with 3 internal nodes form a circuit of 15.1242 +length~5: They are 15.1243 +$$\mathcode`.="2201 % \cdot 15.1244 +(a.b).(c.d),\quad a.(b.(c.d)),\quad a.((b.c).d),\quad (a.(b.c)).d,\quad 15.1245 +((a.b).c).d,$$ 15.1246 +if we use infix notation and name the leaves $(a,b,c,d)$ from left to right. 15.1247 +Here each tree is related to its two neighbors by associativity, and the 15.1248 +first and last trees are also related in the same way. 15.1249 + 15.1250 +If |max_height=0|, it is changed to |n|, which means there is no 15.1251 +restriction on the height of a leaf. In this case the graph will have 15.1252 +exactly ${2n+1\choose n}/ (2n+1)$ vertices; furthermore, each vertex 15.1253 +will have exactly $n-1$ neighbors, because a rotation will be possible 15.1254 +just above every internal node except the root. The graph in this 15.1255 +graph can also be interpreted geometrically: The vertices are in one 15.1256 +to one correspondence with the triangulations of a regular 15.1257 +$(n+2)$-gon; two triangulations are adjacent if and only if one is obtained 15.1258 +from the other by replacing the pair of adjacent triangles $ABC,DCB$ 15.1259 +by the pair $ADC,BDA$. 15.1260 + 15.1261 +@(gb_basic.h@>= 15.1262 +#define all_trees(n,directed) @[binary(n,0,directed)@] 15.1263 + 15.1264 + 15.1265 +@ The program for |binary| is very similar in structure to the program 15.1266 +for |parts| already considered. But the details are more exciting. 15.1267 + 15.1268 +@<Basic subroutines@>= 15.1269 +Graph *binary(n,max_height,directed) 15.1270 + unsigned n; /* the number of internal nodes */ 15.1271 + unsigned max_height; /* maximum height of a leaf */ 15.1272 + int directed; /* should the graph be directed? */ 15.1273 +{@+@<Vanilla local variables@>@; 15.1274 + if (2*n+2>BUF_SIZE) panic(bad_specs); /* |n| is too huge for us */ 15.1275 + if (max_height==0 || max_height>n) max_height=n; 15.1276 + if (max_height>30) panic(very_bad_specs); /* more than a billion vertices */ 15.1277 + @<Create a graph with one vertex for each binary tree@>; 15.1278 + @<Name the trees and create the arcs or edges@>; 15.1279 + if (gb_alloc_trouble) { 15.1280 + gb_recycle(new_graph); 15.1281 + panic(alloc_fault); /* uff da, we ran out of memory somewhere back there */ 15.1282 + } 15.1283 + return new_graph; 15.1284 +} 15.1285 + 15.1286 +@ The number of vertices is the coefficient of $z^n$ 15.1287 +in the power series $G_h$, where $h=|max_height|$ and the recurrence 15.1288 +$$G_0=1,\qquad G_{h+1}=1+z G_h^2$$ 15.1289 +defines $G_h$. 15.1290 + 15.1291 +The coefficients of $G_5$ are $\le55308$, but the 15.1292 +coefficients of $G_6$ are much larger; they exceed one billion when 15.1293 +$28\le n\le49$, and they exceed one million when $17\le n\le 56$. 15.1294 +In order to avoid overflow during this calculation, we use a 15.1295 +special method when $h\ge6$ and $n\ge20$: In such cases, graphs 15.1296 +of reasonable size arise only if $n\ge 2^h-7$, and we look at the 15.1297 +coefficient of $z^{-(2^h-1-n)}$ in $R_h=G_h/z^{2^h-1}$, which is a 15.1298 +power series in $z^{-1}$ defined by the recurrence 15.1299 +$$R_0=1,\qquad R_{h+1}=R_h^2+z^{1-2^{h+1}}.$$ 15.1300 + 15.1301 +@<Create a graph with one vertex for each binary tree@>= 15.1302 +{@+long nverts; /* the number of vertices */ 15.1303 + if (n>=20 && max_height>=6) @<Compute |nverts| using the $R$ series@>@; 15.1304 + else { 15.1305 + nn[0]=nn[1]=1; 15.1306 + for (k=2;k<=n;k++) nn[k]=0; 15.1307 + for (j=2;j<=max_height;j++) 15.1308 + for (k=n-1;k;k--) { 15.1309 + for (s=0,i=k;i>=0;i--) s+=nn[i]*nn[k-i]; /* overflow impossible */ 15.1310 + nn[k+1]=s; 15.1311 + } 15.1312 + nverts=nn[n]; 15.1313 + } 15.1314 + new_graph=gb_new_graph(nverts); 15.1315 + if (new_graph==NULL) 15.1316 + panic(no_room); /* out of memory before we're even started */ 15.1317 + sprintf(new_graph->id,"binary(%u,%u,%d)", 15.1318 + n,max_height,directed?1:0); 15.1319 + strcpy(new_graph->format,"VVZZZZZZZZZZZZ"); /* hash table will be used */ 15.1320 +} 15.1321 + 15.1322 +@ The smallest nontrivial graph that is unilaterally disallowed by 15.1323 +this procedure on the grounds of size limitations occurs when |max_height=6| 15.1324 +and |n=20|; it has 14,162,220 vertices. 15.1325 + 15.1326 +@<Compute |nverts| using the $R$ series@>= 15.1327 +{@+register float ss; 15.1328 + d=(1<<max_height)-1-n; 15.1329 + if (d>8) panic(bad_specs+1); /* too many vertices */ 15.1330 + if (d<0) nverts=0; 15.1331 + else { 15.1332 + nn[0]=nn[1]=1; 15.1333 + for (k=2;k<=d;k++) nn[k]=0; 15.1334 + for (j=2;j<=max_height;j++) { 15.1335 + for (k=d;k;k--) { 15.1336 + for (ss=0.0,i=k;i>=0;i--) ss+=((float)nn[i])*((float)nn[k-i]); 15.1337 + if (ss>MAX_NNN) panic(very_bad_specs+1); /* way too big */ 15.1338 + for (s=0,i=k;i>=0;i--) s+=nn[i]*nn[k-i]; /* overflow impossible */ 15.1339 + nn[k]=s; 15.1340 + } 15.1341 + i=(1<<j)-1; 15.1342 + if (i<=d) nn[i]++; /* add $z^{1-2^j}$ */ 15.1343 + } 15.1344 + nverts=nn[d]; 15.1345 + } 15.1346 +} 15.1347 + 15.1348 +@ We generate the trees in lexicographic order of their Polish prefix 15.1349 +notation, encoded in binary notation as $x_0x_1\ldots x_{2n}$, using `1' 15.1350 +for an internal node and `0' for a leaf. For example, the five 15.1351 +trees when $n=3$ are 15.1352 +$$1010100,\quad 1011000,\quad 1100100,\quad 1101000,\quad 1110000,$$ 15.1353 +in lexicographic order. The algorithm for lexicographic generation maintains 15.1354 +three auxiliary arrays $l_j$, $y_j$, and $\sigma_j$, where 15.1355 +$$\sigma_j\;=\;n-j+\sum_{i=0}^{j-1}x_i\;=\;-1+\sum_{i=j}^{2n}(1-x_i)$$ 15.1356 +is one less than the number of 0's (leaves) in $(x_j,\ldots,x_{2n})$. 15.1357 +The values of $l_j$ and $y_j$ are harder 15.1358 +to describe formally; $l_j$ is $2^{h-l}$ when $h=|max_height|$ and when 15.1359 +$x_j$ represents a node at level~$l$ of the tree, based on the values 15.1360 +of $(x_0,\ldots,x_{j-1})$. The value of $y_j$ is a binary encoding of 15.1361 +tree levels in which an internal node has not yet received a right child; 15.1362 +$y_j$ is also the maximum number of future leaves that can be produced by 15.1363 +previously specified internal nodes, without exceeding the maximum height. 15.1364 +The number of 1-bits in $y_j$ is the minimum number of future leaves, 15.1365 +based on previous specifications. 15.1366 + 15.1367 +Therefore if $\sigma_j>y_j$, $x_j$ is forced to be~1. If $l_j=1$, 15.1368 +$x_j$ is forced to be~0. If the number of 1-bits of $y_j$ is equal 15.1369 +to $\sigma_j$, $x_j$ is forced to be~0. Otherwise $x_j$ can be 15.1370 +either 0 or~1, and it will be possible to complete the partial 15.1371 +solution $x_0\ldots x_j$ to a full Polish prefix code $x_0\ldots x_{2n}$. 15.1372 + 15.1373 +For example, here are the arrays for one of the binary trees 15.1374 +that is generated when $n=h=3$: 15.1375 +$$\vcenter{\halign{$\hfil#$\quad=&&\quad#\cr 15.1376 +j &0&1&2&3&4&5&6\cr 15.1377 +l_j &8&4&2&2&1&1&4\cr 15.1378 +y_j &0&4&6&4&5&4&0\cr 15.1379 +\sigma_j&3&3&3&2&2&1&0\cr 15.1380 +x_j &1&1&0&1&0&0&0\cr}}$$ 15.1381 +If $x_j=1$ and $j<2n$, we have $l_{j+1}=l_j/2$, $y_{j+1}=y_j+l_{j+1}$, 15.1382 +and $\sigma_{j+1}=\sigma_j$. If $x_j=0$ and $j<2n$, we have $l_{j+1}= 15.1383 +2^t$, $y_{j+1}=y_j-2^t$, and $\sigma_{j+1}=\sigma_j-1$, where $2^t$ is the 15.1384 +least power of~2 in the binary representation of~$y_j$. It is not difficult to 15.1385 +prove by induction that $\sigma_j<y_j+l_j$, assuming that $n<2^h$. 15.1386 + 15.1387 +@<Name the trees and create the arcs or edges@>= 15.1388 +{@+register long *xtab,*ytab,*ltab,*stab; 15.1389 + @<Initialize |xtab|, |ytab|, |ltab|, and |stab|; also set |d=2n|@>; 15.1390 + v=new_graph->vertices; 15.1391 + if (ltab[0]>n) { 15.1392 + k=0;@+xtab[0]=n?1:0; 15.1393 + while (1) { 15.1394 + @<Complete the partial tree $x_0\ldots x_k$@>; 15.1395 + @<Assign a Polish prefix code name to vertex~|v|@>; 15.1396 + @<Create arcs or edges from |v| to previous trees@>; 15.1397 + v++; 15.1398 + @<Advance to the next partial tree $x_0\ldots x_k$, where |k| is 15.1399 + as large as possible; |goto last| if there are no more solutions@>; 15.1400 + } 15.1401 + } 15.1402 +} 15.1403 +last:@+if (v!=new_graph->vertices+new_graph->n) 15.1404 + panic(impossible); /* can't happen */ 15.1405 +gb_free(working_storage); 15.1406 + 15.1407 +@ @<Initialize |xtab|, |ytab|, |ltab|, and |stab|...@>= 15.1408 +xtab=gb_alloc_type(8*n+4,@[int@],working_storage); 15.1409 +if (gb_alloc_trouble) { /* no room for |xtab| */ 15.1410 + gb_recycle(new_graph);@+panic(no_room+2);@+} 15.1411 +d=n+n; 15.1412 +ytab=xtab+(d+1); 15.1413 +ltab=ytab+(d+1); 15.1414 +stab=ltab+(d+1); 15.1415 +ltab[0]=1<<max_height; 15.1416 +stab[0]=n; /* |ytab[0]=0| */ 15.1417 + 15.1418 +@ @<Complete the partial tree...@>= 15.1419 +for (j=k+1;j<=d;j++) { 15.1420 + if (xtab[j-1]) { 15.1421 + ltab[j]=ltab[j-1]>>1; 15.1422 + ytab[j]=ytab[j-1]+ltab[j]; 15.1423 + stab[j]=stab[j-1]; 15.1424 + } else { 15.1425 + ytab[j]=ytab[j-1]&(ytab[j-1]-1); /* remove least significant 1-bit */ 15.1426 + ltab[j]=ytab[j-1]-ytab[j]; 15.1427 + stab[j]=stab[j-1]-1; 15.1428 + } 15.1429 + if (stab[j]<=ytab[j]) xtab[j]=0; 15.1430 + else xtab[j]=1; /* this is the lexicographically smallest completion */ 15.1431 +} 15.1432 + 15.1433 +@ As in previous routines, we seek the largest $k$ such that $x_k$ can 15.1434 +be increased without violating the necessary and sufficient conditions 15.1435 +stated earlier. 15.1436 + 15.1437 +@<Advance to the next partial tree...@>= 15.1438 +for (k=d-1;;k--) { 15.1439 + if (k<=0) goto last; /* this happens only when |n<=1| */ 15.1440 + if (xtab[k]) break; /* find rightmost 1 */ 15.1441 +} 15.1442 +for (k--;;k--) { 15.1443 + if (xtab[k]==0 && ltab[k]>1) break; 15.1444 + if (k==0) goto last; 15.1445 +} 15.1446 +xtab[k]++; 15.1447 + 15.1448 +@ In the |name| field, we encode internal nodes of the binary tree by 15.1449 +`\..' and leaves by `\.x'. Thus the five trees shown above in binary 15.1450 +code will be named 15.1451 +$$\.{.x.x.xx},\quad \.{.x..xxx},\quad \.{..xx.xx},\quad \.{..x.xxx},\quad 15.1452 +\.{...xxxx},$$ 15.1453 +respectively. 15.1454 + 15.1455 +@<Assign a Polish prefix...@>= 15.1456 +{@+register char *p=buffer; /* string pointer */ 15.1457 + for (k=0;k<=d;k++,p++) *p=(xtab[k]? '.': 'x'); 15.1458 + v->name=gb_save_string(buffer); 15.1459 + hash_in(v); /* enter |v->name| into the hash table 15.1460 + (via utility fields |u,v|) */ 15.1461 +} 15.1462 + 15.1463 +@ Since we are generating the trees in lexicographic order of their 15.1464 +Polish prefix notation, it is relatively easy to find all pairs of trees that 15.1465 +are adjacent via one application of the associative law: We simply 15.1466 +replace a substring of the form $\..\..\alpha\beta$ by 15.1467 +$\..\alpha\..\beta$, when $\alpha$ and $\beta$ are Polish prefix 15.1468 +strings. The result comes earlier in lexicographic order, so it will 15.1469 +be an existing vertex unless it violates the |max_height| restriction. 15.1470 + 15.1471 +@<Create arcs or edges from |v| to previous trees@>= 15.1472 +for (j=0;j<d;j++) 15.1473 + if (xtab[j]==1 && xtab[j+1]==1) { 15.1474 + for (i=j+1,s=0;s>=0;s+=(xtab[i+1]<<1)-1,i++) xtab[i]=xtab[i+1]; 15.1475 + xtab[i]=1; 15.1476 + {@+register char *p=buffer; /* string pointer */ 15.1477 + register Vertex *u; 15.1478 + for (k=0;k<=d;k++,p++) *p=(xtab[k]? '.': 'x'); 15.1479 + u=hash_out(buffer); 15.1480 + if (u) { 15.1481 + if (directed) gb_new_arc(v,u,1); 15.1482 + else gb_new_edge(v,u,1); 15.1483 + } 15.1484 + } 15.1485 + for (i--;i>j;i--) xtab[i+1]=xtab[i]; /* restore |xtab| */ 15.1486 + xtab[i+1]=1; 15.1487 + } 15.1488 + 15.1489 +@* Complementing and copying. We have seen how to create a wide 15.1490 +variety of basic graphs with the |board|, |simplex|, |subsets|, 15.1491 +|perms|, |parts|, and |binary| procedures. The remaining routines 15.1492 +of |gb_basic| are somewhat different. They transform existing 15.1493 +graphs into new ones, thereby presenting us with an almost 15.1494 +mind-boggling array of further possibilities. 15.1495 + 15.1496 +The first of these transformations is perhaps the simplest: It 15.1497 +complements a given graph, i.e., makes vertices adjacent if and only if 15.1498 +they were previously non-adjacent. More precisely, the subroutine call 15.1499 +`|complement(g,copy,self,directed)|' returns a graph with the 15.1500 +same vertices as |g|, but with complemented arcs. 15.1501 +If |self!=0|, the new graph will have a self-loop from a vertex |v| to itself 15.1502 +when the original graph did not; if |self=0|, the new graph will 15.1503 +have no self-loops. If |directed!=0|, the new graph will have 15.1504 +an arc from |u| to |v| when the original graph did not; if |directed=0|, 15.1505 +the new graph will be undirected, and it will have an edge between |u| 15.1506 +and~|v| when the original graph did not. In the latter case, the original 15.1507 +graph should also be undirected (i.e., its arcs should come in pairs, 15.1508 +as described in the |gb_new_edge| routine of |gb_graph|). 15.1509 + 15.1510 +If |copy!=0|, a double complement will actually be done. This means that 15.1511 +the new graph will essentially be a copy of the old, except that 15.1512 +duplicate arcs (and possibly self-loops) will be removed. Information 15.1513 +that may have been in the utility fields is not copied, and arc lengths 15.1514 +are all set to~1. 15.1515 + 15.1516 +One possibly useful feature of the graphs returned by |complement| is 15.1517 +worth noting: The vertices adjacent to~|v|, namely the list 15.1518 +$$\hbox{|v->arcs->tip|,\quad |v->arcs->next->tip|,\quad 15.1519 + |v->arcs->next->next->tip|,\quad \dots\thinspace,}$$ 15.1520 +will be in strictly decreasing order (except in the case of an 15.1521 +undirected self-loop, when |v| itself will appear twice in succession). 15.1522 + 15.1523 +@ @<Basic subroutines@>= 15.1524 +Graph *complement(g,copy,self,directed) 15.1525 + Graph *g; /* graph to be complemented */ 15.1526 + int copy; /* should we double-complement? */ 15.1527 + int self; /* should we produce self-loops? */ 15.1528 + int directed; /* should the graph be directed? */ 15.1529 +{@+@<Vanilla local variables@>@; 15.1530 + register int n; 15.1531 + register Vertex *u; 15.1532 + register unsigned long delta; /* difference in memory addresses */ 15.1533 + if (g==NULL) panic(missing_operand); /* where's |g|? */ 15.1534 + @<Set up a graph with the vertices of |g|@>; 15.1535 + sprintf(buffer,",%d,%d,%d)",copy?1:0,self?1:0,directed?1:0); 15.1536 + make_compound_id(new_graph,"complement(",g,buffer); 15.1537 + @<Insert complementary arcs or edges@>; 15.1538 + if (gb_alloc_trouble) { 15.1539 + gb_recycle(new_graph); 15.1540 + panic(alloc_fault); 15.1541 + /* worse luck, we ran out of memory somewhere back there */ 15.1542 + } 15.1543 + return new_graph; 15.1544 +} 15.1545 + 15.1546 +@ In several of the following routines it is efficient to circumvent 15.1547 +\Cee's normal rules for pointer arithmetic, and to use the 15.1548 +fact that the vertices of a graph being copied are a constant distance away 15.1549 +in memory from the vertices of its clone. 15.1550 + 15.1551 +@d vert_offset(v,delta) ((Vertex*)(((unsigned long)v)+delta)) 15.1552 +@^pointer hacks@> 15.1553 + 15.1554 +@<Set up a graph with the vertices of |g|@>= 15.1555 +n=g->n; 15.1556 +new_graph=gb_new_graph(n); 15.1557 +if (new_graph==NULL) 15.1558 + panic(no_room); /* out of memory before we're even started */ 15.1559 +delta=((unsigned long)(new_graph->vertices))-((unsigned long)(g->vertices)); 15.1560 +for (u=new_graph->vertices,v=g->vertices;v<g->vertices+n;u++,v++) 15.1561 + u->name=gb_save_string(v->name); 15.1562 + 15.1563 +@ A temporary utility field in the new graph is used to remember which 15.1564 +vertices are adjacent to a given vertex in the old one. We stamp the |tmp| 15.1565 +field of~|v| with a pointer to~|u| when there's an arc from |u| to~|v|. 15.1566 + 15.1567 +@d tmp u.v /* utility field |u| for temporary use as a vertex pointer */ 15.1568 + 15.1569 +@<Insert comp...@>= 15.1570 +for (v=g->vertices;v<g->vertices+n;v++) {@+register Vertex *vv; 15.1571 + u=vert_offset(v,delta); 15.1572 + /* vertex in |new_graph| corresponding to |v| in |g| */ 15.1573 + {@+register Arc *a; 15.1574 + for (a=v->arcs;a;a=a->next) vert_offset(a->tip,delta)->tmp=u; 15.1575 + } 15.1576 + if (directed) { 15.1577 + for (vv=new_graph->vertices;vv<new_graph->vertices+n;vv++) 15.1578 + if ((vv->tmp==u && copy) || (vv->tmp!=u && !copy)) 15.1579 + if (vv!=u || self) gb_new_arc(u,vv,1); 15.1580 + } else { 15.1581 + for (vv=(self?u:u+1);vv<new_graph->vertices+n;vv++) 15.1582 + if ((vv->tmp==u && copy) || (vv->tmp!=u && !copy)) 15.1583 + gb_new_edge(u,vv,1); 15.1584 + } 15.1585 +} 15.1586 +for (v=new_graph->vertices;v<new_graph->vertices+n;v++) v->tmp=NULL; 15.1587 + 15.1588 +@* Graph union and intersection. Another simple way to get new graphs 15.1589 +from old ones is to take the union or intersection of their sets of arcs. The 15.1590 +subroutine call `|gunion(g,gg,multi,directed)|' produces a graph 15.1591 +with the vertices and arcs of |g| together with the 15.1592 +arcs of another graph~|gg|. The subroutine call `|intersection(g,gg,multi, 15.1593 +directed)|' produces a graph with the vertices of |g| but with only the 15.1594 +arcs that appear in both |g| and |gg|. In both cases we assume 15.1595 +that |gg| has the same vertices as |g|, in the sense that vertices 15.1596 +in the same relative position from the beginning of the vertex array 15.1597 +are considered identical. If the actual number of vertices in |gg| exceeds 15.1598 +the number in |g|, the extra vertices and all arcs touching them in~|gg| are 15.1599 +suppressed. 15.1600 + 15.1601 +The input graphs are assumed to be undirected, unless the |directed| 15.1602 +parameter is nonzero. Peculiar results may occur if you mix directed 15.1603 +and undirected graphs, but the subroutines will not ``crash'' 15.1604 +when they are asked to produce undirected output from directed input. 15.1605 + 15.1606 +If |multi| is nonzero, the new graph may have multiple edges: Suppose 15.1607 +there are $k_1$ arcs from $u$ to $v$ in |g|, and $k_2$ in |gg|. Then 15.1608 +there will be $k_1+k_2$ in the union and $\min(k_1,k_2)$ in the 15.1609 +intersection when |multi!=0|, but at most 15.1610 +one in the union or intersection when |multi=0|. 15.1611 + 15.1612 +The lengths of arcs are copied to the union graph when |multi!=0|; 15.1613 +the minimum length of multiple arcs is retained in the union when |multi=0|. 15.1614 + 15.1615 +The lengths of arcs in the intersection graph are a bit trickier. 15.1616 +If multiple arcs occur in |g|, their minimum length, |l|, is computed. Then 15.1617 +we compute the maximum of |l| and the lengths of corresponding arcs 15.1618 +in |gg|. If |multi=0|, only the minimum of those maxima will survive. 15.1619 + 15.1620 +@ @<Basic subroutines@>= 15.1621 +Graph *gunion(g,gg,multi,directed) 15.1622 + Graph *g,*gg; /* graphs to be united */ 15.1623 + int multi; /* should we reproduce multiple arcs? */ 15.1624 + int directed; /* should the graph be directed? */ 15.1625 +{@+@<Vanilla local variables@>@; 15.1626 + register int n; 15.1627 + register Vertex *u; 15.1628 + register unsigned long delta,ddelta; /* differences in memory addresses */ 15.1629 + if (g==NULL || gg==NULL) panic(missing_operand); 15.1630 + /* where are |g| and |gg|? */ 15.1631 + @<Set up a graph with the vertices of |g|@>; 15.1632 + sprintf(buffer,",%d,%d)",multi?1:0,directed?1:0); 15.1633 + make_double_compound_id(new_graph,"gunion(",g,",",gg,buffer); 15.1634 + ddelta=((unsigned long)(new_graph->vertices))-((unsigned long)(gg->vertices)); 15.1635 + @<Insert arcs or edges present in either |g| or |gg|@>; 15.1636 + if (gb_alloc_trouble) { 15.1637 + gb_recycle(new_graph); 15.1638 + panic(alloc_fault); /* uh oh, we ran out of memory somewhere back there */ 15.1639 + } 15.1640 + return new_graph; 15.1641 +} 15.1642 + 15.1643 +@ @<Insert arcs or edges present in either |g| or |gg|@>= 15.1644 +for (v=g->vertices;v<g->vertices+n;v++) {@+register Arc *a; 15.1645 + register Vertex *vv=vert_offset(v,delta); 15.1646 + /* vertex in |new_graph| corresponding to |v| in |g| */ 15.1647 + register Vertex *vvv=vert_offset(vv,-ddelta); 15.1648 + /* vertex in |gg| corresponding to |v| in |g| */ 15.1649 + for (a=v->arcs;a;a=a->next) { 15.1650 + u=vert_offset(a->tip,delta); 15.1651 + @<Insert a union arc or edge from |vv| to |u|, if appropriate@>; 15.1652 + } 15.1653 + if (vvv<gg->vertices+gg->n) for (a=vvv->arcs;a;a=a->next) { 15.1654 + u=vert_offset(a->tip,ddelta); 15.1655 + if (u<new_graph->vertices+n) 15.1656 + @<Insert a union arc or edge from |vv| to |u|, if appropriate@>; 15.1657 + } 15.1658 +} 15.1659 +for (v=new_graph->vertices;v<new_graph->vertices+n;v++) 15.1660 + v->tmp=NULL,v->tlen=NULL; 15.1661 + 15.1662 +@ We use the |tmp| trick of |complement| to remember which arcs have 15.1663 +already been recorded from |u|, and we extend it so that we can maintain 15.1664 +minimum lengths. Namely, |uu->tmp| will equal |u| if and only 15.1665 +if we have already seen an arc from |u| to |uu|; and if so, |uu->tlen| 15.1666 +will be one such arc. In the undirected case, |uu->tlen| will point to the 15.1667 +first arc of an edge pair that touches~|u|. 15.1668 + 15.1669 +The only thing slightly nontrivial here is the way we keep undirected 15.1670 +edges grouped in pairs. We generate a new edge from |vv| to |u| only 15.1671 +if |vv<=u|, and if equality holds we advance~|a| so that we don't 15.1672 +see the self-loop in both directions. Similar logic will be repeated 15.1673 +in many of the programs below. 15.1674 + 15.1675 +@d tlen z.a /* utility field |z| regarded as a pointer to an arc */ 15.1676 + 15.1677 +@<Insert a union arc or edge from |vv| to |u|, if appropriate@>= 15.1678 +{@+register Arc *b; 15.1679 + if (directed) { 15.1680 + if (multi || u->tmp!=vv) gb_new_arc(vv,u,a->len); 15.1681 + else { 15.1682 + b=u->tlen; 15.1683 + if (a->len<b->len) b->len=a->len; 15.1684 + } 15.1685 + u->tmp=vv; /* remember that we've seen this */ 15.1686 + u->tlen=vv->arcs; 15.1687 + } else if (u>=vv) { 15.1688 + if (multi || u->tmp!=vv) gb_new_edge(vv,u,a->len); 15.1689 + else { 15.1690 + b=u->tlen; 15.1691 + if (a->len<b->len) b->len=(b+1)->len=a->len; 15.1692 + } 15.1693 + u->tmp=vv; 15.1694 + u->tlen=vv->arcs; 15.1695 + if (u==vv && a->next==a+1) a++; /* bypass second half of self-loop */ 15.1696 + } 15.1697 +} 15.1698 + 15.1699 +@ @<Basic subroutines@>= 15.1700 +Graph *intersection(g,gg,multi,directed) 15.1701 + Graph *g,*gg; /* graphs to be intersected */ 15.1702 + int multi; /* should we reproduce multiple arcs? */ 15.1703 + int directed; /* should the graph be directed? */ 15.1704 +{@+@<Vanilla local variables@>@; 15.1705 + register int n; 15.1706 + register Vertex *u; 15.1707 + register unsigned long delta,ddelta; /* differences in memory addresses */ 15.1708 + if (g==NULL || gg==NULL) panic(no_room+1); /* where are |g| and |gg|? */ 15.1709 + @<Set up a graph with the vertices of |g|@>; 15.1710 + sprintf(buffer,",%d,%d)",multi?1:0,directed?1:0); 15.1711 + make_double_compound_id(new_graph,"intersection(",g,",",gg,buffer); 15.1712 + ddelta=((unsigned long)(new_graph->vertices))-((unsigned long)(gg->vertices)); 15.1713 + @<Insert arcs or edges present in both |g| and |gg|@>; 15.1714 + if (gb_alloc_trouble) { 15.1715 + gb_recycle(new_graph); 15.1716 + panic(alloc_fault); /* whoops, we ran out of memory somewhere back there */ 15.1717 + } 15.1718 + return new_graph; 15.1719 +} 15.1720 + 15.1721 +@ Two more temporary utility fields are needed here. 15.1722 + 15.1723 +@d mult v.i /* utility field |v|, counts multiplicity of arcs */ 15.1724 +@d minlen w.i /* utility field |w|, records the smallest length */ 15.1725 + 15.1726 +@<Insert arcs or edges present in both |g| and |gg|@>= 15.1727 +for (v=g->vertices;v<g->vertices+n;v++) {@+register Arc *a; 15.1728 + register Vertex *vv=vert_offset(v,delta); 15.1729 + /* vertex in |new_graph| corresponding to |v| in |g| */ 15.1730 + register Vertex *vvv=vert_offset(vv,-ddelta); 15.1731 + /* vertex in |gg| corresponding to |v| in |g| */ 15.1732 + if (vvv>=gg->vertices+gg->n) continue; 15.1733 + @<Take note of all arcs from |v|@>; 15.1734 + for (a=vvv->arcs;a;a=a->next) { 15.1735 + u=vert_offset(a->tip,ddelta); 15.1736 + if (u>=new_graph->vertices+n) continue; 15.1737 + if (u->tmp==vv) {@+int l=u->minlen; 15.1738 + if (a->len>l) l=a->len; /* maximum */ 15.1739 + if (u->mult<0) @<Update minimum of multiple maxima@>@; 15.1740 + else @<Generate a new arc or edge for the intersection, 15.1741 + and reduce the multiplicity@>; 15.1742 + } 15.1743 + } 15.1744 +} 15.1745 +@<Clear out the temporary utility fields@>; 15.1746 + 15.1747 +@ @<Generate a new arc or edge for the intersection...@>= 15.1748 +{ 15.1749 + if (directed) gb_new_arc(vv,u,l); 15.1750 + else { 15.1751 + if (vv<=u) gb_new_edge(vv,u,l); 15.1752 + if (vv==u && a->next==a+1) a++; /* skip second half of self-loop */ 15.1753 + } 15.1754 + if (!multi) { 15.1755 + u->tlen=vv->arcs; 15.1756 + u->mult=-1; 15.1757 + } else if (u->mult==0) u->tmp=NULL; 15.1758 + else u->mult--; 15.1759 +} 15.1760 + 15.1761 +@ We get here if and only |multi=0| and |gg|~has more than one arc from |vv| 15.1762 +to~|u| and |g|~has at least one arc from |vv| to~|u|. 15.1763 + 15.1764 +@<Update minimum of multiple maxima@>= 15.1765 +{@+register Arc *b=u->tlen; /* previous arc or edge from |vv| to |u| */ 15.1766 + if (l<b->len) { 15.1767 + b->len=l; 15.1768 + if (!directed) (b+1)->len=l; 15.1769 + } 15.1770 +} 15.1771 + 15.1772 +@ @<Take note of all arcs from |v|@>= 15.1773 +for (a=v->arcs;a;a=a->next) { 15.1774 + u=vert_offset(a->tip,delta); 15.1775 + if (u->tmp==vv) { 15.1776 + u->mult++; 15.1777 + if (a->len<u->minlen) u->minlen=a->len; 15.1778 + } else u->tmp=vv, u->mult=0, u->minlen=a->len; 15.1779 + if (u==vv && !directed && a->next==a+1) a++; 15.1780 + /* skip second half of self-loop */ 15.1781 +} 15.1782 + 15.1783 +@ @<Clear out the temporary utility fields@>= 15.1784 +for (v=new_graph->vertices;v<new_graph->vertices+n;v++) { 15.1785 + v->tmp=NULL; 15.1786 + v->tlen=NULL; 15.1787 + v->mult=0; 15.1788 + v->minlen=0; 15.1789 +} 15.1790 + 15.1791 +@* Line graphs. The next operation in |gb_basic|'s repertoire constructs 15.1792 +the so-called line graph of a given graph~$g$. The subroutine that does 15.1793 +this is invoked by calling `|lines(g,directed)|'. 15.1794 + 15.1795 +If |directed=0|, the line graph has one vertex for each edge of~|g|; 15.1796 +two vertices are adjacent if and only if the corresponding edges 15.1797 +have a common vertex. 15.1798 + 15.1799 +If |directed!=0|, the line graph has one vertex for each arc of~|g|; 15.1800 +there is an arc from vertex |u| to vertex |v| if and only if the 15.1801 +arc corresponding to~|u| ends at the vertex that begins the arc 15.1802 +corresponding to~|v|. 15.1803 + 15.1804 +All arcs of the line graph will have length~1. 15.1805 + 15.1806 +Utility fields |u.v| and |v.v| of each vertex in the line graph will point to 15.1807 +the vertices of |g| that define the corresponding arc or edge, and |w.a| will 15.1808 +point to the arc from |u.v| to |v.v| in~|g|. In the undirected case we will 15.1809 +have |u.v<=v.v|. 15.1810 + 15.1811 +@<Basic subroutines@>= 15.1812 +Graph *lines(g,directed) 15.1813 + Graph *g; /* graph whose lines will become vertices */ 15.1814 + int directed; /* should the graph be directed? */ 15.1815 +{@+@<Vanilla local variables@>@; 15.1816 + register int m; /* the number of lines */ 15.1817 + register Vertex *u; 15.1818 + if (g==NULL) panic(no_room+1); /* where is |g|? */ 15.1819 + @<Set up a graph whose vertices are the lines of |g|@>; 15.1820 + if (directed) @<Insert arcs of a directed line graph@>@; 15.1821 + else @<Insert edges of an undirected line graph@>; 15.1822 + @<Restore |g| to its pristine original condition@>; 15.1823 + if (gb_alloc_trouble) { 15.1824 + gb_recycle(new_graph); 15.1825 + panic(alloc_fault); /* (sigh) we ran out of memory somewhere back there */ 15.1826 + } 15.1827 + return new_graph; 15.1828 +near_panic:@<Recover from potential disaster due to bad data@>; 15.1829 +} 15.1830 + 15.1831 +@ We want to add a data structure to |g| so that the line graph can be 15.1832 +built efficiently. But we also want to preserve |g| so that it 15.1833 +exhibits no traces of occupation when |lines| has finished its 15.1834 +work. To do this, we will move utility field~|v->z| temporarily into 15.1835 +a utility field~|u->z| of the line graph, where |u| is the first 15.1836 +vertex having |u->u.v==v|, whenever such a |u| exists. Then we'll 15.1837 +set |v->map=u|. We will then be able to find |u| when |v| 15.1838 +is given, and we'll be able to cover our tracks later. 15.1839 + 15.1840 +In the undirected case further structure is needed. We will temporarily 15.1841 +change the |tip| field in the second arc of each edge pair so that 15.1842 +it points to the line-graph vertex that points to the first arc of the pair. 15.1843 + 15.1844 +The |format| field of the graph does not indicate the fact that utility 15.1845 +fields |u.v|, |v.v|, and |w.a| of each vertex will be set, because those 15.1846 +utility fields are pointers from the new graph to the original graph. 15.1847 +The |save_graph| procedure does not deal with pointers between graphs. 15.1848 + 15.1849 +@d map z.v /* the |z| field treated as a vertex pointer */ 15.1850 + 15.1851 +@<Restore |g| to its pristine original condition@>= 15.1852 +for (u=new_graph->vertices,v=NULL;u<new_graph->vertices+m;u++) { 15.1853 + if (u->u.v!=v) { 15.1854 + v=u->u.v; /* original vertex of |g| */ 15.1855 + v->map=u->map; /* restore original value of |v->z| */ 15.1856 + u->map=NULL; 15.1857 + } 15.1858 + if (!directed) ((u->w.a)+1)->tip=v; 15.1859 +} 15.1860 + 15.1861 +@ Special care must be taken to avoid chaos when the user is trying to 15.1862 +construct the undirected line graph of a directed graph. Otherwise we 15.1863 +might trash the memory, or leave the original graph in a garbled state 15.1864 +with pointers leading into supposedly free space. 15.1865 + 15.1866 +@<Set up a graph whose vertices are the lines of |g|@>= 15.1867 +m=(directed? g->m: (g->m)/2); 15.1868 +new_graph=gb_new_graph(m); 15.1869 +if (new_graph==NULL) 15.1870 + panic(no_room); /* out of memory before we're even started */ 15.1871 +make_compound_id(new_graph,"lines(",g,directed? ",1)": ",0)"); 15.1872 +u=new_graph->vertices; 15.1873 +for (v=g->vertices+g->n-1;v>=g->vertices;v--) {@+register Arc *a; 15.1874 + register int mapped=0; /* has |v->map| been set? */ 15.1875 + for (a=v->arcs;a;a=a->next) {@+register Vertex *vv=a->tip; 15.1876 + if (!directed) { 15.1877 + if (vv<v) continue; 15.1878 + if (vv>=g->vertices+g->n) goto near_panic; 15.1879 + /* original graph not undirected */ 15.1880 + } 15.1881 + @<Make |u| a vertex representing the arc |a| from |v| to |vv|@>; 15.1882 + if (!mapped) { 15.1883 + u->map=v->map; /* |z.v=map| incorporates all bits of utility field |z|, 15.1884 + whatever its type */ 15.1885 + v->map=u; 15.1886 + mapped=1; 15.1887 + } 15.1888 + u++; 15.1889 + } 15.1890 +} 15.1891 +if (u!=new_graph->vertices+m) goto near_panic; 15.1892 + 15.1893 +@ @<Recover...@>= 15.1894 +m=u-new_graph->vertices; 15.1895 +@<Restore |g| to its pristine...@>; 15.1896 +gb_recycle(new_graph); 15.1897 +panic(invalid_operand); 15.1898 + /* |g| did not obey the conventions for an undirected graph */ 15.1899 + 15.1900 +@ The vertex names in the line graph are pairs of original vertex names, 15.1901 +separated by `\.{--}' when undirected, `\.{->}' when directed. If either 15.1902 +of the original names is horrendously long, the villainous Procrustes 15.1903 +chops it off arbitrarily so that it fills at most half of the name buffer. 15.1904 + 15.1905 +@<Make |u| a vertex representing the arc |a| from |v| to |vv|@>= 15.1906 +u->u.v=v; 15.1907 +u->v.v=vv; 15.1908 +u->w.a=a; 15.1909 +if (!directed) { 15.1910 + if (u>=new_graph->vertices+m || (a+1)->tip!=v) goto near_panic; 15.1911 + if (v==vv && a->next==a+1) a++; /* skip second half of self-loop */ 15.1912 + else (a+1)->tip=u; 15.1913 +} 15.1914 +sprintf(buffer,"%.*s-%c%.*s",(BUF_SIZE-3)/2,v->name,@| 15.1915 + directed? '>': '-',BUF_SIZE/2-1,vv->name); 15.1916 +u->name=gb_save_string(buffer); 15.1917 + 15.1918 +@ @<Insert arcs of a directed line graph@>= 15.1919 +for (u=new_graph->vertices;u<new_graph->vertices+m;u++) { 15.1920 + v=u->v.v; 15.1921 + if (v->arcs) { /* |v->map| has been set up */ 15.1922 + v=v->map; 15.1923 + do@+{gb_new_arc(u,v,1); 15.1924 + v++; 15.1925 + }@+while (v->u.v==u->v.v); 15.1926 + } 15.1927 +} 15.1928 + 15.1929 +@ An undirected line graph will contain no self-loops. It contains 15.1930 +multiple edges only if the original graph did; in that case, there 15.1931 +are two edges joining a line to each of its parallel mates, because 15.1932 +each mate hits both of its endpoints. 15.1933 + 15.1934 +The details of this section are worthy of careful study. We use the 15.1935 +fact that the first vertices of the lines occur in nonincreasing order. 15.1936 + 15.1937 +@<Insert edges of an undirected line graph@>= 15.1938 +for (u=new_graph->vertices;u<new_graph->vertices+m;u++) {@+register Vertex *vv; 15.1939 + register Arc *a;@+register int mapped=0; 15.1940 + v=u->u.v; /* we look first for prior lines that touch the first vertex */ 15.1941 + for (vv=v->map;vv<u;vv++) gb_new_edge(u,vv,1); 15.1942 + v=u->v.v; /* then we look for prior lines that touch the other one */ 15.1943 + for (a=v->arcs;a;a=a->next) { 15.1944 + vv=a->tip; 15.1945 + if (vv<u && vv>=new_graph->vertices) gb_new_edge(u,vv,1); 15.1946 + else if (vv>=v && vv<g->vertices+g->n) mapped=1; 15.1947 + } 15.1948 + if (mapped && v>u->u.v) 15.1949 + for (vv=v->map;vv->u.v==v;vv++) gb_new_edge(u,vv,1); 15.1950 +} 15.1951 + 15.1952 +@* Graph products. Three ways have traditionally been used to define the 15.1953 +product of two graphs. In all three cases the vertices of the product graph 15.1954 +are ordered pairs $(v,v')$, where $v$ and $v'$ are vertices of the original 15.1955 +graphs; the difference occurs in the definition of arcs. Suppose $g$ has 15.1956 +$m$ arcs and $n$ vertices, while $g'$ has $m'$ arcs and $n'$ vertices. The 15.1957 +{\it cartesian product\/} of $g$ and~$g'$ has $mn'+m'n$ arcs, namely from 15.1958 +$(u,u')$ to $(v,u')$ whenever there's an arc from $u$ to $v$ in~$g$, and from 15.1959 +$(u,u')$ to $(u,v')$ whenever there's an arc from $u'$ to $v'$ in~$g'$. 15.1960 +The {\it direct product\/} has $mm'$ arcs, namely from $(u,u')$ to 15.1961 +$(v,v')$ in the same circumstances. The {\it strong product\/} 15.1962 +has both the arcs of the cartesian product and the direct product. 15.1963 + 15.1964 +Notice that an undirected graph with $m$ edges has $2m$ arcs. Thus the 15.1965 +number of edges in the direct product of two undirected graphs is 15.1966 +twice the product of the number of edges in the individual graphs. 15.1967 +A self-loop in~$g$ will combine with an edge in~$g'$ to make 15.1968 +two parallel edges in the direct product. 15.1969 + 15.1970 +The subroutine call `|product(g,gg,type,directed)|' produces the product 15.1971 +graph of one of these three types, where |type=0| for cartesian product, 15.1972 +|type=1| for direct product, and |type=2| for strong product. 15.1973 +The length of an arc in the cartesian product is copied from the length 15.1974 +of the original arc that it replicates; the length of an arc in the direct 15.1975 +product is the minimum of the two arc lengths that induce it. If |directed=0|, 15.1976 +the product graph will be an undirected graph, with its edges consisting 15.1977 +of consecutive arc pairs according to the standard GraphBase conventions, 15.1978 +and the input graphs should adhere to the same conventions. 15.1979 + 15.1980 +@(gb_basic.h@>= 15.1981 +#define cartesian 0 15.1982 +#define direct 1 15.1983 +#define strong 2 15.1984 + 15.1985 +@ @<Basic subroutines@>= 15.1986 +Graph *product(g,gg,type,directed) 15.1987 + Graph *g,*gg; /* graphs to be multiplied */ 15.1988 + int type; /* |cartesian|, |direct|, or |strong| */ 15.1989 + int directed; /* should the graph be directed? */ 15.1990 +{@+@<Vanilla local variables@>@; 15.1991 + register Vertex *u,*vv; 15.1992 + register long n; /* the number of vertices in the product graph */ 15.1993 + if (g==NULL || gg==NULL) panic(no_room+1); /* where are |g| and |gg|? */ 15.1994 + @<Set up a graph with ordered pairs of vertices@>; 15.1995 + if ((type&1)==0) @<Insert arcs or edges for cartesian product@>; 15.1996 + if (type) @<Insert arcs or edges for direct product@>; 15.1997 + if (gb_alloc_trouble) { 15.1998 + gb_recycle(new_graph); 15.1999 + panic(alloc_fault); 15.2000 + /* @@?`$*$\#!\&, we ran out of memory somewhere back there */ 15.2001 + } 15.2002 + return new_graph; 15.2003 +} 15.2004 + 15.2005 +@ We must be constantly on guard against running out of memory, especially 15.2006 +when multiplying information. 15.2007 + 15.2008 +The vertex names in the product are pairs of original vertex names, separated 15.2009 +by a comma. 15.2010 + 15.2011 +@<Set up a graph with ordered pairs of vertices@>= 15.2012 +{@+float test_product=((float)(g->n))*((float)(gg->n)); 15.2013 + if (test_product>MAX_NNN) panic(very_bad_specs); /* way too many vertices */ 15.2014 +} 15.2015 +n=(g->n)*(gg->n); 15.2016 +new_graph=gb_new_graph(n); 15.2017 +if (new_graph==NULL) 15.2018 + panic(no_room); /* out of memory before we're even started */ 15.2019 +for (u=new_graph->vertices,v=g->vertices,vv=gg->vertices;@| 15.2020 + u<new_graph->vertices+n;u++) { 15.2021 + sprintf(buffer,"%.*s,%.*s",BUF_SIZE/2-1,v->name,(BUF_SIZE-1)/2,vv->name); 15.2022 + u->name=gb_save_string(buffer); 15.2023 + if (++vv==gg->vertices+gg->n) vv=gg->vertices,v++; /* ``carry'' */ 15.2024 +} 15.2025 +sprintf(buffer,",%d,%d)",(type?2:0)-(type&1),directed?1:0); 15.2026 +make_double_compound_id(new_graph,"product(",g,",",gg,buffer); 15.2027 + 15.2028 +@ @<Insert arcs or edges for cartesian product@>= 15.2029 +{@+register Vertex *uu,*uuu; 15.2030 + register Arc *a; 15.2031 + register unsigned long delta; /* difference in memory addresses */ 15.2032 + delta=((unsigned long)(new_graph->vertices))-((unsigned long)(gg->vertices)); 15.2033 + for (u=gg->vertices;u<gg->vertices+gg->n;u++) 15.2034 + for (a=u->arcs;a;a=a->next) { 15.2035 + v=a->tip; 15.2036 + if (!directed) { 15.2037 + if (u>v) continue; 15.2038 + if (u==v && a->next==a+1) a++; /* skip second half of self-loop */ 15.2039 + } 15.2040 + for (uu=vert_offset(u,delta),vv=vert_offset(v,delta);@| 15.2041 + uu<new_graph->vertices+n;uu+=gg->n,vv+=gg->n) 15.2042 + if (directed) gb_new_arc(uu,vv,a->len); 15.2043 + else gb_new_edge(uu,vv,a->len); 15.2044 + } 15.2045 + @<Insert arcs or edges for first component of cartesian product@>; 15.2046 +} 15.2047 + 15.2048 +@ @<Insert arcs or edges for first component...@>= 15.2049 +for (u=g->vertices,uu=new_graph->vertices;uu<new_graph->vertices+n; 15.2050 + u++,uu+=gg->n) 15.2051 + for (a=u->arcs;a;a=a->next) { 15.2052 + v=a->tip; 15.2053 + if (!directed) { 15.2054 + if (u>v) continue; 15.2055 + if (u==v && a->next==a+1) a++; /* skip second half of self-loop */ 15.2056 + } 15.2057 + vv=new_graph->vertices+((gg->n)*(v-g->vertices)); 15.2058 + for (uuu=uu;uuu<uu+gg->n;uuu++,vv++) 15.2059 + if (directed) gb_new_arc(uuu,vv,a->len); 15.2060 + else gb_new_edge(uuu,vv,a->len); 15.2061 + } 15.2062 + 15.2063 +@ @<Insert arcs or edges for direct product@>= 15.2064 +{@+Vertex *uu;@+Arc *a; 15.2065 + unsigned long delta0= 15.2066 + ((unsigned long)(new_graph->vertices))-((unsigned long)(gg->vertices)); 15.2067 + unsigned long del=(gg->n)*sizeof(Vertex); 15.2068 + register unsigned long delta,ddelta; 15.2069 + for (uu=g->vertices,delta=delta0;uu<g->vertices+g->n;uu++,delta+=del) 15.2070 + for (a=uu->arcs;a;a=a->next) { 15.2071 + vv=a->tip; 15.2072 + if (!directed) { 15.2073 + if (uu>vv) continue; 15.2074 + if (uu==vv && a->next==a+1) a++; /* skip second half of self-loop */ 15.2075 + ddelta=delta0+del*(vv-g->vertices); 15.2076 + for (u=gg->vertices;u<gg->vertices+gg->n;u++) {@+register Arc *aa; 15.2077 + for (aa=u->arcs;aa;aa=aa->next) {@+long length=a->len; 15.2078 + if (length>aa->len) length=aa->len; 15.2079 + v=aa->tip; 15.2080 + if (directed) 15.2081 + gb_new_arc(vert_offset(u,delta),vert_offset(v,ddelta),length); 15.2082 + else gb_new_edge(vert_offset(u,delta),vert_offset(v,ddelta),length); 15.2083 + } 15.2084 + } 15.2085 + } 15.2086 + } 15.2087 +} 15.2088 + 15.2089 +@* Induced graphs. Another important way to transform a graph is to 15.2090 +remove, identify, or split some of its vertices. All of these 15.2091 +operations are performed by the |induced| routine, which users can 15.2092 +invoke by calling `|induced(g,description,self,multi,directed)|'. 15.2093 + 15.2094 +Each vertex |v| of |g| should first be assigned an ``induction code'' in 15.2095 +its field |v->ind|, which is actually utility field~|z|. The 15.2096 +induction code is 0~if |v| is to be eliminated; it is 1~if |v| is to be 15.2097 +retained; it is |k>1| if |v| is to be split into $k$ nonadjacent vertices 15.2098 +having the same neighbors as~|v| did; and it is |k<0| if |v| is to be 15.2099 +identified with all other vertices having the same value of~|k|. 15.2100 + 15.2101 +For example, suppose |g| is a circuit with vertices $\{0,1,\ldots,9\}$, 15.2102 +where |j| is adjacent to~|k| if and only if $k=(j\pm1)\bmod10$. 15.2103 +If we set 15.2104 +$$\vcenter{\halign{\hbox{\hfil#\hfil}\cr 15.2105 +|0->ind=0|,\quad |1->ind=5->ind=9->ind=-1|,\quad |2->ind=3->ind=-2|,\cr 15.2106 +|4->ind=6->ind=8->ind=1|,\quad and |7->ind=3|,\cr}}$$ 15.2107 +the induced graph will have vertices $\{-1,-2,4,6,7,7',7'',8\}$. 15.2108 +The vertices adjacent to 6, say, will be $-1$ (formerly~5), 7, $7'$, 15.2109 +and~$7''$. The vertices adjacent to $-1$ will be those formerly 15.2110 +adjacent to 1, 5, or~9, namely $-2$ (formerly~2), 4, 6, and~8. The 15.2111 +vertices adjacent to $-2$ will be those formerly adjacent to 2 or~3, 15.2112 +namely $-1$ (formerly~1), $-2$ (formerly~3), $-2$ (formerly~2), and~4. 15.2113 +Duplicate edges will be discarded if |multi==0|, and self-loops will 15.2114 +be discarded if |self==0|. 15.2115 + 15.2116 +The total number of vertices in the induced graph will be the sum 15.2117 +of the positive |ind| fields plus the absolute value of the most 15.2118 +negative |ind| field. This rule implies, for example, that if at least 15.2119 +one vertex has |ind=-5|, the induced graph will always have a vertex $-4$, 15.2120 +even though no |ind| field has been set to~$-4$. 15.2121 + 15.2122 +The |description| parameter is a string that will appear as part of 15.2123 +the name of the induced graph; if |description=0|, this string will 15.2124 +be empty. In the latter case, users are encouraged to assign a suitable 15.2125 +name to the |id| field of the induced graph, characterizing the method 15.2126 +by which the |ind| codes were set. 15.2127 + 15.2128 +If the |directed| parameter is zero, the input graph will be assumed to 15.2129 +be undirected, and the output graph will be undirected. 15.2130 + 15.2131 +When |multi=0|, the length of an arc that represents multiple arcs 15.2132 +will be the minimum of the multiple arc lengths. 15.2133 + 15.2134 +@d ind z.i 15.2135 + 15.2136 +@(gb_basic.h@>= 15.2137 +#define ind @[z.i /* utility field |z| when used to induce a graph */@] 15.2138 + 15.2139 +@ Here's a simple example: To get a complete bipartite graph with 15.2140 +parts of sizes |n1| and |n2|, we can start with a trivial two-point 15.2141 +graph and split its vertices into |n1| and |n2| parts. 15.2142 + 15.2143 +@<Applications...@>= 15.2144 +Graph *complete_bipartite(n1,n2,directed) 15.2145 + unsigned n1; /* size of first part */ 15.2146 + unsigned n2; /* size of second part */ 15.2147 + int directed; /* should all arcs go from first part to second? */ 15.2148 +{@+Graph *new_graph=board(2,0,0,0,1,0,directed); 15.2149 + if (new_graph) { 15.2150 + new_graph->vertices->ind=n1; 15.2151 + (new_graph->vertices+1)->ind=n2; 15.2152 + new_graph=induced(new_graph,0,0,0,directed); 15.2153 + if (new_graph) { 15.2154 + sprintf(new_graph->id,"complete_bipartite(%u,%u,%d)",@| 15.2155 + n1,n2,directed?1:0); 15.2156 + mark_bipartite(new_graph,n1); 15.2157 + } 15.2158 + } 15.2159 + return new_graph; 15.2160 +} 15.2161 + 15.2162 +@ The |induced| routine also provides a special feature not mentioned 15.2163 +above: If the |ind| field of any vertex |v| is |IND_GRAPH| or greater 15.2164 +(where |IND_GRAPH| is a large constant, much larger than the number 15.2165 +of vertices that would fit in computer memory), then utility field |v->subst| 15.2166 +should point to a graph. A copy of the vertices of 15.2167 +that graph will then be substituted for |v| in the induced graph. 15.2168 + 15.2169 +This feature extends the ordinary case when |v->ind>0|, which essentially 15.2170 +substitutes an empty graph for~|v|. 15.2171 + 15.2172 +If substitution is being used to replace all of $g$'s vertices 15.2173 +by disjoint copies of some other graph~$g'$, 15.2174 +the induced graph will be somewhat similar to 15.2175 +a product graph. But it will not be the same as any of the three 15.2176 +types of output produced by |product|, because the relation between 15.2177 +$g$ and $g'$ is not symmetrical. Assuming that no self-loops are 15.2178 +present, and that graphs $(g,g')$ have respectively $(m,m')$ arcs and 15.2179 +$(n,n')$ vertices, the resulting of substituting $g'$ for all 15.2180 +vertices of~$g$ has $m'n+mn'^2$ arcs. 15.2181 + 15.2182 + 15.2183 +@d IND_GRAPH 1000000000 /* when |ind| is a billion or more, */ 15.2184 +@d subst y.g /* we'll look at the |subst| field */ 15.2185 + 15.2186 +@(gb_basic.h@>= 15.2187 +#define IND_GRAPH 1000000000 15.2188 +#define subst @[y.g@] 15.2189 + 15.2190 +@ For example, we can use the |IND_GRAPH| feature to create a 15.2191 +``wheel'' of $n$ vertices arranged cyclically, all connected to one or 15.2192 +more center points. In the directed case, the arcs will run from the 15.2193 +center(s) to a cycle; in the undirected case, the edges will join the 15.2194 +center(s) to a circuit. 15.2195 + 15.2196 +@<Applications...@>= 15.2197 +Graph *wheel(n,n1,directed) 15.2198 + unsigned n; /* size of the rim */ 15.2199 + unsigned n1; /* number of center points */ 15.2200 + int directed; /* should all arcs go from center to rim and around? */ 15.2201 +{@+Graph *new_graph=board(2,0,0,0,1,0,directed); /* trivial 2-vertex graph */ 15.2202 + if (new_graph) { 15.2203 + new_graph->vertices->ind=n1; 15.2204 + (new_graph->vertices+1)->ind=IND_GRAPH; 15.2205 + (new_graph->vertices+1)->subst=board(n,0,0,0,1,1,directed); 15.2206 + /* cycle or circuit */ 15.2207 + new_graph=induced(new_graph,0,0,0,directed); 15.2208 + if (new_graph) { 15.2209 + sprintf(new_graph->id,"wheel(%u,%u,%d)",@| 15.2210 + n,n1,directed?1:0); 15.2211 + } 15.2212 + } 15.2213 + return new_graph; 15.2214 +} 15.2215 + 15.2216 +@ @(gb_basic.h@>= 15.2217 +extern Graph *complete_bipartite(); 15.2218 +extern Graph *wheel(); /* standard applications of |induced| */ 15.2219 + 15.2220 +@ @<Basic subroutines@>= 15.2221 +Graph *induced(g,description,self,multi,directed) 15.2222 + Graph *g; /* graph marked for induction in its |ind| fields */ 15.2223 + char *description; /* string to be mentioned in |new_graph->id| */ 15.2224 + int self; /* should self-loops be permitted? */ 15.2225 + int multi; /* should multiple arcs be permitted? */ 15.2226 + int directed; /* should the graph be directed? */ 15.2227 +{@+@<Vanilla local variables@>@; 15.2228 + register Vertex *u; 15.2229 + register long n=0; /* total number of vertices in induced graph */ 15.2230 + register long nn=0; /* number of negative vertices in induced graph */ 15.2231 + if (g==NULL) panic(missing_operand); /* where is |g|? */ 15.2232 + @<Set up a graph with the induced vertices@>; 15.2233 + @<Insert arcs or edges for induced vertices@>; 15.2234 + @<Restore |g| to its original state@>; 15.2235 + if (gb_alloc_trouble) { 15.2236 + gb_recycle(new_graph); 15.2237 + panic(alloc_fault); /* aargh, we ran out of memory somewhere back there */ 15.2238 + } 15.2239 + return new_graph; 15.2240 +} 15.2241 + 15.2242 +@ @<Set up a graph with the induced vertices@>= 15.2243 +@<Determine |n| and |nn|@>; 15.2244 +new_graph=gb_new_graph(n); 15.2245 +if (new_graph==NULL) 15.2246 + panic(no_room); /* out of memory before we're even started */ 15.2247 +@<Assign names to the new vertices, and create a map from |g| to |new_graph|@>; 15.2248 +sprintf(buffer,",%s,%d,%d,%d)",@|description?description:null_string,@| 15.2249 + self?1:0,multi?1:0,directed?1:0); 15.2250 +make_compound_id(new_graph,"induced(",g,buffer); 15.2251 + 15.2252 +@ @<Determine |n| and |nn|@>= 15.2253 +for (v=g->vertices;v<g->vertices+g->n;v++) 15.2254 + if (v->ind>0) { 15.2255 + if (n>IND_GRAPH) panic(very_bad_specs); /* way too big */ 15.2256 + if (v->ind>=IND_GRAPH) { 15.2257 + if (v->subst==NULL) panic(missing_operand+1); 15.2258 + /* substitute graph is missing */ 15.2259 + n+=v->subst->n; 15.2260 + } else n+=v->ind; 15.2261 + } else if (v->ind<-nn) nn=-(v->ind); 15.2262 +if (n>IND_GRAPH || nn>IND_GRAPH) panic(very_bad_specs+1); /* gigantic */ 15.2263 +n+=nn; 15.2264 + 15.2265 +@ The negative vertices get the negative number as their name. Split vertices 15.2266 +get names with an optional prime appended, if the |ind| field is 2; 15.2267 +otherwise split vertex names are obtained by appending a colon and an index 15.2268 +number between |0| and~|ind-1|. The name of a vertex within a 15.2269 +graph |v->subst| is composed of the name of |v| followed by a 15.2270 +colon and the name within that graph. 15.2271 + 15.2272 +We store the original |ind| field in the |mult| field of the first 15.2273 +corresponding vertex in the new graph, and change |ind| to point to 15.2274 +that vertex. That convention will make it easy 15.2275 +to determine the location of each vertex's clone or clones. 15.2276 +Of course, if the original |ind| field is zero, we leave it zero (|NULL|), 15.2277 +because it has no corresponding vertex in the new graph. 15.2278 + 15.2279 +@<Assign names to the new vertices, and create a map from |g| to |new_graph|@>= 15.2280 +for (k=1,u=new_graph->vertices;k<=nn;k++,u++) { 15.2281 + u->mult=-k; 15.2282 + sprintf(buffer,"%d",-k); 15.2283 + u->name=gb_save_string(buffer); 15.2284 +} 15.2285 +for (v=g->vertices;v<g->vertices+g->n;v++) 15.2286 + if ((k=v->ind)<0) v->map=(new_graph->vertices)-(k+1); 15.2287 + else if (k>0) { 15.2288 + u->mult=k; 15.2289 + v->map=u; 15.2290 + if (k<=2) { 15.2291 + u->name=gb_save_string(v->name); 15.2292 + u++; 15.2293 + if (k==2) { 15.2294 + sprintf(buffer,"%s'",v->name); 15.2295 + u->name=gb_save_string(buffer); 15.2296 + u++; 15.2297 + } 15.2298 + } else if (k>=IND_GRAPH) @<Make names and arcs for a substituted graph@>@; 15.2299 + else for (j=0;j<k;j++,u++) { 15.2300 + sprintf(buffer,"%.*s:%d",BUF_SIZE-12,v->name,j); 15.2301 + u->name=gb_save_string(buffer); 15.2302 + } 15.2303 + } 15.2304 + 15.2305 +@ @<Restore |g| to its original state@>= 15.2306 +for (v=g->vertices;v<g->vertices+g->n;v++) 15.2307 + if (v->map) v->ind=v->map->mult; 15.2308 +for (v=new_graph->vertices;v<new_graph->vertices+n;v++) 15.2309 + v->u.i=v->v.i=v->z.i=0; /* clear |tmp|, |mult|, |tlen| */ 15.2310 + 15.2311 +@ The heart of the procedure to construct an induced graph is, of course, 15.2312 +the part where we map the arcs of |g| into arcs of |new_graph|. 15.2313 + 15.2314 +Notice that if |v| has a self-loop 15.2315 +in the original graph and if |v| is being split into several vertices, 15.2316 +it will produce arcs between different clones of itself, but it will not 15.2317 +produce self-loops unless |self!=0|. In an undirected graph, a loop 15.2318 +from a vertex to itself will not produce multiple edges among its clones, 15.2319 +even if |multi!=0|. 15.2320 + 15.2321 +More precisely, if |v| has |k| clones |u| through |u+k-1|, an original 15.2322 +directed arc from |v| to~|v| will generate all $k^2$ possible arcs between 15.2323 +them, except that the |k| self-loops will be eliminated when 15.2324 +|self==0|. An original undirected edge from |v| to~|v| will generate 15.2325 +$k\choose2$ edges between distinct clones, together with |k| 15.2326 +undirected self-loops if |self!=0|. 15.2327 + 15.2328 +@<Insert arcs or edges for induced vertices@>= 15.2329 +for (v=g->vertices;v<g->vertices+g->n;v++) { 15.2330 + u=v->map; 15.2331 + if (u) {@+register Arc *a;@+register Vertex *uu,*vv; 15.2332 + k=u->mult; 15.2333 + if (k<0) k=1; /* |k| is the number of clones of |v| */ 15.2334 + else if (k>=IND_GRAPH) k=v->subst->n; 15.2335 + for (;k;k--,u++) { 15.2336 + if (!multi) 15.2337 + @<Take note of existing edges that touch |u|@>; 15.2338 + for (a=v->arcs;a;a=a->next) { 15.2339 + vv=a->tip; 15.2340 + uu=vv->map; 15.2341 + if (uu==NULL) continue; 15.2342 + j=uu->mult; 15.2343 + if (j<0) j=1; /* |j| is the number of clones of |vv| */ 15.2344 + else if (j>=IND_GRAPH) j=vv->subst->n; 15.2345 + if (!directed) { 15.2346 + if (vv<v) continue; 15.2347 + if (vv==v) { 15.2348 + if (a->next==a+1) a++; /* skip second half of self-loop */ 15.2349 + j=k,uu=u; /* also skip duplicate edges generated by self-loop */ 15.2350 + } 15.2351 + } 15.2352 + @<Insert arcs or edges from vertex |u| to vertices 15.2353 + |uu| through |uu+j-1|@>; 15.2354 + } 15.2355 + } 15.2356 + } 15.2357 +} 15.2358 + 15.2359 +@ Again we use the |tmp| and |tlen| trick of |gunion| to handle 15.2360 +multiple arcs. (This trick explains why the code in the previous 15.2361 +section tries to generate as many arcs as possible from a single 15.2362 +vertex |u|, before changing~|u|.) 15.2363 + 15.2364 +@<Take note of existing edges that touch |u|@>= 15.2365 +for (a=u->arcs;a;a=a->next) { 15.2366 + a->tip->tmp=u; 15.2367 + if (directed || a->tip>u || a->next==a+1) a->tip->tlen=a; 15.2368 + else a->tip->tlen=a+1; 15.2369 +} 15.2370 + 15.2371 +@ @<Insert arcs or edges from vertex |u| to vertices |uu|...@>= 15.2372 +for (;j;j--,uu++) { 15.2373 + if (u==uu && !self) continue; 15.2374 + if (uu->tmp==u && !multi) 15.2375 + @<Update the minimum arc length from |u| to |uu|, then |continue|@>; 15.2376 + if (directed) gb_new_arc(u,uu,a->len); 15.2377 + else gb_new_edge(u,uu,a->len); 15.2378 + uu->tmp=u; 15.2379 + uu->tlen=((directed || u<=uu)? u->arcs: uu->arcs); 15.2380 +} 15.2381 + 15.2382 +@ @<Update the minimum arc length from |u| to |uu|, then |continue|@>= 15.2383 +{@+register Arc *b=uu->tlen; /* existing arc or edge from |u| to |uu| */ 15.2384 + if (a->len<b->len) { 15.2385 + b->len=a->len; /* remember the minimum length */ 15.2386 + if (!directed) (b+1)->len=a->len; 15.2387 + } 15.2388 + continue; 15.2389 +} 15.2390 + 15.2391 +@ We have now accumulated enough experience to finish off the one 15.2392 +remaining piece of program with ease. 15.2393 + 15.2394 +@<Make names and arcs for a sub...@>= 15.2395 +{@+register Graph *gg=v->subst; 15.2396 + register Vertex *vv=gg->vertices; 15.2397 + register Arc *a; 15.2398 + unsigned long delta=((unsigned long)u)-((unsigned long)vv); 15.2399 + for (j=0;j<v->subst->n;j++,u++,vv++) { 15.2400 + sprintf(buffer,"%.*s:%.*s",BUF_SIZE/2-1,v->name,(BUF_SIZE-1)/2,vv->name); 15.2401 + u->name=gb_save_string(buffer); 15.2402 + for (a=vv->arcs;a;a=a->next) {@+register Vertex *vvv=a->tip; 15.2403 + Vertex *uu=vert_offset(vvv,delta); 15.2404 + if (vvv==vv && !self) continue; 15.2405 + if (uu->tmp==u && !multi) @<Update the minimum arc length...@>; 15.2406 + if (!directed) { 15.2407 + if (vvv<vv) continue; 15.2408 + if (vvv==vv && a->next==a+1) a++; /* skip second half of self-loop */ 15.2409 + gb_new_edge(u,uu,a->len); 15.2410 + } else gb_new_arc(u,uu,a->len); 15.2411 + uu->tmp=u; 15.2412 + uu->tlen=((directed || u<=uu)? u->arcs: uu->arcs); 15.2413 + } 15.2414 + } 15.2415 +} 15.2416 + 15.2417 +@* Index. As usual, we close with an index that 15.2418 +shows where the identifiers of \\{gb\_basic} are defined and used.
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/gb_books.w Mon Oct 03 23:29:42 2011 +0200 16.3 @@ -0,0 +1,542 @@ 16.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 16.5 +\def\title{GB\_\thinspace BOOKS} 16.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 16.7 +\def\<#1>{\hbox{$\langle$\rm#1$\rangle$}} 16.8 + 16.9 +\prerequisites{GB\_\thinspace GRAPH}{GB\_\thinspace IO} 16.10 +@* Introduction. This GraphBase module contains the |book| 16.11 +subroutine, which creates a family of undirected graphs that are based on 16.12 +classic works of literature. It also contains the |bi_book| 16.13 +subroutine, which creates a related family of bipartite graphs. 16.14 +An example of the use of |book| can be found in the demonstration 16.15 +program |book_components|. 16.16 + 16.17 +@(gb_books.h@>= 16.18 +extern Graph *book(); 16.19 +extern Graph *bi_book(); 16.20 + 16.21 +@ The subroutine call `|book(@t\<title>@>,n,x,first_chapter,last_chapter, 16.22 +in_weight,out_weight,seed)|' 16.23 +constructs a graph based on the information in \<title>\.{.dat}, 16.24 +where \<title> is either \.{"anna"} (for {\sl Anna Karenina\/}), 16.25 +\.{"david"} (for {\sl David Copperfield\/}), 16.26 +\.{"jean"} (for {\sl Les Mis\'erables\/}), 16.27 +\.{"huck"} (for {\sl Huckleberry Finn\/}), or 16.28 +\.{"homer"} (for {\sl The Iliad\/}). 16.29 +Each vertex of the graph corresponds to one of the characters in the 16.30 +selected book. Edges between vertices correspond to encounters between 16.31 +those characters. The length of each edge is~1. 16.32 + 16.33 +Subsets of the book can be selected by specifying that the edge data should be 16.34 +restricted to chapters between |first_chapter| and |last_chapter|, 16.35 +inclusive. If |first_chapter=0|, the result is the same as if 16.36 +|first_chapter=1|. If |last_chapter=0|, or if |last_chapter| exceeds 16.37 +the total number of chapters in the book, the result is the same as 16.38 +if |last_chapter| were the number of the book's final chapter. 16.39 + 16.40 +The constructed graph will have $\min(n,m)-x$ vertices, where |m| is the 16.41 +total number of characters in the selected book. 16.42 +However, if |n| is zero, |n| is automatically made equal to the maximum 16.43 +possible value,~|m|. If |n| is less than~|m|, the |n-x| characters will be 16.44 +selected by assigning a weight to each character and choosing the |n| with 16.45 +largest weight, then excluding the largest~|x| of these, 16.46 +using random numbers to break ties in case of equal weights. 16.47 +Weights are computed by the formula 16.48 +$$ |in_weight|\cdot\\{chapters\_in}+|out_weight|\cdot\\{chapters\_out}, $$ 16.49 +where \\{chapters\_in} is the number of chapters between |first_chapter| 16.50 +and |last_chapter| in which a particular character appears, and 16.51 +\\{chapters\_out} is the number of other chapters in which that 16.52 +character appears. Both |in_weight| and |out_weight| must be at most 16.53 +1,000,000 in absolute value. 16.54 + 16.55 +Vertices of the graph will appear in order of decreasing weight. 16.56 +The |seed| parameter defines the pseudo-random numbers used wherever 16.57 +a ``random'' choice between equal-weight vertices needs to be made. 16.58 +As usual with GraphBase routines, different choices of |seed| 16.59 +will in general produce different selections, 16.60 +but in a system-independent manner; identical results will be obtained on 16.61 +all computers when identical parameters have been specified. 16.62 +Any |seed| value between 0 and $2^{31}-1$ is permissible. 16.63 + 16.64 +@ Examples: The call |book("anna",0,0,0,0,0,0,0)| will construct a 16.65 +graph on 138 vertices, representing all 138 characters of Tolstoy's 16.66 +{\sl Anna Karenina\/} that are recorded in \.{anna.dat}. Two vertices will 16.67 +be adjacent if the corresponding characters 16.68 +encounter each other anywhere in the book. The call 16.69 +|book("anna",50,0,0,0,1,1,0)| is similar, but it is restricted to 16.70 +the 50 characters that occur most frequently, i.e., in the most chapters. 16.71 +The call |book("anna",50,0,10,120,1,1,0)| has the same vertices, but it 16.72 +has edges only for encounters that take place between chapter~10 16.73 +and chapter~120, inclusive. The call |book("anna",50,0,10,120,1,0,0)| is 16.74 +similar, but its vertices are the 50 characters that occur most often in 16.75 +chapters 10 through~120, without regard to how often they occur in 16.76 +the rest of the book. The call |book("anna",50,0,10,120,0,0,0)| is 16.77 +also similar, but it chooses 50 characters completely at random 16.78 +(possibly from those that don't occur in the selected chapters at all). 16.79 + 16.80 +Parameter |x|, which causes the |x| vertices of highest weight to be 16.81 +excluded, is usually either 0 or~1. It is provided primarily so that 16.82 +users can set |x=1| with respect to {\sl David Copperfield\/} and {\sl 16.83 +Huckleberry Finn}; those novels are narrated by their principal 16.84 +character, so they have edges between the principal character and 16.85 +almost everybody else. (Characters cannot get into the action of a 16.86 +first-person account unless they encounter the narrator or unless the 16.87 +narrator is quoting some other person's story.) The corresponding 16.88 +graphs tend to have more interesting connectivity properties if we 16.89 +leave the narrator out by setting |x=1|. For example, there are 87 16.90 +characters in {\sl David Copperfield\/}; the call 16.91 +|book("david",0,1,0,0,1,1,0)| produces a graph with 86 vertices, one 16.92 +for every character except David Copperfield himself. 16.93 + 16.94 +@ The subroutine call |bi_book(@t\<title>@>,n,x,first_chapter,last_chapter, 16.95 +in_weight,out_weight,seed)| produces a bipartite graph in which the 16.96 +vertices of the first part are exactly the same as the vertices of the 16.97 +graph returned by |book|, while the vertices of the second part are 16.98 +the selected chapters. For example, 16.99 +$|bi_book|(|"anna"|,\allowbreak 50,0,10,120,1,1,0)$ 16.100 +creates a bipartite graph with $50+111$ vertices. There is an edge between 16.101 +each character and the chapters in which that character appears. 16.102 + 16.103 +@ Chapter numbering needs further explanation. {\sl Anna Karenina\/} 16.104 +has 239 chapters, which are numbered 1.1 through 8.19 in the 16.105 +work itself but renumbered 1 through 239 as far as the |book| routine 16.106 +is concerned. Thus, setting |first_chapter=10| and |last_chapter=120| 16.107 +turns out to be equivalent to selecting chapters 1.10 through 4.19 16.108 +(more precisely, chapter~10 of book~1 through chapter~19 of book~4). 16.109 +{\sl Les Mis\'erables\/} has an even more involved scheme; its 16.110 +356 chapters range from 1.1.1 (part~1, book~1, chapter~1) to 16.111 +5.9.6 (part~5, book~9, chapter~6). After |book| or |bi_book| has created 16.112 +a graph, the external integer variable |chapters| will contain the total 16.113 +number of chapters, and |chap_name| will be an array of strings 16.114 +containing the structured chapter numbers. For example, after 16.115 +|book("jean",@t\dots@>)|, we will have |chapters=356|, 16.116 +|chap_name[1]="1.1.1"|, \dots, |chap_name[356]="5.9.6"|; 16.117 +|chap_name[0]| will be~|""|. 16.118 + 16.119 +@d MAX_CHAPS 360 /* no book will have this many chapters */ 16.120 + 16.121 +@<External variables@>= 16.122 +int chapters; /* the total number of chapters in the selected book */ 16.123 +char *chap_name[MAX_CHAPS]={""}; /* string names of those chapters */ 16.124 + 16.125 +@ As usual, we put declarations of the external variables into the header file 16.126 +for user to {\bf include}. 16.127 + 16.128 +@(gb_books.h@>= 16.129 +extern int chapters; /* the total number of chapters in the selected book */ 16.130 +extern char *chap_name[]; /* string names of those chapters */ 16.131 + 16.132 +@ If the |book| or |bi_book| routine encounters a problem, it 16.133 +returns |NULL| (\.{NULL}), 16.134 +after putting a code number into the external variable 16.135 +|panic_code|. This code number identifies the type of failure. 16.136 +Otherwise |book| returns a pointer to the newly created graph, which 16.137 +will be represented with the data structures explained in |gb_graph|. 16.138 +(The external variable |@!panic_code| is itself defined in |gb_graph|.) 16.139 + 16.140 +@d panic(c) @+{@+panic_code=c;@+gb_alloc_trouble=0;@+return NULL;@+} 16.141 +@# 16.142 +@f Graph int /* |gb_graph| defines the |Graph| type and a few others */ 16.143 +@f Vertex int 16.144 +@f Arc int 16.145 +@f Area int 16.146 +@f node int /* the \&{node} type is defined below */ 16.147 + 16.148 +@ The \Cee\ file \.{gb\_books.c} has the overall shape shown here. 16.149 +It makes use of an internal subroutine 16.150 +called |bgraph|, which combines the work of |book| and |bi_book|. 16.151 +@p 16.152 +#include "gb_io.h" /* we will use the |gb_io| routines for input */ 16.153 +#include "gb_flip.h" /* we will use the |gb_flip| routines 16.154 + for random numbers */ 16.155 +#include "gb_graph.h" /* we will use the |gb_graph| data structures */ 16.156 +#include "gb_sort.h" /* and the |gb_linksort| routine */ 16.157 +@# 16.158 +@<Type declarations@>@; 16.159 +@<Private variables@>@; 16.160 +@<External variables@>@; 16.161 +@# 16.162 +static Graph *bgraph(bipartite, 16.163 + title,n,x,first_chapter,last_chapter,in_weight,out_weight,seed) 16.164 + int bipartite; /* should we make the graph bipartite? */ 16.165 + char *title; /* identification of the selected book */ 16.166 + unsigned n; /* number of vertices desired before exclusion */ 16.167 + unsigned x; /* number of vertices to exclude */ 16.168 + unsigned first_chapter, last_chapter; 16.169 + /* interval of chapters leading to edges */ 16.170 + long in_weight; /* weight coefficient pertaining to chapters 16.171 + in that interval */ 16.172 + long out_weight; /* weight coefficient pertaining to chapters 16.173 + not in that interval */ 16.174 + long seed; /* random number seed */ 16.175 +{@+@<Local variables@>@; 16.176 + gb_init_rand(seed); 16.177 + @<Check that the parameters are valid@>; 16.178 + @<Skim the data file, recording the characters and computing their weights@>; 16.179 + @<Choose the vertices and put them into an empty graph@>; 16.180 + @<Read the data file more carefully and fill the graph as instructed@>; 16.181 + if (gb_alloc_trouble) { 16.182 + gb_recycle(new_graph); 16.183 + panic(alloc_fault); /* (expletive deleted) 16.184 + we ran out of memory somewhere back there */ 16.185 + } 16.186 + return new_graph; 16.187 +} 16.188 +@# 16.189 +Graph *book(title,n,x,first_chapter,last_chapter,in_weight,out_weight,seed) 16.190 + char *title; 16.191 + unsigned n, x, first_chapter, last_chapter; 16.192 + long in_weight,out_weight,seed; 16.193 +{@+return bgraph(0,title,n,x,first_chapter,last_chapter, 16.194 + in_weight,out_weight,seed);@+} 16.195 +Graph *bi_book(title,n,x,first_chapter,last_chapter,in_weight,out_weight,seed) 16.196 + char *title; 16.197 + unsigned n, x, first_chapter, last_chapter; 16.198 + long in_weight,out_weight,seed; 16.199 +{@+return bgraph(1,title,n,x,first_chapter,last_chapter, 16.200 + in_weight,out_weight,seed);@+} 16.201 + 16.202 +@ @<Local var...@>= 16.203 +Graph *new_graph; /* the graph constructed by |book| or |bi_book| */ 16.204 +register int j,k; /* all-purpose indices */ 16.205 +register node *p; 16.206 +int characters; /* the total number of characters in the selected book */ 16.207 + 16.208 +@ @d MAX_CHARS 600 /* there won't be more characters than this */ 16.209 + 16.210 +@<Check that the parameters are valid@>= 16.211 +if (n==0) n=MAX_CHARS; 16.212 +if (first_chapter==0) first_chapter=1; 16.213 +if (last_chapter==0) last_chapter=MAX_CHAPS; 16.214 +if (in_weight>1000000 || in_weight<-1000000 || 16.215 + out_weight>1000000 || out_weight<-1000000) 16.216 + panic(bad_specs); /* the magnitude of at least one weight is too big */ 16.217 +sprintf(file_name,"%.6s.dat",title); 16.218 +if (gb_open(file_name)!=0) 16.219 + panic(early_data_fault); /* couldn't open the file; |io_errors| tells why */ 16.220 + 16.221 +@ @<Priv...@>= 16.222 +static char file_name[]="xxxxxx.dat"; 16.223 +static char null_string[1]; /* a null string constant */ 16.224 + 16.225 +@*Vertices. 16.226 +Each character in a book has been given a two-letter code name for 16.227 +internal use. The code names are explained at the beginning of each 16.228 +data file by a number of lines that look like this: 16.229 +$$\hbox{\tt XX \<name>,\<description>}$$ 16.230 +For example, here's one of the lines near the beginning of |"anna.dat"|: 16.231 +$$\hbox{\tt AL Alexey Alexandrovitch Karenin, minister of state}$$ 16.232 +The \<name> does not contain a comma; the \<description> might. 16.233 + 16.234 +A blank line follows the cast of characters. 16.235 + 16.236 +Internally, we will think of the two-letter code as a radix-36 integer. 16.237 +Thus, \.{AA} will be the number $10\times36+10$, and \.{ZZ} will be 16.238 +$35\times36+35$. The |gb_number| routine in |gb_io| is set up to 16.239 +input radix-36 integers just as it does hexadecimal ones. 16.240 +In {\sl The Iliad}, many of the minor characters have numeric digits 16.241 +in their code names, because the total number of characters is too 16.242 +large to permit mnemonic codes for everybody. 16.243 + 16.244 +@d MAX_CODE 1296 /* $36\times36$, the number of two-digit codes in radix 36 */ 16.245 + 16.246 +@ In order to choose the vertices, we want to represent each character 16.247 +as a node whose key corresponds to its weight; then the |gb_linksort| 16.248 +routine of |gb_sort| will provide the desired rank-ordering. We will 16.249 +find it convenient to use these nodes for all the data processing that 16.250 +|bgraph| has to do. 16.251 + 16.252 +@<Type dec...@>= 16.253 +typedef struct node_struct { /* records to be sorted by |gb_linksort| */ 16.254 + long key; /* the nonnegative sort key (weight plus $2^{30}$) */ 16.255 + struct node_struct *link; /* pointer to next record */ 16.256 + int code; /* code number of this character */ 16.257 + int in; /* number of occurrences in selected chapters */ 16.258 + int out; /* number of occurrences in unselected chapters */ 16.259 + int chap; /* seen most recently in this chapter */ 16.260 + Vertex *v; /* vertex corresponding to this character */ 16.261 +} node; 16.262 + 16.263 +@ Not only do nodes point to codes, we also want codes to point to nodes. 16.264 + 16.265 +@<Priv...@>= 16.266 +static node node_block[MAX_CHARS]; /* array of nodes for working storage */ 16.267 +static node *xnode[MAX_CODE]; /* the node, if any, having a given code */ 16.268 + 16.269 +@ We will read the data file twice, once quickly (to collect statistics) 16.270 +and once more thoroughly (to record detailed information). Here is the 16.271 +quick version. 16.272 + 16.273 +@<Skim the data file, recording the characters and computing their weights@>= 16.274 +@<Read the character codes at the beginning of the data file, and 16.275 + prepare a node for each one@>; 16.276 +@<Skim the chapter information, counting the number of chapters in 16.277 + which each character appears@>; 16.278 +if (gb_close()!=0) 16.279 + panic(late_data_fault); 16.280 + /* check sum or other failure in data file; see |io_errors| */ 16.281 + 16.282 +@ @<Read the character codes...@>= 16.283 +for (k=0;k<MAX_CODE;k++) xnode[k]=NULL; 16.284 +{@+register int c; /* current code entering the system */ 16.285 + p=node_block; /* current node entering the system */ 16.286 + while ((c=gb_number(36))!=0) { /* note that \.{00} is not a legal code */ 16.287 + if (c>=MAX_CODE || gb_char()!=' ') panic(syntax_error); 16.288 + /* unreadable line in data file */ 16.289 + if (p>=&node_block[MAX_CHARS]) 16.290 + panic(syntax_error+1); /* data has too many characters */ 16.291 + p->link=(p==node_block?NULL:p-1); 16.292 + p->code=c; 16.293 + xnode[c]=p; 16.294 + p->in=p->out=p->chap=0; 16.295 + p->v=NULL; 16.296 + p++; 16.297 + gb_newline(); 16.298 + } 16.299 + characters=p-node_block; 16.300 + gb_newline(); /* bypass the blank line that terminates the character data */ 16.301 +} 16.302 + 16.303 +@ Later we will read through this part of the file again, extracting 16.304 +additional information if it turns out to be relevant. The 16.305 +\<description> string is provided to users in a |desc| field, 16.306 +in case anybody cares to look at it. The |in| and |out| statistics 16.307 +are also made available in utility fields called |in_count| and |out_count|. 16.308 +The code value is placed in the |short_code| field. 16.309 + 16.310 +@d desc z.s /* utility field |z| points to the \<description> string */ 16.311 +@d in_count y.i /* utility field |y| counts appearances in selected chapters */ 16.312 +@d out_count x.i /* utility field |x| counts appearances in other chapters */ 16.313 +@d short_code u.i /* utility field |u| contains a radix-36 number */ 16.314 + 16.315 +@<Read the data about characters again, noting vertex names and the 16.316 + associated descriptions@>= 16.317 +{@+register int c; /* current code entering the system a second time */ 16.318 + while ((c=gb_number(36))!=0) {@+register Vertex *v=xnode[c]->v; 16.319 + if (v) { 16.320 + if (gb_char()!=' ') panic(impossible); /* can't happen */ 16.321 + gb_string(str_buf,','); /* scan the \<name> part */ 16.322 + v->name=gb_save_string(str_buf); 16.323 + if (gb_char()!=',') 16.324 + panic(syntax_error+2); /* missing comma after \<name> */ 16.325 + gb_string(str_buf,'\n'); /* scan the \<description> part */ 16.326 + v->desc=gb_save_string(str_buf); 16.327 + v->in_count=xnode[c]->in; 16.328 + v->out_count=xnode[c]->out; 16.329 + v->short_code=c; 16.330 + } 16.331 + gb_newline(); 16.332 + } 16.333 + gb_newline(); /* bypass the blank line that terminates the character data */ 16.334 +} 16.335 + 16.336 +@ @(gb_books.h@>= 16.337 +#define desc @t\quad@> z.s /* utility field definitions for the header file */ 16.338 +#define in_count @t\quad@> y.i 16.339 +#define out_count @t\quad@> x.i 16.340 +#define short_code @t\quad@> u.i 16.341 + 16.342 +@*Edges. 16.343 +The second part of the data file has a line for each chapter, containing 16.344 +``cliques of encouters.'' For example, the line 16.345 +$$\hbox{\tt3.22:AA,BB,CC,DD;CC,DD,EE;AA,FF}$$ 16.346 +means that, in chapter 22 of book 3, there were encounters between the pairs 16.347 +$$\def\\{{\rm,} } 16.348 +\hbox{\tt AA-BB\\AA-CC\\AA-DD\\BB-CC\\BB-DD\\CC-DD\\CC-EE\\DD-EE\\{\rm and }% 16.349 +AA-FF\rm.}$$ 16.350 +(The encounter \.{CC-DD} is specified twice, once in the clique 16.351 +\.{AA,BB,CC,DD} and once in \.{CC,DD,EE}; this does not imply anything about 16.352 +the actual number of encounters between \.{CC} and \.{DD} in the chapter.) 16.353 + 16.354 +A clique might involve one character only, when that character is featured 16.355 +in sort of a soliloquy. 16.356 + 16.357 +A chapter might contain no references to characters at all. In such a case 16.358 +the `\.:' following the chapter number is omitted. 16.359 + 16.360 +There may be more encounters than will fit on a single line. In such cases, 16.361 +continuation lines begin with `\.{\&:}'. This convention turns out to be 16.362 +needed only in \.{homer.dat}; chapters in {\sl The Iliad\/} are 16.363 +substantially more complex than the chapters in other GraphBase books. 16.364 + 16.365 +On our first pass over the data, we simply want to compute statistics about 16.366 +who appears in what chapters, so we ignore the distinction between 16.367 +commas and semicolons. 16.368 + 16.369 +@<Skim the chapter information, counting the number of chapters in 16.370 + which each character appears@>= 16.371 +for (k=1; k<MAX_CHAPS && !gb_eof(); k++) { 16.372 + gb_string(str_buf,':'); /* read past the chapter number */ 16.373 + if (str_buf[0]=='&') k--; /* continuation of previous chapter */ 16.374 + while (gb_char()!='\n') {@+register int c=gb_number(36); 16.375 + register node *p; 16.376 + if (c>=MAX_CODE) 16.377 + panic(syntax_error+3); /* missing punctuation between characters */ 16.378 + p=xnode[c]; 16.379 + if (p==NULL) panic(syntax_error+4); /* unknown character */ 16.380 + if (p->chap!=k) { 16.381 + p->chap=k; 16.382 + if (k>=first_chapter && k<=last_chapter) p->in++; 16.383 + else p->out++; 16.384 + } 16.385 + } 16.386 + gb_newline(); 16.387 +} 16.388 +if (k==MAX_CHAPS) panic(syntax_error+5); /* too many chapters */ 16.389 +chapters=k; 16.390 + 16.391 +@ Our second pass over the data is very similar to the first, if we 16.392 +are simply computing a bipartite graph. In that case we add an edge 16.393 +to the graph between each selected chapter and each selected character 16.394 +in that chapter. Local variable |chap_base| will point to a 16.395 +vertex such that |chap_base+k| is the vertex corresponding to chapter~|k|. 16.396 + 16.397 +The |in_count| of a chapter vertex is the degree of that vertex, i.e., the 16.398 +number of selected characters that appear in the corresponding chapter. 16.399 +The |out_count| is the number of characters that appear in the 16.400 +chapter but were omitted from the graph. Thus, the |in_count| and 16.401 +|out_count| for chapters are analogous to the |in_count| and |out_count| 16.402 +for characters. 16.403 + 16.404 +@<Read the chapter information a second time and create the 16.405 + appropriate bipartite edges@>= 16.406 +{ 16.407 + for (p=node_block;p<node_block+characters;p++) p->chap=0; 16.408 + for (k=1; !gb_eof(); k++) { 16.409 + gb_string(str_buf,':'); /* read the chapter number */ 16.410 + if (str_buf[0]=='&') k--; 16.411 + else chap_name[k]=gb_save_string(str_buf); 16.412 + if (k>=first_chapter && k<=last_chapter) {@+register Vertex *u=chap_base+k; 16.413 + if (str_buf[0]!='&') { 16.414 + u->name=chap_name[k]; 16.415 + u->desc=null_string; 16.416 + u->in_count=u->out_count=0; 16.417 + } 16.418 + while (gb_char()!='\n') {@+register int c=gb_number(36); 16.419 + p=xnode[c]; 16.420 + if (p->chap!=k) {@+register Vertex *v=p->v; 16.421 + p->chap=k; 16.422 + if (v) { 16.423 + gb_new_edge(v,u,1); 16.424 + u->in_count++; 16.425 + } else u->out_count++; 16.426 + } 16.427 + } 16.428 + } 16.429 + gb_newline(); 16.430 + } 16.431 +} 16.432 + 16.433 +@ @<Local variables@>= 16.434 +Vertex *chap_base; 16.435 + /* the bipartite vertex for chapter~|k| is |chap_base+k| */ 16.436 + 16.437 +@ The second pass has to work a little harder when we are recording 16.438 +encounters from cliques, but the logic isn't difficult really. 16.439 +We insert a reference to the first chapter that generated each edge, in 16.440 +utility field |chap_no| of the corresponding |Arc| record. 16.441 + 16.442 +@d chap_no a.i /* utility field |a| holds a chapter number */ 16.443 + 16.444 +@<Read the chapter information a second time and create the 16.445 + appropriate edges for encounters@>= 16.446 +for (k=1; !gb_eof(); k++) { 16.447 + gb_string(str_buf,':'); /* read the chapter number */ 16.448 + if (str_buf[0]=='&') k--; 16.449 + else chap_name[k]=gb_save_string(str_buf); 16.450 + if (k>=first_chapter && k<=last_chapter) {@+register int c=gb_char(); 16.451 + while (c!='\n') {@+register Vertex **pp=clique_table; 16.452 + register Vertex **qq,**rr; /* pointers within the clique table */ 16.453 + do@+{ 16.454 + c=gb_number(36); /* set |c| to code for next character of clique */ 16.455 + if (xnode[c]->v) /* is that character a selected vertex? */ 16.456 + *pp++=xnode[c]->v; /* if so, that vertex joins the current clique */ 16.457 + c=gb_char(); 16.458 + }@+while (c==','); /* repeat until end of the clique */ 16.459 + for (qq=clique_table;qq+1<pp;qq++) 16.460 + for (rr=qq+1;rr<pp;rr++) 16.461 + @<Make the vertices |*qq| and |*rr| adjacent, 16.462 + if they aren't already@>; 16.463 + } 16.464 + } 16.465 + gb_newline(); 16.466 +} 16.467 + 16.468 +@ @(gb_books.h@>= 16.469 +#define chap_no @[a.i@] /* utility field definition in the header file */ 16.470 + 16.471 +@ @<Priv...@>= 16.472 +static Vertex *clique_table[30]; 16.473 + /* pointers to vertices in the current clique */ 16.474 + 16.475 +@ @<Make the vertices |*qq| and |*rr| adjacent...@>= 16.476 +{@+register Vertex *u=*qq, *v=*rr; 16.477 + register Arc *a; 16.478 + for (a=u->arcs; a; a=a->next) 16.479 + if (a->tip==v) goto found; 16.480 + gb_new_edge(u,v,1); /* not found, so they weren't already adjacent */ 16.481 + if (u<v) a=u->arcs; 16.482 + else a=v->arcs; /* the new edge consists of arcs |a| and |a+1| */ 16.483 + a->chap_no=(a+1)->chap_no=k; 16.484 +found:; 16.485 +} 16.486 + 16.487 +@*Administration. 16.488 +The program is now complete except for a few missing organizational details. 16.489 +I will add these after lunch. 16.490 +@^out to lunch@> 16.491 + 16.492 +@ OK, I'm back; what needs to be done? The main thing is to create 16.493 +the graph itself. 16.494 + 16.495 +@<Choose the vertices and put them into an empty graph@>= 16.496 +if (n>characters) n=characters; 16.497 +if (x>n) x=n; 16.498 +if (last_chapter>chapters) last_chapter=chapters; 16.499 +if (first_chapter>last_chapter) first_chapter=last_chapter+1; 16.500 +new_graph=gb_new_graph(n-x+(bipartite?last_chapter-first_chapter+1:0)); 16.501 +if (new_graph==NULL) panic(no_room); /* out of memory already */ 16.502 +strcpy(new_graph->format,"IZZIISIZZZZZZZ"); 16.503 + /* declare the types of utility fields */ 16.504 +sprintf(new_graph->id,"%sbook(\"%s\",%u,%u,%u,%u,%ld,%ld,%ld)", 16.505 + bipartite?"bi_":"",title,n,x,first_chapter,last_chapter, 16.506 + in_weight,out_weight,seed); 16.507 +if (bipartite) { 16.508 + mark_bipartite(new_graph,n-x); 16.509 + chap_base=new_graph->vertices+(new_graph->n_1-first_chapter); 16.510 +} 16.511 +@<Compute the weights and assign vertices to chosen nodes@>; 16.512 + 16.513 +@ @<Compute the weights and assign vertices to chosen nodes@>= 16.514 +for (p=node_block; p<node_block+characters; p++) 16.515 + p->key=in_weight*(p->in)+out_weight*(p->out)+0x40000000; 16.516 +gb_linksort(node_block+characters-1); 16.517 +k=n; /* we will look at this many nodes */ 16.518 +{@+register Vertex *v=new_graph->vertices; /* the next vertex to define */ 16.519 + for (j=127; j>=0; j--) 16.520 + for (p=(node*)gb_sorted[j]; p; p=p->link) { 16.521 + if (x>0) x--; /* ignore this node */ 16.522 + else p->v=v++; /* choose this node */ 16.523 + if (--k==0) goto done; 16.524 + } 16.525 +} 16.526 +done:; 16.527 + 16.528 +@ Once the graph is there, we're ready to fill it in. 16.529 + 16.530 +@<Read the data file more carefully and fill the graph as instructed@>= 16.531 +if (gb_open(file_name)!=0) 16.532 + panic(impossible+1); 16.533 + /* this can't happen, because we were successful before */ 16.534 +@<Read the data about characters again, noting vertex names and the 16.535 + associated descriptions@>; 16.536 +if (bipartite) 16.537 + @<Read the chapter information a second time and create the 16.538 + appropriate bipartite edges@>@; 16.539 +else @<Read the chapter information a second time and create the 16.540 + appropriate edges for encounters@>; 16.541 +if (gb_close()!=0) 16.542 + panic(impossible+2); /* again, can hardly happen the second time around */ 16.543 + 16.544 +@* Index. As usual, we close with an index that 16.545 +shows where the identifiers of \\{gb\_books} are defined and used.
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/gb_dijk.w Mon Oct 03 23:29:42 2011 +0200 17.3 @@ -0,0 +1,445 @@ 17.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 17.5 +\def\title{GB\_\thinspace DIJK} 17.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 17.7 + 17.8 +\prerequisite{GB\_\thinspace GRAPH} 17.9 +@* Introduction. The GraphBase demonstration routine |dijkstra(uu,vv,gg,hh)| 17.10 +finds a shortest path from vertex~|uu| to vertex~|vv| in graph~|gg|, with the 17.11 +aid of an optional heuristic function~|hh|. This function implements a 17.12 +version of Dijkstra's algorithm, a general procedure for determining 17.13 +shortest paths in a directed graph that has nonnegative arc lengths 17.14 +[E.~W. Dijkstra, ``A note a two problems in connexion with graphs,'' 17.15 +{\sl Numerische Mathematik\/ \bf1} (1959), 269--271]. 17.16 + 17.17 +If |hh| is null, the length of 17.18 +every arc in |gg| must be nonnegative. If |hh| is non-null, |hh| should be 17.19 +a function defined on the vertices of the graph such that the 17.20 +length |d| of an arc from |u| to~|v| always satisfies the condition 17.21 +$$ d \ge |hh|(u)-|hh|(v)\,. $$ 17.22 +In such a case, we can effectively replace each arc length |d| by 17.23 +|d-hh(u)+hh(v)|, obtaining a graph with nonnegative arc lengths; 17.24 +the shortest paths between vertices in this modified graph 17.25 +are the same as they were in the original graph. 17.26 + 17.27 +The basic idea of Dijkstra's algorithm is to explore the vertices of 17.28 +the graph in order of their distance from the starting vertex~|uu|, 17.29 +proceeding until |vv| is encountered. If the distances have been 17.30 +modified by a heuristic function |hh| such that |hh(u)| happens to equal 17.31 +the true distance from |u| to~|vv|, for all~|u|, 17.32 +then all of the modified distances on 17.33 +shortest paths to |vv| will be zero; this means that the algorithm 17.34 +will explore all of the most useful arcs first, so it will not waste 17.35 +time wandering off in unfruitful directions. In practice we usually 17.36 +don't know the exact distances to |vv| in advance, but we can often 17.37 +compute an approximate value |hh(u)| that will help focus the search. 17.38 + 17.39 +If the external variable |verbose| is nonzero, |dijkstra| will record 17.40 +its activities, by printing the distances from |uu| to all vertices 17.41 +it visits on the standard output file. 17.42 + 17.43 +After |dijkstra| has found a shortest path, it returns the length of 17.44 +that path. If no path from |uu| to~|vv| exists (in particular, if 17.45 +|vv| is~|NULL|), it returns |-1|; in such a case, the shortest distances from 17.46 +|uu| to all vertices reachable from it will have been computed and 17.47 +they can be found in the graph. 17.48 +An auxiliary function, |print_dijkstra_result(vv)|, can be used 17.49 +to display the actual path found, if one exists. 17.50 + 17.51 +Examples of the use of |dijkstra| appear in the |ladders| demonstration module. 17.52 + 17.53 +@f Vertex int 17.54 +@f Arc int 17.55 +@f Graph int 17.56 + 17.57 +@ This \Cee\ module is meant to be loaded as part of another program. 17.58 +It has the following simple structure: 17.59 + 17.60 +@p 17.61 +#include "gb_graph.h" /* define the standard GraphBase data structures */ 17.62 +@<Priority queue procedures@>@; 17.63 +@<Global declarations@>@; 17.64 +@<The |dijkstra| procedure@>@; 17.65 +@<The |print_dijkstra_result| procedure@>@; 17.66 + 17.67 +@ Users of |gb_dijk| should include the header file \.{gb\_dijk.h}: 17.68 + 17.69 +@(gb_dijk.h@>= 17.70 +extern long dijkstra(); /* procedure to calculate shortest paths */ 17.71 +extern void print_dijkstra_result(); /* procedure to display the answer */ 17.72 + 17.73 +@* The main algorithm. 17.74 +As Dijkstra's algorithm proceeds, it ``knows'' shortest paths from |uu| 17.75 +to more and more vertices; we will call these vertices ``known.'' 17.76 +Initially only |uu| itself is known. The procedure terminates when |vv| 17.77 +becomes known, or when all vertices reachable from~|uu| are known. 17.78 + 17.79 +Dijkstra's algorithm looks at all vertices adjacent to known vertices. 17.80 +A vertex is said to have been ``seen'' if it is either known or 17.81 +adjacent to a vertex that's known. 17.82 + 17.83 +The algorithm proceeds by learning to know all vertices in a greater 17.84 +and greater radius from the starting point. Thus, if |v|~is a known 17.85 +vertex at distance~|d| from~|uu|, every vertex at distance |<d| from 17.86 +|uu| will also be known. (Throughout this discussion the word 17.87 +``distance'' actually means ``distance modified by the heuristic 17.88 +function''; we omit mentioning the heuristic because we can assume that 17.89 +the algorithm is operating on a graph with modified distances.) 17.90 + 17.91 +The algorithm maintains an auxiliary list of all vertices that have been 17.92 +seen but aren't yet known. For every such vertex~|v|, it remembers 17.93 +the shortest distance~|d| from |uu| to~|v| by a path that passes entirely 17.94 +through known vertices except for the very last arc. 17.95 + 17.96 +This auxiliary list is actually a priority queue, ordered by the |d| values. 17.97 +If |v|~is a vertex of the priority queue having the smallest |d|, we can 17.98 +remove |v| from the queue and consider it known, because there cannot be 17.99 +a path of length less than~|d| from |uu| to~|v|. (This is where the 17.100 +assumption of nonnegative arc length is crucial to the algorithm's validity.) 17.101 + 17.102 +@ To implement the ideas just sketched, we use several of the utility 17.103 +fields in vertex records. Each vertex~|v| has a |dist| field |v->dist|, 17.104 +representing its true distance from |uu| if |v| is known, otherwise 17.105 +representing the shortest distance from |uu| discovered so far. 17.106 + 17.107 +Each vertex |v| also has a |backlink| field |v->backlink|, which is non-|NULL| 17.108 +if and only if |v| has been seen. In that case |v->backlink| is a vertex one 17.109 +step ``closer'' to |uu|, on a path from |uu| to |v| that achieves the 17.110 +current distance |v->dist|. (Exception: 17.111 +Vertex~|uu| has a backlink pointing to itself.) The backlink 17.112 +fields thereby allow us to construct shortest paths from |uu| to all the 17.113 +known vertices, if desired. 17.114 + 17.115 +@d dist z.i /* distance from |uu|, modified by |hh|, 17.116 + appears in vertex utility field |z| */ 17.117 +@d backlink y.v /* pointer to previous vertex appears in utility field |y| */ 17.118 + 17.119 +@(gb_dijk.h@>= 17.120 +#define dist @[z.i@] 17.121 +#define backlink @[y.v@] 17.122 + 17.123 +@ The priority queue is implemented by four procedures: 17.124 + 17.125 +\def\]#1 {\smallskip\hangindent2\parindent \hangafter1 \indent #1 } 17.126 + 17.127 +\]|init_queue(d)| makes the queue empty and prepares for subsequent keys |>=d|. 17.128 + 17.129 +\]|enqueue(v,d)| puts vertex |v| in the queue and assigns it the key 17.130 +value |v->dist=d|. 17.131 + 17.132 +\]|requeue(v,d)| takes vertex |v| out of the queue and enters it again 17.133 +with the smaller key value |v->dist=d|. 17.134 + 17.135 +\]|delete_min()| removes a vertex with minimum key from the queue and 17.136 +returns a pointer to that vertex. If the queue is empty, |NULL| is returned. 17.137 + 17.138 +\smallskip\noindent 17.139 +These procedures are accessed via external pointers, 17.140 +so that the user of |gb_dijk| can supply alternate queueing methods if desired. 17.141 + 17.142 +@(gb_dijk.h@>= 17.143 +extern void (*init_queue)(); /* create an empty priority queue for |dijkstra| */ 17.144 +extern void (*enqueue)(); /* insert a new element in the priority queue */ 17.145 +extern void (*requeue)(); /* decrease the key of an element in the queue */ 17.146 +extern Vertex *(*delete_min)(); /* remove an element with smallest key */ 17.147 + 17.148 +@ The heuristic function may take awhile to compute, so we avoid recomputation 17.149 +by storing |hh(v)| in another utility field |v->hh_val| once we've 17.150 +evaluated it. 17.151 + 17.152 +@d hh_val x.i /* computed value of |hh(u)| */ 17.153 + 17.154 +@(gb_dijk.h@>= 17.155 +#define hh_val @[x.i@] 17.156 + 17.157 +@ If no heuristic function is supplied by the user, we replace it by a 17.158 +dummy function that simply returns 0 in all cases. 17.159 + 17.160 +@<Global...@>= 17.161 +long dummy(v) 17.162 + Vertex *v; 17.163 +{@+return 0;@+} 17.164 + 17.165 +@ Here now is |dijkstra|: 17.166 + 17.167 +@<The |dijkstra| procedure@>= 17.168 +long dijkstra(uu,vv,gg,hh) 17.169 + Vertex *uu; /* the starting point */ 17.170 + Vertex *vv; /* the ending point */ 17.171 + Graph *gg; /* the graph they belong to */ 17.172 + long (*hh)(); /* heuristic function */ 17.173 +{@+register Vertex *t; /* current vertex of interest */ 17.174 + if (hh==NULL) 17.175 + hh=dummy; /* change to default heuristic */ 17.176 + @<Make |uu| the only vertex seen; also make it known@>; 17.177 + t=uu; 17.178 + if (verbose) @<Print initial message@>; 17.179 + while (t!=vv) { 17.180 + @<Put all unseen vertices adjacent to |t| into the queue, 17.181 + and update the distances of other vertices adjacent to~|t|@>; 17.182 + t=(*delete_min)(); 17.183 + if (t==NULL) 17.184 + return -1; /* if the queue becomes, there's no way to get to |vv| */ 17.185 + if (verbose) @<Print the distance to |t|@>; 17.186 + } 17.187 + return vv->dist-vv->hh_val+uu->hh_val; /* true distance from |uu| to |vv| */ 17.188 +} 17.189 + 17.190 +@ As stated above, a vertex is considered seen only when its backlink 17.191 +isn't null, and known only when it is seen but not in the queue. 17.192 + 17.193 +@<Make |uu| the only...@>= 17.194 +for (t=gg->vertices+gg->n-1; t>=gg->vertices; t--) t->backlink=NULL; 17.195 +uu->backlink=uu; 17.196 +uu->dist=0; 17.197 +uu->hh_val=(*hh)(uu); 17.198 +(*init_queue)(0); /* make the priority queue empty */ 17.199 + 17.200 +@ Here we help the \Cee\ compiler in case it hasn't got a great optimizer. 17.201 + 17.202 +@<Put all unseen vertices adjacent to |t| into the queue...@>= 17.203 +{@+register Arc *a; /* an arc leading from |t| */ 17.204 + register long d = t->dist - t->hh_val; 17.205 + for (a=t->arcs; a; a=a->next) { 17.206 + register Vertex *v = a->tip; /* a vertex adjacent to |t| */ 17.207 + if (v->backlink) { /* |v| has already been seen */ 17.208 + register long dd = d + a->len + v->hh_val; 17.209 + if (dd< v->dist) { 17.210 + v->backlink = t; 17.211 + (*requeue)(v,dd); /* we found a better way to get there */ 17.212 + } 17.213 + } else { /* |v| hasn't been seen before */ 17.214 + v->hh_val = (*hh)(v); 17.215 + v->backlink = t; 17.216 + (*enqueue)(v, d + a->len + v->hh_val); 17.217 + } 17.218 + } 17.219 +} 17.220 + 17.221 +@ The |dist| fields don't contain true distances in the graph; they 17.222 +represent distances modified by the heuristic function. The true distance 17.223 +from |uu| to vertex |v| is |v->dist - v->hh_val + uu->hh_val|. 17.224 + 17.225 +When printing the results, we show true distances. Also, if a nontrivial 17.226 +heuristic is being used, we give the |hh| value in brackets; the user can then 17.227 +observe that vertices are becoming known in order of true distance 17.228 +plus |hh| value. 17.229 + 17.230 +@<Print initial message@>= 17.231 +{@+printf("Distances from %s", uu->name); 17.232 + if (hh!=dummy) printf(" [%ld]", uu->hh_val); 17.233 + printf(":\n"); 17.234 +} 17.235 + 17.236 +@ @<Print the distance to |t|@>= 17.237 +{@+printf(" %ld to %s", t->dist - t->hh_val + uu->hh_val, t->name); 17.238 + if (hh!=dummy) printf(" [%ld]", t->hh_val); 17.239 + printf(" via %s\n", t->backlink->name); 17.240 +} 17.241 + 17.242 +@ After |dijkstra| has found a shortest path, the backlinks from~|vv| 17.243 +specify the steps of that path. We want to print the path in the forward 17.244 +direction, so we reverse the links. 17.245 + 17.246 +We also unreverse them again, just in case the user didn't want the backlinks 17.247 +to be trashed. Indeed, this procedure can be used for any vertex |vv| whose 17.248 +backlink is nonnull, not only the |vv| that was a parameter to |dijkstra|. 17.249 + 17.250 +List reversal is conveniently regarded as a process of popping off one stack 17.251 +and pushing onto another. 17.252 + 17.253 +@<The |print_dijkstra_result| procedure@>= 17.254 +void print_dijkstra_result(vv) 17.255 + Vertex *vv; /* ending vertices */ 17.256 +{@+register Vertex *t, *p, *q; /* registers for reversing links */ 17.257 + t=NULL, p=vv; 17.258 + if (!p->backlink) { 17.259 + printf("Sorry, %s is unreachable.\n",p->name); 17.260 + return; 17.261 + } 17.262 + do { /* pop an item from |p| to |t| */ 17.263 + q=p->backlink; 17.264 + p->backlink=t; 17.265 + t=p; 17.266 + p=q; 17.267 + } while (t!=p); /* the loop stops with |t==p==uu| */ 17.268 + do { 17.269 + printf("%10ld %s\n", t->dist-t->hh_val+p->hh_val, t->name); 17.270 + t=t->backlink; 17.271 + } while (t); 17.272 + t=p; 17.273 + do { /* pop an item from |t| to |p| */ 17.274 + q=t->backlink; 17.275 + t->backlink=p; 17.276 + p=t; 17.277 + t=q; 17.278 + } while (p!=vv); 17.279 +} 17.280 + 17.281 +@* Priority queues. Here we provide a simple doubly linked list 17.282 +for queueing; this is a convenient default, good enough for applications 17.283 +that aren't too large. (See |miles_span| for implementations of 17.284 +other schemes that are more efficient when the queue gets large.) 17.285 + 17.286 +@<Glob...@>= 17.287 +void (*init_queue)() = init_dlist; /* create an empty dlist */ 17.288 +void (*enqueue)() = enlist; /* insert a new element in dlist */ 17.289 +void (*requeue)() = reenlist ; /* decrease the key of an element in dlist */ 17.290 +Vertex *(*delete_min)() = delete_first; /* remove element with smallest key */ 17.291 + 17.292 +@ The two queue links will occupy two of a vertex's remaining utility fields. 17.293 +There's a special list head, from which we get to everything else in the 17.294 +queue in decreasing order of keys by following |llink| fields. 17.295 + 17.296 +The following declaration actually provides for 128 list heads. Only the first 17.297 +of these will be used here, but we'll find something to do with the 17.298 +other 127 later. 17.299 + 17.300 +@d llink v.v /* |llink| is stored in utility field |v| of a vertex */ 17.301 +@d rlink w.v /* |rlink| is stored in utility field |w| of a vertex */ 17.302 + 17.303 +@<Prior...@>= 17.304 +Vertex head[128]; /* list-head elements that are always present */ 17.305 +@# 17.306 +void init_dlist(d) 17.307 + long d; 17.308 +{ 17.309 + head->llink=head->rlink=head; 17.310 + head->dist=d-1; /* a value guaranteed to be smaller than any actual key */ 17.311 +} 17.312 + 17.313 +@ It seems reasonable to assume that an element entering the queue for the 17.314 +first time will tend to have a larger key than the other elements. 17.315 + 17.316 +Indeed, in the special case that all arcs in the graph have the same 17.317 +length, this strategy turns out to be quite fast. For in that case, 17.318 +every vertex will be added to the end of the queue and deleted from the 17.319 +front, without any requeueing; the algorithm will produce a strict 17.320 +first-in-first-one queueing discipline. 17.321 + 17.322 +@<Prior...@>= 17.323 +void enlist(v,d) 17.324 + Vertex *v; 17.325 + long d; 17.326 +{@+register Vertex *t=head->llink; 17.327 + v->dist=d; 17.328 + while (d<t->dist) t=t->llink; 17.329 + v->llink=t; 17.330 + (v->rlink=t->rlink)->llink=v; 17.331 + t->rlink=v; 17.332 +} 17.333 + 17.334 +@ @<Prior...@>= 17.335 +void reenlist(v,d) 17.336 + Vertex *v; 17.337 + long d; 17.338 +{@+register Vertex *t=v->llink; 17.339 + (t->rlink=v->rlink)->llink=v->llink; /* remove |v| */ 17.340 + v->dist=d; /* we assume that the new |dist| is smaller than it was before */ 17.341 + while (d<t->dist) t=t->llink; 17.342 + v->llink=t; 17.343 + (v->rlink=t->rlink)->llink=v; 17.344 + t->rlink=v; 17.345 +} 17.346 + 17.347 +@ @<Prior...@>= 17.348 +Vertex *delete_first() 17.349 +{@+Vertex *t; 17.350 + t=head->rlink; 17.351 + if (t==head) return NULL; 17.352 + (head->rlink=t->rlink)->llink=head; 17.353 + return t; 17.354 +} 17.355 + 17.356 +@* A special case. When the arc lengths in the graph are all fairly small, 17.357 +we can substitute another queuing discipline that does each operation 17.358 +quickly. Suppose the only lengths are 0, 1, \dots,~|k-1|; then we can 17.359 +prove easily that the priority queue will never contain more than |k| 17.360 +different values at once. Moreover, we can implement it by maintaining 17.361 +|k| doubly linked lists, one for each key value mod~|k|. 17.362 + 17.363 +For example, let |k=128|. Here is an alternate set of queue commands, 17.364 +to be used when the arc lengths are known to be less than~128. 17.365 + 17.366 +@ @<Prior...@>= 17.367 +long master_key; /* smallest key that may be present in the priority queue */ 17.368 +@# 17.369 +void init_128(d) 17.370 + long d; 17.371 +{@+register Vertex *u; 17.372 + master_key=d; 17.373 + for (u=head; u<head+128; u++) 17.374 + u->llink=u->rlink=u; 17.375 +} 17.376 + 17.377 +@ If the number of lists were not a power of 2, we would calculate a remainder 17.378 +by division instead of by logical-anding with |0x7f|. 17.379 + 17.380 +@<Prior...@>= 17.381 +Vertex *delete_from_128() 17.382 +{@+long d; 17.383 + register Vertex *u, *t; 17.384 + for (d=master_key; d<master_key+128; d++) { 17.385 + u=head+(d&0x7f); /* that's |d%128| */ 17.386 + t=u->rlink; 17.387 + if (t!=u) { /* we found a nonempty list with minimum key */ 17.388 + master_key=d; 17.389 + (u->rlink = t->rlink)->llink = u; 17.390 + return t; /* incidentally, |t->dist = d| */ 17.391 + } 17.392 + } 17.393 + return NULL; /* all 128 lists are empty */ 17.394 +} 17.395 + 17.396 +@ @<Prior...@>= 17.397 +void enqueue_128(v,d) 17.398 + Vertex *v; /* new vertex for the queue */ 17.399 + long d; /* its |dist| */ 17.400 +{@+register Vertex *u=head+(d&0x7f); 17.401 + v->dist = d; 17.402 + (v->llink = u->llink)->rlink = v; 17.403 + v->rlink = u; 17.404 + u->llink = v; 17.405 +} 17.406 + 17.407 +@ All of these operations have been so simple, one wonders why the lists 17.408 +should be doubly linked. Single linking would indeed be plenty---if we 17.409 +didn't have to support the |requeue| operation. 17.410 + 17.411 +But requeueing involves deleting an arbitrary element from the middle of 17.412 +its list. And we do seem to need two links for that. 17.413 + 17.414 +In the application to Dijkstra's algorithm, the new |d| will always 17.415 +be |master_key| or more. But we want to implement requeueing in general, 17.416 +so that this procedure can be used also for other algorithms, 17.417 +such as the calculation of minimum spanning trees (see |miles_span|). 17.418 + 17.419 +@<Prior...@>= 17.420 +void requeue_128(v,d) 17.421 + Vertex *v; /* vertex to be moved to another list */ 17.422 + long d; /* its new |dist| */ 17.423 +{@+register Vertex *u=head+(d&0x7f); 17.424 + (v->llink->rlink=v->rlink)->llink=v->llink; /* remove |v| */ 17.425 + v->dist=d; /* the new |dist| is smaller than it was before */ 17.426 + (v->llink=u->llink)->rlink = v; 17.427 + v->rlink = u; 17.428 + u->llink = v; 17.429 + if (d<master_key) master_key=d; /* not needed for Dijkstra's algorithm */ 17.430 +} 17.431 + 17.432 +@ The user of |gb_dijk| needs to know the names of these queueing procedures 17.433 +if changes to the defaults are made, so we'd better put the necessary info 17.434 +into the header file. 17.435 + 17.436 +@(gb_dijk.h@>= 17.437 +extern void init_dlist(); 17.438 +extern void enlist(); 17.439 +extern void reenlist(); 17.440 +extern Vertex *delete_first(); 17.441 +extern void init_128(); 17.442 +extern Vertex *delete_from_128(); 17.443 +extern void enqueue_128(); 17.444 +extern void requeue_128(); 17.445 + 17.446 +@* Index. Here is a list that shows where the identifiers of this program are 17.447 +defined and used. 17.448 +
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/gb_econ.w Mon Oct 03 23:29:42 2011 +0200 18.3 @@ -0,0 +1,635 @@ 18.4 +% This file is part of the Stanford GraphBase (c) Stanford University 1992 18.5 +\def\title{GB\_\thinspace ECON} 18.6 +@i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES! 18.7 + 18.8 +\prerequisites{GB\_\thinspace GRAPH}{GB\_\thinspace IO} 18.9 +@* Introduction. This GraphBase module contains the |econ| subroutine, 18.10 +which creates a family of directed graphs related to the flow of money 18.11 +between industries. An example of the use of this procedure can be 18.12 +found in the demo program |econ_order|. 18.13 + 18.14 +@(gb_econ.h@>= 18.15 +extern Graph *econ(); 18.16 + 18.17 +@ The subroutine call `|econ(n,omit,threshold,seed)|' 18.18 +constructs a directed graph based on the information in \.{econ.dat}. 18.19 +Each vertex of the graph corresponds to one of 81 sectors of the U.S. 18.20 +economy. The data comes from the year 1985; it was derived from 18.21 +tables published in {\sl Survey of Current Business\/ \bf70} (1990), 41--56. 18.22 + 18.23 +If |omit=threshold=0|, the directed graph is a ``circulation''; 18.24 +i.e., each arc has an associated |flow| value, and 18.25 +the sum of arc flows leaving each vertex is equal to the 18.26 +sum of arc flows entering. This sum is called the ``total commodity output'' 18.27 +for the sector in question. The flow in an arc from sector $j$~to 18.28 +sector~$k$ is the amount of the commodity made by sector~$j$ that was 18.29 +used by sector~$k$, rounded to millions of dollars at producers' prices. 18.30 +For example, the total commodity output of the sector called \.{Apparel} 18.31 +is 54031, meaning that the total cost of making all kinds of apparel in 18.32 +1985 was about 54 billion dollars. There is an arc from \.{Apparel} to 18.33 +itself with a flow of 9259, meaning that 9.259 billion dollars' worth 18.34 +of apparel went from one group within the apparel industry to another; 18.35 +there is also an arc of flow~44 from \.{Apparel} to \.{Household} 18.36 +\.{furniture}, indicating that some 44 million dollars' worth of apparel 18.37 +went into the making of household furniture. By looking at all 18.38 +arcs leaving the \.{Apparel} vertex, you can see where all that 18.39 +new apparel went; by looking at all arcs that enter \.{Apparel}, you can 18.40 +see what ingredients the apparel industry needed to make~it. 18.41 + 18.42 +One vertex, called \.{Users}, represents people like you and me, the 18.43 +non-industrial end users of everything. The arc from \.{Apparel} to 18.44 +\.{Users} has flow 42172; this is the ``total final demand'' for 18.45 +apparel, the amount that didn't flow into other sectors of the economy 18.46 +before it reached people like us. The arc from \.{Users} to \.{Apparel} 18.47 +has flow 19409, which is called the ``value added'' by users; it 18.48 +represents wages and salaries paid to support the manufacturing 18.49 +process. The sum of total final demand over all sectors, which also 18.50 +equals the sum of value added over all sectors, is conventionally 18.51 +called the Gross National Product (GNP). In 1985 the GNP was 3999362, 18.52 +nearly 4 trillion dollars, according to \.{econ.dat}. (The sum of all 18.53 +arc flows coming out of all vertices was 7198680; this sum 18.54 +overestimates the total economic activity, because it counts some 18.55 +items more than once---statistics are recorded whenever an item 18.56 +passes a statistics gatherer. Economists try to adjust the data so that 18.57 +they avoid double-counting as much as possible.) 18.58 + 18.59 +Speaking of economists, there is another special vertex called 18.60 +\.{Adjustments}, included by economists so that GNP is measured 18.61 +more accurately. This vertex takes account of such things as changes in 18.62 +the value of inventories, and imported materials that cannot be obtained 18.63 +within the U.S., as well as work done for the government and for foreign 18.64 +concerns. In 1985, these adjustments accounted for about 11\% of the GNP. 18.65 + 18.66 +Incidentally, some of the ``total final demand'' arcs 18.67 +are negative. For example, the arc from \.{Petroleum} \.{and} 18.68 +\.{natural} \.{gas} \.{production} to \.{Users} has flow $-27032$. 18.69 +This may seem strange at first, but it makes sense, because crude oil 18.70 +and natural gas go more to other industries than to end users. Total 18.71 +final demand does not mean total user demand. 18.72 + 18.73 +@d flow a.i /* utility field |a| specifies the flow in an arc */ 18.74 + 18.75 +@ If |omit=1|, the \.{Users} vertex is omitted from the digraph; in 18.76 +particular, this will eliminate all arcs of negative flow. If 18.77 +|omit=2|, the \.{Adjustments} vertex is also omitted, thereby leaving 18.78 +79~sectors with arcs showing inter-industry flow. (The graph is no 18.79 +longer a ``circulation,'' of course, when |omit>0|.) If \.{Users} and 18.80 +\.{Adjustments} are not omitted, \.{Users} is the last vertex of the 18.81 +graph, and \.{Adjustments} is next-to-last. 18.82 + 18.83 +If |threshold=0|, the digraph has an arc for every nonzero |flow|. 18.84 +But if |threshold>0|, the digraph becomes more sparse; 18.85 +there is then an arc from $j$ to~$k$ if and 18.86 +only if the amount of commodity $j$ used by sector~$k$ exceeds 18.87 +|threshold/65536| times the total input of sector~$k$. (The total 18.88 +input figure always includes value added, even if |omit>0|.) 18.89 +Thus, the arcs go to each sector from 18.90 +that sector's main suppliers. When |n=79|, |omit=2|, and 18.91 +|threshold=0|, the digraph has 4602 arcs out of a possible 18.92 +$79\times79=6241$; raising |threshold| to 1 decreases the number of 18.93 +arcs to 4473; raising it to 6000 leaves only~72 arcs. 18.94 +The |len| field in each arc is~1. 18.95 + 18.96 +The constructed graph will have $\min(n,81-|omit|)$ vertices. If |n| is less 18.97 +than |81-omit|, the |n| vertices will be selected by repeatedly combining 18.98 +related sectors. For example, two of the 81 original sectors are called 18.99 +`\.{Paper} \.{products,} \.{except} \.{containers}' and 18.100 +`\.{Paperboard} \.{containers} \.{and} \.{boxes}'; these might be combined 18.101 +into a sector called `\.{Paper} \.{products}'. There is a binary tree 18.102 +with 79 leaves, which describes a fixed hierarchical breakdown of the 18.103 +79 non-special sectors. This tree is 18.104 +pruned, if necessary, by replacing pairs of leaves by their parent node, 18.105 +which becomes a new leaf; pruning continues 18.106 +until just |n| leaves remain. Although pruning is a bottom-up process, its 18.107 +effect can also be obtained from the top down if we imagine ``growing'' 18.108 +the tree, starting out with a whole economy as a single sector and 18.109 +repeatedly subdividing a sector into two parts. For example, 18.110 +if |omit=2| and |n=2|, the two sectors will 18.111 +be called \.{Goods} and \.{Services}. If |n=3|, \.{Goods} might be 18.112 +subdivided into \.{Natural} \.{Resources} and \.{Manufacturing}; or 18.113 +\.{Services} might be subdivided into \.{Indirect} \.{Services} and 18.114 +\.{Direct} \.{Services}. 18.115 + 18.116 +If |seed=0|, the binary tree is pruned in such a way that the |n| 18.117 +resulting sectors are as equal as possible with respect to total 18.118 +input and output, while respecting the tree structure. If |seed>0|, 18.119 +the pruning is carried out at random, in such a way that all |n|-leaf 18.120 +subtrees of the original tree are obtained with approximately equal 18.121 +probability (depending on |seed| in a machine-independent fashion). 18.122 +Any |seed| value from 1 to $2^{31}-1=2147483647$ is permissible. 18.123 + 18.124 +As usual in GraphBase routines, you can set |n=0| to get the default 18.125 +situation where |n| has its maximum value. For example, either 18.126 +|econ(0,0,0,0)| or |econ(81,0,0,0)| produces the full graph; 18.127 +|econ(0,2,0,0)| or |econ(79,2,0,0)| produces the full graph except 18.128 +for the two special vertices. 18.129 + 18.130 +@d MAX_N 81 /* maximum number of vertices in constructed graph */ 18.131 +@d NORM_N MAX_N-2 /* the number of normal BEA sectors */ 18.132 +@d ADJ_SEC MAX_N-1 /* code number for the \.{Adjustments} sector */ 18.133 + 18.134 +@ The U.S. Bureau of Economic Analysis (BEA) has assigned code numbers 18.135 +1--79 to the individual sectors for which statistics are given in 18.136 +\.{econ.dat}. If for some reason you wish to know the BEA codes for 18.137 +all sectors represented by vertex |v| of a graph generated by |econ|, 18.138 +you can access them via a list of |Arc| nodes starting at the utility 18.139 +field |v->BEA_codes|. 18.140 +This list is linked by |next| fields in the usual way, and each 18.141 +BEA code appears in the |len| field; the |tip| field is unused. 18.142 + 18.143 +The special vertex \.{Adjustments} is given code number~80; it is 18.144 +actually a composite of six different BEA categories, numbered 80--86 in their 18.145 +published tables. 18.146 + 18.147 +For example, if |n=80| and |omit=1|, each list will have length~1; 18.148 +hence |v->BEA_codes->next| will equal |NULL| for each~|v|, and 18.149 +|v->BEA_codes->len| will be |v|'s BEA code, a number between 1 and~80. 18.150 + 18.151 +The special vertex \.{Users} has no BEA code; it is the only vertex 18.152 +whose |BEA_codes| field will be null in the graph returned by |econ|. 18.153 + 18.154 +@d BEA_codes z.a /* utility field |z| leads to the BEA codes for a vertex */ 18.155 + 18.156 +@ The total output of each sector, which also equals the total input of that 18.157 +sector, is placed in utility field |sector_total| of the corresponding vertex. 18.158 + 18.159 +@d sector_total y.i /* utility field |y| holds the total flow in and out */ 18.160 + 18.161 +@(gb_econ.h@>= 18.162 +#define flow @t\quad@> a.i 18.163 + /* definitions of utility fields in the header file */ 18.164 +#define BEA_codes @t\quad@> z.a 18.165 +#define sector_total @t\quad@> y.i 18.166 + 18.167 +@ If the |econ| routine encounters a problem, it returns |NULL| 18.168 +(\.{NULL}), after putting a nonzero number into the external variable 18.169 +|panic_code|. This code number identifies the type of failure. 18.170 +Otherwise |econ| returns a pointer to the newly created graph, which 18.171 +will be represented with the data structures explained in |gb_graph|. 18.172 +(The external variable |@!panic_code| is itself defined in 18.173 +|gb_graph|.) 18.174 + 18.175 +@d panic(c) @+{@+panic_code=c;@+gb_alloc_trouble=0;@+return NULL;@+} 18.176 +@f Graph int /* |gb_graph| defines the |Graph| type and a few others */ 18.177 +@f Vertex int 18.178 +@f Arc int 18.179 +@f Area int 18.180 + 18.181 +@ The \Cee\ file \.{gb\_econ.c} has the following overall shape: 18.182 + 18.183 +@p 18.184 +#include "gb_io.h" /* we will use the |gb_io| routines for input */ 18.185 +#include "gb_flip.h" 18.186 + /* we will use the |gb_flip| routines for random numbers */ 18.187 +#include "gb_graph.h" 18.188 + /* and of course we'll use the |gb_graph| data structures */ 18.189 +@# 18.190 +@<Type declarations@>@; 18.191 +@<Private variables@>@; 18.192 +@# 18.193 +Graph *econ(n,omit,threshold,seed) 18.194 + unsigned n; /* number of vertices desired */ 18.195 + unsigned omit; /* number of special vertices to omit */ 18.196 + unsigned long threshold; /* minimum per-64K-age in arcs leading in */ 18.197 + long seed; /* random number seed */ 18.198 +{@+@<Local variables@>@; 18.199 + gb_init_rand(seed); 18.200 + init_area(working_storage); 18.201 + @<Check the parameters and adjust them for defaults@>; 18.202 + @<Set up a graph with |n| vertices@>; 18.203 + @<Read \.{econ.dat} and note the binary tree structure@>; 18.204 + @<Determine the |n| sectors to use in the graph@>; 18.205 + @<Put the appropriate arcs into the graph@>; 18.206 + if (gb_close()!=0) 18.207 + panic(late_data_fault); 18.208 + /* something's wrong with |"econ.dat"|; see |io_errors| */ 18.209 + gb_free(working_storage); 18.210 + if (gb_alloc_trouble) { 18.211 + gb_recycle(new_graph); 18.212 + panic(alloc_fault); /* oops, we ran out of memory somewhere back there */ 18.213 + } 18.214 + return new_graph; 18.215 +} 18.216 + 18.217 +@ @<Local var...@>= 18.218 +Graph *new_graph; /* the graph constructed by |econ| */ 18.219 +register int j,k; /* all-purpose indices */ 18.220 +Area working_storage; /* tables needed while |econ| does its thinking */ 18.221 + 18.222 +@ @<Check the param...@>= 18.223 +if (omit>2) omit=2; 18.224 +if (n==0 || n>MAX_N-omit) n=MAX_N-omit; 18.225 +else if (n+omit<3) omit=3-n; /* we need at least one normal sector */ 18.226 +if (threshold>65536) threshold=65536; 18.227 + 18.228 +@ @<Set up a graph with |n| vertices@>= 18.229 +new_graph=gb_new_graph(n); 18.230 +if (new_graph==NULL) 18.231 + panic(no_room); /* out of memory before we're even started */ 18.232 +sprintf(new_graph->id,"econ(%u,%u,%lu,%ld)",n,omit,threshold,seed); 18.233 +strcpy(new_graph->format,"ZZZZIAIZZZZZZZ"); 18.234 + 18.235 +@* The economic tree. 18.236 +As we read in the data, we construct a sequential list of nodes, 18.237 +each of which represents either a micro-sector of the economy (one of 18.238 +the basic BEA sectors) or a macro-sector (which is the union of two subnodes). 18.239 +In more technical terms, the nodes form an extended binary tree, 18.240 +whose external nodes correspond to micro-sectors and whose internal nodes 18.241 +correspond to macro-sectors. The nodes of the tree appear in preorder. 18.242 +Subsequently we will do a variety of operations on this binary tree, 18.243 +proceeding either top-down (from the beginning of the list to the end) 18.244 +or bottom-up (from the end to the beginning). 18.245 + 18.246 +Each node is a rather large record, because we will store a complete 18.247 +vector of sector output data in each node. 18.248 + 18.249 +@<Type declarations@>= 18.250 +typedef struct node_struct { /* records for micro and macro-sectors */ 18.251 + struct node_struct *rchild; /* pointer to right child of macro-sector */ 18.252 + char title[44]; /* |"Sector name"| */ 18.253 + long table[MAX_N+1]; /* outputs from this sector */ 18.254 + unsigned long total; /* total input to this sector ($=$ total output) */ 18.255 + long thresh; /* |flow| must exceed |thresh| in arcs to this sector */ 18.256 + int BEA_code; /* BEA code number; initially zero in macro-sectors */ 18.257 + int tag; /* 1 if this node will be a vertex in the graph */ 18.258 + struct node_struct *link; /* next smallest unexplored sector */ 18.259 + Arc *BEA_list; /* first item on list of BEA codes */ 18.260 +} node; 18.261 + 18.262 +@ When we read the given data in preorder, we'll need a stack to remember 18.263 +what nodes still need to have their |rchild| pointer filled in. 18.264 +(There is a no need for an |lchild| pointer, because the left child 18.265 +always follows its parent immediately in preorder.) 18.266 + 18.267 +@<Private v...@>= 18.268 +static node *stack[NORM_N+NORM_N]; 18.269 +static node **stack_ptr; /* current position in |stack| */ 18.270 +static node *node_block; /* array of nodes, specifies the tree in preorder */ 18.271 +static node *node_index[MAX_N+1]; /* which node has a given BEA code */ 18.272 + 18.273 +@ @<Local v...@>= 18.274 +register node *p,*pl,*pr; /* current node and its children */ 18.275 +register node *q,*r; /* registers for list manipulation */ 18.276 + 18.277 +@ @<Read \.{econ.dat} and note the binary tree structure@>= 18.278 +node_block=gb_alloc_type(2*MAX_N-3,@[node@],working_storage); 18.279 +if (gb_alloc_trouble) panic(no_room+1); /* no room to copy the data */ 18.280 +if (gb_open("econ.dat")!=0) 18.281 + panic(early_data_fault); 18.282 + /* couldn't open |"econ.dat"| using GraphBase conventions */ 18.283 +@<Read and store the sector names and BEA numbers@>; 18.284 +for (k=1; k<=MAX_N; k++) 18.285 + @<Read and store the output coefficients for sector |k|@>; 18.286 + 18.287 +@ The first part of \.{econ.dat} specifies the nodes of the binary 18.288 +tree in preorder. Each line contains a node name 18.289 +followed by a colon, and the colon is followed by the BEA number if 18.290 +that node is a leaf. 18.291 + 18.292 +The tree is uniquely specified in this way, 18.293 +because of the nature of preorder. (Think of Polish prefix notation, 18.294 +in which a formula like `${+}x{+}xx$' means `${+}(x,{+}(x,x))$'; the 18.295 +parentheses in Polish notation are redundant.) 18.296 + 18.297 +The two special sector names don't appear in the file; we manufacture 18.298 +them ourselves. 18.299 + 18.300 +The program here is careful not to clobber itself in the 18.301 +presence of arbitrarily garbled data. 18.302 + 18.303 +@<Read and store the sector names...@>= 18.304 +stack_ptr=stack; 18.305 +for (p=node_block; p<node_block+NORM_N+NORM_N-1; p++) {@+register int c; 18.306 + gb_string(p->title,':'); 18.307 + if (strlen(p->title)>43) panic(syntax_error); /* sector name too long */ 18.308 + if (gb_char()!=':') panic(syntax_error+1); /* missing colon */ 18.309 + p->BEA_code=c=gb_number(10); 18.310 + if (c==0) /* macro-sector */ 18.311 + *stack_ptr++=p; /* left child is |p+1|, we'll know |rchild| later */ 18.312 + else { /* micro-sector; |p+1| will be somebody's right child */ 18.313 + node_index[c]=p; 18.314 + if (stack_ptr>stack) (*--stack_ptr)->rchild=p+1; 18.315 + } 18.316 + if (gb_char()!='\n') panic(syntax_error+2); /* garbage on the line */ 18.317 + gb_newline(); 18.318 +} 18.319 +if (stack_ptr!=stack) panic(syntax_error+3); /* tree malformed */ 18.320 +for (k=NORM_N;k;k--) if (node_index[k]==0) 18.321 + panic(syntax_error+4); /* BEA code not mentioned in the tree */ 18.322 +strcpy(p->title,"Adjustments");@+p->BEA_code=ADJ_SEC;@+node_index[ADJ_SEC]=p; 18.323 +strcpy((p+1)->title,"Users");@+node_index[MAX_N]=p+1; 18.324 + 18.325 +@ The remaining part of \.{econ.dat} is an $81\times80$ matrix in which 18.326 +the $k$th row contains the outputs of sector~$k$ to all sectors except 18.327 +\.{Users}. Each row consists of 18.328 +a blank line followed by 8 lines of 10 numbers each, separated by commas; 18.329 +zero entries are represented by |""| instead of by |"0"|. For example, 18.330 +the line 18.331 +$$\hbox{\tt 8490,2182,42,467,,,,,,}$$ 18.332 +follows the initial blank line; it means that sector~1 output 8490 million 18.333 +dollars to itself, \$2182M to sector~2, \dots, \$0M to sector~10. 18.334 + 18.335 +@<Read and store the output...@>= 18.336 +{@+register int s=0; /* row sum */ 18.337 + register int x; /* entry read from \.{econ.dat} */ 18.338 + if (gb_char()!='\n') panic(syntax_error+5); 18.339 + /* blank line missing between rows */ 18.340 + gb_newline(); 18.341 + p=node_index[k]; 18.342 + for (j=1;j<MAX_N;j++) { 18.343 + p->table[j]=x=gb_number(10);@+s+=x; 18.344 + node_index[j]->total+=x; 18.345 + if ((j%10)==0) { 18.346 + if (gb_char()!='\n') panic(syntax_error+6); 18.347 + /* out of synch in input file */ 18.348 + gb_newline(); 18.349 + } else if (gb_char()!=',') panic(syntax_error+7); 18.350 + /* missing comma after entry */ 18.351 + } 18.352 + p->table[MAX_N]=s; /* sum of |table[1]| through |table[80]| */ 18.353 +} 18.354 + 18.355 +@* Growing a subtree. 18.356 +Once all the data appears in |node_block|, we want to extract from it and 18.357 +combine~it as specified by parameters |n|, |omit|, and |seed|. This may mean 18.358 +pruning the tree; or, rather, growing a subtree of the full economic tree. 18.359 + 18.360 +@<Determine the |n| sectors to use in the graph@>= 18.361 +{@+int l=n+omit-2; /* the number of leaves in the desired subtree */ 18.362 + if (l==NORM_N) @<Choose all sectors@>@; 18.363 + else if (seed) @<Grow a random subtree with |l| leaves@>@; 18.364 + else @<Grow a subtree with |l| leaves by subdividing largest sectors first@>; 18.365 +} 18.366 + 18.367 +@ The chosen leaves of our subtree will be identified by having their 18.368 +|tag| field set to~1. 18.369 + 18.370 +@<Choose all sectors@>= 18.371 +for (k=NORM_N;k;k--) node_index[k]->tag=1; 18.372 + 18.373 +@ To grow the |l|-leaf subtree when |seed=0|, we first pass over the 18.374 +tree bottom-up to compute the total input (and output) of each macro-sector; 18.375 +then we proceed from the top down to subdivide sectors in decreasing 18.376 +order of their total input. This provides a good introduction to the 18.377 +bottom-up and top-down tree methods we will be using in several other 18.378 +parts of the program. 18.379 + 18.380 +The |special| node is used here for two purposes: It is the head of a 18.381 +linked list of unexplored nodes, sorted by decreasing order of 18.382 +their |total| fields; and it appears at the end of that list, because 18.383 +|special->total=0|. 18.384 + 18.385 +@<Grow a subtree with |l| leaves by subdividing largest sectors first@>= 18.386 +{@+register node *special=node_index[MAX_N]; 18.387 + /* the \.{Users} node at the end of |node_block| */ 18.388 + for (p=node_index[ADJ_SEC]-1;p>=node_block;p--) /* bottom up */ 18.389 + if (p->rchild) 18.390 + p->total=(p+1)->total+p->rchild->total; 18.391 + special->link=node_block;@+node_block->link=special; /* start at the root */ 18.392 + k=1; /* |k| is the number of nodes we have tagged or put onto the list */ 18.393 + while (k<l) @<If the first node on the list is a leaf, delete it and tag it; 18.394 + otherwise replace it by its two children@>; 18.395 + for (p=special->link;p!=special;p=p->link) 18.396 + p->tag=1; /* tag everything on the list */ 18.397 +} 18.398 + 18.399 +@ @<If the first node on the list is a leaf,...@>= 18.400 +{ 18.401 + p=special->link; /* remove |p|, the node with greatest |total| */ 18.402 + special->link=p->link; 18.403 + if (p->rchild==0) p->tag=1; /* |p| is a leaf */ 18.404 + else { 18.405 + pl=p+1;@+pr=p->rchild; 18.406 + for (q=special;q->link->total>pl->total;q=q->link) ; 18.407 + pl->link=q->link;@+q->link=pl; /* insert left child in proper place */ 18.408 + for (q=special;q->link->total>pr->total;q=q->link) ; 18.409 + pr->link=q->link;@+q->link=pr; /* insert right child in proper place */ 18.410 + k++; 18.411 + } 18.412 +} 18.413 + 18.414 +@ We can obtain a uniformly distributed |l|-leaf subtree of a given tree 18.415 +by choosing the root when |l=1| or by using the following idea when |l>1|: 18.416 +Suppose the given tree~$T$ has subtrees $T_0$ and $T_1$. Then it has 18.417 +$T(l)$ subtrees with |l|~leaves, where $T(l)=\sum_k T_0(k)T_1(l-k)$. 18.418 +We choose a random number $r$ between 0 and $T(l)-1$, and we find the 18.419 +smallest $m$ such that $\sum_{k\le m}T_0(k)T_1(l-k)>r$. Then we 18.420 +proceed recursively to 18.421 +compute a random $m$-leaf subtree of~$T_0$ and a random $(l-m)$-leaf 18.422 +subtree of~$T_1$. 18.423 + 18.424 +A difficulty arises when $T(l)$ is $2^{31}$ or more. But then we can replace 18.425 +$T_0(k)$ and $T_1(l-k)$ in the formulas above by $\lceil T_0(k)/d_0\rceil$ 18.426 +and $\lceil T_1(k)/d_1\rceil$, respectively, where $d_0$ and $d_1$ are 18.427 +arbitrary constants; this yields smaller values 18.428 +$T(l)$ that define approximately the same distribution of~$k$. 18.429 + 18.430 +The program here computes the $T(l)$ values bottom-up, then grows a 18.431 +random tree top-down. If node~|p| is not a leaf, its |table[0]| field 18.432 +will be set to the number of leaves below it; and its |table[l]| field 18.433 +will be set to $T(l)$, for |1<=l<=table[0]|. 18.434 + 18.435 +The data in |econ.dat| is sufficiently simple that most of the $T(l)$ 18.436 +values are less than $2^{31}$. We need to scale them 18.437 +down to avoid overflow only at the root node of the tree; this 18.438 +case is handled separately. 18.439 + 18.440 +We will set the |tag| field of a node equal to the number of leaves to be 18.441 +grown in the subtree rooted at that node. This convention is consistent 18.442 +with our previous stipulation that |tag=1| should characterize the 18.443 +nodes that are chosen to be vertices. 18.444 + 18.445 +@<Grow a random subtree with |l| leaves@>= 18.446 +{ 18.447 + node_block->tag=l; 18.448 + for (p=node_index[ADJ_SEC]-1;p>node_block;p--) /* bottom up, except root */ 18.449 + if (p->rchild) @<Compute the $T(l)$ values for subtree |p|@>; 18.450 + for (p=node_block;p<node_index[ADJ_SEC];p++) /* top down, from root */ 18.451 + if (p->tag>1) { 18.452 + l=p->tag; 18.453 + pl=p+1;@+pr=p->rchild; 18.454 + if (pl->rchild==NULL) { 18.455 + pl->tag=1;@+pr->tag=l-1; 18.456 + } else if (pr->rchild==NULL) { 18.457 + pl->tag=l-1;@+pr->tag=1; 18.458 + } else @<Stochastically determine the number of leaves to grow in 18.459 + each of |p|'s children@>; 18.460 + } 18.461 +} 18.462 + 18.463 +@ Here we are essentially multiplying two generating functions. 18.464 +Suppose $f(z)=\sum_l T(l)z^l$; then we are computing $f_p(z)= 18.465 +z+f_{pl}(z)f_{pr}(z)$. 18.466 + 18.467 +@<Compute the $T(l)$ values for subtree |p|@>= 18.468 +{ 18.469 + pl=p+1;@+pr=p->rchild; 18.470 + p->table[1]=p->table[2]=1; /* $T(1)$ and $T(2)$ are always 1 */ 18.471 + if (pl->rchild==0) { /* left child is a leaf */ 18.472 + if (pr->rchild==0) p->table[0]=2; /* and so is the right child */ 18.473 + else { /* no, it isn't */ 18.474 + for (k=2;k<=pr->table[0];k++) p->table[1+k]=pr->table[k]; 18.475 + p->table[0]=pr->table[0]+1; 18.476 + } 18.477 + } else if (pr->rchild==0) { /* right child is a leaf */ 18.478 + for (k=2;k<=pl->table[0];k++) p->table[1+k]=pl->table[k]; 18.479 + p->table[0]=pl->table[0]+1; 18.480 + } else { /* neither child is a leaf */ 18.481 + @<Set |p->table[2]|, |p->table[3]|, \dots\ to convolution of 18.482 + |pl| and |pr| table entries@>; 18.483 + p->table[0]=pl->table[0]+pr->table[0]; 18.484 + } 18.485 +} 18.486 + 18.487 +@ @<Set |p->table[2]|, |p->table[3]|, \dots\ to convolution...@>= 18.488 +p->table[2]=0; 18.489 +for (j=pl->table[0];j;j--) {@+register long t=pl->table[j]; 18.490 + for (k=pr->table[0];k;k--) 18.491 + p->table[j+k]+=t*pr->table[k]; 18.492 +} 18.493 + 18.494 +@ @<Stochastically determine the number of leaves to grow...@>= 18.495 +{@+register long s,r; 18.496 + j=0; /* we will set |j=1| if scaling is necessary at the root */ 18.497 + if (p==node_block) { 18.498 + s=0; 18.499 + if (l>29 && l<67) { 18.500 + j=1; /* more than $2^{31}$ possibilities exist */ 18.501 + for (k=(l>pr->table[0]? l-pr->table[0]: 1);k<=pl->table[0] && k<l;k++) 18.502 + s+=((pl->table[k]+0x3ff)>>10)*pr->table[l-k]; 18.503 + /* scale with $d_0=1024$, $d_1=1$ */ 18.504 + } else 18.505 + for (k=(l>pr->table[0]? l-pr->table[0]: 1);k<=pl->table[0] && k<l;k++) 18.506 + s+=pl->table[k]*pr->table[l-k]; 18.507 + } else s=p->table[l]; 18.508 + r=gb_unif_rand(s); 18.509 + if (j) 18.510 + for (s=0,k=(l>pr->table[0]? l-pr->table[0]: 1);s<=r;k++) 18.511 + s+=((pl->table[k]+0x3ff)>>10)*pr->table[l-k]; 18.512 + else for (s=0,k=(l>pr->table[0]? l-pr->table[0]: 1);s<=r;k++) 18.513 + s+=pl->table[k]*pr->table[l-k]; 18.514 + pl->tag=k-1;@+pr->tag=l-k+1; 18.515 +} 18.516 + 18.517 +@* Arcs. 18.518 +In the general case, we have to combine some of the basic micro-sectors 18.519 +into macro-sectors by adding together the appropriate input/output 18.520 +coefficients. This is a bottom-up pruning process. 18.521 + 18.522 +Suppose |p| is being formed as the union of |pl| and~|pr|. 18.523 +Then the arcs leading out of |p| are obtaining by summing the numbers 18.524 +on arcs leading out of |pl| and~|pr|; the arcs leading into |p| are 18.525 +obtained by summing the numbers on arcs leading into |pl| and~|pr|; 18.526 +the arcs from |p| to itself are obtained by summing the four numbers 18.527 +on arcs leading from |pl| or~|pr| to |pl| or~|pr|. 18.528 + 18.529 +We maintain the |node_index| table so that its non-|NULL| entries 18.530 +contain all the currently active nodes. When |pl| and~|pr| are 18.531 +being pruned in favor of~|p|, node |p|~inherits |pl|'s place in 18.532 +|node_index|; |pr|'s former place becomes~|NULL|. 18.533 + 18.534 +@<Put the appropriate arcs into the graph@>= 18.535 +@<Prune the sectors that are used in macro-sectors, and form 18.536 + the lists of BEA sector codes@>; 18.537 +@<Make the special nodes invisible if they are omitted, visible otherwise@>; 18.538 +@<Compute individual thresholds for each chosen sector@>; 18.539 +{@+register Vertex *v=new_graph->vertices+n; 18.540 + for (k=MAX_N;k;k--) 18.541 + if ((p=node_index[k])!=NULL) { 18.542 + vert_index[k]=--v; 18.543 + v->name=gb_save_string(p->title); 18.544 + v->BEA_codes=p->BEA_list; 18.545 + v->sector_total=p->total; 18.546 + } 18.547 + if (v!=new_graph->vertices) 18.548 + panic(impossible); /* bug in algorithm; this can't happen */ 18.549 + for (j=MAX_N;j;j--) 18.550 + if ((p=node_index[j])!=NULL) {@+register Vertex *u=vert_index[j]; 18.551 + for (k=MAX_N;k;k--) 18.552 + if ((v=vert_index[k])!=NULL) 18.553 + if (p->table[k]!=0 && p->table[k]>node_