45 int num_shared_neighbors = 0;
47 for (j = 0; j <
graph[u].nedges; j++) {
51 num_shared_neighbors++;
58 return ((
double) num_shared_neighbors) / (
graph[v].nedges +
60 num_shared_neighbors);
66 for (j = 0; j <
graph[vtx].nedges; j++) {
67 vtx_vec[
graph[vtx].edges[j]] = fabsf(
graph[vtx].ewgts[j]);
70 for (j = 0; j <
graph[vtx].nedges; j++) {
71 vtx_vec[
graph[vtx].edges[j]] = 1;
81 for (j = 0; j <
graph[vtx].nedges; j++) {
82 vtx_vec[
graph[vtx].edges[j]] = 1;
89 for (j = 0; j <
graph[vtx].nedges; j++) {
90 vtx_vec[
graph[vtx].edges[j]] = 0;
100 for (i = 1; i <
graph[node1].nedges; i++) {
101 u =
graph[node1].edges[i];
105 for (j = 1; j <
graph[u].nedges; j++) {
106 v =
graph[u].edges[j];
110 for (k = 1; k <
graph[v].nedges; k++) {
111 if (
graph[v].edges[k] == node2) {
131 return hypot(x_v - x_u, y_v - y_u);
157 float max_norm_edge_weight;
159 double *matchability =
gv_calloc(nvtxs,
sizeof(
double));
161 double closest_val = -1, val;
162 int closest_neighbor;
163 float *vtx_vec =
gv_calloc(nvtxs,
sizeof(
float));
164 float *weighted_vtx_vec =
gv_calloc(nvtxs,
sizeof(
float));
167 double avg_edge_len = 0, avg_deg_2 = 0;
170 for (i = 0; i < nvtxs; i++) {
171 avg_deg_2 +=
graph[i].nedges;
172 for (j = 1; j <
graph[i].nedges; j++) {
173 avg_edge_len +=
ddist(geom_graph, i,
graph[i].edges[j]);
179 avg_deg_2 *= avg_deg_2;
185 max_norm_edge_weight = -1;
186 for (i = 0; i < nvtxs; i++) {
187 inv_size = sqrt(1.0 / geom_graph[i].size);
188 for (j = 1; j <
graph[i].nedges; j++) {
189 if (
graph[i].ewgts[j] * inv_size /
190 sqrt((
float) geom_graph[
graph[i].edges[j]].size) >
191 max_norm_edge_weight) {
192 max_norm_edge_weight =
193 (float) (
graph[i].ewgts[j] * inv_size /
195 geom_graph[
graph[i].edges[j]].size));
200 max_norm_edge_weight = 1;
204 iptr = order =
gv_calloc(nvtxs,
sizeof(
int));
206 for (i = 0; i < nvtxs; i++) {
216 for (i = 0; i < nvtxs; i++) {
218 matchability[vtx] =
graph[vtx].nedges;
219 matchability[vtx] += geom_graph[vtx].
size;
221 for (j = 1; j <
graph[vtx].nedges; j++) {
224 ddist(geom_graph, vtx,
225 graph[vtx].edges[j]) / avg_edge_len);
227 matchability[vtx] += min_edge_len;
228 matchability[vtx] += ((double) rand()) / RAND_MAX;
230 sort_place(matchability, order, (
size_t)nvtxs);
234 for (i = 0; i < nvtxs; i++) {
237 for (i = 0; i < nvtxs; i++) {
238 weighted_vtx_vec[i] = 0;
242 for (i = 0; i < nvtxs; i++) {
244 if (mflag[vtx] >= 0) {
247 inv_size = sqrt(1.0 / geom_graph[vtx].size);
250 closest_neighbor = -1;
260 for (j = 1; j < geom_graph[vtx].
nedges; j++) {
277 B * avg_deg_2 / (
graph[vtx].nedges *
286 (weighted_vtx_vec[
neighbor] * inv_size /
287 sqrt((
float) geom_graph[
neighbor].size)) /
288 max_norm_edge_weight;
292 if (val > closest_val || closest_neighbor == -1) {
298 if (closest_neighbor != -1) {
299 mflag[vtx] = closest_neighbor;
300 mflag[closest_neighbor] = vtx;
309 free(weighted_vtx_vec);
323 for (i = 0; i < nvtxs; i++) {
327 cv2v[2 * j + 1] = -1;
329 }
else if (mflag[i] > i) {
333 cv2v[2 * j + 1] = mflag[i];
352 int *index =
gv_calloc(cnvtxs,
sizeof(
int));
361 edges =
gv_calloc(2 * maxCnedges + cnvtxs,
sizeof(
int));
362 eweights =
gv_calloc(2 * maxCnedges + cnvtxs,
sizeof(
float));
366 for (cv = 0; cv < cnvtxs; cv++) {
370 cgraph[cv].
edges = edges;
371 cgraph[cv].
ewgts = eweights;
375 for (j = 1; j <
graph[v].nedges; j++) {
378 intra_weight = 2 *
graph[v].ewgts[j];
384 cgraph[cv].
ewgts[cv_nedges] =
graph[v].ewgts[j];
393 if ((v = cv2v[2 * cv + 1]) != -1) {
394 for (j = 1; j <
graph[v].nedges; j++) {
401 cgraph[cv].
ewgts[cv_nedges] =
graph[v].ewgts[j];
408 cgraph[cv].
ewgts[0] +=
graph[v].ewgts[0] + intra_weight;
410 cgraph[cv].
nedges = cv_nedges;
411 cgraph[cv].
edges[0] = cv;
413 eweights += cv_nedges;
414 cnedges += cv_nedges;
416 for (j = 1; j < cgraph[cv].
nedges; j++)
417 index[cgraph[cv].edges[j]] = 0;
420 int internal_weight = 0;
422 for (cv = 0; cv < cnvtxs; cv++) {
424 cgraph[cv].
edges = edges;
425 cgraph[cv].
ewgts = eweights;
429 for (j = 1; j <
graph[v].nedges; j++) {
438 cgraph[cv].
ewgts[cv_nedges] = -1;
444 cgraph[cv].
ewgts[0] = (float)
graph[v].edges[0];
445 if ((v = cv2v[2 * cv + 1]) != -1) {
446 for (j = 1; j <
graph[v].nedges; j++) {
453 cgraph[cv].
ewgts[cv_nedges] = -1;
460 cgraph[cv].
ewgts[0] +=
461 (float)
graph[v].edges[0] - internal_weight;
466 cgraph[cv].
nedges = cv_nedges;
467 cgraph[cv].
edges[0] = cv;
469 eweights += cv_nedges;
470 cnedges += cv_nedges;
472 for (j = 1; j < cgraph[cv].
nedges; j++)
473 index[cgraph[cv].edges[j]] = 0;
498 int *index =
gv_calloc(cnvtxs,
sizeof(
int));
506 edges =
gv_calloc(2 * cnedges + cnvtxs,
sizeof(
int));
508 for (cv = 0; cv < cnvtxs; cv++) {
510 cgraph[cv].
edges = edges;
514 for (j = 1; j <
graph[v].nedges; j++) {
528 if ((v = cv2v[2 * cv + 1]) != -1) {
529 for (j = 1; j <
graph[v].nedges; j++) {
542 graph[v].size *
graph[v].x_coord) / (cgraph[cv].size +
546 graph[v].size *
graph[v].y_coord) / (cgraph[cv].size +
550 cgraph[cv].
nedges = cv_nedges;
551 cgraph[cv].
edges[0] = cv;
554 for (j = 1; j < cgraph[cv].
nedges; j++)
555 index[cgraph[cv].edges[j]] = 0;
595 nmerged =
maxmatch(
graph, geom_graph, nvtxs, mflag, dist2_limit);
601 *cnp = cnvtxs = nvtxs - nmerged;
603 *v2cvp = v2cv =
gv_calloc(nvtxs,
sizeof(
int));
604 *cv2vp = cv2v =
gv_calloc(2 * cnvtxs,
sizeof(
int));
628 for (i = 0; i < n; i++) {
632 for (j = 0; j <
graph[i].nedges; j++) {
633 edges[j] =
graph[i].edges[j];
635 edges +=
graph[i].nedges;
637 for (j = 0; j <
graph[i].nedges; j++) {
638 ewgts[j] =
graph[i].ewgts[j];
640 ewgts +=
graph[i].nedges;
656 for (i = 0; i < n; i++) {
659 for (j = 0; j <
graph[i].nedges; j++) {
660 edges[j] =
graph[i].edges[j];
662 edges +=
graph[i].nedges;
672 int cngeom_edges = ngeom_edges;
673 static const int min_nvtxs = 20;
674 int nlevels =
MAX(5, 10 * (
int) log((
float) (nvtxs / min_nvtxs)));
685 hierarchy->
nvtxs[0] = nvtxs;
689 hierarchy->
nvtxs[cur_level] > min_nvtxs
690 && cur_level < 50 ; cur_level++) {
691 if (cur_level == nlevels - 1) {
703 ngeom_edges = cngeom_edges;
705 (hierarchy->
graphs[cur_level],
707 hierarchy->
nvtxs[cur_level], hierarchy->
nedges[cur_level],
708 ngeom_edges, &hierarchy->
graphs[cur_level + 1],
710 &hierarchy->
nvtxs[cur_level + 1],
711 &hierarchy->
nedges[cur_level + 1], &cngeom_edges,
712 &hierarchy->
v2cv[cur_level], &hierarchy->
cv2v[cur_level + 1],
716 hierarchy->
nlevels = cur_level + 1;
727 for (i = 1; i < num_foci; i++) {
748 int n = hierarchy->
nvtxs[min_level];
752 double *distances =
gv_calloc(n,
sizeof(
double));
753 for (
int i = 0; i < n; i++) {
765 int level = min_level;
766 int group_size =
parms->num_fine_nodes * num_foci;
767 int thresh = group_size;
768 for (
int i = 0; i < n; i++) {
769 const int vtx = nodes[i];
770 if (i > thresh && level < hierarchy->nlevels - 1) {
772 group_size = (int) (group_size *
parms->coarsening_rate);
773 thresh += group_size;
775 graph[vtx].active_level = level;
785 for (level = min_level + 1; level < hierarchy->
nlevels; level++) {
788 const int *
const cv2v = hierarchy->
cv2v[level];
789 n = hierarchy->
nvtxs[level];
790 for (
int i = 0; i < n; i++) {
791 const int v = cv2v[2 * i];
792 const int u = cv2v[2 * i + 1];
794 if (
graph[v].active_level < level
795 ||
graph[u].active_level < level) {
799 graph[v].active_level =
800 MIN(
graph[v].active_level, level - 1);
801 graph[u].active_level =
802 MIN(
graph[u].active_level, level - 1);
816 for (level = hierarchy->
nlevels - 1; level > 0; level--) {
819 const int *
const cv2v = hierarchy->
cv2v[level];
820 n = hierarchy->
nvtxs[level];
821 for (
int i = 0; i < n; i++) {
822 if (cgraph[i].active_level < level) {
826 const int v = cv2v[2 * i];
827 const int u = cv2v[2 * i + 1];
846 int level,
double x,
double y,
847 double closest_dist,
int *closest_node,
848 int *closest_node_level)
856 double delx = x -
graph[
node].physical_x_coord;
857 double dely = y -
graph[
node].physical_y_coord;
858 double dist = delx*delx + dely*dely;
860 if (
dist < closest_dist)
863 *closest_node =
node;
864 *closest_node_level = level;
873 level - 1, x, y, closest_dist, closest_node,
876 if (hierarchy->
cv2v[level][2 *
node + 1] >= 0) {
879 hierarchy->
cv2v[level][2 *
node + 1],
880 level - 1, x, y, closest_dist,
881 closest_node, closest_node_level);
906 int *closest_fine_node)
908 int i, closest_node, closest_node_level;
909 int top_level = hierarchy->
nlevels - 1;
910 double min_dist = 1e20;
912 for (i = 0; i < hierarchy->
nvtxs[top_level]; i++)
914 min_dist =
findClosestActiveNode(hierarchy, i, top_level, x, y,min_dist, &closest_node, &closest_node_level);
921 double *x_coords,
double *y_coords,
ex_vtx_data ** gp)
927 int nedges1 = 0, nedges2 = 0;
929 int i, j, k, l, first_nedges;
931 for (i = 0; i < n; i++) {
932 nedges1 += graph1[i].
nedges;
933 nedges2 += graph2[i].
nedges;
935 int *edges =
gv_calloc(nedges1 + nedges2,
sizeof(
int));
938 for (i = 0; i < n; i++) {
939 geom_graph[i].
edges = edges;
940 geom_graph[i].
size = 1;
941 geom_graph[i].
x_coord = (float) x_coords[i];
942 geom_graph[i].
y_coord = (float) y_coords[i];
943 geom_graph[i].
edges[0] = i;
944 for (j = 1; j < graph1[i].
nedges; j++) {
945 edges[j] = graph1[i].
edges[j];
947 first_nedges = k = graph1[i].
nedges;
948 for (j = 1; j < graph2[i].
nedges; j++) {
950 for (l = 1; l < first_nedges; l++) {
955 if (l == first_nedges) {
974 double *x_coords,
double *y_coords,
981 y_coords[counter++] =
graph[
node].y_coord;
988 level - 1, x_coords, y_coords,
991 if (hierarchy->
cv2v[level][2 *
node + 1] >= 0) {
996 level - 1, x_coords, y_coords,
1008 double *x_coords,
double *y_coords,
int counter)
1013 if (
graph[
node].active_level == level) {
1014 graph[
node].physical_x_coord = (float) x_coords[counter];
1015 graph[
node].physical_y_coord = (float) y_coords[counter++];
1022 level - 1, x_coords, y_coords, counter);
1024 if (hierarchy->
cv2v[level][2 *
node + 1] >= 0) {
1027 hierarchy->
cv2v[level][2*
node + 1],
1028 level - 1, x_coords, y_coords,
1040 while (active_level > level) {
1053 while (active_level > level) {
1069 float *x,
float *y) {
1071 while (active_level > level) {
1084 for (i=0; i<hierarchy->
nlevels; i++) {
1086 for (j=0; j<hierarchy->
nvtxs[i]; j++) {
1087 graph->active_level = 0;
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
static void * gv_calloc(size_t nmemb, size_t size)
static void * gv_alloc(size_t size)
static double dist(int dim, double *x, double *y)
double distance(double *x, int dim, int i, int j)
Agraph_t * graph(char *name)
static double findClosestActiveNode(Hierarchy *hierarchy, int node, int level, double x, double y, double closest_dist, int *closest_node, int *closest_node_level)
void init_active_level(Hierarchy *hierarchy)
void set_active_levels(Hierarchy *hierarchy, int *foci_nodes, int num_foci, levelparms_t *parms)
static double unweighted_common_fraction(v_data *graph, int v, int u, float *v_vector)
size_t extract_active_logical_coords(Hierarchy *hierarchy, int node, int level, double *x_coords, double *y_coords, size_t counter)
void find_closest_active_node(Hierarchy *hierarchy, double x, double y, int *closest_fine_node)
static void fill_neighbors_vec_unweighted(v_data *graph, int vtx, float *vtx_vec)
static double dist_from_foci(ex_vtx_data *graph, int node, int *foci, int num_foci)
static int find_leftmost_descendant(Hierarchy *hierarchy, int node, int level)
Hierarchy * create_hierarchy(v_data *graph, int nvtxs, int nedges, ex_vtx_data *geom_graph, int ngeom_edges, bool dist2_limit)
int set_active_physical_coords(Hierarchy *hierarchy, int node, int level, double *x_coords, double *y_coords, int counter)
void find_old_physical_coords(Hierarchy *hierarchy, int level, int node, float *x, float *y)
static void fill_neighbors_vec(v_data *graph, int vtx, float *vtx_vec)
void find_active_ancestor_info(Hierarchy *hierarchy, int level, int node, int *levell, int *nodee)
static double ddist(ex_vtx_data *geom_graph, int v, int u)
static void empty_neighbors_vec(v_data *graph, int vtx, float *vtx_vec)
static int make_coarse_ex_graph(ex_vtx_data *graph, int nedges, ex_vtx_data **cgp, int cnvtxs, int *v2cv, int *cv2v)
static ex_vtx_data * cpExGraph(ex_vtx_data *graph, int n, int nedges)
static void makev2cv(int *mflag, int nvtxs, int *v2cv, int *cv2v)
static int make_coarse_graph(v_data *graph, int nedges, v_data **cgp, int cnvtxs, int *v2cv, int *cv2v)
static int maxmatch(v_data *graph, ex_vtx_data *geom_graph, int nvtxs, int *mflag, bool dist2_limit)
static v_data * cpGraph(v_data *graph, int n, int nedges)
static int dist3(v_data *graph, int node1, int node2)
static void coarsen_match(v_data *graph, ex_vtx_data *geom_graph, int nvtxs, int nedges, int geom_nedges, v_data **cgraph, ex_vtx_data **cgeom_graph, int *cnp, int *cnedges, int *cgeom_nedges, int **v2cvp, int **cv2vp, bool dist2_limit)
void find_physical_coords(Hierarchy *hierarchy, int level, int node, float *x, float *y)
int init_ex_graph(v_data *graph1, v_data *graph2, int n, double *x_coords, double *y_coords, ex_vtx_data **gp)
#define neighbor(t, i, edim, elist)
static int nedges
total no. of edges used in routing
qsort with carried along context
static void sort_place(double *place, int *ordering, size_t size)
sort an array of doubles based on an list of their desired order
ex_vtx_data ** geom_graphs
float old_physical_y_coord
float old_physical_x_coord