/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/neatogen/closest.c

Go to the documentation of this file.
00001 /* $Id: closest.c,v 1.2 2006/12/07 22:49:36 erg Exp $ $Revision: 1.2 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 
00018 #include "kkutils.h"
00019 #include "closest.h"
00020 #include <stdlib.h>
00021 
00022 /*****************************************
00023 ** This module contains functions that  **
00024 ** given a 1-D layout construct a graph **
00025 ** where close nodes in this layout are **
00026 ** adjacent                             **
00027 *****************************************/
00028 
00029 typedef struct {
00030     /* this structure represents two nodes in the 1-D layout */
00031     int left;                   /* the left node in the pair */
00032     int right;                  /* the right node in the pair */
00033     double dist;                /* distance between the nodes in the layout */
00034 } Pair;
00035 
00036 #define LT(p,q) ((p).dist < (q).dist)
00037 #define EQ(p,q) ((p).dist == (q).dist)
00038 
00039 /*
00040 Pair(int v, int u) {left=v; right=u;}
00041 bool operator>(Pair other) {return dist>other.dist;}
00042 bool operator>=(Pair other) {return dist>=other.dist;}
00043 bool operator<(Pair other) {return dist<other.dist;}
00044 bool operator<=(Pair other) {return dist<=other.dist;}
00045 bool operator==(Pair other) {return dist==other.dist;}
00046 */
00047 
00048 typedef struct {
00049     Pair *data;
00050     int max_size;
00051     int top;
00052 } PairStack;
00053 
00054 static void initStack(PairStack * s, int n)
00055 {
00056     s->data = N_GNEW(n, Pair);
00057     s->max_size = n;
00058     s->top = 0;
00059 }
00060 
00061 static void freeStack(PairStack * s)
00062 {
00063     free(s->data);
00064 }
00065 
00066 #define push(s,x) { \
00067         if (s->top>=s->max_size) { \
00068                 s->max_size *= 2; \
00069                 s->data = (Pair*) realloc(s->data, s->max_size*sizeof(Pair)); \
00070         } \
00071         s->data[s->top++] = x; \
00072 }
00073 
00074 #define pop(s,x) ((s->top==0) ? FALSE : (s->top--, x = s->data[s->top], TRUE))
00075 
00076 #define read_top(h,x) ((s->top==0) ? FALSE : (x = s->data[s->top-1], TRUE))
00077 
00078 #define sub(h,i) (h->data[i])
00079 
00080 /* An auxulliary data structure (a heap) for 
00081  * finding the closest pair in the layout
00082  */
00083 typedef struct {
00084     Pair *data;
00085     int heapSize;
00086     int maxSize;
00087 } PairHeap;
00088 
00089 #define left(i) (2*(i))
00090 #define right(i) (2*(i)+1)
00091 #define parent(i) ((i)/2)
00092 #define insideHeap(h,i) ((i)<h->heapSize)
00093 #define greaterPriority(h,i,j) \
00094   (LT(h->data[i],h->data[j]) || ((EQ(h->data[i],h->data[j])) && (rand()%2)))
00095 
00096 #define exchange(h,i,j) {Pair temp; \
00097         temp=h->data[i]; \
00098         h->data[i]=h->data[j]; \
00099         h->data[j]=temp; \
00100 }
00101 #define assign(h,i,j) {h->data[i]=h->data[j]}
00102 
00103 static void heapify(PairHeap * h, int i)
00104 {
00105     int l, r, largest;
00106     while (1) {
00107         l = left(i);
00108         r = right(i);
00109         if (insideHeap(h, l) && greaterPriority(h, l, i))
00110             largest = l;
00111         else
00112             largest = i;
00113         if (insideHeap(h, r) && greaterPriority(h, r, largest))
00114             largest = r;
00115         if (largest == i)
00116             break;
00117 
00118         exchange(h, largest, i);
00119         i = largest;
00120     }
00121 }
00122 
00123 #ifdef UNUSED
00124 static void mkHeap(PairHeap * h, int size)
00125 {
00126     h->data = N_GNEW(size, Pair);
00127     h->maxSize = size;
00128     h->heapSize = 0;
00129 }
00130 #endif
00131 
00132 static void freeHeap(PairHeap * h)
00133 {
00134     free(h->data);
00135 }
00136 
00137 static void initHeap(PairHeap * h, double *place, int *ordering, int n)
00138 {
00139     int i;
00140     Pair edge;
00141     int j;
00142 
00143     h->heapSize = n - 1;
00144 #ifdef REDO
00145     if (h->heapSize > h->maxSize) {
00146         h->maxSize = h->heapSize;
00147         h->data = (Pair *) realloc(h->data, h->maxSize * sizeof(Pair));
00148     }
00149 #else
00150     h->maxSize = h->heapSize;
00151     h->data = N_GNEW(h->maxSize, Pair);
00152 #endif
00153 
00154     for (i = 0; i < n - 1; i++) {
00155         edge.left = ordering[i];
00156         edge.right = ordering[i + 1];
00157         edge.dist = place[ordering[i + 1]] - place[ordering[i]];
00158         h->data[i] = edge;
00159     }
00160     for (j = (n - 1) / 2; j >= 0; j--) {
00161         heapify(h, j);
00162     }
00163 }
00164 
00165 static boolean extractMax(PairHeap * h, Pair * max)
00166 {
00167     if (h->heapSize == 0)
00168         return FALSE;
00169 
00170     *max = h->data[0];
00171     h->data[0] = h->data[h->heapSize - 1];
00172     h->heapSize--;
00173     heapify(h, 0);
00174     return TRUE;
00175 }
00176 
00177 static void insert(PairHeap * h, Pair edge)
00178 {
00179     int i = h->heapSize;
00180     if (h->heapSize == h->maxSize) {
00181         h->maxSize *= 2;
00182         h->data = (Pair *) realloc(h->data, h->maxSize * sizeof(Pair));
00183     }
00184     h->heapSize++;
00185     h->data[i] = edge;
00186     while (i > 0 && greaterPriority(h, i, parent(i))) {
00187         exchange(h, i, parent(i));
00188         i = parent(i);
00189     }
00190 }
00191 
00192 /*
00193 static bool
00194 isheap(PairHeap* h)
00195 {
00196         int i,l,r;
00197         for (i=0; i<h->heapSize; i++) {
00198                 l=left(i); r=right(i);
00199                 if (insideHeap(h,l) && greaterPriority(h,l,i))
00200                         return FALSE;
00201                 if (insideHeap(h,r) && greaterPriority(h,r,i))
00202                         return FALSE;
00203         }
00204         return TRUE;
00205 }
00206 */
00207 
00208 static void
00209 find_closest_pairs(double *place, int n, int num_pairs,
00210                    PairStack * pairs_stack)
00211 {
00212     /* Fill the stack 'pairs_stack' with 'num_pairs' closest pairs int the 1-D layout 'place' */
00213     int i;
00214     PairHeap heap;
00215     int *left = N_GNEW(n, int);
00216     int *right = N_GNEW(n, int);
00217     Pair pair = { 0, 0 }, new_pair;
00218 
00219     /* Order the nodes according to their place */
00220     int *ordering = N_GNEW(n, int);
00221     int *inv_ordering = N_GNEW(n, int);
00222 
00223     for (i = 0; i < n; i++) {
00224         ordering[i] = i;
00225     }
00226     quicksort_place(place, ordering, 0, n - 1);
00227     for (i = 0; i < n; i++) {
00228         inv_ordering[ordering[i]] = i;
00229     }
00230 
00231     /* Intialize heap with all consecutive pairs */
00232     initHeap(&heap, place, ordering, n);
00233 
00234     /* store the leftmost and rightmost neighbors of each node that were entered into heap */
00235     for (i = 1; i < n; i++) {
00236         left[ordering[i]] = ordering[i - 1];
00237     }
00238     for (i = 0; i < n - 1; i++) {
00239         right[ordering[i]] = ordering[i + 1];
00240     }
00241 
00242     /* extract the 'num_pairs' closest pairs */
00243     for (i = 0; i < num_pairs; i++) {
00244         int left_index;
00245         int right_index;
00246         int neighbor;
00247 
00248         if (!extractMax(&heap, &pair)) {
00249             break;              /* not enough pairs */
00250         }
00251         push(pairs_stack, pair);
00252         /* insert to heap "descendant" pairs */
00253         left_index = inv_ordering[pair.left];
00254         right_index = inv_ordering[pair.right];
00255         if (left_index > 0) {
00256             neighbor = ordering[left_index - 1];
00257             if (inv_ordering[right[neighbor]] < right_index) {
00258                 /* we have a new pair */
00259                 new_pair.left = neighbor;
00260                 new_pair.right = pair.right;
00261                 new_pair.dist = place[pair.right] - place[neighbor];
00262                 insert(&heap, new_pair);
00263                 right[neighbor] = pair.right;
00264                 left[pair.right] = neighbor;
00265             }
00266         }
00267         if (right_index < n - 1) {
00268             neighbor = ordering[right_index + 1];
00269             if (inv_ordering[left[neighbor]] > left_index) {
00270                 /* we have a new pair */
00271                 new_pair.left = pair.left;
00272                 new_pair.right = neighbor;
00273                 new_pair.dist = place[neighbor] - place[pair.left];
00274                 insert(&heap, new_pair);
00275                 left[neighbor] = pair.left;
00276                 right[pair.left] = neighbor;
00277             }
00278         }
00279     }
00280     free(left);
00281     free(right);
00282     free(ordering);
00283     free(inv_ordering);
00284     freeHeap(&heap);
00285 }
00286 
00287 static void add_edge(vtx_data * graph, int u, int v)
00288 {
00289     int i;
00290     for (i = 0; i < graph[u].nedges; i++) {
00291         if (graph[u].edges[i] == v) {
00292             /* edge already exist */
00293             return;
00294         }
00295     }
00296     /* add the edge */
00297     graph[u].edges[graph[u].nedges++] = v;
00298     graph[v].edges[graph[v].nedges++] = u;
00299     if (graph[0].ewgts != NULL) {
00300         graph[u].ewgts[0]--;
00301         graph[v].ewgts[0]--;
00302     }
00303 }
00304 
00305 static void
00306 construct_graph(int n, PairStack * edges_stack, vtx_data ** New_graph)
00307 {
00308     /* construct an unweighted graph using the edges 'edges_stack' */
00309     int i;
00310     vtx_data *new_graph;
00311 
00312     /* first compute new degrees and nedges; */
00313     int *degrees = N_GNEW(n, int);
00314     int top = edges_stack->top;
00315     int new_nedges = 2 * top + n;
00316     Pair pair;
00317     int *edges = N_GNEW(new_nedges, int);
00318     float *weights = N_GNEW(new_nedges, float);
00319 
00320     for (i = 0; i < n; i++) {
00321         degrees[i] = 1;         /* save place for the self loop */
00322     }
00323     for (i = 0; i < top; i++) {
00324         pair = sub(edges_stack, i);
00325         degrees[pair.left]++;
00326         degrees[pair.right]++;
00327     }
00328 
00329     /* copy graph into new_graph: */
00330     for (i = 0; i < new_nedges; i++) {
00331         weights[i] = 1.0;
00332     }
00333 
00334     *New_graph = new_graph = N_GNEW(n, vtx_data);
00335     for (i = 0; i < n; i++) {
00336         new_graph[i].nedges = 1;
00337         new_graph[i].ewgts = weights;
00338 #ifdef USE_STYLES
00339         new_graph[i].styles = NULL;
00340 #endif
00341         new_graph[i].edges = edges;
00342         *edges = i;             /* self loop for Lap */
00343         *weights = 0;           /* self loop weight for Lap */
00344         weights += degrees[i];
00345         edges += degrees[i];    /* reserve space for possible more edges */
00346     }
00347 
00348     free(degrees);
00349 
00350     /* add all edges from stack */
00351     while (pop(edges_stack, pair)) {
00352         add_edge(new_graph, pair.left, pair.right);
00353     }
00354 }
00355 
00356 void
00357 closest_pairs2graph(double *place, int n, int num_pairs, vtx_data ** graph)
00358 {
00359     /* build a graph with with edges between the 'num_pairs' closest pairs in the 1-D space: 'place' */
00360     PairStack pairs_stack;
00361     initStack(&pairs_stack, num_pairs);
00362     find_closest_pairs(place, n, num_pairs, &pairs_stack);
00363     construct_graph(n, &pairs_stack, graph);
00364     freeStack(&pairs_stack);
00365 }

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1