Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/compress.c
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* compress.c4*5* This file contains code for compressing nodes with identical adjacency6* structure and for prunning dense columns7*8* Started 9/17/979* George10*/1112#include "metislib.h"1314/*************************************************************************/15/*! This function compresses a graph by merging identical vertices16The compression should lead to at least 10% reduction.1718The compressed graph that is generated has its adjwgts set to 1.1920\returns 1 if compression was performed, otherwise it returns 0.2122*/23/**************************************************************************/24graph_t *CompressGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy,25idx_t *vwgt, idx_t *cptr, idx_t *cind)26{27idx_t i, ii, iii, j, jj, k, l, cnvtxs, cnedges;28idx_t *cxadj, *cadjncy, *cvwgt, *mark, *map;29ikv_t *keys;30graph_t *graph=NULL;3132mark = ismalloc(nvtxs, -1, "CompressGraph: mark");33map = ismalloc(nvtxs, -1, "CompressGraph: map");34keys = ikvmalloc(nvtxs, "CompressGraph: keys");3536/* Compute a key for each adjacency list */37for (i=0; i<nvtxs; i++) {38k = 0;39for (j=xadj[i]; j<xadj[i+1]; j++)40k += adjncy[j];41keys[i].key = k+i; /* Add the diagonal entry as well */42keys[i].val = i;43}4445ikvsorti(nvtxs, keys);4647l = cptr[0] = 0;48for (cnvtxs=i=0; i<nvtxs; i++) {49ii = keys[i].val;50if (map[ii] == -1) {51mark[ii] = i; /* Add the diagonal entry */52for (j=xadj[ii]; j<xadj[ii+1]; j++)53mark[adjncy[j]] = i;5455map[ii] = cnvtxs;56cind[l++] = ii;5758for (j=i+1; j<nvtxs; j++) {59iii = keys[j].val;6061if (keys[i].key != keys[j].key || xadj[ii+1]-xadj[ii] != xadj[iii+1]-xadj[iii])62break; /* Break if keys or degrees are different */6364if (map[iii] == -1) { /* Do a comparison if iii has not been mapped */65for (jj=xadj[iii]; jj<xadj[iii+1]; jj++) {66if (mark[adjncy[jj]] != i)67break;68}6970if (jj == xadj[iii+1]) { /* Identical adjacency structure */71map[iii] = cnvtxs;72cind[l++] = iii;73}74}75}7677cptr[++cnvtxs] = l;78}79}8081IFSET(ctrl->dbglvl, METIS_DBG_INFO,82printf(" Compression: reduction in # of vertices: %"PRIDX".\n", nvtxs-cnvtxs));838485if (cnvtxs < COMPRESSION_FRACTION*nvtxs) {86/* Sufficient compression is possible, so go ahead and create the87compressed graph */8889graph = CreateGraph();9091cnedges = 0;92for (i=0; i<cnvtxs; i++) {93ii = cind[cptr[i]];94cnedges += xadj[ii+1]-xadj[ii];95}9697/* Allocate memory for the compressed graph */98cxadj = graph->xadj = imalloc(cnvtxs+1, "CompressGraph: xadj");99cvwgt = graph->vwgt = ismalloc(cnvtxs, 0, "CompressGraph: vwgt");100cadjncy = graph->adjncy = imalloc(cnedges, "CompressGraph: adjncy");101graph->adjwgt = ismalloc(cnedges, 1, "CompressGraph: adjwgt");102103/* Now go and compress the graph */104iset(nvtxs, -1, mark);105l = cxadj[0] = 0;106for (i=0; i<cnvtxs; i++) {107mark[i] = i; /* Remove any dioganal entries in the compressed graph */108for (j=cptr[i]; j<cptr[i+1]; j++) {109ii = cind[j];110111/* accumulate the vertex weights of the consistuent vertices */112cvwgt[i] += (vwgt == NULL ? 1 : vwgt[ii]);113114/* generate the combined adjancency list */115for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {116k = map[adjncy[jj]];117if (mark[k] != i) {118mark[k] = i;119cadjncy[l++] = k;120}121}122}123cxadj[i+1] = l;124}125126graph->nvtxs = cnvtxs;127graph->nedges = l;128graph->ncon = 1;129130SetupGraph_tvwgt(graph);131SetupGraph_label(graph);132}133134gk_free((void **)&keys, &map, &mark, LTERM);135136return graph;137138}139140141142/*************************************************************************/143/*! This function prunes all the vertices in a graph with degree greater144than factor*average.145146\returns the number of vertices that were prunned.147*/148/*************************************************************************/149graph_t *PruneGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t *xadj, idx_t *adjncy,150idx_t *vwgt, idx_t *iperm, real_t factor)151{152idx_t i, j, k, l, nlarge, pnvtxs, pnedges;153idx_t *pxadj, *padjncy, *padjwgt, *pvwgt;154idx_t *perm;155graph_t *graph=NULL;156157perm = imalloc(nvtxs, "PruneGraph: perm");158159factor = factor*xadj[nvtxs]/nvtxs;160161pnvtxs = pnedges = nlarge = 0;162for (i=0; i<nvtxs; i++) {163if (xadj[i+1]-xadj[i] < factor) {164perm[i] = pnvtxs;165iperm[pnvtxs++] = i;166pnedges += xadj[i+1]-xadj[i];167}168else {169perm[i] = nvtxs - ++nlarge;170iperm[nvtxs-nlarge] = i;171}172}173174IFSET(ctrl->dbglvl, METIS_DBG_INFO,175printf(" Pruned %"PRIDX" of %"PRIDX" vertices.\n", nlarge, nvtxs));176177178if (nlarge > 0 && nlarge < nvtxs) {179/* Prunning is possible, so go ahead and create the prunned graph */180graph = CreateGraph();181182/* Allocate memory for the prunned graph*/183pxadj = graph->xadj = imalloc(pnvtxs+1, "PruneGraph: xadj");184pvwgt = graph->vwgt = imalloc(pnvtxs, "PruneGraph: vwgt");185padjncy = graph->adjncy = imalloc(pnedges, "PruneGraph: adjncy");186graph->adjwgt = ismalloc(pnedges, 1, "PruneGraph: adjwgt");187188pxadj[0] = pnedges = l = 0;189for (i=0; i<nvtxs; i++) {190if (xadj[i+1]-xadj[i] < factor) {191pvwgt[l] = (vwgt == NULL ? 1 : vwgt[i]);192193for (j=xadj[i]; j<xadj[i+1]; j++) {194k = perm[adjncy[j]];195if (k < pnvtxs)196padjncy[pnedges++] = k;197}198pxadj[++l] = pnedges;199}200}201202graph->nvtxs = pnvtxs;203graph->nedges = pnedges;204graph->ncon = 1;205206SetupGraph_tvwgt(graph);207SetupGraph_label(graph);208}209else if (nlarge > 0 && nlarge == nvtxs) {210IFSET(ctrl->dbglvl, METIS_DBG_INFO,211printf(" Pruning is ignored as it removes all vertices.\n"));212nlarge = 0;213}214215216gk_free((void **)&perm, LTERM);217218return graph;219}220221222223224225226227228229230231