kkutils.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include <neatogen/bfs.h>
  11. #include <neatogen/dijkstra.h>
  12. #include <neatogen/kkutils.h>
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <util/alloc.h>
  16. #include <util/sort.h>
  17. size_t common_neighbors(vtx_data *graph, int u, int *v_vector) {
  18. // count number of common neighbors of 'v_vector' and 'u'
  19. int neighbor;
  20. size_t num_shared_neighbors = 0;
  21. for (size_t j = 1; j < graph[u].nedges; j++) {
  22. neighbor = graph[u].edges[j];
  23. if (v_vector[neighbor] > 0) {
  24. // a shared neighbor
  25. num_shared_neighbors++;
  26. }
  27. }
  28. return num_shared_neighbors;
  29. }
  30. void fill_neighbors_vec_unweighted(vtx_data * graph, int vtx, int *vtx_vec)
  31. {
  32. /* a node is NOT a neighbor of itself! */
  33. /* unlike the other version of this function */
  34. for (size_t j = 1; j < graph[vtx].nedges; j++) {
  35. vtx_vec[graph[vtx].edges[j]] = 1;
  36. }
  37. }
  38. void empty_neighbors_vec(vtx_data * graph, int vtx, int *vtx_vec)
  39. {
  40. /* a node is NOT a neighbor of itself! */
  41. /* unlike the other version ofthis function */
  42. for (size_t j = 1; j < graph[vtx].nedges; j++) {
  43. vtx_vec[graph[vtx].edges[j]] = 0;
  44. }
  45. }
  46. /* compute_apsp_dijkstra:
  47. * Assumes the graph has weights
  48. */
  49. static DistType **compute_apsp_dijkstra(vtx_data * graph, int n)
  50. {
  51. int i;
  52. DistType *storage = gv_calloc((size_t)(n * n), sizeof(DistType));
  53. DistType **dij = gv_calloc(n, sizeof(DistType*));
  54. for (i = 0; i < n; i++)
  55. dij[i] = storage + i * n;
  56. for (i = 0; i < n; i++) {
  57. dijkstra(i, graph, n, dij[i]);
  58. }
  59. return dij;
  60. }
  61. static DistType **compute_apsp_simple(vtx_data * graph, int n)
  62. {
  63. /* compute all pairs shortest path */
  64. /* for unweighted graph */
  65. int i;
  66. DistType *storage = gv_calloc((size_t)(n * n), sizeof(DistType));
  67. DistType **dij = gv_calloc(n, sizeof(DistType*));
  68. for (i = 0; i < n; i++) {
  69. dij[i] = storage + i * n;
  70. }
  71. for (i = 0; i < n; i++) {
  72. bfs(i, graph, n, dij[i]);
  73. }
  74. return dij;
  75. }
  76. DistType **compute_apsp(vtx_data * graph, int n)
  77. {
  78. if (graph->ewgts)
  79. return compute_apsp_dijkstra(graph, n);
  80. else
  81. return compute_apsp_simple(graph, n);
  82. }
  83. DistType **compute_apsp_artificial_weights(vtx_data *graph, int n) {
  84. DistType **Dij;
  85. /* compute all-pairs-shortest-path-length while weighting the graph */
  86. /* so high-degree nodes are distantly located */
  87. float *old_weights = graph[0].ewgts;
  88. compute_new_weights(graph, n);
  89. Dij = compute_apsp_dijkstra(graph, n);
  90. restore_old_weights(graph, n, old_weights);
  91. return Dij;
  92. }
  93. /**********************/
  94. /* */
  95. /* Quick Sort */
  96. /* */
  97. /**********************/
  98. double distance_kD(double **coords, int dim, int i, int j)
  99. {
  100. /* compute a k-D Euclidean distance between 'coords[*][i]' and 'coords[*][j]' */
  101. double sum = 0;
  102. int k;
  103. for (k = 0; k < dim; k++) {
  104. sum +=
  105. (coords[k][i] - coords[k][j]) * (coords[k][i] - coords[k][j]);
  106. }
  107. return sqrt(sum);
  108. }
  109. static int fcmpf(const void *a, const void *b, void *context) {
  110. const int *ip1 = a;
  111. const int *ip2 = b;
  112. float *fvals = context;
  113. float d1 = fvals[*ip1];
  114. float d2 = fvals[*ip2];
  115. if (d1 < d2) {
  116. return -1;
  117. }
  118. if (d1 > d2) {
  119. return 1;
  120. }
  121. return 0;
  122. }
  123. void quicksort_placef(float *place, int *ordering, int first, int last)
  124. {
  125. if (first < last) {
  126. gv_sort(ordering + first, last - first + 1, sizeof(ordering[0]), fcmpf, place);
  127. }
  128. }
  129. static int cmp(const void *a, const void *b, void *context) {
  130. const int *x = a;
  131. const int *y = b;
  132. const double *place = context;
  133. if (place[*x] < place[*y]) {
  134. return -1;
  135. }
  136. if (place[*x] > place[*y]) {
  137. return 1;
  138. }
  139. return 0;
  140. }
  141. void quicksort_place(double *place, int *ordering, int size) {
  142. gv_sort(ordering, size, sizeof(ordering[0]), cmp, place);
  143. }
  144. void compute_new_weights(vtx_data * graph, int n)
  145. {
  146. /* Reweight graph so that high degree nodes will be separated */
  147. int i;
  148. size_t nedges = 0;
  149. int *vtx_vec = gv_calloc(n, sizeof(int));
  150. size_t deg_i, deg_j;
  151. int neighbor;
  152. for (i = 0; i < n; i++) {
  153. nedges += graph[i].nedges;
  154. }
  155. float *weights = gv_calloc(nedges, sizeof(float));
  156. for (i = 0; i < n; i++) {
  157. graph[i].ewgts = weights;
  158. fill_neighbors_vec_unweighted(graph, i, vtx_vec);
  159. deg_i = graph[i].nedges - 1;
  160. for (size_t j = 1; j <= deg_i; j++) {
  161. neighbor = graph[i].edges[j];
  162. deg_j = graph[neighbor].nedges - 1;
  163. weights[j] =
  164. (float)(deg_i + deg_j - 2 * common_neighbors(graph, neighbor, vtx_vec));
  165. }
  166. empty_neighbors_vec(graph, i, vtx_vec);
  167. weights += graph[i].nedges;
  168. }
  169. free(vtx_vec);
  170. }
  171. void restore_old_weights(vtx_data * graph, int n, float *old_weights)
  172. {
  173. int i;
  174. free(graph[0].ewgts);
  175. graph[0].ewgts = NULL;
  176. if (old_weights != NULL) {
  177. for (i = 0; i < n; i++) {
  178. graph[i].ewgts = old_weights;
  179. old_weights += graph[i].nedges;
  180. }
  181. }
  182. }