00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kkutils.h"
00019 #include "closest.h"
00020 #include <stdlib.h>
00021
00022
00023
00024
00025
00026
00027
00028
00029 typedef struct {
00030
00031 int left;
00032 int right;
00033 double dist;
00034 } Pair;
00035
00036 #define LT(p,q) ((p).dist < (q).dist)
00037 #define EQ(p,q) ((p).dist == (q).dist)
00038
00039
00040
00041
00042
00043
00044
00045
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
00081
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
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 static void
00209 find_closest_pairs(double *place, int n, int num_pairs,
00210 PairStack * pairs_stack)
00211 {
00212
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
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
00232 initHeap(&heap, place, ordering, n);
00233
00234
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
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;
00250 }
00251 push(pairs_stack, pair);
00252
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
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
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
00293 return;
00294 }
00295 }
00296
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
00309 int i;
00310 vtx_data *new_graph;
00311
00312
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;
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
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;
00343 *weights = 0;
00344 weights += degrees[i];
00345 edges += degrees[i];
00346 }
00347
00348 free(degrees);
00349
00350
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
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 }