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_