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