44 int num_shared_neighbors = 0;
46 for (j = 0; j <
graph[u].nedges; j++) {
50 num_shared_neighbors++;
57 return ((
double) num_shared_neighbors) / (
graph[v].nedges +
59 num_shared_neighbors);
65 for (j = 0; j <
graph[vtx].nedges; j++) {
66 vtx_vec[
graph[vtx].edges[j]] = fabsf(
graph[vtx].ewgts[j]);
69 for (j = 0; j <
graph[vtx].nedges; j++) {
70 vtx_vec[
graph[vtx].edges[j]] = 1;
80 for (j = 0; j <
graph[vtx].nedges; j++) {
81 vtx_vec[
graph[vtx].edges[j]] = 1;
88 for (j = 0; j <
graph[vtx].nedges; j++) {
89 vtx_vec[
graph[vtx].edges[j]] = 0;
99 for (i = 1; i <
graph[node1].nedges; i++) {
100 u =
graph[node1].edges[i];
104 for (j = 1; j <
graph[u].nedges; j++) {
105 v =
graph[u].edges[j];
109 for (k = 1; k <
graph[v].nedges; k++) {
110 if (
graph[v].edges[k] == node2) {
130 return hypot(x_v - x_u, y_v - y_u);
158 float max_norm_edge_weight;
160 double *matchability =
gv_calloc(nvtxs,
sizeof(
double));
162 double closest_val = -1, val;
163 int closest_neighbor;
164 float *vtx_vec =
gv_calloc(nvtxs,
sizeof(
float));
165 float *weighted_vtx_vec =
gv_calloc(nvtxs,
sizeof(
float));
168 double avg_edge_len = 0, avg_deg_2 = 0;
171 for (i = 0; i < nvtxs; i++) {
172 avg_deg_2 +=
graph[i].nedges;
173 for (j = 1; j <
graph[i].nedges; j++) {
174 avg_edge_len +=
ddist(geom_graph, i,
graph[i].edges[j]);
180 avg_deg_2 *= avg_deg_2;
186 max_norm_edge_weight = -1;
187 for (i = 0; i < nvtxs; i++) {
188 inv_size = sqrt(1.0 / geom_graph[i].size);
189 for (j = 1; j <
graph[i].nedges; j++) {
190 if (
graph[i].ewgts[j] * inv_size /
191 sqrt((
float) geom_graph[
graph[i].edges[j]].size) >
192 max_norm_edge_weight) {
193 max_norm_edge_weight =
194 (float) (
graph[i].ewgts[j] * inv_size /
196 geom_graph[
graph[i].edges[j]].size));
201 max_norm_edge_weight = 1;
205 iptr = order =
gv_calloc(nvtxs,
sizeof(
int));
207 for (i = 0; i < nvtxs; i++) {
217 for (i = 0; i < nvtxs; i++) {
219 matchability[vtx] =
graph[vtx].nedges;
220 matchability[vtx] += geom_graph[vtx].
size;
222 for (j = 1; j <
graph[vtx].nedges; j++) {
225 ddist(geom_graph, vtx,
226 graph[vtx].edges[j]) / avg_edge_len);
228 matchability[vtx] += min_edge_len;
229 matchability[vtx] += ((double) rand()) / RAND_MAX;
235 for (i = 0; i < nvtxs; i++) {
238 for (i = 0; i < nvtxs; i++) {
239 weighted_vtx_vec[i] = 0;
243 for (i = 0; i < nvtxs; i++) {
245 if (mflag[vtx] >= 0) {
248 inv_size = sqrt(1.0 / geom_graph[vtx].size);
251 closest_neighbor = -1;
261 for (j = 1; j < geom_graph[vtx].
nedges; j++) {
278 B * avg_deg_2 / (
graph[vtx].nedges *
287 (weighted_vtx_vec[
neighbor] * inv_size /
288 sqrt((
float) geom_graph[
neighbor].size)) /
289 max_norm_edge_weight;
293 if (val > closest_val || closest_neighbor == -1) {
299 if (closest_neighbor != -1) {
300 mflag[vtx] = closest_neighbor;
301 mflag[closest_neighbor] = vtx;
310 free(weighted_vtx_vec);
324 for (i = 0; i < nvtxs; i++) {
328 cv2v[2 * j + 1] = -1;
330 }
else if (mflag[i] > i) {
334 cv2v[2 * j + 1] = mflag[i];
353 int *index =
gv_calloc(cnvtxs,
sizeof(
int));
362 edges =
gv_calloc(2 * maxCnedges + cnvtxs,
sizeof(
int));
363 eweights =
gv_calloc(2 * maxCnedges + cnvtxs,
sizeof(
float));
367 for (cv = 0; cv < cnvtxs; cv++) {
371 cgraph[cv].
edges = edges;
372 cgraph[cv].
ewgts = eweights;
376 for (j = 1; j <
graph[v].nedges; j++) {
379 intra_weight = 2 *
graph[v].ewgts[j];
385 cgraph[cv].
ewgts[cv_nedges] =
graph[v].ewgts[j];
394 if ((v = cv2v[2 * cv + 1]) != -1) {
395 for (j = 1; j <
graph[v].nedges; j++) {
402 cgraph[cv].
ewgts[cv_nedges] =
graph[v].ewgts[j];
409 cgraph[cv].
ewgts[0] +=
graph[v].ewgts[0] + intra_weight;
411 cgraph[cv].
nedges = cv_nedges;
412 cgraph[cv].
edges[0] = cv;
414 eweights += cv_nedges;
415 cnedges += cv_nedges;
417 for (j = 1; j < cgraph[cv].
nedges; j++)
418 index[cgraph[cv].edges[j]] = 0;
421 int internal_weight = 0;
423 for (cv = 0; cv < cnvtxs; cv++) {
425 cgraph[cv].
edges = edges;
426 cgraph[cv].
ewgts = eweights;
430 for (j = 1; j <
graph[v].nedges; j++) {
439 cgraph[cv].
ewgts[cv_nedges] = -1;
445 cgraph[cv].
ewgts[0] = (float)
graph[v].edges[0];
446 if ((v = cv2v[2 * cv + 1]) != -1) {
447 for (j = 1; j <
graph[v].nedges; j++) {
454 cgraph[cv].
ewgts[cv_nedges] = -1;
461 cgraph[cv].
ewgts[0] +=
462 (float)
graph[v].edges[0] - internal_weight;
467 cgraph[cv].
nedges = cv_nedges;
468 cgraph[cv].
edges[0] = cv;
470 eweights += cv_nedges;
471 cnedges += cv_nedges;
473 for (j = 1; j < cgraph[cv].
nedges; j++)
474 index[cgraph[cv].edges[j]] = 0;
499 int *index =
gv_calloc(cnvtxs,
sizeof(
int));
507 edges =
gv_calloc(2 * cnedges + cnvtxs,
sizeof(
int));
509 for (cv = 0; cv < cnvtxs; cv++) {
511 cgraph[cv].
edges = edges;
515 for (j = 1; j <
graph[v].nedges; j++) {
529 if ((v = cv2v[2 * cv + 1]) != -1) {
530 for (j = 1; j <
graph[v].nedges; j++) {
543 graph[v].size *
graph[v].x_coord) / (cgraph[cv].size +
547 graph[v].size *
graph[v].y_coord) / (cgraph[cv].size +
551 cgraph[cv].
nedges = cv_nedges;
552 cgraph[cv].
edges[0] = cv;
555 for (j = 1; j < cgraph[cv].
nedges; j++)
556 index[cgraph[cv].edges[j]] = 0;
596 nmerged =
maxmatch(
graph, geom_graph, nvtxs, mflag, dist2_limit);
602 *cnp = cnvtxs = nvtxs - nmerged;
604 *v2cvp = v2cv =
gv_calloc(nvtxs,
sizeof(
int));
605 *cv2vp = cv2v =
gv_calloc(2 * cnvtxs,
sizeof(
int));
629 for (i = 0; i < n; i++) {
633 for (j = 0; j <
graph[i].nedges; j++) {
634 edges[j] =
graph[i].edges[j];
636 edges +=
graph[i].nedges;
638 for (j = 0; j <
graph[i].nedges; j++) {
639 ewgts[j] =
graph[i].ewgts[j];
641 ewgts +=
graph[i].nedges;
657 for (i = 0; i < n; i++) {
660 for (j = 0; j <
graph[i].nedges; j++) {
661 edges[j] =
graph[i].edges[j];
663 edges +=
graph[i].nedges;
673 int cngeom_edges = ngeom_edges;
677 static const int min_nvtxs = 20;
678 int nlevels =
MAX(5, 10 * (
int) log((
float) (nvtxs / min_nvtxs)));
689 hierarchy->
nvtxs[0] = nvtxs;
693 hierarchy->
nvtxs[cur_level] > min_nvtxs
694 && cur_level < 50 ; cur_level++) {
695 if (cur_level == nlevels - 1) {
707 ngeom_edges = cngeom_edges;
709 (hierarchy->
graphs[cur_level],
711 hierarchy->
nvtxs[cur_level], hierarchy->
nedges[cur_level],
712 ngeom_edges, &hierarchy->
graphs[cur_level + 1],
714 &hierarchy->
nvtxs[cur_level + 1],
715 &hierarchy->
nedges[cur_level + 1], &cngeom_edges,
716 &hierarchy->
v2cv[cur_level], &hierarchy->
cv2v[cur_level + 1],
720 hierarchy->
nlevels = cur_level + 1;
723 for (i = 0; i < hierarchy->
nlevels; i++) {
725 for (j = 0; j < hierarchy->
nvtxs[i]; j++) {
740 for (i = 1; i < num_foci; i++) {
761 int n = hierarchy->
nvtxs[min_level];
765 double *distances =
gv_calloc(n,
sizeof(
double));
766 for (
int i = 0; i < n; i++) {
778 int level = min_level;
779 int group_size =
parms->num_fine_nodes * num_foci;
780 int thresh = group_size;
781 for (
int i = 0; i < n; i++) {
782 const int vtx = nodes[i];
783 if (i > thresh && level < hierarchy->nlevels - 1) {
785 group_size = (int) (group_size *
parms->coarsening_rate);
786 thresh += group_size;
788 graph[vtx].active_level = level;
798 for (level = min_level + 1; level < hierarchy->
nlevels; level++) {
801 const int *
const cv2v = hierarchy->
cv2v[level];
802 n = hierarchy->
nvtxs[level];
803 for (
int i = 0; i < n; i++) {
804 const int v = cv2v[2 * i];
805 const int u = cv2v[2 * i + 1];
807 if (
graph[v].active_level < level
808 ||
graph[u].active_level < level) {
812 graph[v].active_level =
813 MIN(
graph[v].active_level, level - 1);
814 graph[u].active_level =
815 MIN(
graph[u].active_level, level - 1);
829 for (level = hierarchy->
nlevels - 1; level > 0; level--) {
832 const int *
const cv2v = hierarchy->
cv2v[level];
833 n = hierarchy->
nvtxs[level];
834 for (
int i = 0; i < n; i++) {
835 if (cgraph[i].active_level < level) {
839 const int v = cv2v[2 * i];
840 const int u = cv2v[2 * i + 1];
859 int level,
double x,
double y,
860 double closest_dist,
int *closest_node,
861 int *closest_node_level)
869 double delx = x -
graph[
node].physical_x_coord;
870 double dely = y -
graph[
node].physical_y_coord;
871 double dist = delx*delx + dely*dely;
873 if (
dist < closest_dist)
876 *closest_node =
node;
877 *closest_node_level = level;
886 level - 1, x, y, closest_dist, closest_node,
889 if (hierarchy->
cv2v[level][2 *
node + 1] >= 0) {
892 hierarchy->
cv2v[level][2 *
node + 1],
893 level - 1, x, y, closest_dist,
894 closest_node, closest_node_level);
907 while (level > cur_level)
921 int *closest_fine_node)
923 int i, closest_node, closest_node_level;
924 int top_level = hierarchy->
nlevels - 1;
925 double min_dist = 1e20;
927 for (i = 0; i < hierarchy->
nvtxs[top_level]; i++)
929 min_dist =
findClosestActiveNode(hierarchy, i, top_level, x, y,min_dist, &closest_node, &closest_node_level);
938 double *x_coords,
double *y_coords,
ex_vtx_data ** gp)
944 int nedges1 = 0, nedges2 = 0;
946 int i, j, k, l, first_nedges;
948 for (i = 0; i < n; i++) {
949 nedges1 += graph1[i].
nedges;
950 nedges2 += graph2[i].
nedges;
952 int *edges =
gv_calloc(nedges1 + nedges2,
sizeof(
int));
955 for (i = 0; i < n; i++) {
956 geom_graph[i].
edges = edges;
957 geom_graph[i].
size = 1;
958 geom_graph[i].
x_coord = (float) x_coords[i];
959 geom_graph[i].
y_coord = (float) y_coords[i];
960 geom_graph[i].
edges[0] = i;
961 for (j = 1; j < graph1[i].
nedges; j++) {
962 edges[j] = graph1[i].
edges[j];
964 first_nedges = k = graph1[i].
nedges;
965 for (j = 1; j < graph2[i].
nedges; j++) {
967 for (l = 1; l < first_nedges; l++) {
972 if (l == first_nedges) {
991 double *x_coords,
double *y_coords,
998 y_coords[counter++] =
graph[
node].y_coord;
1005 level - 1, x_coords, y_coords,
1008 if (hierarchy->
cv2v[level][2 *
node + 1] >= 0) {
1013 level - 1, x_coords, y_coords,
1025 double *x_coords,
double *y_coords,
int counter)
1030 if (
graph[
node].active_level == level) {
1031 graph[
node].physical_x_coord = (float) x_coords[counter];
1032 graph[
node].physical_y_coord = (float) y_coords[counter++];
1039 level - 1, x_coords, y_coords, counter);
1041 if (hierarchy->
cv2v[level][2 *
node + 1] >= 0) {
1044 hierarchy->
cv2v[level][2*
node + 1],
1045 level - 1, x_coords, y_coords,
1057 while (active_level > level) {
1070 while (active_level > level) {
1086 float *x,
float *y) {
1088 while (active_level > level) {
1105 while (active_level > level) {
1110 if (active_level == level)
1120 for (i=0; i<hierarchy->
nlevels; i++) {
1122 for (j=0; j<hierarchy->
nvtxs[i]; j++) {
1123 graph->active_level = level;
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 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)
void quicksort_place(double *, int *, size_t size)
size_t extract_active_logical_coords(Hierarchy *hierarchy, int node, int level, double *x_coords, double *y_coords, size_t counter)
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)
int find_active_ancestor(Hierarchy *hierarchy, int level, int node)
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)
double find_closest_active_node(Hierarchy *hierarchy, double x, double y, int *closest_fine_node)
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)
void init_active_level(Hierarchy *hierarchy, int level)
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)
static int find_leftmost_descendant(Hierarchy *hierarchy, int node, int level, int cur_level)
#define neighbor(t, i, edim, elist)
static int nedges
total no. of edges used in routing
ex_vtx_data ** geom_graphs
float old_physical_y_coord
float old_physical_x_coord