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