static void coarsen_match ( v_data * graph, /* graph to be matched */ ex_vtx_data* geom_graph, /* another graph (with coords) on the same nodes */ int nvtxs, /* number of vertices in graph */ int nedges, /* number of edges in graph */ int geom_nedges, /* number of edges in geom_graph */ v_data ** cgraph, /* coarsened version of graph */ ex_vtx_data ** cgeom_graph, /* coarsened version of geom_graph */ int *cnp, /* number of vtxs in coarsened graph */ int *cnedges, /* number of edges in coarsened graph */ int *cgeom_nedges, /* number of edges in coarsened geom_graph */ int **v2cvp, /* reference from vertices to coarse vertices */ int **cv2vp, /* reference from vertices to coarse vertices */ int dist2_limit ) /* * This function gets two graphs with the same node set and * constructs two corresponding coarsened graphs of about * half the size */ { int *mflag; /* flag indicating vtx matched or not */ int nmerged; /* number of edges contracted */ int *v2cv; /* reference from vertices to coarse vertices */ int *cv2v; /* reference from vertices to coarse vertices */ int cnvtxs; /* Allocate and initialize space. */ mflag = N_NEW(nvtxs, int); /* Find a maximal matching in the graphs */ nmerged = maxmatch(graph, geom_graph, nvtxs, mflag, dist2_limit); /* Now construct coarser graph by contracting along matching edges. */ /* Pairs of values in mflag array indicate matched vertices. */ /* A negative value indicates that vertex is unmatched. */ *cnp = cnvtxs = nvtxs - nmerged; *v2cvp = v2cv = N_NEW(nvtxs, int); *cv2vp = cv2v = N_NEW(2 * cnvtxs, int); makev2cv(mflag, nvtxs, v2cv, cv2v); free(mflag); *cnedges = make_coarse_graph(graph, nvtxs, nedges, cgraph, cnvtxs, v2cv, cv2v); *cgeom_nedges = make_coarse_ex_graph(geom_graph, nvtxs, geom_nedges, cgeom_graph, cnvtxs, v2cv, cv2v); }
void makecgraph2 ( struct vtx_data **graph, /* array of vtx data for graph */ int nvtxs, /* number of vertices in graph */ int nedges, /* number of edges in graph */ struct vtx_data ***pcgraph, /* coarsened version of graph */ int *pcnvtxs, /* number of vtxs in coarsened graph */ int *pcnedges, /* number of edges in coarsened graph */ int *mflag, /* flag indicating vtx matched or not */ int *v2cv, /* mapping from vtxs to coarsened vtxs */ int nmerged, /* number of merged vertices */ int using_ewgts, /* are edge weights being used? */ int igeom, /* dimensions of geometric data */ float **coords, /* coordinates for vertices */ float **ccoords /* coordinates for coarsened vertices */ ) { extern double make_cgraph_time; extern int DEBUG_COARSEN; /* debug flag for coarsening output */ extern int COARSEN_VWGTS; /* turn off vertex weights in coarse graph? */ extern int COARSEN_EWGTS; /* turn off edge weights in coarse graph? */ struct vtx_data **cgraph; /* coarsened version of graph */ struct vtx_data *links=NULL; /* space for all the vertex data */ struct vtx_data **gptr=NULL; /* loops through cgraph */ struct vtx_data *cgptr=NULL; /* loops through cgraph */ int *iptr=NULL; /* loops through integer arrays */ int *seenflag=NULL; /* flags for vtxs already put in edge list */ int *sptr=NULL; /* loops through seenflags */ float *eweights=NULL; /* space for edge weights in coarsened graph */ float *ewptr=NULL; /* loops through eweights */ float *fptr=NULL; /* loops through eweights */ float ewgt; /* edge weight */ double ewgt_sum; /* sum of edge weights */ double time; /* timing parameters */ int nseen; /* number of edges of coarse graph seen so far */ int cnvtxs; /* number of vtxs in coarsened graph */ int cnedges; /* twice number of edges in coarsened graph */ int neighbor; /* neighboring vertex */ int size; /* space needed for coarsened graph */ int *edges=NULL; /* space for edges in coarsened graph */ int *eptr=NULL; /* loops through edges data structure */ int cvtx; /* vertex number in coarsened graph */ int cneighbor; /* neighboring vertex number in coarsened graph */ double m1, m2; /* vertex weights of vertices being merged */ int v1, v2; /* vertices being merged */ int i, j; /* loop counters */ double seconds(); void makev2cv(); /* Compute the number of vertices and edges in the coarsened graph, */ /* and construct start pointers into coarsened edge array. */ time = seconds(); *pcnvtxs = cnvtxs = nvtxs - nmerged; /* Construct mapping from original graph vtxs to coarsened graph vtxs. */ makev2cv(mflag, nvtxs, v2cv); /* Compute an upper bound on the number of coarse graph edges. */ cnedges = nedges - nmerged; /* Now allocate space for the new graph. */ *pcgraph = cgraph = smalloc((cnvtxs + 1) * sizeof(struct vtx_data *)); links = smalloc(cnvtxs * sizeof(struct vtx_data)); size = 2 * cnedges + cnvtxs; edges = smalloc(size * sizeof(int)); if (COARSEN_EWGTS) { ewptr = eweights = smalloc(size * sizeof(float)); } /* Zero all the seen flags. */ seenflag = smalloc((cnvtxs + 1) * sizeof(int)); sptr = seenflag; for (i = cnvtxs; i; i--) { *(++sptr) = 0; } /* Use the renumbering to fill in the edge lists for the new graph. */ /* Note: This assumes coarse graph vertices are encountered in order. */ cnedges = 0; eptr = edges; ewgt = 1; sptr = seenflag; for (i = 1; i <= nvtxs; i++) { if (mflag[i] > i || mflag[i] == 0) { /* Unmatched edge, or first appearance of matched edge. */ nseen = 1; cvtx = v2cv[i]; cgptr = cgraph[cvtx] = links++; if (COARSEN_VWGTS) cgptr->vwgt = 0; else cgptr->vwgt = 1; eptr[0] = cvtx; cgptr->edges = eptr; if (COARSEN_EWGTS) { cgptr->ewgts = ewptr; } else cgptr->ewgts = NULL; *(++sptr) = 0; ewgt_sum = 0; iptr = graph[i]->edges; if (using_ewgts) fptr = graph[i]->ewgts; for (j = graph[i]->nedges - 1; j; j--) { neighbor = *(++iptr); cneighbor = v2cv[neighbor]; if (cneighbor != cvtx) { if (using_ewgts) ewgt = *(++fptr); ewgt_sum += ewgt; /* Seenflags being used as map from cvtx to index. */ if (seenflag[cneighbor] == 0) { /* New neighbor. */ cgptr->edges[nseen] = cneighbor; if (COARSEN_EWGTS) cgptr->ewgts[nseen] = ewgt; seenflag[cneighbor] = nseen++; } else { /* Already seen neighbor. */ if (COARSEN_EWGTS) cgptr->ewgts[seenflag[cneighbor]] += ewgt; } } else if (using_ewgts) ++fptr; } if (mflag[i] > i) { /* Now handle the matched vertex. */ iptr = graph[mflag[i]]->edges; if (using_ewgts) fptr = graph[mflag[i]]->ewgts; for (j = graph[mflag[i]]->nedges - 1; j; j--) { neighbor = *(++iptr); cneighbor = v2cv[neighbor]; if (cneighbor != cvtx) { if (using_ewgts) ewgt = *(++fptr); ewgt_sum += ewgt; if (seenflag[cneighbor] == 0) { /* New neighbor. */ cgptr->edges[nseen] = cneighbor; if (COARSEN_EWGTS) cgptr->ewgts[nseen] = ewgt; seenflag[cneighbor] = nseen++; } else { /* Already seen neighbor. */ if (COARSEN_EWGTS) cgptr->ewgts[seenflag[cneighbor]] += ewgt; } } else if (using_ewgts) ++fptr; } } if (COARSEN_EWGTS) cgptr->ewgts[0] = -ewgt_sum; /* Increment pointers into edges list. */ cgptr->nedges = nseen; eptr += nseen; if (COARSEN_EWGTS) { ewptr += nseen; } /* Now clear the seenflag values. */ iptr = cgptr->edges; for (j = nseen - 1; j; j--) { seenflag[*(++iptr)] = 0; } cnedges += nseen - 1; } } sfree(seenflag); /* Form new vertex weights by adding those from contracted edges. */ if (COARSEN_VWGTS) { gptr = graph; for (i = 1; i <= nvtxs; i++) { cgraph[v2cv[i]]->vwgt += (*(++gptr))->vwgt; } } /* If desired, make new vtx coordinates = center-of-mass of their parents. */ if (coords != NULL && ccoords != NULL && igeom > 0) { for (i = 0; i < igeom; i++) { ccoords[i] = smalloc((cnvtxs + 1) * sizeof(float)); } for (j = 1; j <= nvtxs; j++) { if (mflag[j] == 0) {/* If unmatched, leave it alone. */ for (i = 0; i < igeom; i++) { ccoords[i][v2cv[j]] = coords[i][j]; } } else if (j < mflag[j]) { /* If matched, use center of mass. */ v1 = j; v2 = mflag[j]; m1 = graph[v1]->vwgt; m2 = graph[v2]->vwgt; for (i = 0; i < igeom; i++) { ccoords[i][v2cv[j]] = (m1 * coords[i][v1] + m2 * coords[i][v2]) / (m1 + m2); } } } } cnedges /= 2; *pcnedges = cnedges; size = 2 * cnedges + cnvtxs; edges = srealloc(edges, size * sizeof(int)); if (COARSEN_EWGTS) { eweights = srealloc(eweights, size * sizeof(float)); } if (DEBUG_COARSEN > 0) { printf(" Coarse graph has %d vertices and %d edges\n", cnvtxs, cnedges); } make_cgraph_time += seconds() - time; }
void makecgraph ( struct vtx_data **graph, /* array of vtx data for graph */ int nvtxs, /* number of vertices in graph */ struct vtx_data ***pcgraph, /* coarsened version of graph */ int *pcnvtxs, /* number of vtxs in coarsened graph */ int *pcnedges, /* number of edges in coarsened graph */ int *mflag, /* flag indicating vtx matched or not */ int *v2cv, /* mapping from vtxs to coarsened vtxs */ int nmerged, /* number of merged vertices */ int using_ewgts, /* are edge weights being used? */ int igeom, /* dimensions of geometric data */ float **coords, /* coordinates for vertices */ float **ccoords /* coordinates for coarsened vertices */ ) { extern double make_cgraph_time; extern int DEBUG_COARSEN; /* debug flag for coarsening output */ extern int COARSEN_VWGTS; /* turn off vertex weights in coarse graph? */ extern int COARSEN_EWGTS; /* turn off edge weights in coarse graph? */ struct vtx_data **cgraph=NULL; /* coarsened version of graph */ struct vtx_data *links=NULL; /* space for all the vertex data */ struct vtx_data **gptr=NULL; /* loops through cgraph */ struct vtx_data *cgptr=NULL; /* loops through cgraph */ int *start=NULL; /* start of edgevals list for each vertex */ int *iptr=NULL; /* loops through integer arrays */ int *seenflag=NULL; /* flags for vtxs already put in edge list */ int *sptr=NULL; /* loops through seenflags */ float *eweights=NULL; /* space for edge weights in coarsened graph */ float *fptr=NULL; /* loops through eweights */ float ewgt=0.0; /* edge weight */ double ewgt_sum; /* sum of edge weights */ double time; /* timing parameters */ int nseen; /* number of edges of coarse graph seen so far */ int cnvtxs; /* number of vtxs in coarsened graph */ int cnedges; /* twice number of edges in coarsened graph */ int neighbor; /* neighboring vertex */ int size; /* space needed for coarsened graph */ int *edges=NULL; /* space for edges in coarsened graph */ int cvtx; /* vertex number in coarsened graph */ int cneighbor; /* neighboring vertex number in coarsened graph */ int i, j; /* loop counters */ double seconds(); void makev2cv(), countcedges(); /* Compute the number of vertices and edges in the coarsened graph, */ /* and construct start pointers into coarsened edge array. */ time = seconds(); *pcnvtxs = cnvtxs = nvtxs - nmerged; /* Construct mapping from original graph vtxs to coarsened graph vtxs. */ makev2cv(mflag, nvtxs, v2cv); start = smalloc((cnvtxs + 2) * sizeof(int)); seenflag = smalloc((cnvtxs + 1) * sizeof(int)); sptr = seenflag; for (i = cnvtxs; i; i--) *(++sptr) = 0; countcedges(graph, nvtxs, start, seenflag, mflag, v2cv, pcnedges); cnedges = *pcnedges; if (DEBUG_COARSEN > 0) { printf(" Coarse graph has %d vertices and %d edges\n", cnvtxs, cnedges); } /* Now allocate space for the new graph. */ *pcgraph = cgraph = smalloc((cnvtxs + 1) * sizeof(struct vtx_data *)); links = smalloc(cnvtxs * sizeof(struct vtx_data)); size = 2 * cnedges + cnvtxs; edges = smalloc(size * sizeof(int)); if (COARSEN_EWGTS) { eweights = smalloc(size * sizeof(float)); } /* Fill in simple data fields for coarsened graph. */ /* Edges and weights are put in later. */ gptr = cgraph; sptr = seenflag; for (i = 1; i <= cnvtxs; i++) { size = start[i + 1] - start[i] + 1; links->nedges = size; links->edges = edges; links->edges[0] = i; edges += size; if (COARSEN_VWGTS) links->vwgt = 0; else links->vwgt = 1; if (COARSEN_EWGTS) { links->ewgts = eweights; eweights += size; } else links->ewgts = NULL; *(++gptr) = links++; *(++sptr) = 0; } sfree(start); /* Now form new vertex weights by adding those from contracted edges. */ if (COARSEN_VWGTS) { gptr = graph; for (i = 1; i <= nvtxs; i++) { cgraph[v2cv[i]]->vwgt += (*(++gptr))->vwgt; } } /* Use the renumbering to fill in the edge lists for the new graph. */ ewgt = 1; for (i = 1; i <= nvtxs; i++) { if (mflag[i] > i || mflag[i] == 0) { /* Unmatched edge, or first appearance of matched edge. */ nseen = 1; cvtx = v2cv[i]; cgptr = cgraph[cvtx]; ewgt_sum = 0; iptr = graph[i]->edges; if (using_ewgts) fptr = graph[i]->ewgts; for (j = graph[i]->nedges - 1; j; j--) { neighbor = *(++iptr); cneighbor = v2cv[neighbor]; if (cneighbor != cvtx) { if (using_ewgts) ewgt = *(++fptr); ewgt_sum += ewgt; /* Seenflags being used as map from cvtx to index. */ if (seenflag[cneighbor] == 0) { /* New neighbor. */ cgptr->edges[nseen] = cneighbor; if (COARSEN_EWGTS) cgptr->ewgts[nseen] = ewgt; seenflag[cneighbor] = nseen++; } else { /* Already seen neighbor. */ if (COARSEN_EWGTS) cgptr->ewgts[seenflag[cneighbor]] += ewgt; } } else if (using_ewgts) ++fptr; } if (mflag[i] > i) { /* Now handle the matched vertex. */ iptr = graph[mflag[i]]->edges; if (using_ewgts) fptr = graph[mflag[i]]->ewgts; for (j = graph[mflag[i]]->nedges - 1; j; j--) { neighbor = *(++iptr); cneighbor = v2cv[neighbor]; if (cneighbor != cvtx) { if (using_ewgts) ewgt = *(++fptr); ewgt_sum += ewgt; if (seenflag[cneighbor] == 0) { /* New neighbor. */ cgptr->edges[nseen] = cneighbor; if (COARSEN_EWGTS) cgptr->ewgts[nseen] = ewgt; seenflag[cneighbor] = nseen++; } else { /* Already seen neighbor. */ if (COARSEN_EWGTS) cgptr->ewgts[seenflag[cneighbor]] += ewgt; } } else if (using_ewgts) ++fptr; } } if (COARSEN_EWGTS) cgptr->ewgts[0] = -ewgt_sum; /* Now clear the seenflag values. */ iptr = cgraph[cvtx]->edges; for (j = cgraph[cvtx]->nedges - 1; j; j--) { seenflag[*(++iptr)] = 0; } } } sfree(seenflag); /* If desired, make new vtx coordinates = center-of-mass of their parents. */ if (coords != NULL && ccoords != NULL && igeom > 0) { makeccoords(graph, nvtxs, cnvtxs, mflag, v2cv, igeom, coords, ccoords); } make_cgraph_time += seconds() - time; }
void coarsen1 ( struct vtx_data **graph, /* array of vtx data for graph */ int nvtxs, /* number of vertices in graph */ int nedges, /* number of edges in graph */ struct vtx_data ***pcgraph, /* coarsened version of graph */ int *pcnvtxs, /* number of vtxs in coarsened graph */ int *pcnedges, /* number of edges in coarsened graph */ int **pv2cv, /* pointer to v2cv */ int igeom, /* dimension for geometric information */ float **coords, /* coordinates for vertices */ float **ccoords, /* coordinates for coarsened vertices */ int using_ewgts /* are edge weights being used? */ ) { extern double coarsen_time; extern double match_time; double time; /* time routine is entered */ int *v2cv; /* maps from vtxs to cvtxs */ int *mflag; /* flag indicating vtx matched or not */ int cnvtxs; /* number of vtxs in coarse graph */ int nmerged; /* number of edges contracted */ double seconds(); int maxmatch(); void makev2cv(), makefgraph(); time = seconds(); /* Allocate and initialize space. */ v2cv = smalloc((nvtxs + 1) * sizeof(int)); mflag = smalloc((nvtxs + 1) * sizeof(int)); /* Find a maximal matching in the graph. */ nmerged = maxmatch(graph, nvtxs, nedges, mflag, using_ewgts, igeom, coords); match_time += seconds() - time; /* Now construct coarser graph by contracting along matching edges. */ /* Pairs of values in mflag array indicate matched vertices. */ /* A zero value indicates that vertex is unmatched. */ /* makecgraph(graph, nvtxs, pcgraph, pcnvtxs, pcnedges, mflag, *pv2cv, nmerged, using_ewgts, igeom, coords, ccoords); makecgraph2(graph, nvtxs, nedges, pcgraph, pcnvtxs, pcnedges, mflag, *pv2cv, nmerged, using_ewgts, igeom, coords, ccoords); */ makev2cv(mflag, nvtxs, v2cv); sfree(mflag); cnvtxs = nvtxs - nmerged; makefgraph(graph, nvtxs, nedges, pcgraph, cnvtxs, pcnedges, v2cv, using_ewgts, igeom, coords, ccoords); *pcnvtxs = cnvtxs; *pv2cv = v2cv; coarsen_time += seconds() - time; }