Cloned library METIS with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

433 lines
12 KiB

/**
\file
\brief Functions that deal with setting up the graphs for METIS.
\date Started 7/25/1997
\author George
\author Copyright 1997-2009, Regents of the University of Minnesota
\version\verbatim $Id: graph.c 15817 2013-11-25 14:58:41Z karypis $ \endverbatim
*/
#include "metislib.h"
/*************************************************************************/
/*! This function sets up the graph from the user input */
/*************************************************************************/
graph_t *SetupGraph(ctrl_t *ctrl, idx_t nvtxs, idx_t ncon, idx_t *xadj,
idx_t *adjncy, idx_t *vwgt, idx_t *vsize, idx_t *adjwgt)
{
idx_t i, j, k, sum;
real_t *nvwgt;
graph_t *graph;
/* allocate the graph and fill in the fields */
graph = CreateGraph();
graph->nvtxs = nvtxs;
graph->nedges = xadj[nvtxs];
graph->ncon = ncon;
graph->xadj = xadj;
graph->free_xadj = 0;
graph->adjncy = adjncy;
graph->free_adjncy = 0;
graph->droppedewgt = 0;
/* setup the vertex weights */
if (vwgt) {
graph->vwgt = vwgt;
graph->free_vwgt = 0;
}
else {
vwgt = graph->vwgt = ismalloc(ncon*nvtxs, 1, "SetupGraph: vwgt");
}
graph->tvwgt = imalloc(ncon, "SetupGraph: tvwgts");
graph->invtvwgt = rmalloc(ncon, "SetupGraph: invtvwgts");
for (i=0; i<ncon; i++) {
graph->tvwgt[i] = isum(nvtxs, vwgt+i, ncon);
graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1);
}
if (ctrl->objtype == METIS_OBJTYPE_VOL) {
/* Setup the vsize */
if (vsize) {
graph->vsize = vsize;
graph->free_vsize = 0;
}
else {
vsize = graph->vsize = ismalloc(nvtxs, 1, "SetupGraph: vsize");
}
/* Allocate memory for edge weights and initialize them to the sum of the vsize */
adjwgt = graph->adjwgt = imalloc(graph->nedges, "SetupGraph: adjwgt");
for (i=0; i<nvtxs; i++) {
for (j=xadj[i]; j<xadj[i+1]; j++)
adjwgt[j] = 1+vsize[i]+vsize[adjncy[j]];
}
}
else { /* For edgecut minimization */
/* setup the edge weights */
if (adjwgt) {
graph->adjwgt = adjwgt;
graph->free_adjwgt = 0;
}
else {
adjwgt = graph->adjwgt = ismalloc(graph->nedges, 1, "SetupGraph: adjwgt");
}
}
/* setup various derived info */
SetupGraph_tvwgt(graph);
if (ctrl->optype == METIS_OP_PMETIS || ctrl->optype == METIS_OP_OMETIS)
SetupGraph_label(graph);
ASSERT(CheckGraph(graph, ctrl->numflag, 1));
return graph;
}
/*************************************************************************/
/*! Set's up the tvwgt/invtvwgt info */
/*************************************************************************/
void SetupGraph_tvwgt(graph_t *graph)
{
idx_t i;
if (graph->tvwgt == NULL)
graph->tvwgt = imalloc(graph->ncon, "SetupGraph_tvwgt: tvwgt");
if (graph->invtvwgt == NULL)
graph->invtvwgt = rmalloc(graph->ncon, "SetupGraph_tvwgt: invtvwgt");
for (i=0; i<graph->ncon; i++) {
graph->tvwgt[i] = isum(graph->nvtxs, graph->vwgt+i, graph->ncon);
graph->invtvwgt[i] = 1.0/(graph->tvwgt[i] > 0 ? graph->tvwgt[i] : 1);
}
}
/*************************************************************************/
/*! Set's up the label info */
/*************************************************************************/
void SetupGraph_label(graph_t *graph)
{
idx_t i;
if (graph->label == NULL)
graph->label = imalloc(graph->nvtxs, "SetupGraph_label: label");
for (i=0; i<graph->nvtxs; i++)
graph->label[i] = i;
}
/*************************************************************************/
/*! Setup the various arrays for the split graph */
/*************************************************************************/
graph_t *SetupSplitGraph(graph_t *graph, idx_t snvtxs, idx_t snedges)
{
graph_t *sgraph;
sgraph = CreateGraph();
sgraph->nvtxs = snvtxs;
sgraph->nedges = snedges;
sgraph->ncon = graph->ncon;
/* Allocate memory for the split graph */
sgraph->xadj = imalloc(snvtxs+1, "SetupSplitGraph: xadj");
sgraph->vwgt = imalloc(sgraph->ncon*snvtxs, "SetupSplitGraph: vwgt");
sgraph->adjncy = imalloc(snedges, "SetupSplitGraph: adjncy");
sgraph->adjwgt = imalloc(snedges, "SetupSplitGraph: adjwgt");
sgraph->label = imalloc(snvtxs, "SetupSplitGraph: label");
sgraph->tvwgt = imalloc(sgraph->ncon, "SetupSplitGraph: tvwgt");
sgraph->invtvwgt = rmalloc(sgraph->ncon, "SetupSplitGraph: invtvwgt");
if (graph->vsize)
sgraph->vsize = imalloc(snvtxs, "SetupSplitGraph: vsize");
return sgraph;
}
/*************************************************************************/
/*! This function creates and initializes a graph_t data structure */
/*************************************************************************/
graph_t *CreateGraph(void)
{
graph_t *graph;
graph = (graph_t *)gk_malloc(sizeof(graph_t), "CreateGraph: graph");
InitGraph(graph);
return graph;
}
/*************************************************************************/
/*! This function initializes a graph_t data structure */
/*************************************************************************/
void InitGraph(graph_t *graph)
{
memset((void *)graph, 0, sizeof(graph_t));
/* graph size constants */
graph->nvtxs = -1;
graph->nedges = -1;
graph->ncon = -1;
graph->mincut = -1;
graph->minvol = -1;
graph->nbnd = -1;
/* memory for the graph structure */
graph->xadj = NULL;
graph->vwgt = NULL;
graph->vsize = NULL;
graph->adjncy = NULL;
graph->adjwgt = NULL;
graph->label = NULL;
graph->cmap = NULL;
graph->tvwgt = NULL;
graph->invtvwgt = NULL;
/* by default these are set to true, but the can be explicitly changed afterwards */
graph->free_xadj = 1;
graph->free_vwgt = 1;
graph->free_vsize = 1;
graph->free_adjncy = 1;
graph->free_adjwgt = 1;
/* memory for the partition/refinement structure */
graph->where = NULL;
graph->pwgts = NULL;
graph->id = NULL;
graph->ed = NULL;
graph->bndptr = NULL;
graph->bndind = NULL;
graph->nrinfo = NULL;
graph->ckrinfo = NULL;
graph->vkrinfo = NULL;
/* linked-list structure */
graph->coarser = NULL;
graph->finer = NULL;
}
/*************************************************************************/
/*! This function frees the memory storing the structure of the graph */
/*************************************************************************/
void FreeSData(graph_t *graph)
{
/* free graph structure */
if (graph->free_xadj)
gk_free((void **)&graph->xadj, LTERM);
if (graph->free_vwgt)
gk_free((void **)&graph->vwgt, LTERM);
if (graph->free_vsize)
gk_free((void **)&graph->vsize, LTERM);
if (graph->free_adjncy)
gk_free((void **)&graph->adjncy, LTERM);
if (graph->free_adjwgt)
gk_free((void **)&graph->adjwgt, LTERM);
}
/*************************************************************************/
/*! This function frees the refinement/partition memory stored in a graph */
/*************************************************************************/
void FreeRData(graph_t *graph)
{
/* The following is for the -minconn and -contig to work properly in
the vol-refinement routines */
if ((void *)graph->ckrinfo == (void *)graph->vkrinfo)
graph->ckrinfo = NULL;
/* free partition/refinement structure */
gk_free((void **)&graph->where, &graph->pwgts, &graph->id, &graph->ed,
&graph->bndptr, &graph->bndind, &graph->nrinfo, &graph->ckrinfo,
&graph->vkrinfo, LTERM);
}
/*************************************************************************/
/*! This function deallocates any memory stored in a graph */
/*************************************************************************/
void FreeGraph(graph_t **r_graph)
{
graph_t *graph;
graph = *r_graph;
/* free the graph structure's fields */
FreeSData(graph);
/* free the partition/refinement fields */
FreeRData(graph);
gk_free((void **)&graph->tvwgt, &graph->invtvwgt, &graph->label,
&graph->cmap, &graph, LTERM);
*r_graph = NULL;
}
/*************************************************************************/
/*! This function writes the key contents of the graph on disk and frees
the associated memory */
/*************************************************************************/
void graph_WriteToDisk(ctrl_t *ctrl, graph_t *graph)
{
idx_t nvtxs, ncon, *xadj;
static int gID = 1;
char outfile[1024];
FILE *fpout;
if (ctrl->ondisk == 0)
return;
if (sizeof(idx_t)*(graph->nvtxs*(graph->ncon+1)+2*graph->xadj[graph->nvtxs]) < 128*1024*1024)
return;
if (graph->gID > 0) {
sprintf(outfile, "metis%d.%d", (int)ctrl->pid, graph->gID);
gk_rmpath(outfile);
}
graph->gID = gID++;
sprintf(outfile, "metis%d.%d", (int)ctrl->pid, graph->gID);
if ((fpout = fopen(outfile, "wb")) == NULL)
return;
nvtxs = graph->nvtxs;
ncon = graph->ncon;
xadj = graph->xadj;
if (graph->free_xadj) {
if (fwrite(graph->xadj, sizeof(idx_t), nvtxs+1, fpout) != nvtxs+1)
goto error;
}
if (graph->free_vwgt) {
if (fwrite(graph->vwgt, sizeof(idx_t), nvtxs*ncon, fpout) != nvtxs*ncon)
goto error;
}
if (graph->free_adjncy) {
if (fwrite(graph->adjncy, sizeof(idx_t), xadj[nvtxs], fpout) != xadj[nvtxs])
goto error;
}
if (graph->free_adjwgt) {
if (fwrite(graph->adjwgt, sizeof(idx_t), xadj[nvtxs], fpout) != xadj[nvtxs])
goto error;
}
if (ctrl->objtype == METIS_OBJTYPE_VOL) {
if (graph->free_vsize) {
if (fwrite(graph->vsize, sizeof(idx_t), nvtxs, fpout) != nvtxs)
goto error;
}
}
fclose(fpout);
if (graph->free_xadj)
gk_free((void **)&graph->xadj, LTERM);
if (graph->free_vwgt)
gk_free((void **)&graph->vwgt, LTERM);
if (graph->free_vsize)
gk_free((void **)&graph->vsize, LTERM);
if (graph->free_adjncy)
gk_free((void **)&graph->adjncy, LTERM);
if (graph->free_adjwgt)
gk_free((void **)&graph->adjwgt, LTERM);
graph->ondisk = 1;
return;
error:
printf("Failed on writing %s\n", outfile);
fclose(fpout);
gk_rmpath(outfile);
graph->ondisk = 0;
}
/*************************************************************************/
/*! This function reads the key contents of a graph from the disk */
/*************************************************************************/
void graph_ReadFromDisk(ctrl_t *ctrl, graph_t *graph)
{
idx_t nvtxs, ncon, *xadj;
char infile[1024];
FILE *fpin;
if (graph->ondisk == 0)
return; /* this graph is not on the disk */
sprintf(infile, "metis%d.%d", (int)ctrl->pid, graph->gID);
if ((fpin = fopen(infile, "rb")) == NULL)
return;
nvtxs = graph->nvtxs;
ncon = graph->ncon;
if (graph->free_xadj) {
graph->xadj = imalloc(nvtxs+1, "graph_ReadFromDisk: xadj");
if (fread(graph->xadj, sizeof(idx_t), nvtxs+1, fpin) != nvtxs+1)
goto error;
}
xadj = graph->xadj;
if (graph->free_vwgt) {
graph->vwgt = imalloc(nvtxs*ncon, "graph_ReadFromDisk: vwgt");
if (fread(graph->vwgt, sizeof(idx_t), nvtxs*ncon, fpin) != nvtxs*ncon)
goto error;
}
if (graph->free_adjncy) {
graph->adjncy = imalloc(xadj[nvtxs], "graph_ReadFromDisk: adjncy");
if (fread(graph->adjncy, sizeof(idx_t), xadj[nvtxs], fpin) != xadj[nvtxs])
goto error;
}
if (graph->free_adjwgt) {
graph->adjwgt = imalloc(xadj[nvtxs], "graph_ReadFromDisk: adjwgt");
if (fread(graph->adjwgt, sizeof(idx_t), xadj[nvtxs], fpin) != xadj[nvtxs])
goto error;
}
if (ctrl->objtype == METIS_OBJTYPE_VOL) {
if (graph->free_vsize) {
graph->vsize = imalloc(nvtxs, "graph_ReadFromDisk: vsize");
if (fread(graph->vsize, sizeof(idx_t), nvtxs, fpin) != nvtxs)
goto error;
}
}
fclose(fpin);
// printf("ondisk: deleting %s\n", infile);
gk_rmpath(infile);
graph->gID = 0;
graph->ondisk = 0;
return;
error:
fclose(fpin);
gk_rmpath(infile);
graph->ondisk = 0;
gk_errexit(SIGERR, "Failed to restore graph %s from the disk.\n", infile);
}