miles_span.w
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:68k
源码类别:

通讯编程

开发平台:

Visual C++

  1. % This file is part of the Stanford GraphBase (c) Stanford University 1993
  2. @i boilerplate.w %<< legal stuff: PLEASE READ IT BEFORE MAKING ANY CHANGES!
  3. @i gb_types.w
  4. deftitle{MILES_,SPAN}
  5. def<#1>{$langle${rm#1}$rangle$}
  6. prerequisite{GB_,MILES}
  7. @* Minimum spanning trees.
  8. A classic paper by R. L. Graham and Pavol Hell about the history of
  9. @^Graham, Ronald Lewis@>
  10. @^Hell, Pavol@>
  11. algorithms to find the minimum-length spanning tree of a graph
  12. [{sl Annals of the History of Computing bf7} (1985), 43--57]
  13. describes three main approaches to that problem. Algorithm~1,
  14. ``two nearest fragments,'' repeatedly adds a shortest edge that joins
  15. two hitherto unconnected fragments of the graph; this algorithm was
  16. first published by J.~B. Kruskal in 1956. Algorithm~2, ``nearest
  17. @^Kruskal, Joseph Bernard@>
  18. neighbor,'' repeatedly adds a shortest edge that joins a particular
  19. fragment to a vertex not in that fragment; this algorithm was first
  20. published by V. Jarn'{i}k in 1930. Algorithm~3, ``all nearest
  21. @^Jarn{'i}k, Vojtu ech@>
  22. fragments,'' repeatedly adds to each existing fragment the shortest
  23. edge that joins it to another fragment; this method, seemingly the
  24. most sophisticated in concept, also turns out to be the oldest,
  25. being first published by Otakar Bor{accent23u}vka in 1926.
  26. @^Bor{accent23u}vka, Otakar@>
  27. The present program contains simple implementations of all three
  28. approaches, in an attempt to make practical comparisons of how
  29. they behave on ``realistic'' data. One of the main goals of this
  30. program is to demonstrate a simple way to make machine-independent
  31. comparisons of programs written in CEE/, by counting memory
  32. references or ``mems.'' In other words, this program is intended
  33. to be read, not just performed.
  34. The author believes that mem counting sheds considerable light on
  35. the problem of determining the relative efficiency of competing
  36. algorithms for practical problems. He hopes other researchers will
  37. enjoy rising to the challenge of devising algorithms that find minimum
  38. spanning trees in significantly fewer mem units than the algorithms
  39. presented here, on problems of the size considered here.
  40. Indeed, mem counting promises to be significant for combinatorial
  41. algorithms of all kinds. The standard graphs available in the
  42. Stanford GraphBase should make it possible to carry out a large
  43. number of machine-independent experiments concerning the practical
  44. efficiency of algorithms that have previously been studied
  45. only asymptotically.
  46. @ The graphs we will deal with are produced by the |miles| subroutine,
  47. found in the {sc GB_,MILES} module. As explained there,
  48. |miles(n,north_weight,west_weight,pop_weight,0,max_degree,seed)| produces a
  49. graph of |n<=128| vertices based on the driving distances between
  50. North American cities. By default we take |n=100|, |north_weight=west_weight
  51. =pop_weight=0|, and |max_degree=10|; this gives billions of different sparse
  52. graphs, when different |seed| values are specified, since a different
  53. random number seed generally results in the selection of another
  54. one of the $,128,choose100$ possible subgraphs.
  55. The default parameters can be changed by specifying options on the
  56. command line, at least in a UNIX/ implementation, thereby obtaining a
  57. variety of special effects. For example, the value of |n| can be
  58. raised or lowered and/or the graph can be made more or less sparse.
  59. The user can bias the selection by ranking cities according to their
  60. population and/or position, if nonzero values are given to any of the
  61. parameters |north_weight|, |west_weight|, or |pop_weight|.
  62. Command-line options .{-n}<number>, .{-N}<number>, .{-W}<number>,
  63. .{-P}<number>, .{-d}<number>, and .{-s}<number>
  64. are used to specify non-default values of the respective quantities |n|,
  65. |north_weight|, |west_weight|, |pop_weight|, |max_degree|, and |seed|.
  66. If the user specifies a .{-r} option, for example by saying `.{miles_span}
  67. .{-r10}', this program will investigate the spanning trees of a
  68. series of, say, 10 graphs having consecutive |seed| values. (This
  69. option makes sense only if |north_weight=west_weight=pop_weight=0|,
  70. because |miles| chooses the top |n| cities by weight. The procedure rarely
  71. needs to use random numbers to break ties when the weights are nonzero,
  72. because cities rarely have exactly the same weight in that case.)
  73. The special command-line option .{-g}$langle,$filename$,rangle$
  74. overrides all others. It substitutes an external graph previously saved by
  75. |save_graph| for the graphs produced by |miles|. 
  76. @^UNIX dependencies@>
  77. Here is the overall layout of this CEE/ program:
  78. @p
  79. #include "gb_graph.h" /* the GraphBase data structures */
  80. #include "gb_save.h" /* |restore_graph| */
  81. #include "gb_miles.h" /* the |miles| routine */
  82. @h@#
  83. @<Global variables@>@;
  84. @<Procedures to be declared early@>@;
  85. @<Priority queue subroutines@>@;
  86. @<Subroutines@>@;
  87. main(argc,argv)
  88.   int argc; /* the number of command-line arguments */
  89.   char *argv[]; /* an array of strings containing those arguments */
  90. {@+unsigned long n=100; /* the desired number of vertices */
  91.   unsigned long n_weight=0; /* the |north_weight| parameter */
  92.   unsigned long w_weight=0; /* the |west_weight| parameter */
  93.   unsigned long p_weight=0; /* the |pop_weight| parameter */
  94.   unsigned long d=10; /* the |max_degree| parameter */
  95.   long s=0; /* the random number seed */
  96.   unsigned long r=1; /* the number of repetitions */
  97.   char *file_name=NULL; /* external graph to be restored */
  98.   @<Scan the command-line options@>;
  99.   while (r--) {
  100.     if (file_name) g=restore_graph(file_name);
  101.     else g=miles(n,n_weight,w_weight,p_weight,0L,d,s);
  102.     if (g==NULL || g->n<=1) {
  103.       fprintf(stderr,"Sorry, can't create the graph! (error code %ld)n",
  104.                panic_code);
  105.       return -1; /* error code 0 means the graph is too small */
  106.     }
  107.     @<Report the number of mems needed to compute a minimum spanning tree
  108.        of |g| by various algorithms@>;
  109.     gb_recycle(g);
  110.     s++; /* increase the |seed| value */
  111.   }
  112.   return 0; /* normal exit */
  113. }
  114. @ @<Global...@>=
  115. Graph *g; /* the graph we will work on */
  116. @ @<Scan the command-line options@>=
  117. while (--argc) {
  118. @^UNIX dependencies@>
  119.   if (sscanf(argv[argc],"-n%lu",&n)==1) ;
  120.   else if (sscanf(argv[argc],"-N%lu",&n_weight)==1) ;
  121.   else if (sscanf(argv[argc],"-W%lu",&w_weight)==1) ;
  122.   else if (sscanf(argv[argc],"-P%lu",&p_weight)==1) ;
  123.   else if (sscanf(argv[argc],"-d%lu",&d)==1) ;
  124.   else if (sscanf(argv[argc],"-r%lu",&r)==1) ;
  125.   else if (sscanf(argv[argc],"-s%ld",&s)==1) ;
  126.   else if (strcmp(argv[argc],"-v")==0) verbose=1;
  127.   else if (strncmp(argv[argc],"-g",2)==0) file_name=argv[argc]+2;
  128.   else {
  129.     fprintf(stderr,
  130.              "Usage: %s [-nN][-dN][-rN][-sN][-NN][-WN][-PN][-v][-gfoo]n",
  131.              argv[0]);
  132.     return -2;
  133.   }
  134. }
  135. if (file_name) r=1;
  136. @ We will try out four basic algorithms that have received prominent
  137. attention in the literature. Graham and Hell's Algorithm~1 is represented
  138. by the |krusk| procedure, which uses Kruskal's algorithm after the
  139. edges have been sorted by length with a radix sort. Their Algorithm~2
  140. is represented by the |jar_pr| procedure, which incorporates a 
  141. priority queue structure that we implement in two ways, either as
  142. a simple binary heap or as a Fibonacci heap. And their Algorithm~3
  143. is represented by the |cher_tar_kar| procedure, which implements a
  144. method similar to Bor{accent23u}vka's that was independently
  145. discovered by Cheriton and Tarjan and later simplified and refined by
  146. Karp and Tarjan.
  147. @^Cheriton, David Ross@>
  148. @^Tarjan, Robert Endre@>
  149. @^Karp, Richard Manning@>
  150. @d INFINITY (unsigned long)-1
  151.  /* value returned when there's no spanning tree */
  152. @<Report the number...@>=
  153. printf("The graph %s has %ld edges,n",g->id,g->m/2);
  154. sp_length=krusk(g);
  155. if (sp_length==INFINITY) printf("  and it isn't connected.n");
  156. else printf("  and its minimum spanning tree has length %ld.n",sp_length);
  157. printf(" The Kruskal/radix-sort algorithm takes %ld mems;n",mems);
  158. @<Execute |jar_pr(g)| with binary heaps as the priority queue algorithm@>;
  159. printf(" the Jarnik/Prim/binary-heap algorithm takes %ld mems;n",mems);
  160. @<Allocate additional space needed by the more complex algorithms;
  161.     or |goto done| if there isn't enough room@>;
  162. @<Execute |jar_pr(g)| with Fibonacci heaps as
  163.      the priority queue algorithm@>;
  164. printf(" the Jarnik/Prim/Fibonacci-heap algorithm takes %ld mems;n",mems);
  165. if (sp_length!=cher_tar_kar(g)) {
  166.   if (gb_trouble_code) printf(" ...oops, I've run out of memory!n");
  167.   else printf(" ...oops, I've got a bug, please fix fix fixn");
  168.   return -3;
  169. }
  170. printf(" the Cheriton/Tarjan/Karp algorithm takes %ld mems.nn",mems);
  171. done:;
  172. @ @<Glob...@>=
  173. unsigned long sp_length; /* length of the minimum spanning tree */
  174. @ When the |verbose| switch is nonzero, edges found by the various
  175. algorithms will call the |report| subroutine.
  176. @<Sub...@>=
  177. report(u,v,l)
  178.   Vertex *u,*v; /* adjacent vertices in the minimum spanning tree */
  179.   long l; /* the length of the edge between them */
  180. { printf("  %ld miles between %s and %s [%ld mems]n",
  181.            l,u->name,v->name,mems);
  182. }
  183. @*Strategies and ground rules.
  184. Let us say that a {sl fragment/} is any subtree of a minimum
  185. spanning tree. All three algorithms we implement make use of a basic
  186. principle first stated in full generality by R.~C. Prim in 1957:
  187. @^Prim, Robert Clay@>
  188. ``If a fragment~$F$ does not include all the vertices, and if $e$~is
  189. a shortest edge joining $F$ to a vertex not in~$F$, then $Fcup e$
  190. is a fragment.'' To prove Prim's principle, let $T$ be a minimum
  191. spanning tree that contains $F$ but not~$e$. Adding $e$ to~$T$ creates
  192. a circuit containing some edge $e'ne e$, where $e'$ runs from a vertex
  193. in~$F$ to a vertex not in~$F$. Deleting $e'$ from
  194. $Tcup e$ produces a spanning tree~$T'$ of total length no larger
  195. than the total length of~$T$. Hence $T'$ is a minimum spanning
  196. tree containing $Fcup e$, QED.
  197. @ The graphs produced by |miles| have special properties, and it is fair game
  198. to make use of those properties if we can.
  199. First, the length of each edge is a positive integer less than $2^{12}$.
  200. Second, the $k$th vertex $v_k$ of the graph is represented in CEE/ programs by
  201. the pointer expression |g->vertices+k|. If weights have been assigned,
  202. these vertices will be in order by weight. For example, if |north_weight=1|
  203. but |west_weight=pop_weight=0|, vertex $v_0$ will be the most northerly city
  204. and vertex $v_{n-1}$ will be the most southerly.
  205. Third, the edges accessible from a vertex |v| appear in a linked list
  206. starting at |v->arcs|. An edge from |v| to $v_j$ will precede an
  207. edge from |v| to $v_k$ in this list if and only if $j>k$.
  208. Fourth, the vertices have coordinates |v->x_coord| and |v->y_coord|
  209. that are correlated with the length of edges between them: The
  210. Euclidean distance between the coordinates of two vertices tends to be small
  211. if and only if those vertices are connected by a relatively short edge.
  212. (This is only a tendency, not a certainty; for example, some cities
  213. around Chesapeake Bay are fairly close together as the crow flies, but not
  214. within easy driving range of each other.)
  215. Fifth, the edge lengths satisfy the triangle inequality: Whenever
  216. three edges form a cycle, the longest is no longer than the sum of
  217. the lengths of the two others. (It can be proved that
  218. the triangle inequality is of no use in finding minimum spanning
  219. trees; we mention it here only to exhibit yet another way in which
  220. the data produced by |miles| is known to be nonrandom.)
  221. Our implementation of Kruskal's algorithm will make use of the first
  222. property, and it also uses part of the third to avoid considering an
  223. edge more than once. We will not exploit the other properties, but a
  224. reader who wants to design algorithms that use fewer mems to find minimum
  225. spanning trees of these graphs is free to use any idea that helps.
  226. @ Speaking of mems, here are the simple CEE/ instrumentation macros that we
  227. use to count memory references. The macros are called |o|, |oo|, |ooo|,
  228. and |oooo|; hence Jon Bentley has called this a ``little oh analysis.''
  229. @^Bentley, Jon Louis@>
  230. Implementors who want to count mems are supposed to say, e.g., `|oo|,'
  231. just before an assignment statement or boolean expression that makes
  232. two references to memory. The CEE/ preprocessor will convert this
  233. to a statement that increases |mems| by~2 as that statement or expression
  234. is evaluated.
  235. The semantics of CEE/ tell us that the evaluation of an expression
  236. like `|a&&(o,a->len>10)|' will increment |mems| if and only if the
  237. pointer variable~|a| is non-null. Warning: The parentheses are very
  238. important in this example, because CEE/'s operator |&&| (i.e.,
  239. .{&&}) has higher precedence than comma.
  240. Values of significant variables, like |a| in the previous example,
  241. can be assumed to be in ``registers,'' and no charge is made for
  242. arithmetic computations that involve only registers. But the total
  243. number of registers in an implementation must be finite and fixed,
  244. independent of the problem size.
  245. @^discussion of \{mems}@>
  246. CEE/ does not allow the |o| macros to appear in declarations, so we cannot
  247. take full advantage of CEE/'s initialization mechanism when we are
  248. counting mems. But it's easy to initialize variables in separate
  249. statements after the declarations are done.
  250. @d o mems++
  251. @d oo mems+=2
  252. @d ooo mems+=3
  253. @d oooo mems+=4
  254. @<Glob...@>=
  255. long mems; /* the number of memory references counted */
  256. @ Examples of these mem-counting conventions appear throughout the
  257. program that follows. Some people will undoubtedly ask why the insertion of
  258. macros by hand is being recommended here, when it would be possible to
  259. develop a fancy system that counts mems automatically. The author
  260. believes that it is best to rely on programmers to introduce |o| and
  261. |oo|, etc., by themselves, for several reasons. (1)~The macros can be
  262. inserted easily and quickly using a text editor. (2)~An implementation
  263. need not pay for mems that could be avoided by a suitable optimizing
  264. compiler or by making the CEE/ program text slightly more complex;
  265. thus, authors can use their good judgment to keep programs more
  266. readable than if the code were overly hand-optimized. (3)~The
  267. programmer should be able to see exactly where mems are being charged,
  268. as an aid to bottleneck elimination. Occurrences of |o| and |oo| make
  269. this plain without messing up the program text. (4)~An implementation
  270. need not be charged for mems that merely provide diagnostic output, or
  271. mems that do redundant computations just to double-check the validity
  272. of ``proven'' assertions as a program is being tested.
  273. @^discussion of \{mems}@>
  274. Computer architecture is converging rapidly these days to the
  275. design of machines in which the exact running time of a program
  276. depends on complicated interactions between pipelined circuitry and
  277. the dynamic properties of cache mapping in a memory hierarchy,
  278. not to mention the effects of compilers and operating systems.
  279. But a good approximation to running time is usually obtained if we
  280. assume that the amount of computation is proportional to the activity
  281. of the memory bus between registers and main memory. This
  282. approximation is likely to get even better in the future, as
  283. RISC computers get faster and faster in comparison to memory devices.
  284. Although the mem measure is far from perfect, it appears to be
  285. significantly less distorted than any other measurement that can
  286. be obtained without considerably more work. An implementation that
  287. is designed to use few mems will almost certainly be efficient
  288. on today's sequential computers, as well as on the sequential computers
  289. we can expect to be built in the foreseeable future. And the converse
  290. statement is even more true: An algorithm that runs fast will not
  291. consume many mems.
  292. Of course authors are expected to be reasonable and fair when they
  293. are competing for minimum-mem prizes. They must be ready to
  294. submit their programs to inspection by impartial judges. A good
  295. algorithm will not need to abuse the spirit of realistic mem-counting.
  296. Mems can be analyzed theoretically as well as empirically.
  297. This means we can attach constants to estimates of running time, instead of
  298. always resorting to $O$~notation.
  299. @*Kruskal's algorithm.
  300. The first algorithm we shall implement and instrument is the simplest:
  301. It considers the edges one by one in order of nondecreasing length,
  302. selecting each edge that does not form a cycle with previously
  303. selected edges.
  304. We know that the edge lengths are less than $2^{12}$, so we can sort them
  305. into order with two passes of a $2^6$-bucket radix sort.
  306. We will arrange to have them appear in the buckets as linked lists
  307. of |Arc| records; the two utility fields of an |Arc| will be called
  308. |from| and |klink|, respectively.
  309. @d from a.V /* an edge goes from vertex |a->from| to vertex |a->tip| */
  310. @d klink b.A /* the next longer edge after |a| will be |a->klink| */
  311. @<Put all the edges into |bucket[0]| through |bucket[63]|@>=
  312. o,n=g->n;
  313. for (l=0;l<64;l++) oo,aucket[l]=bucket[l]=NULL;
  314. for (o,v=g->vertices;v<g->vertices+n;v++)
  315.   for (o,a=v->arcs;a&&(o,a->tip>v);o,a=a->next) {
  316.     o,a->from=v;
  317.     o,l=a->len&0x3f; /* length mod 64 */
  318.     oo,a->klink=aucket[l];
  319.     o,aucket[l]=a;
  320.   }
  321. for (l=63;l>=0;l--)
  322.   for (o,a=aucket[l];a;) {@+register long ll;
  323.     register Arc *aa=a;
  324.     o,a=a->klink;
  325.     o,ll=aa->len>>6; /* length divided by 64 */
  326.     oo,aa->klink=bucket[ll];
  327.     o,bucket[ll]=aa;
  328.   }
  329. @ @<Glob...@>=
  330. Arc *aucket[64], *bucket[64]; /* heads of linked lists of arcs */
  331. @ Kruskal's algorithm now takes the following form.
  332. @<Sub...@>=
  333. unsigned long krusk(g)
  334.   Graph *g;
  335. {@+@<Local variables for |krusk|@>@;@#
  336.   mems=0;
  337.   @<Put all the edges...@>;
  338.   if (verbose) printf("   [%ld mems to sort the edges into buckets]n",mems);
  339.   @<Put all the vertices into components by themselves@>;
  340.   for (l=0;l<64;l++)
  341.     for (o,a=bucket[l];a;o,a=a->klink) {
  342.       o,u=a->from;
  343.       o,v=a->tip;
  344.       @<If |u| and |v| are already in the same component, |continue|@>;
  345.       if (verbose) report(a->from,a->tip,a->len);
  346.       o,tot_len+=a->len;
  347.       if (--components==1) return tot_len;
  348.       @<Merge the components containing |u| and |v|@>;
  349.     }
  350.   return INFINITY; /* the graph wasn't connected */
  351. }
  352. @ Lest we forget, we'd better declare all the local variables we've
  353. been using.
  354. @<Local variables for |krusk|@>=
  355. register Arc *a; /* current edge of interest */
  356. register long l; /* current bucket of interest */
  357. register Vertex *u,*v,*w; /* current vertices of interest */
  358. unsigned long tot_len=0; /* total length of edges already chosen */
  359. long n; /* the number of vertices */
  360. long components;
  361. @ The remaining things that |krusk| needs to do are easily recognizable
  362. as an application of ``equivalence algorithms'' or ``union/find''
  363. data structures. We will use a simple approach whose average running
  364. time on random graphs was shown to be linear by Knuth and Sch"onhage
  365. @^Knuth, Donald Ervin@>
  366. @^Sch"onhage, Arnold@>
  367. in {sl Theoretical Computer Science/ bf 6} (1978), 281--315.
  368. The vertices of each component (that is, of each connected fragment defined by
  369. the edges selected so far) will be linked circularly by |clink| pointers.
  370. Each vertex also has a |comp| field that points to a unique vertex
  371. representing its component. Each component representative also has
  372. a |csize| field that tells how many vertices are in the component.
  373. @d clink z.V /* pointer to another vertex in the same component */
  374. @d comp y.V /* pointer to component representative */
  375. @d csize x.I /* size of the component (maintained only for representatives) */
  376. @<If |u| and |v| are already in the same component, |continue|@>=
  377. if (oo,u->comp==v->comp) continue;
  378. @ We don't need to charge any mems for fetching |g->vertices|, because
  379. |krusk| has already referred to it.
  380. @^discussion of \{mems}@>
  381. @<Put all the vertices...@>=
  382. for (v=g->vertices;v<g->vertices+n;v++) {
  383.   oo,v->clink=v->comp=v;
  384.   o,v->csize=1;
  385. }
  386. components=n;
  387. @ The operation of merging two components together requires us to
  388. change two |clink| pointers, one |csize| field, and the |comp|
  389. fields in each vertex of the smaller component.
  390. Here we charge two mems for the first |if| test, since |u->csize| and
  391. |v->csize| are being fetched from memory. Then we charge only one mem
  392. when |u->csize| is being updated, since the values being added together
  393. have already been fetched. True, the compiler has to be smart to
  394. realize that it's safe to add the fetched values |u->csize+v->csize|
  395. even though |u| and |v| might have been swapped in the meantime;
  396. but we are assuming that the compiler is extremely clever. (Otherwise we
  397. would have to clutter up our program every time we don't trust the compiler.
  398. After all, programs that count mems are intended primarily to be read.
  399. They aren't intended for production jobs.) % Prim-arily?
  400. @^discussion of \{mems}@>
  401. @<Merge the components containing |u| and |v|@>=
  402. u=u->comp; /* |u->comp| has already been fetched from memory */
  403. v=v->comp; /* ditto for |v->comp| */
  404. if (oo,u->csize<v->csize) {
  405.   w=u;@+u=v;@+v=w;
  406. } /* now |v|'s component is smaller than |u|'s (or equally small) */
  407. o,u->csize+=v->csize;
  408. o,w=v->clink;
  409. oo,v->clink=u->clink;
  410. o,u->clink=w;
  411. for (;;o,w=w->clink) {
  412.   o,w->comp=u;
  413.   if (w==v) break;
  414. }
  415.   
  416. @* Jarn{'i}k and Prim's algorithm.
  417. A second approach to minimum spanning trees is also pretty simple,
  418. except for one technicality: We want to write it in a sufficiently
  419. general manner that different priority queue algorithms can be plugged in.
  420. The basic idea is to choose an arbitrary vertex $v_0$ and connect it to its
  421. nearest neighbor~$v_1$, then to connect that fragment to its nearest
  422. neighbor~$v_2$, and so on. A priority queue holds all vertices that
  423. are adjacent to but not already in the current fragment; the key value
  424. stored with each vertex is its distance to the current fragment.
  425. We want the priority queue data structure to support the four
  426. operations |init_queue(d)|, |enqueue(v,d)|, |requeue(v,d)|, and
  427. |del_min()|, described in the {sc GB_,DIJK} module. Dijkstra's
  428. algorithm for shortest paths, described there, is remarkably similar
  429. to Jarn{'i}k and Prim's algorithm for minimum spanning trees; in
  430. fact, Dijkstra discovered the latter algorithm independently, at the
  431. @^Dijkstra, Edsger Wijbe@>
  432. same time as he came up with his procedure for shortest paths.
  433. As in {sc GB_,DIJK}, we define pointers to priority queue subroutines
  434. so that the queueing mechanism can be varied.
  435. @d dist z.I /* this is the key field for vertices in the priority queue */
  436. @d backlink y.V /* this vertex is the stated |dist| away */
  437. @<Glob...@>=
  438. void @[@] (*init_queue)(); /* create an empty priority queue */
  439. void @[@] (*enqueue)(); /* insert a new element in the priority queue */
  440. void @[@] (*requeue)(); /* decrease the key of an element in the queue */
  441. Vertex *(*del_min)(); /* remove an element with smallest key */
  442. @ The vertices in this algorithm are initially ``unseen''; they become
  443. ``seen'' when they enter the priority queue, and finally ``known''
  444. when they leave it and enter the current fragment.
  445. We will put a special constant in the |backlink| field
  446. of known vertices. A vertex will be unseen if and only if its
  447. |backlink| is~|NULL|.
  448. @d KNOWN (Vertex*)1 /* special |backlink| to mark known vertices */
  449. @<Sub...@>=
  450. unsigned long jar_pr(g)
  451.   Graph *g;
  452. {@+register Vertex *t; /* vertex that is just becoming known */
  453.   long fragment_size; /* number of vertices in the tree so far */
  454.   unsigned long tot_len=0; /* sum of edge lengths in the tree so far */
  455.   mems=0;
  456.   @<Make |t=g->vertices| the only vertex seen; also make it known@>;
  457.   while (fragment_size<g->n) {
  458.     @<Put all unseen vertices adjacent to |t| into the queue,
  459.       and update the distances of the other vertices adjacent to~|t|@>;
  460.     t=(*del_min)();
  461.     if (t==NULL) return INFINITY; /* the graph is disconnected */
  462.     if (verbose) report(t->backlink,t,t->dist);
  463.     o,tot_len+=t->dist;
  464.     o,t->backlink=KNOWN;
  465.     fragment_size++;
  466.   }
  467.   return tot_len;
  468. }
  469. @ Notice that we don't charge any mems for the subroutine call
  470. to |init_queue|, except for mems counted in the subroutine itself.
  471. What should we charge in general for subroutine linkage when we are
  472. counting mems? The parameters to subroutines generally go into
  473. registers, and registers are ``free''; also, a compiler can often
  474. choose to implement a procedure in line, thereby reducing the
  475. overhead to zero. Hence, the recommended method for charging mems
  476. with respect to subroutines is: Charge nothing if the subroutine
  477. is not recursive; otherwise charge twice the number of things that need
  478. to be saved on a runtime stack. (The return address is one of the
  479. things that needs to be saved.)
  480. @^discussion of \{mems}@>
  481. @<Make |t=g->vertices| the only vertex seen; also make it known@>=
  482. for (oo,t=g->vertices+g->n-1;t>g->vertices;t--) o,t->backlink=NULL;
  483. o,t->backlink=KNOWN;
  484. fragment_size=1;
  485. (*init_queue)(0L); /* make the priority queue empty */
  486. @ @<Put all unseen vertices adjacent to |t| into the queue,
  487.       and update the distances of the other vertices adjacent to~|t|@>=
  488. {@+register Arc *a; /* an arc leading from |t| */
  489.   for (o,a=t->arcs; a; o,a=a->next) {
  490.     register Vertex *v; /* a vertex adjacent to |t| */
  491.     o,v=a->tip;
  492.     if (o,v->backlink) { /* |v| has already been seen */
  493.       if (v->backlink>KNOWN) {
  494.         if (oo,a->len<v->dist) {
  495.           o,v->backlink=t;
  496.           (*requeue)(v,a->len); /* we found a better way to get there */
  497.         }
  498.       }
  499.     }@+else { /* |v| hasn't been seen before */
  500.       o,v->backlink=t;
  501.       o,(*enqueue)(v,a->len);
  502.     }
  503.   }
  504. }
  505. @*Binary heaps.
  506. To complete the |jar_pr| routine, we need to fill in the four
  507. priority queue functions. Jarn{'i}k wrote his original paper before
  508. computers were known; Prim and Dijkstra wrote theirs before efficient priority
  509. queue algorithms were known. Their original algorithms therefore
  510. took $Theta(n^2)$ steps. 
  511. Kerschenbaum and Van Slyke pointed out in 1972 that binary heaps could
  512. @^Kerschenbaum, A.@>
  513. @^Van Slyke, Richard Maurice@>
  514. do better. A simplified version of binary heaps (invented by Williams
  515. @^Williams, John William Joseph@>
  516. in 1964) is presented here.
  517. A binary heap is an array of $n$ elements, and we need space for it.
  518. Fortunately the space is already there; we can use utility field
  519. |u| in each of the vertex records of the graph. Moreover, if
  520. |heap_elt(i)| points to vertex~|v|, we will arrange things so that
  521. |v->heap_index=i|.
  522. @d heap_elt(i) (gv+i)->u.V /* the |i|th vertex of the heap; |gv=g->vertices| */
  523. @d heap_index v.I
  524.  /* the |v| utility field says where a vertex is in the heap */
  525. @<Glob...@>=
  526. Vertex *gv; /* |g->vertices|, the base of the heap array */
  527. long hsize; /* the number of elements currently in the heap */
  528. @ To initialize the heap, we need only initialize two ``registers'' to
  529. known values, so we don't have to charge any mems at all. (In a production
  530. implementation, this code would appear in-line as part of the
  531. spanning tree algorithm.)
  532. @^discussion of \{mems}@>
  533. Important Note: This routine refers to the global variable |g|, which is
  534. set in |main| (not in |jar_pr|). Suitable changes need to be made
  535. if these binary heap routines are used in other programs.
  536. @<Priority queue subroutines@>=
  537. void init_heap(d) /* makes the heap empty */
  538.   long d;
  539. {
  540.   gv=g->vertices;
  541.   hsize=0;
  542. }
  543. @ The key invariant property that makes heaps work is
  544. $$hbox{|heap_elt(k/2)->dist<=heap_elt(k)->dist|, qquad for |1<k<=hsize|.}$$
  545. (A reader who has not seen heap ordering before should stop at this
  546. point and study the beautiful consequences of this innocuously simple
  547. set of inequalities.) The enqueueing operation turns out to be quite simple:
  548. @<Priority queue subroutines@>=
  549. void enq_heap(v,d)
  550.   Vertex *v; /* vertex that is entering the queue */
  551.   long d; /* its key (aka |dist|) */
  552. {@+register unsigned long k; /* position of a ``hole'' in the heap */
  553.   register unsigned long j; /* the parent of that position */
  554.   register Vertex *u; /* |heap_elt(j)| */
  555.   o,v->dist=d;
  556.   k=++hsize;
  557.   j=k>>1; /* |k/2| */
  558.   while (j>0 && (oo,(u=heap_elt(j))->dist>d)) {
  559.     o,heap_elt(k)=u; /* the hole moves to parent position */
  560.     o,u->heap_index=k;
  561.     k=j;
  562.     j=k>>1;
  563.   }
  564.   o,heap_elt(k)=v;
  565.   o,v->heap_index=k;
  566. }
  567. @ And in fact, the general requeueing operation is almost identical to
  568. enqueueing.  This operation is popularly called ``siftup,'' because
  569. the vertex whose key is being reduced may displace its ancestors
  570. higher in the heap. We could have implemented enqueueing by first
  571. placing the new element at the end of the heap, then requeueing it;
  572. that would have cost at most a couple mems more.
  573. @<Priority queue subroutines@>=
  574. void req_heap(v,d)
  575.   Vertex *v; /* vertex whose key is being reduced */
  576.   long d; /* its new |dist| */
  577. {@+register unsigned long k; /* position of a ``hole'' in the heap */
  578.   register unsigned long j; /* the parent of that position */
  579.   register Vertex *u; /* |heap_elt(j)| */
  580.   o,v->dist=d;
  581.   o,k=v->heap_index; /* now |heap_elt(k)=v| */
  582.   j=k>>1; /* |k/2| */
  583.   if (j>0 && (oo,(u=heap_elt(j))->dist>d)) { /* change is needed */
  584.     do@+{
  585.       o,heap_elt(k)=u; /* the hole moves to parent position */
  586.       o,u->heap_index=k;
  587.       k=j;
  588.       j=k>>1; /* |k/2| */
  589.     }@+while (j>0 && (oo,(u=heap_elt(j))->dist>d));
  590.     o,heap_elt(k)=v;
  591.     o,v->heap_index=k;
  592.   }
  593. }
  594. @ Finally, the procedure for removing the vertex with smallest key is
  595. only a bit more difficult. The vertex to be removed is always
  596. |heap_elt(1)|. After we delete it, we ``sift down'' |heap_elt(hsize)|,
  597. until the basic heap inequalities hold once again.
  598. At a crucial point in this process, we have |j->dist<u->dist|. We cannot
  599. then have
  600. |j=hsize+1|, because the previous steps have made |(hsize+1)->dist=u->dist=d|.
  601. @<Prior...@>=
  602. Vertex *del_heap()
  603. {@+Vertex *v; /* vertex to return */
  604.   register Vertex *u; /* vertex being sifted down */
  605.   register unsigned long k; /* hole in the heap */
  606.   register unsigned long j; /* child of that hole */
  607.   register long d; /* |u->dist|, the vertex of the vertex being sifted */
  608.   if (hsize==0) return NULL;
  609.   o,v=heap_elt(1);
  610.   o,u=heap_elt(hsize--);
  611.   o,d=u->dist;
  612.   k=1;
  613.   j=2;
  614.   while (j<=hsize) {
  615.     if (oooo,heap_elt(j)->dist>heap_elt(j+1)->dist) j++;
  616.     if (heap_elt(j)->dist>=d) break;
  617.     o,heap_elt(k)=heap_elt(j); /* NB: we cannot have |j>hsize|, see above */
  618.     o,heap_elt(k)->heap_index=k;
  619.     k=j; /* the hole moves to child position */
  620.     j=k<<1; /* |2k| */
  621.   }
  622.   o,heap_elt(k)=u;
  623.   o,u->heap_index=k;
  624.   return v;
  625. }
  626. @ OK, here's how we plug binary heaps into Jarn{'i}k/Prim.
  627. @<Execute |jar_pr(g)| with binary heaps as the priority queue algorithm@>=
  628. init_queue=init_heap;
  629. enqueue=enq_heap;
  630. requeue=req_heap;
  631. del_min=del_heap;
  632. if (sp_length!=jar_pr(g)) {
  633.   printf(" ...oops, I've got a bug, please fix fix fixn");
  634.   return -4;
  635. }
  636. @*Fibonacci heaps.
  637. The running time of Jarn{'i}k/Prim with binary heaps, when the algorithm is
  638. applied to a connected graph with $n$ vertices and $m$ edges, is $O(mlog n)$,
  639. because the total number of operations is $O(m+n)=O(m)$ and each
  640. heap operation takes at most $O(log n)$ time.
  641. Fibonacci heaps were invented by Fredman and Tarjan in 1984, in order
  642. @^Fibonacci, Leonardo, heaps@>
  643. @^Fredman, Michael Lawrence@>
  644. @^Tarjan, Robert Endre@>
  645. to do better than this. The Jarn{'i}k/Prim algorithm does $O(n)$
  646. enqueueing operations, $O(n)$ delete-min operations, and $O(m)$
  647. requeueing operations; so Fredman and Tarjan designed a data structure
  648. that would support requeueing in ``constant amortized time.'' In other
  649. words, Fibonacci heaps allow us to do $m$ requeueing operations with a
  650. total cost of~$O(m)$, even though some of the individual requeueings
  651. might take longer. The resulting asymptotic running time is then
  652. $O(m+nlog n)$. (This turns out to be optimum within a constant
  653. factor, when the same technique is applied to Dijkstra's algorithm for
  654. shortest paths. But for minimum spanning trees the Fibonacci method is
  655. not always optimum; for example, if $mapprox nsqrt{mathstrutlog n}$, the
  656. algorithm of Cheriton and Tarjan has slightly better asymptotic
  657. behavior, $O(mloglog n)$.)
  658. Fibonacci heaps are more complex than binary heaps, so we can expect
  659. that overhead  costs will make them non-competitive unless $m$ and $n$ are
  660. quite large. Furthermore, it is not clear that the running time with simple
  661. binary heaps will behave as $mlog n$ on realistic data, because
  662. $O(mlog n)$ is a worst-case estimate based on rather pessimistic
  663. assumptions. (For example, requeueing might rarely require many
  664. iterations of the siftup loop.) But it will be instructive to
  665. implement Fibonacci heaps as best we can, just to see how good they
  666. look in actual practice.
  667. Let us say that the {sl rank/} of a node in a forest is the number
  668. of children it has. A Fibonacci heap is an unordered forest of trees
  669. in which the key of each node is less than or equal to the key of each
  670. child of that node, and in which the following further condition,
  671. called property~F, also holds: The ranks ${r_1,r_2,ldots,r_k}$ of the
  672. children of every node of rank~$k$, when put into nondecreasing
  673. order $r_1le r_2lecdotsle r_k$, satisfy $r_jge j-2$ for all~$j$.
  674. As a consequence of property F, we can prove by induction that every
  675. node of rank~$k$ has at least $F_{k+2}$ descendants (including itself).
  676. Therefore, for example, we cannot have a node of rank $ge30$ unless
  677. the total size of the forest is at least $F_{32}=2{,}178{,}309$. We cannot
  678. have a node of rank $ge46$ unless the total size of the forest
  679. exceeds~$2^{32}$.
  680. @ We will represent a Fibonacci heap with a rather elaborate data structure,
  681. in order to guarantee the efficiency of all the necessary operations.
  682. Each node will have four pointers: |parent|, the node's parent (or
  683. |NULL| if the node is a root); |child|, one of the node's children
  684. (or undefined if the node has no children); |lsib| and |rsib|, the
  685. node's left and right siblings. The children of each node, and the
  686. roots of the forest, are doubly linked by |lsib| and |rsib| in
  687. circular lists; the nodes in these lists can appear in any convenient
  688. order, and the |child| pointer can point to any child.
  689. Besides the four pointers, there is a \{rank} field, which tells how
  690. many children exist, and a \{tag} field, which is either 0 or~1.
  691. Suppose a node has children of ranks ${r_1,r_2,ldots,r_k}$, where
  692. $r_1le r_2lecdotsle r_k$. We know that $r_jge j-2$ for all~$j$;
  693. we say that the node has $l$ {sl critical/} children if there are
  694. $l$ cases of equality, where $r_j=j-2$. Our implementation will
  695. guarantee that any node with $l$ critical children will have at
  696. least $l$ tagged children of the corresponding ranks. For example,
  697. suppose a node has seven children, of respective ranks ${1,1,1,2,4,4,6}$.
  698. Then it has three critical children, because $r_3=1$, $r_4=2$, and
  699. $r_6=4$. In our implementation, at least one of the children of
  700. rank~1 will have $\{tag}=1$, and so will the child of rank~2; so will
  701. one of the children of rank~4.
  702. There is an external pointer called |F_heap|, which indicates a node
  703. whose key is smallest. (If the heap is empty, |F_heap| is~|NULL|.)
  704. @<Prior...@>=
  705. void init_F_heap(d)
  706.   long d;
  707. {@+F_heap=NULL;@+}
  708. @ @<Glob...@>=
  709. Vertex *F_heap; /* pointer to the ring of root nodes */
  710. @ We can save a bit of space and time by combining the \{rank} and \{tag}
  711. fields into a single |rank_tag| field, which contains $\{rank}*2+\{tag}$.
  712. Vertices in GraphBase graphs have six utility fields. That's just enough
  713. for |parent|, |child|, |lsib|, |rsib|, |rank_tag|, and the key field
  714. |dist|. But unfortunately we also need the |backlink| field, so
  715. we are over the limit. That's not really so bad, however; we
  716. can set up another array of $n$ records, and point to it. The
  717. extra running time needed for indirect pointing does not have to
  718. be charged to mems, because a production system involving Fibonacci
  719. heaps would simply redefine |Vertex| records to have seven utility
  720. fields instead of six. In this way we can simulate the behavior of larger
  721. records without changing the basic GraphBase conventions.
  722. @^discussion of \{mems}@>
  723. We will want an |Arc| record for each vertex in our next algorithm,
  724. so we might as well allocate storage for it now even though Fibonacci
  725. heaps need only two of the five fields.
  726. @d newarc u.A /* |v->newarc| points to an |Arc| record associated with |v| */
  727. @d parent newarc->tip
  728. @d child newarc->a.V
  729. @d lsib v.V
  730. @d rsib w.V
  731. @d rank_tag x.I
  732. @<Allocate additional space needed by the more complex algorithms...@>=
  733. {@+register Arc *aa;
  734.   register Vertex *uu;
  735.   aa=gb_typed_alloc(g->n,Arc,g->aux_data);
  736.   if (aa==NULL) {
  737.     printf(" and there isn't enough space to try the other methods.nn");
  738.     goto done;
  739.   }
  740.   for (uu=g->vertices;uu<g->vertices+g->n;uu++,aa++)
  741.     uu->newarc=aa;
  742. }
  743. @ The {sl potential energy/} of a Fibonacci heap, as we are
  744. representing it, is defined to be the number of trees in the forest
  745. plus twice the total number of tagged children. When we operate on a
  746. heap, we will store potential energy to be used up later; then it will
  747. be possible to do the later operations with only a small incremental
  748. cost to the running time. (Potential energy is just a way to prove
  749. that the amortized cost is small; it does not appear explicitly in our
  750. implementation. It simply explains why the number of mems we compute
  751. will always be $O(m+nlog n)$.)
  752. Enqueueing is easy: We simply insert the new element as a new tree in
  753. the forest. This costs a constant amount of time, including the cost of
  754. one new unit of potential energy for the new tree.
  755. We can assume that |F_heap->dist| appears in a register, so we need not
  756. charge a mem to fetch~it.
  757. @<Prior...@>=
  758. void enq_F_heap(v,d)
  759.   Vertex *v; /* vertex that is entering the queue */
  760.   long d; /* its key (aka |dist|) */
  761. {
  762.   o,v->dist=d;
  763.   o,v->parent=NULL;
  764.   o,v->rank_tag=0; /* |v->child| need not be set */
  765.   if (F_heap==NULL) {
  766.     oo,F_heap=v->lsib=v->rsib=v;
  767.   }@+else {@+register Vertex *u;
  768.     o,u=F_heap->lsib;
  769.     o,v->lsib=u;
  770.     o,v->rsib=F_heap;
  771.     oo,F_heap->lsib=u->rsib=v;
  772.     if (F_heap->dist>d) F_heap=v;
  773.   }
  774. }
  775. @ Requeueing is of medium difficulty. If the key is being decreased in
  776. a root node, or if the decrease doesn't make the key less than the key
  777. of its parent, no links need to change (except possibly |F_heap|
  778. itself). Otherwise we detach the node and its descendants from its
  779. present family and put this former subtree into the forest as a new
  780. tree. (One unit of potential energy must be stored with it.)
  781. The rank of the former parent, |p|, decreases by~1. If |p| is a root,
  782. we're done. Otherwise if |p| was not tagged, we tag it (and pay for
  783. two additional units of energy). Property~F still holds, because an
  784. untagged node can always admit a decrease in rank. If |p| was tagged,
  785. however, we detach |p| and its remaining descendants, making it another
  786. new tree of the forest, with |p| no longer tagged. Removing the tag
  787. releases enough stored energy to pay for the extra work of moving~|p|.
  788. Then we must decrease the rank of |p|'s parent, and so on, until finally
  789. we get to a root or to an untagged node. The total net cost is at most
  790. three units of energy plus the cost of relinking the original node,
  791. so it is $O(1)$.
  792. We needn't clear the tag fields of root nodes, because we never
  793. look at them.
  794. @<Prior...@>=
  795. void req_F_heap(v,d)
  796.   Vertex *v; /* vertex whose key is being reduced */
  797.   long d; /* its new |dist| */
  798. {@+register Vertex *p,*pp; /* parent and grandparent of |v| */
  799.   register Vertex *u,*w; /* other vertices being modified */
  800.   register long r; /* twice the rank plus the tag */
  801.   o,v->dist=d;
  802.   o,p=v->parent;
  803.   if (p==NULL) {
  804.     if (F_heap->dist>d) F_heap=v;
  805.   }@+else if (o,p->dist>d)
  806.     while(1) {
  807.       o,r=p->rank_tag;
  808.       if (r>=4) /* |v| is not an only child */
  809.         @<Remove |v| from its family@>;
  810.       @<Insert |v| into the forest@>;
  811.       o,pp=p->parent;
  812.       if (pp==NULL) { /* the parent of |v| is a root */
  813.         o,p->rank_tag=r-2;@+break;
  814.       }
  815.       if ((r&1)==0) { /* the parent of |v| is untagged */
  816.         o,p->rank_tag=r-1;@+break; /* now it's tagged */
  817.       }@+else o,p->rank_tag=r-2; /* tagged parent will become a root */
  818.       v=p;@+p=pp;
  819.     }
  820. }
  821. @ @<Remove |v| from its family@>=
  822. {
  823.   o,u=v->lsib;
  824.   o,w=v->rsib;
  825.   o,u->rsib=w;
  826.   o,w->lsib=u;
  827.   if (o,p->child==v) o,p->child=w;
  828. }
  829. @ @<Insert |v| into the forest@>=
  830. o,v->parent=NULL;
  831. o,u=F_heap->lsib;
  832. o,v->lsib=u;
  833. o,v->rsib=F_heap;
  834. oo,F_heap->lsib=u->rsib=v;
  835. if (F_heap->dist>d) F_heap=v; /* this can happen only with the original |v| */
  836. @ The |del_min| operation is even more interesting; this, in fact,
  837. is where most of the action lies. We know that |F_heap| points to the
  838. vertex~$v$ we will be deleting. That's nice, but we need to figure out
  839. the new value of |F_heap|. So we have to look at all the children of~$v$
  840. and at all the root nodes in the forest. We have stored up enough
  841. potential energy to do that, but we can reclaim the potential only if
  842. we rebuild the Fibonacci heap so that the rebuilt version contains
  843. relatively few trees.
  844. The solution is to make sure that the new heap has at most one root
  845. of each rank. Whenever we have two tree roots of equal rank, we can
  846. make one the child of the other, thus reducing the number of
  847. trees by~1. (The new child does not violate Property~F, nor is it
  848. critical, so we can mark it untagged.) The largest rank is always
  849. $O(log n)$, if there are $n$ nodes altogether, and we can afford to
  850. pay $log n$ units of time for the work that isn't reclaimed from
  851. potential energy.
  852. An array of pointers to roots of known rank is used to help control
  853. this part of the process.
  854. @<Glob...@>=
  855. Vertex *new_roots[46]; /* big enough for queues of size $2^{32}$ */
  856. @ @<Prio...@>=
  857. Vertex *del_F_heap()
  858. {@+Vertex *final_v=F_heap; /* the node to return */
  859.   register Vertex *t,*u,*v,*w; /* registers for manipulation of links */
  860.   register long h=-1; /* the highest rank present in |new_roots| */
  861.   register long r; /* rank of current tree */
  862.   if (F_heap) {
  863.     if (o,F_heap->rank_tag<2) o,v=F_heap->rsib;
  864.     else {
  865.       o,w=F_heap->child;
  866.       o,v=w->rsib;
  867.       oo,w->rsib=F_heap->rsib;
  868.         /* link children of deleted node into the list */
  869.       for (w=v;w!=F_heap->rsib;o,w=w->rsib)
  870.         o,w->parent=NULL;
  871.     }
  872.     while (v!=F_heap) {
  873.       o,w=v->rsib;
  874.       @<Put the tree rooted at |v| into the |new_roots| forest@>;
  875.       v=w;
  876.     }
  877.     @<Rebuild |F_heap| from |new_roots|@>;
  878.   }
  879.   return final_v;
  880. }
  881. @ The work we do in this step is paid for by the unit of potential
  882. energy being freed as |v| leaves the old forest, except for the
  883. work of increasing~|h|; we charge the latter to the $O(log n)$ cost of
  884. building |new_roots|.
  885. @<Put the tree rooted at |v| into the |new_roots| forest@>=
  886. o,r=v->rank_tag>>1;
  887. while (1) {
  888.   if (h<r) {
  889.     do@+{
  890.       h++;
  891.       o,new_roots[h]=(h==r?v:NULL);
  892.     }@+while (h<r);
  893.     break;
  894.   }
  895.   if (o,new_roots[r]==NULL) {
  896.     o,new_roots[r]=v;
  897.     break;
  898.   }
  899.   u=new_roots[r];
  900.   o,new_roots[r]=NULL;
  901.   if (oo,u->dist<v->dist) {
  902.     o,v->rank_tag=r<<1; /* |v| is not critical and needn't be tagged */
  903.     t=u;@+u=v;@+v=t;
  904.   }
  905.   @<Make |u| a child of |v|@>;
  906.   r++;
  907. }
  908. o,v->rank_tag=r<<1; /* every root in |new_roots| is untagged */
  909. @ When we get to this step, |u| and |v| both have rank |r|, and
  910. |u->dist>=v->dist|; |u| is untagged.
  911. @<Make |u| a child of |v|@>=
  912. if (r==0) {
  913.   o,v->child=u;
  914.   oo,u->lsib=u->rsib=u;
  915. }@+else {
  916.   o,t=v->child;
  917.   oo,u->rsib=t->rsib;
  918.   o,u->lsib=t;
  919.   oo,u->rsib->lsib=t->rsib=u;
  920. }
  921. u->parent=v;
  922. @ And now we can breathe easy, because the last step is trivial.
  923. @<Rebuild |F_heap| from |new_roots|@>=
  924. if (h<0) F_heap=NULL;
  925. else {@+long d; /* smallest key value seen so far */
  926.   o,u=v=new_roots[h];
  927.    /* |u| and |v| will point to beginning and end of list, respectively */
  928.   o,d=u->dist;
  929.   F_heap=u;
  930.   for (h--;h>=0;h--)
  931.     if (o,new_roots[h]) {
  932.       w=new_roots[h];
  933.       o,w->lsib=v;
  934.       o,v->rsib=w;
  935.       if (o,w->dist<d) {
  936.         F_heap=w;
  937.         d=w->dist;
  938.       }
  939.       v=w;
  940.     }
  941.   o,v->rsib=u;
  942.   o,u->lsib=v;
  943. }
  944. @ @<Execute |jar_pr(g)| with Fibonacci heaps...@>=
  945. init_queue=init_F_heap;
  946. enqueue=enq_F_heap;
  947. requeue=req_F_heap;
  948. del_min=del_F_heap;
  949. if (sp_length!=jar_pr(g)) {
  950.   printf(" ...oops, I've got a bug, please fix fix fixn");
  951.   return -5;
  952. }
  953. @*Binomial queues.
  954. Jean Vuillemin's ``binomial queue'' structures [{sl CACM/ bf21} (1978),
  955. @^Vuillemin, Jean Etienne@>
  956. 309--314] provide yet another appealing way to maintain priority queues.
  957. A binomial queue is a forest of trees with keys ordered as in Fibonacci
  958. heaps, satisfying two conditions that are considerably stronger than
  959. the Fibonacci heap property: Each node of rank~$k$ has children of
  960. respective ranks ${0,1,ldots,k-1}$; and each root of the forest
  961. has a different rank. It follows that each node of rank~$k$ has exactly
  962. $2^k$ descendants (including itself), and that a binomial queue of
  963. $n$ elements has exactly as many trees as the number $n$ has 1's in
  964. binary notation.
  965. We could plug binomial queues into the Jarn{'i}k/Prim algorithm, but
  966. they don't offer advantages over the heap methods already considered
  967. because they don't support the requeueing operation as nicely.
  968. Binomial queues do, however, permit efficient merging---the operation
  969. of combining two priority queues into one---and they achieve this
  970. without as much space overhead as Fibonacci heaps. In fact, we can
  971. implement binomial queues with only two pointers per node, namely a
  972. pointer to the largest child and another to the next sibling. This means we
  973. have just enough space in the utility fields of GraphBase |Arc| records
  974. to link the arcs that extend out of a spanning tree fragment. The
  975. algorithm of Cheriton, Tarjan, and Karp, which we will consider
  976. soon, maintains priority queues of arcs, not vertices; and it
  977. requires the operation of merging, not requeueing. Therefore binomial
  978. queues are well suited to it, and we will prepare ourselves for that
  979. algorithm by implementing basic binomial queue procedures.
  980. Incidentally, if you wonder why Vuillemin called his structure a
  981. binomial queue, it's because the trees of $2^k$ elements have many
  982. pleasant combinatorial properties, among which is the fact that the
  983. number of elements on level~$l$ is the binomial coefficient~$kchoose
  984. l$. The backtrack tree for subsets of a $k$-set has the same
  985. structure. A picture of a binomial-queue tree with $k=5$, drawn by
  986. @^Knuth, Nancy Jill Carter@>
  987. Jill~C. Knuth, appears as the frontispiece of {sl The Art of Computer
  988. Programming}, facing page~1 of Volume~1.
  989. @d qchild a.A /* pointer to the arc for largest child of an arc */
  990. @d qsib b.A /* pointer to next larger sibling, or from largest to smallest */
  991. @ A special header node is used at the head of a binomial queue, to represent
  992. the queue itself. The |qsib| field of this node points to the smallest
  993. root node in the forest. (``Smallest'' means smallest in rank, not in
  994. key value.) The header also contains a |qcount| field, which
  995. takes the place of |qchild|; the |qcount| is the total number of nodes,
  996. so its binary representation characterizes the sizes of the trees
  997. accessible from |qsib|.
  998. For example, suppose a queue with header node |h| contains five elements
  999. ${a,b,c,d,e}$ whose keys happen to be ordered alphabetically. The first
  1000. tree might be the single node~$c$; the other tree might be rooted at~$a$,
  1001. with children $e$ and~$b$. Then we have
  1002. $$vbox{halign{#hfil&qquad#hfilcr
  1003. |h->qcount=5|,&|h->qsib=c|;cr
  1004. |c->qsib=a|;cr
  1005. |a->qchild=b|;cr
  1006. |b->qchild=d|,&|b->qsib=e|;cr
  1007. |e->qsib=b|.cr}}$$
  1008. The other fields |c->qchild|, |a->qsib|, |e->qchild|, |d->qsib|, and
  1009. |d->qchild| are undefined. We can save time by not loading or storing the
  1010. undefined fields, which make up about 3/8 of the structure.
  1011. An empty binomial queue would have |h->qcount=0| and |h->qsib| undefined.
  1012. Like Fibonacci heaps, binomial queues store potential energy: The
  1013. number of energy units present is simply the number of trees in the forest.
  1014. @d qcount a.I /* this field takes the place of |qchild| in header nodes */
  1015. @ Most of the operations we want to do with binomial queues rely on
  1016. the following basic subroutine, which merges a forest of |m| nodes
  1017. starting at |q| with a forest of |mm| nodes starting at |qq|, putting
  1018. a pointer to the resulting forest of |m+mm| nodes into |h->qsib|.
  1019. The amortized running time is $O(log m)$, independent of |mm|.
  1020. The |len| field, not |dist|, is the key field for this queue, because our
  1021. nodes in this case are arcs instead of vertices.
  1022. @<Prio...@>=
  1023. qunite(m,q,mm,qq,h)
  1024.   register long m,mm; /* number of nodes in the forests */
  1025.   register Arc *q,*qq; /* binomial trees in the forests, linked by |qsib| */
  1026.   Arc *h; /* |h->qsib| will get the result */
  1027. {@+register Arc *p; /* tail of the list built so far */
  1028.   register long k=1; /* size of trees currently being processed */
  1029.   p=h;
  1030.   while (m) {
  1031.     if ((m&k)==0) {
  1032.       if (mm&k) { /* |qq| goes into the merged list */
  1033.         o,p->qsib=qq;@+p=qq;@+mm-=k;
  1034.         if (mm) o,qq=qq->qsib;
  1035.       }
  1036.     }@+else if ((mm&k)==0) { /* |q| goes into the merged list */
  1037.       o,p->qsib=q;@+p=q;@+m-=k;
  1038.       if (m) o,q=q->qsib;
  1039.     }@+else @<Combine |q| and |qq| into a ``carry'' tree, and continue
  1040.              merging until the carry no longer propagates@>;
  1041.     k<<=1;
  1042.   }
  1043.   if (mm) o,p->qsib=qq;
  1044. }
  1045.     
  1046. @ As we have seen in Fibonacci heaps, two heap-ordered trees can be combined
  1047. by simply attaching one as a new child of the other. This operation preserves
  1048. binomial trees. (In fact, if we use Fibonacci heaps without ever doing
  1049. a requeue operation, the forests that appear after every |del_min|
  1050. are binomial queues.) The number of trees decreases by~1, so we have a
  1051. unit of potential energy to pay for this computation.
  1052. @<Combine |q| and |qq| into a ``carry'' tree, and continue
  1053.              merging until the carry no longer propagates@>=
  1054. {@+register Arc *c; /* the ``carry,'' a tree of size |2k| */
  1055.   register long key; /* |c->len| */
  1056.   register Arc *r,*rr; /* remainders of the input lists */
  1057.   m-=k;@+if (m) o,r=q->qsib;
  1058.   mm-=k;@+if (mm) o,rr=qq->qsib;
  1059.   @<Set |c| to the combination of |q| and |qq|@>;
  1060.   k<<=1;@+q=r;@+qq=rr;
  1061.   while ((m|mm)&k) {
  1062.     if ((m&k)==0) @<Merge |qq| into |c| and advance |qq|@>@;
  1063.     else {
  1064.       @<Merge |q| into |c| and advance |q|@>;
  1065.       if (mm&k) {
  1066.         o,p->qsib=qq;@+p=qq;@+mm-=k;
  1067.         if (mm) o,qq=qq->qsib;
  1068.       }
  1069.     }
  1070.     k<<=1;
  1071.   }
  1072.   o,p->qsib=c;@+p=c;
  1073. }
  1074. @ @<Set |c| to the combination of |q| and |qq|@>=
  1075. if (oo,q->len<qq->len) {
  1076.   c=q,key=q->len;
  1077.   q=qq;
  1078. }@+else c=qq,key=qq->len;
  1079. if (k==1) o,c->qchild=q;
  1080. else {
  1081.   o,qq=c->qchild;
  1082.   o,c->qchild=q;
  1083.   if (k==2) o,q->qsib=qq;
  1084.   else oo,q->qsib=qq->qsib;
  1085.   o,qq->qsib=q;
  1086. }
  1087. @ At this point, |k>1|.
  1088. @<Merge |q| into |c| and advance |q|@>=
  1089. {
  1090.   m-=k;@+if (m) o,r=q->qsib;
  1091.   if (o,q->len<key) {
  1092.     rr=c;@+c=q;@+key=q->len;@+q=rr;
  1093.   }
  1094.   o,rr=c->qchild;
  1095.   o,c->qchild=q;
  1096.   if (k==2) o,q->qsib=rr;
  1097.   else oo,q->qsib=rr->qsib;
  1098.   o,rr->qsib=q;
  1099.   q=r;
  1100. }
  1101. @ @<Merge |qq| into |c| and advance |qq|@>=
  1102. {
  1103.   mm-=k;@+if (mm) o,rr=qq->qsib;
  1104.   if (o,qq->len<key) {
  1105.     r=c;@+c=qq;@+key=qq->len;@+qq=r;
  1106.   }
  1107.   o,r=c->qchild;
  1108.   o,c->qchild=qq;
  1109.   if (k==2) o,qq->qsib=r;
  1110.   else oo,qq->qsib=r->qsib;
  1111.   o,r->qsib=qq;
  1112.   qq=rr;
  1113. }
  1114. @ OK, now the hard work is done and we can reap the benefits of the
  1115. basic |qunite| routine. One easy application enqueues a new arc
  1116. in $O(1)$ amortized time.
  1117. @<Prio...@>=
  1118. qenque(h,a)
  1119.   Arc *h; /* header of a binomial queue */
  1120.   Arc *a; /* new element for that queue */
  1121. {@+long m;
  1122.   o,m=h->qcount;
  1123.   o,h->qcount=m+1;
  1124.   if (m==0) o,h->qsib=a;
  1125.   else o,qunite(1L,a,m,h->qsib,h);
  1126. }
  1127. @ Here, similarly, is a routine that merges one binomial queue into
  1128. another. The amortized running time is proportional to the logarithm
  1129. of the number of nodes in the smaller queue.
  1130. @<Prio...@>=
  1131. qmerge(h,hh)
  1132.   Arc *h; /* header of binomial queue that will receive the result */
  1133.   Arc *hh; /* header of binomial queue that will be absorbed */
  1134. {@+long m,mm;
  1135.   o,mm=hh->qcount;
  1136.   if (mm) {
  1137.     o,m=h->qcount;
  1138.     o,h->qcount=m+mm;
  1139.     if (m>=mm) oo,qunite(mm,hh->qsib,m,h->qsib,h);
  1140.     else if (m==0) oo,h->qsib=hh->qsib;
  1141.     else oo,qunite(m,h->qsib,mm,hh->qsib,h);
  1142.   }
  1143. @ The other important operation is, of course, deletion of a node
  1144. with the smallest key. The amortized running time is proportional to
  1145. the logarithm of the queue size.
  1146. @<Prio...@>=
  1147. Arc *qdel_min(h)
  1148.   Arc *h; /* header of binomial queue */
  1149. {@+register Arc *p,*pp; /* current node and its predecessor */
  1150.   register Arc *q,*qq; /* current minimum node and its predecessor */
  1151.   register long key; /* |q->len|, the smallest key known so far */
  1152.   long m; /* number of nodes in the queue */
  1153.   long k; /* number of nodes in tree |q| */
  1154.   register long mm; /* number of nodes not yet considered */
  1155.   o,m=h->qcount;
  1156.   if (m==0) return NULL;
  1157.   o,h->qcount=m-1;
  1158.   @<Find and remove a tree whose root |q| has the smallest key@>;
  1159.   if (k>2) {
  1160.     if (k+k<=m) oo,qunite(k-1,q->qchild->qsib,m-k,h->qsib,h);
  1161.     else oo,qunite(m-k,h->qsib,k-1,q->qchild->qsib,h);
  1162.   }@+else if (k==2) o,qunite(1L,q->qchild,m-k,h->qsib,h);
  1163.   return q;
  1164. }
  1165. @ If the tree with smallest key is the largest in the forest,
  1166. we don't have to change any links to remove it,
  1167. because our binomial queue algorithms never look at the last |qsib| pointer.
  1168. We use a well-known binary number trick: |m&(m-1)| is the same as
  1169. |m|, except that the least significant 1~bit is deleted.
  1170. @<Find and remove...@>=    
  1171. mm=m&(m-1);
  1172. o,q=h->qsib;
  1173. k=m-mm;
  1174. if (mm) { /* there's more than one tree */
  1175.   p=q;@+qq=h;
  1176.   o,key=q->len;
  1177.   do@+{@+long t=mm&(mm-1);
  1178.     pp=p;@+o,p=p->qsib;
  1179.     if (o,p->len<=key) {
  1180.       q=p;@+qq=pp;@+k=mm-t;@+key=p->len;
  1181.     }
  1182.     mm=t;
  1183.   }@+while (mm);
  1184.   if (k+k<=m) oo,qq->qsib=q->qsib; /* remove the tree rooted at |q| */
  1185. }
  1186. @ To complete our implementation, here is an algorithm that traverses
  1187. a binomial queue, ``visiting'' each node exactly once, destroying the
  1188. queue as it goes. The total number of mems required is about |1.75m|.
  1189. @<Prio...@>=
  1190. qtraverse(h,visit)
  1191.   Arc *h; /* head of binomial queue to be unraveled */
  1192.   void @[@] (*visit)(); /* procedure to be invoked on each node */
  1193. {@+register long m; /* the number of nodes remaining */
  1194.   register Arc *p,*q,*r; /* current position and neighboring positions */
  1195.   o,m=h->qcount;
  1196.   p=h;
  1197.   while (m) {
  1198.     o,p=p->qsib;
  1199.     (*visit)(p);
  1200.     if (m&1) m--;
  1201.     else {
  1202.       o,q=p->qchild;
  1203.       if (m&2) (*visit)(q);
  1204.       else {
  1205.         o,r=q->qsib;
  1206.         if (m&(m-1)) oo,q->qsib=p->qsib;
  1207.         (*visit)(r);
  1208.         p=r;
  1209.       }
  1210.       m-=2;
  1211.     }
  1212.   }
  1213. }
  1214. @* Cheriton, Tarjan, and Karp's algorithm.
  1215. deflsqrtn{hbox{$lfloorsqrt n,rfloor$}}%
  1216. defusqrtn{hbox{$lfloorsqrt{n+1}+{1over2}rfloor$}}%
  1217. The final algorithm we shall consider takes yet another approach to
  1218. spanning tree minimization. It operates in two distinct stages: Stage~1
  1219. creates small fragments of the minimum tree, working locally with the
  1220. edges that lead out of each fragment instead of dealing with the
  1221. full set of edges at once as in Kruskal's method. As soon as the
  1222. number of component fragments has been reduced from $n$ to lsqrtn,
  1223. stage~2 begins. Stage~2 runs through the remaining edges and builds a
  1224. $lsqrtntimeslsqrtn$ matrix, which represents the problem of
  1225. finding a minimum spanning tree on the remaining lsqrtn components.
  1226. A simple $O(sqrt n,)^2=O(n)$ algorithm then completes the job.
  1227. The philosophy underlying stage~1 is that an edge leading out of a
  1228. vertex in a small component is likely to lead to a vertex in another
  1229. component, rather than in the same one. Thus each delete-min operation
  1230. tends to be productive. Karp and Tarjan proved [{sl Journal of Algorithms/
  1231. @^Karp, Richard Manning@>
  1232. @^Tarjan, Robert Endre@>
  1233. bf1} (1980), 374--393] that the average running time on a random graph with
  1234. $n$ vertices and $m$ edges will be $O(m)$.
  1235. The philosophy underlying stage~2 is that the problem
  1236. on an initially sparse graph eventually reduces to a problem on a smaller
  1237. but dense graph that is best solved by a different method.
  1238. @<Sub...@>=
  1239. unsigned long cher_tar_kar(g)
  1240.   Graph *g;
  1241. {@+@<Local variables for |cher_tar_kar|@>@;@#
  1242.   mems=0;
  1243.   @<Do stage 1 of |cher_tar_kar|@>;
  1244.   if (verbose) printf("    [Stage 1 has used %ld mems]n",mems);
  1245.   @<Do stage 2 of |cher_tar_kar|@>;
  1246.   return tot_len;
  1247. }
  1248. @ We say that a fragment is {sl large} if it contains usqrtn or more
  1249. vertices. As soon as a fragment becomes large, stage~1 stops trying
  1250. to extend it. There cannot be more than lsqrtn large fragments,
  1251. because $(lsqrtn+1)usqrtn>n$. The other fragments are called {sl small}.
  1252. Stage~1 keeps a list of all the small fragments. Initially this list
  1253. contains $n$ fragments consisting of one vertex each. The algorithm
  1254. repeatedly looks at the first fragment on its list, and finds the
  1255. smallest edge leading to another fragment. These two fragments are
  1256. removed from the list and combined. The resulting fragment is put at
  1257. the end of the list if it is still small, or put onto another list if
  1258. it is large.
  1259. @<Local variables for |ch...@>=
  1260. register Vertex *s,*t; /* beginning and end of the small list */
  1261. Vertex *large_list; /* beginning of the list of large fragments */
  1262. long frags; /* current number of fragments, large and small */
  1263. unsigned long tot_len=0; /* total length of all edges in fragments */
  1264. register Vertex *u,*v; /* registers for list manipulation */
  1265. register Arc *a; /* and another */
  1266. register long j,k; /* index registers for stage 2 */
  1267. @ We need to make |lo_sqrt| global so that the |note_edge| procedure
  1268. below can access it.
  1269. @<Glob...@>=
  1270. long lo_sqrt,hi_sqrt; /* lsqrtn and usqrtn */
  1271. @ There is a nonobvious way to compute usqrtn and lsqrtn. Since
  1272. $sqrt n$ is small and arithmetic is mem-free, the author
  1273. couldn't resist writing the |for| loop shown here.
  1274. Of course, different ground rules for counting mems would be
  1275. appropriate if this sort of computing were a critical factor in
  1276. the running time.
  1277. @^discussion of \{mems}@>
  1278. @<Do stage 1 of |cher_tar_kar|@>=
  1279. o,frags=g->n;
  1280. for (hi_sqrt=1;hi_sqrt*(hi_sqrt+1)<=frags;hi_sqrt++) ;
  1281. if (hi_sqrt*hi_sqrt<=frags) lo_sqrt=hi_sqrt;
  1282. else lo_sqrt=hi_sqrt-1;
  1283. large_list=NULL;
  1284. @<Create the small list@>;
  1285. while (frags>lo_sqrt) {
  1286.   @<Combine the first fragment on the small list with its nearest neighbor@>;
  1287.   frags--;
  1288. }
  1289. @ To represent fragments, we will use several utility fields already
  1290. defined above. The |lsib| and |rsib| pointers are used between fragments
  1291. in the small list, which is doubly linked; |s|~points to the first small
  1292. fragment, |s->rsib| to the next, dots, |t->lsib| to the second-from-last,
  1293. and |t| to the last. The pointer fields |s->lsib| and |t->rsib| are
  1294. undefined. The |large_list| is singly linked via |rsib| pointers,
  1295. terminating with |NULL|.
  1296. The |csize| field of each fragment tells how many vertices it contains.
  1297. The |comp| field of each vertex is |NULL| if this vertex represents a
  1298. fragment (i.e., if this vertex is in the small list or |large_list|);
  1299. otherwise it points to another vertex that is closer to the fragment
  1300. representative.
  1301. Finally, the |pq| pointer of each fragment points to the header node of
  1302. its priority queue, which is a binomial queue containing all
  1303. unlooked-at arcs that originate from vertices in the fragment.
  1304. This pointer is identical to the |newarc| pointer already set up.
  1305. In a production implementation, we wouldn't need |pq| as a
  1306. separate field; it would be part of a vertex record. So we do not
  1307. pay any mems for referring to it.
  1308. @^discussion of \{mems}@>
  1309. @d pq newarc
  1310. @<Create the small...@>=
  1311. o,s=g->vertices;
  1312. for (v=s;v<s+frags;v++) {
  1313.   if (v>s) {
  1314.     o,v->lsib=v-1;@+o,(v-1)->rsib=v;
  1315.   }
  1316.   o,v->comp=NULL;
  1317.   o,v->csize=1;
  1318.   o,v->pq->qcount=0; /* the binomial queue is initially empty */
  1319.   for (o,a=v->arcs;a;o,a=a->next) qenque(v->pq,a);
  1320. }
  1321. t=v-1;
  1322. @ @<Combine the first fragment...@>=
  1323. v=s;
  1324. o,s=s->rsib; /* remove |v| from small list */
  1325. do@+{a=qdel_min(v->pq);
  1326.   if (a==NULL) return INFINITY; /* the graph isn't connected */
  1327.   o,u=a->tip;
  1328.   while (o,u->comp) u=u->comp; /* find the fragment pointed to */
  1329. }@+while (u==v); /* repeat until a new fragment is found */
  1330. if (verbose) @<Report the new edge verbosely@>;
  1331. o,tot_len+=a->len;
  1332. o,v->comp=u;
  1333. qmerge(u->pq,v->pq);
  1334. o,old_size=u->csize;
  1335. o,new_size=old_size+v->csize;
  1336. o,u->csize=new_size;
  1337. @<Move |u| to the proper list position@>;
  1338. @ @<Local variables for |cher...@>=
  1339. long old_size,new_size; /* size of fragment |u|, before and after */
  1340. @ Here is a fussy part of the program. We have just merged the small
  1341. fragment |v| into another fragment~|u|. If |u| was already large,
  1342. there's nothing to do (except to check if the small list has just
  1343. become empty). Otherwise we need to move |u| to the end of the small
  1344. list, or we need to put it onto the large list.
  1345. All these cases are special, if we
  1346. want to avoid unnecessary memory references; so let's hope we get them right.
  1347. @<Move |u|...@>=
  1348. if (old_size>=hi_sqrt) { /* |u| was large */
  1349.   if (t==v) s=NULL; /* small list just became empty */
  1350. }@+else if (new_size<hi_sqrt) { /* |u| was and still is small */
  1351.   if (u==t) goto fin; /* |u| is already where we want it */
  1352.   if (u==s) o,s=u->rsib; /* remove |u| from front */
  1353.   else {
  1354.     ooo,u->rsib->lsib=u->lsib; /* detach |u| from middle */
  1355.     o,u->lsib->rsib=u->rsib; /* do you follow the mem-counting here? */
  1356. @^discussion of \{mems}@>
  1357.   }
  1358.   o,t->rsib=u; /* insert |u| at the end */
  1359.   o,u->lsib=t;
  1360.   t=u;
  1361. }@+else { /* |u| has just become large */
  1362.   if (u==t) {
  1363.     if (u==s) goto fin; /* well, keep it small, we're done anyway */
  1364.     o,t=u->lsib; /* remove |u| from end */
  1365.   }@+else if (u==s)
  1366.     o,s=u->rsib; /* remove |u| from front */
  1367.   else {
  1368.     ooo,u->rsib->lsib=u->lsib; /* detach |u| from middle */
  1369.     o,u->lsib->rsib=u->rsib;
  1370.   }
  1371.   o,u->rsib=large_list;@+large_list=u; /* make |u| large */
  1372. }
  1373. fin:;
  1374. @ We don't have room in our binomial queues to keep track of both
  1375. endpoints of the arcs. But the arcs occur in pairs, and by looking
  1376. at the address of |a| we can tell whether the matching arc is
  1377. |a+1| or |a-1|. (See the explanation in {sc GB_,GRAPH}.)
  1378. @<Report the new edge verbosely@>=
  1379. report((edge_trick&(siz_t)a? a-1: a+1)->tip,a->tip,a->len);
  1380. @*Cheriton, Tarjan, and Karp's algorithm (continued).
  1381. And now for the second part of the algorithm. Here we need to
  1382. find room for a $lsqrtntimeslsqrtn$ matrix of edge lengths;
  1383. we will use random access into the |z| utility fields of vertex records,
  1384. since these haven't been used for anything yet by |cher_tar_kar|.
  1385. We can also use the |v| utility fields to record the arcs that
  1386. are the source of the best lengths, since this was the |lsib|
  1387. field (no longer needed). The program doesn't count mems for
  1388. updating that field, since it considers its goal to be simply
  1389. the calculation of minimum spanning tree length; the actual
  1390. edges of the minimum spanning tree are computed only for
  1391. |verbose| mode. (We want to see how competitive |cher_tar_kar| is
  1392. when we streamline it as much as possible.)
  1393. @^discussion of \{mems}@>
  1394. In stage 2, the vertices will be assigned integer index numbers
  1395. between 0 and $lsqrtn-1$. We'll put this into the |csize| field,
  1396. which is no longer needed, and call it |findex|.
  1397. @d findex csize
  1398. @d matx(j,k) (gv+((j)*lo_sqrt+(k)))->z.I
  1399.  /* distance between fragments |j| and |k| */
  1400. @d matx_arc(j,k) (gv+((j)*lo_sqrt+(k)))->v.A
  1401.  /* arc corresponding to |matx(j,k)| */
  1402. @d INF 30000 /* upper bound on all edge lengths */
  1403. @<Do stage 2 of |cher_tar_kar|@>=
  1404. gv=g->vertices; /* the global variable |gv| helps access auxiliary memory */
  1405. @<Map all vertices to their index numbers@>;
  1406. @<Create the reduced matrix by running through all remaining edges@>;
  1407. @<Execute Prim's algorithm on the reduced matrix@>;
  1408. @ The vertex-mapping algorithm is $O(n)$ because each non-null |comp| link
  1409. is examined at most three times. We set the |comp| field to null
  1410. as an indication that |findex| has been set.
  1411. @<Map all...@>=
  1412. if (s==NULL) s=large_list;
  1413. else t->rsib=large_list;
  1414. for (k=0,v=s;v;o,v=v->rsib,k++) o,v->findex=k;
  1415. for (v=g->vertices;v<g->vertices+g->n;v++)
  1416.   if (o,v->comp) {
  1417.     for (t=v->comp;o,t->comp;t=t->comp) ;
  1418.     o,k=t->findex;
  1419.     for (t=v;o,u=t->comp;t=u) {
  1420.       o,t->comp=NULL;
  1421.       o,t->findex=k;
  1422.     }
  1423.   }
  1424. @ @<Create the reduced matrix by running through all remaining edges@>=
  1425. for (j=0;j<lo_sqrt;j++) for (k=0;k<lo_sqrt;k++) o,matx(j,k)=INF;
  1426. for (kk=0;s;o,s=s->rsib,kk++) qtraverse(s->pq,note_edge);
  1427. @ The |note_edge| procedure ``visits'' every edge in the
  1428. binomial queues traversed by |qtraverse| in the preceding code.
  1429. Global variable |kk|, which would be a global register in a
  1430. production version, is the index of the fragment from which
  1431. this arc emanates.
  1432. @<Procedures to be declared early@>=
  1433. void note_edge(a)
  1434.   Arc *a;
  1435. {@+register long k;
  1436.   o,k=a->tip->findex;
  1437.   if (k==kk) return;
  1438.   if (oo,a->len<matx(kk,k)) {
  1439.     o,matx(kk,k)=a->len;
  1440.     o,matx(k,kk)=a->len;
  1441.     matx_arc(kk,k)=matx_arc(k,kk)=a;
  1442.   }
  1443. }
  1444. @ As we work on the final subproblem of size $lsqrtntimeslsqrtn$,
  1445. we'll have a short vector that tells us the distance to each fragment that
  1446. hasn't yet been joined up with fragment~0. The vector has |-1| in positions
  1447. that already have been joined up. In a production version, we could
  1448. keep this in row~0 of |matx|.
  1449. @<Glob...@>=
  1450. long kk; /* current fragment */
  1451. long distance[100]; /* distances to at most lsqrtn unhit fragments */
  1452. Arc *dist_arc[100]; /* the corresponding arcs, for |verbose| mode */
  1453. @ The last step, as suggested by Prim, repeatedly updates
  1454. @^Prim, Robert Clay@>
  1455. the distance table against each row of the matrix as it is encountered.
  1456. This is the algorithm of choice to find the minimum spanning tree of
  1457. a complete graph.
  1458. @<Execute Prim's algorithm on the reduced matrix@>=
  1459. {@+long d; /* shortest entry seen so far in |distance| vector */
  1460.   o,distance[0]=-1;
  1461.   d=INF;
  1462.   for (k=1;k<lo_sqrt;k++) {
  1463.     o,distance[k]=matx(0,k);
  1464.     dist_arc[k]=matx_arc(0,k);
  1465.     if (distance[k]<d) d=distance[k],j=k;
  1466.   }
  1467.   while (frags>1)
  1468.     @<Connect fragment 0 with fragment |j|, since |j| is the column
  1469.       achieving the smallest distance, |d|; also compute |j| and |d|
  1470.       for the next round@>;
  1471. }
  1472. @ @<Connect fragment 0...@>=
  1473. {
  1474.   if (d==INF) return INFINITY; /* the graph isn't connected */
  1475.   o,distance[j]=-1; /* fragment |j| now will join up with fragment 0 */
  1476.   tot_len+=d;
  1477.   if (verbose) {
  1478.     a=dist_arc[j];
  1479.     @<Report the new edge verbosely@>;
  1480.   }
  1481.   frags--;
  1482.   d=INF;
  1483.   for (k=1;k<lo_sqrt;k++)
  1484.     if (o,distance[k]>=0) {
  1485.       if (o,matx(j,k)<distance[k]) {
  1486.         o,distance[k]=matx(j,k);
  1487.         dist_arc[k]=matx_arc(j,k);
  1488.       }
  1489.       if (distance[k]<d) d=distance[k],kk=k;
  1490.     }
  1491.   j=kk;
  1492. }
  1493. @* Conclusions. The winning algorithm, of the four methods considered here,
  1494. on problems of the size considered here, with respect to mem counting, is
  1495. clearly Jarn{'i}k/Prim with binary heaps. Second is Kruskal with
  1496. radix sorting, on sparse graphs, but the Fibonacci heap method beats
  1497. it on dense graphs. Procedure |cher_tar_kar| never comes close,
  1498. although every step it takes seems to be reasonably sensible and
  1499. efficient, and although the implementation above gives it the benefit
  1500. of every doubt when counting its mems. It apparently loses because
  1501. it more or less gives up a factor of~2 by dealing with each edge
  1502. twice; the other methods put very little effort into discarding an arc
  1503. whose mate has already been processed.
  1504. But it is important to realize that mem counting is not the whole story.
  1505. Further tests were made on a Sun SPARCstation~2, in order to measure the true
  1506. @^discussion of \{mems}@>
  1507. running times when all the complications of pipelining, caching, and compiler
  1508. optimization are taken into account. These runs showed that Kruskal's
  1509. algorithm was actually best, at least on the particular system tested:
  1510. $$advanceabovedisplayskip-5pt
  1511. advancebelowdisplayskip-5pt
  1512. advancebaselineskip-1pt
  1513. vbox{halign{#hfil&&quadhfil#cr
  1514. hfill optimization level&.{-g}hfil&.{-O2}hfil&.{-O3}hfil&memshfilcr
  1515. noalign{vskip2pt}
  1516. Kruskal/radix&132&111&111&8379cr
  1517. Jarn{'i}k/Prim/binary&307&226&212&7972cr
  1518. Jarn{'i}k/Prim/Fibonacci&432&350&333&11519cr
  1519. Cheriton/Tarjan/Karp&686&509&492&17090cr}}$$
  1520. (Times are shown in seconds per 100,000 runs with the default graph
  1521. |miles(100,0,0,0,0,10,0)|. Optimization level .{-O4} gave the same results
  1522. as .{-O3}. Optimization does not change the mem count.) Thus the Kruskal
  1523. procedure used only about 160 nanoseconds per mem, without optimization,
  1524. and about 130 with; the others used about 380 to 400 ns/mem without
  1525. optimization, 270 to 300 with. The mem measure gave consistent readings for
  1526. the three ``sophisticated'' data structures, but the ``na{"i}ve'' Kruskal
  1527. method blended better with hardware. The complete graph |miles(100,0,0,0,0,
  1528. 99,0)|, obtained by specifying option .{-d100}, gave somewhat different
  1529. statistics:
  1530. $$advanceabovedisplayskip-5pt
  1531. advancebelowdisplayskip-5pt
  1532. advancebaselineskip-1pt
  1533. vbox{halign{#hfil&&quadhfil#cr
  1534. hfill optimization level&.{-g}hfil&.{-O2}hfil&.{-O3}hfil&memshfilcr
  1535. noalign{vskip2pt}
  1536. Kruskal/radix&1846&1787&1810&63795cr
  1537. Jarn{'i}k/Prim/binary&2246&1958&1845&50594cr
  1538. Jarn{'i}k/Prim/Fibonacci&2675&2377&2248&58544cr
  1539. Cheriton/Tarjan/Karp&8881&6964&6909&165749cr}}$$
  1540. % Kruskal 285 ns/mem; others 360--450, except unoptimized CTK was 536!
  1541. Now the identical machine instructions took significantly longer per
  1542. mem---presumably because of cache misses, although the frequency of
  1543. conditional jump instructions might also be a factor.  Careful analyses
  1544. of these phenomena should be instructive.  Future computers are
  1545. expected to be more nearly limited by memory speed; therefore the running
  1546. time per mem is likely to become more uniform between methods, although
  1547. cache performance will probably always be a factor.
  1548. The |krusk| procedure might go even faster if it were
  1549. given a streamlined union/find algorithm. Or would such ``streamlining''
  1550. negate some of its present efficiency?
  1551. @* Index. We close with a list that shows where the identifiers of this
  1552. program are defined and used. A special index term, `discussion of \{mems}',
  1553. indicates sections where there are nontrivial comments about instrumenting
  1554. a CEE/ program in the manner being recommended here.