Exemple #1
0
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);
}
Exemple #2
0
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;
}
Exemple #4
0
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;
}