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

Go to the documentation of this file.
00001 /* $Id: kkutils.c,v 1.2 2005/07/13 20:29:40 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 "bfs.h"
00019 #include "dijkstra.h"
00020 #include "kkutils.h"
00021 #include <stdlib.h>
00022 #include <math.h>
00023 
00024 int common_neighbors(vtx_data * graph, int v, int u, int *v_vector)
00025 {
00026     /* count number of common neighbors of 'v' and 'u' */
00027     int neighbor;
00028     int num_shared_neighbors = 0;
00029     int j;
00030     for (j = 1; j < graph[u].nedges; j++) {
00031         neighbor = graph[u].edges[j];
00032         if (v_vector[neighbor] > 0) {
00033             /* a shared neighobr */
00034             num_shared_neighbors++;
00035         }
00036     }
00037     return num_shared_neighbors;
00038 }
00039 void fill_neighbors_vec_unweighted(vtx_data * graph, int vtx, int *vtx_vec)
00040 {
00041     /* a node is NOT a neighbor of itself! */
00042     /* unlike the other version of this function */
00043     int j;
00044     for (j = 1; j < graph[vtx].nedges; j++) {
00045         vtx_vec[graph[vtx].edges[j]] = 1;
00046     }
00047 }
00048 
00049 void empty_neighbors_vec(vtx_data * graph, int vtx, int *vtx_vec)
00050 {
00051     int j;
00052     /* a node is NOT a neighbor of itself! */
00053     /* unlike the other version ofthis function */
00054     for (j = 1; j < graph[vtx].nedges; j++) {
00055         vtx_vec[graph[vtx].edges[j]] = 0;
00056     }
00057 }
00058 
00059 /* compute_apsp_dijkstra:
00060  * Assumes the graph has weights
00061  */
00062 static DistType **compute_apsp_dijkstra(vtx_data * graph, int n)
00063 {
00064     int i;
00065     DistType *storage;
00066     DistType **dij;
00067 
00068     storage = N_GNEW(n * n, DistType);
00069     dij = N_GNEW(n, DistType *);
00070     for (i = 0; i < n; i++)
00071         dij[i] = storage + i * n;
00072 
00073     for (i = 0; i < n; i++) {
00074         dijkstra(i, graph, n, dij[i]);
00075     }
00076     return dij;
00077 }
00078 
00079 static DistType **compute_apsp_simple(vtx_data * graph, int n)
00080 {
00081     /* compute all pairs shortest path */
00082     /* for unweighted graph */
00083     int i;
00084     DistType *storage = N_GNEW(n * n, int);
00085     DistType **dij;
00086     Queue Q;
00087 
00088     dij = N_GNEW(n, DistType *);
00089     for (i = 0; i < n; i++) {
00090         dij[i] = storage + i * n;
00091     }
00092     mkQueue(&Q, n);
00093     for (i = 0; i < n; i++) {
00094         bfs(i, graph, n, dij[i], &Q);
00095     }
00096     freeQueue(&Q);
00097     return dij;
00098 }
00099 
00100 DistType **compute_apsp(vtx_data * graph, int n)
00101 {
00102     if (graph->ewgts)
00103         return compute_apsp_dijkstra(graph, n);
00104     else
00105         return compute_apsp_simple(graph, n);
00106 }
00107 
00108 DistType **compute_apsp_artifical_weights(vtx_data * graph, int n)
00109 {
00110     DistType **Dij;
00111     /* compute all-pairs-shortest-path-length while weighting the graph */
00112     /* so high-degree nodes are distantly located */
00113 
00114     float *old_weights = graph[0].ewgts;
00115 
00116     compute_new_weights(graph, n);
00117     Dij = compute_apsp_dijkstra(graph, n);
00118     restore_old_weights(graph, n, old_weights);
00119     return Dij;
00120 }
00121 
00122 
00123 /**********************/
00124 /*                                    */
00125 /*  Quick Sort        */
00126 /*                                    */
00127 /**********************/
00128 
00129 static void
00130 split_by_place(double *place, int *nodes, int first, int last, int *middle)
00131 {
00132     unsigned int splitter =
00133         rand() * ((unsigned) (last - first)) / RAND_MAX + (unsigned) first;
00134     int val;
00135     double place_val;
00136     int left = first + 1;
00137     int right = last;
00138     int temp;
00139 
00140     val = nodes[splitter];
00141     nodes[splitter] = nodes[first];
00142     nodes[first] = val;
00143     place_val = place[val];
00144 
00145     while (left < right) {
00146         while (left < right && place[nodes[left]] <= place_val)
00147             left++;
00148         while (left < right && place[nodes[right]] >= place_val)
00149             right--;
00150         if (left < right) {
00151             temp = nodes[left];
00152             nodes[left] = nodes[right];
00153             nodes[right] = temp;
00154             left++;
00155             right--;            /* (1) */
00156 
00157         }
00158     }
00159     /* in this point either, left==right (meeting), or left=right+1 (because of (1)) */
00160     /* we have to decide to which part the meeting point (or left) belongs. */
00161     if (place[nodes[left]] > place_val)
00162         left = left - 1;        /* notice that always left>first, because of its initialization */
00163     *middle = left;
00164     nodes[first] = nodes[*middle];
00165     nodes[*middle] = val;
00166 }
00167 
00168 double distance_kD(double **coords, int dim, int i, int j)
00169 {
00170     /* compute a k-D Euclidean distance between 'coords[*][i]' and 'coords[*][j]' */
00171     double sum = 0;
00172     int k;
00173     for (k = 0; k < dim; k++) {
00174         sum +=
00175             (coords[k][i] - coords[k][j]) * (coords[k][i] - coords[k][j]);
00176     }
00177     return sqrt(sum);
00178 }
00179 
00180 static float* fvals;
00181 static int
00182 fcmpf (int* ip1, int* ip2)
00183 {
00184     float d1 = fvals[*ip1];
00185     float d2 = fvals[*ip2];
00186     if (d1 < d2) return -1;
00187     else if (d1 > d2) return 1;
00188     else return 0;
00189 }
00190 
00191 void quicksort_placef(float *place, int *ordering, int first, int last)
00192 {
00193     if (first < last) {
00194         fvals = place;
00195         qsort(ordering+first, last-first+1, sizeof(ordering[0]), (qsort_cmpf)fcmpf);
00196     }
00197 }
00198 
00199 /* quicksort_place:
00200  * For now, we keep the current implementation for stability, but
00201  * we should consider replacing this with an implementation similar to
00202  * quicksort_placef above.
00203  */
00204 void quicksort_place(double *place, int *ordering, int first, int last)
00205 {
00206     if (first < last) {
00207         int middle;
00208 #ifdef __cplusplus
00209         split_by_place(place, ordering, first, last, middle);
00210 #else
00211         split_by_place(place, ordering, first, last, &middle);
00212 #endif
00213         quicksort_place(place, ordering, first, middle - 1);
00214         quicksort_place(place, ordering, middle + 1, last);
00215     }
00216 }
00217 
00218 void compute_new_weights(vtx_data * graph, int n)
00219 {
00220     /* Reweight graph so that high degree nodes will be separated */
00221 
00222     int i, j;
00223     int nedges = 0;
00224     float *weights;
00225     int *vtx_vec = N_GNEW(n, int);
00226     int deg_i, deg_j, neighbor;
00227 
00228     for (i = 0; i < n; i++) {
00229         nedges += graph[i].nedges;
00230     }
00231     weights = N_GNEW(nedges, float);
00232 
00233     for (i = 0; i < n; i++) {
00234         vtx_vec[i] = 0;
00235     }
00236 
00237     for (i = 0; i < n; i++) {
00238         graph[i].ewgts = weights;
00239         fill_neighbors_vec_unweighted(graph, i, vtx_vec);
00240         deg_i = graph[i].nedges - 1;
00241         for (j = 1; j <= deg_i; j++) {
00242             neighbor = graph[i].edges[j];
00243             deg_j = graph[neighbor].nedges - 1;
00244             weights[j] =
00245                 (float) (deg_i + deg_j -
00246                          2 * common_neighbors(graph, i, neighbor,
00247                                               vtx_vec));
00248         }
00249         empty_neighbors_vec(graph, i, vtx_vec);
00250         weights += graph[i].nedges;
00251     }
00252     free(vtx_vec);
00253 }
00254 
00255 void restore_old_weights(vtx_data * graph, int n, float *old_weights)
00256 {
00257     int i;
00258     free(graph[0].ewgts);
00259     graph[0].ewgts = NULL;
00260     if (old_weights != NULL) {
00261         for (i = 0; i < n; i++) {
00262             graph[i].ewgts = old_weights;
00263             old_weights += graph[i].nedges;
00264         }
00265     }
00266 }

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