Path: blob/devel/elmergrid/src/metis-5.1.0/libmetis/initpart.c
3206 views
/*1* Copyright 1997, Regents of the University of Minnesota2*3* initpart.c4*5* This file contains code that performs the initial partition of the6* coarsest graph7*8* Started 7/23/979* George10*11*/1213#include "metislib.h"1415/*************************************************************************/16/*! This function computes the initial bisection of the coarsest graph */17/*************************************************************************/18void Init2WayPartition(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,19idx_t niparts)20{21mdbglvl_et dbglvl;2223ASSERT(graph->tvwgt[0] >= 0);2425dbglvl = ctrl->dbglvl;26IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE);27IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO);2829IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));3031switch (ctrl->iptype) {32case METIS_IPTYPE_RANDOM:33if (graph->ncon == 1)34RandomBisection(ctrl, graph, ntpwgts, niparts);35else36McRandomBisection(ctrl, graph, ntpwgts, niparts);37break;3839case METIS_IPTYPE_GROW:40if (graph->nedges == 0)41if (graph->ncon == 1)42RandomBisection(ctrl, graph, ntpwgts, niparts);43else44McRandomBisection(ctrl, graph, ntpwgts, niparts);45else46if (graph->ncon == 1)47GrowBisection(ctrl, graph, ntpwgts, niparts);48else49McGrowBisection(ctrl, graph, ntpwgts, niparts);50break;5152default:53gk_errexit(SIGERR, "Unknown initial partition type: %d\n", ctrl->iptype);54}5556IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Cut: %"PRIDX"\n", graph->mincut));57IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));58ctrl->dbglvl = dbglvl;5960}616263/*************************************************************************/64/*! This function computes the initial separator of the coarsest graph */65/*************************************************************************/66void InitSeparator(ctrl_t *ctrl, graph_t *graph, idx_t niparts)67{68real_t ntpwgts[2] = {0.5, 0.5};69mdbglvl_et dbglvl;7071dbglvl = ctrl->dbglvl;72IFSET(ctrl->dbglvl, METIS_DBG_REFINE, ctrl->dbglvl -= METIS_DBG_REFINE);73IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO, ctrl->dbglvl -= METIS_DBG_MOVEINFO);7475IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));7677/* this is required for the cut-based part of the refinement */78Setup2WayBalMultipliers(ctrl, graph, ntpwgts);7980switch (ctrl->iptype) {81case METIS_IPTYPE_EDGE:82if (graph->nedges == 0)83RandomBisection(ctrl, graph, ntpwgts, niparts);84else85GrowBisection(ctrl, graph, ntpwgts, niparts);8687Compute2WayPartitionParams(ctrl, graph);88ConstructSeparator(ctrl, graph);89break;9091case METIS_IPTYPE_NODE:92GrowBisectionNode(ctrl, graph, ntpwgts, niparts);93break;9495default:96gk_errexit(SIGERR, "Unkown iptype of %"PRIDX"\n", ctrl->iptype);97}9899IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial Sep: %"PRIDX"\n", graph->mincut));100IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));101102ctrl->dbglvl = dbglvl;103104}105106107/*************************************************************************/108/*! This function computes a bisection of a graph by randomly assigning109the vertices followed by a bisection refinement.110The resulting partition is returned in graph->where.111*/112/*************************************************************************/113void RandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,114idx_t niparts)115{116idx_t i, ii, j, k, nvtxs, pwgts[2], zeromaxpwgt, from, me,117bestcut=0, icut, mincut, inbfs;118idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where;119idx_t *perm, *bestwhere;120121WCOREPUSH;122123nvtxs = graph->nvtxs;124xadj = graph->xadj;125vwgt = graph->vwgt;126adjncy = graph->adjncy;127adjwgt = graph->adjwgt;128129Allocate2WayPartitionMemory(ctrl, graph);130where = graph->where;131132bestwhere = iwspacemalloc(ctrl, nvtxs);133perm = iwspacemalloc(ctrl, nvtxs);134135zeromaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[0];136137for (inbfs=0; inbfs<niparts; inbfs++) {138iset(nvtxs, 1, where);139140if (inbfs > 0) {141irandArrayPermute(nvtxs, perm, nvtxs/2, 1);142pwgts[1] = graph->tvwgt[0];143pwgts[0] = 0;144145for (ii=0; ii<nvtxs; ii++) {146i = perm[ii];147if (pwgts[0]+vwgt[i] < zeromaxpwgt) {148where[i] = 0;149pwgts[0] += vwgt[i];150pwgts[1] -= vwgt[i];151if (pwgts[0] > zeromaxpwgt)152break;153}154}155}156157/* Do some partition refinement */158Compute2WayPartitionParams(ctrl, graph);159/* printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut); */160161Balance2Way(ctrl, graph, ntpwgts);162/* printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */163164FM_2WayRefine(ctrl, graph, ntpwgts, 4);165/* printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0], graph->pwgts[1], graph->mincut); */166167if (inbfs==0 || bestcut > graph->mincut) {168bestcut = graph->mincut;169icopy(nvtxs, where, bestwhere);170if (bestcut == 0)171break;172}173}174175graph->mincut = bestcut;176icopy(nvtxs, bestwhere, where);177178WCOREPOP;179}180181182/*************************************************************************/183/*! This function takes a graph and produces a bisection by using a region184growing algorithm. The resulting bisection is refined using FM.185The resulting partition is returned in graph->where.186*/187/*************************************************************************/188void GrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,189idx_t niparts)190{191idx_t i, j, k, nvtxs, drain, nleft, first, last,192pwgts[2], oneminpwgt, onemaxpwgt,193from, me, bestcut=0, icut, mincut, inbfs;194idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where;195idx_t *queue, *touched, *gain, *bestwhere;196197WCOREPUSH;198199nvtxs = graph->nvtxs;200xadj = graph->xadj;201vwgt = graph->vwgt;202adjncy = graph->adjncy;203adjwgt = graph->adjwgt;204205Allocate2WayPartitionMemory(ctrl, graph);206where = graph->where;207208bestwhere = iwspacemalloc(ctrl, nvtxs);209queue = iwspacemalloc(ctrl, nvtxs);210touched = iwspacemalloc(ctrl, nvtxs);211212onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*ntpwgts[1];213oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*ntpwgts[1];214215for (inbfs=0; inbfs<niparts; inbfs++) {216iset(nvtxs, 1, where);217218iset(nvtxs, 0, touched);219220pwgts[1] = graph->tvwgt[0];221pwgts[0] = 0;222223224queue[0] = irandInRange(nvtxs);225touched[queue[0]] = 1;226first = 0;227last = 1;228nleft = nvtxs-1;229drain = 0;230231/* Start the BFS from queue to get a partition */232for (;;) {233if (first == last) { /* Empty. Disconnected graph! */234if (nleft == 0 || drain)235break;236237k = irandInRange(nleft);238for (i=0; i<nvtxs; i++) {239if (touched[i] == 0) {240if (k == 0)241break;242else243k--;244}245}246247queue[0] = i;248touched[i] = 1;249first = 0;250last = 1;251nleft--;252}253254i = queue[first++];255if (pwgts[0] > 0 && pwgts[1]-vwgt[i] < oneminpwgt) {256drain = 1;257continue;258}259260where[i] = 0;261INC_DEC(pwgts[0], pwgts[1], vwgt[i]);262if (pwgts[1] <= onemaxpwgt)263break;264265drain = 0;266for (j=xadj[i]; j<xadj[i+1]; j++) {267k = adjncy[j];268if (touched[k] == 0) {269queue[last++] = k;270touched[k] = 1;271nleft--;272}273}274}275276/* Check to see if we hit any bad limiting cases */277if (pwgts[1] == 0)278where[irandInRange(nvtxs)] = 1;279if (pwgts[0] == 0)280where[irandInRange(nvtxs)] = 0;281282/*************************************************************283* Do some partition refinement284**************************************************************/285Compute2WayPartitionParams(ctrl, graph);286/*287printf("IPART: %3"PRIDX" [%5"PRIDX" %5"PRIDX"] [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n",288graph->nvtxs, pwgts[0], pwgts[1], graph->pwgts[0], graph->pwgts[1], graph->mincut);289*/290291Balance2Way(ctrl, graph, ntpwgts);292/*293printf("BPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0],294graph->pwgts[1], graph->mincut);295*/296297FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);298/*299printf("RPART: [%5"PRIDX" %5"PRIDX"] %5"PRIDX"\n", graph->pwgts[0],300graph->pwgts[1], graph->mincut);301*/302303if (inbfs == 0 || bestcut > graph->mincut) {304bestcut = graph->mincut;305icopy(nvtxs, where, bestwhere);306if (bestcut == 0)307break;308}309}310311graph->mincut = bestcut;312icopy(nvtxs, bestwhere, where);313314WCOREPOP;315}316317318/*************************************************************************/319/*! This function takes a multi-constraint graph and computes a bisection320by randomly assigning the vertices and then refining it. The resulting321partition is returned in graph->where.322*/323/**************************************************************************/324void McRandomBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,325idx_t niparts)326{327idx_t i, ii, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs, qnum;328idx_t *bestwhere, *where, *perm, *counts;329idx_t *vwgt;330331WCOREPUSH;332333nvtxs = graph->nvtxs;334ncon = graph->ncon;335vwgt = graph->vwgt;336337Allocate2WayPartitionMemory(ctrl, graph);338where = graph->where;339340bestwhere = iwspacemalloc(ctrl, nvtxs);341perm = iwspacemalloc(ctrl, nvtxs);342counts = iwspacemalloc(ctrl, ncon);343344for (inbfs=0; inbfs<2*niparts; inbfs++) {345irandArrayPermute(nvtxs, perm, nvtxs/2, 1);346iset(ncon, 0, counts);347348/* partition by spliting the queues randomly */349for (ii=0; ii<nvtxs; ii++) {350i = perm[ii];351qnum = iargmax(ncon, vwgt+i*ncon);352where[i] = (counts[qnum]++)%2;353}354355Compute2WayPartitionParams(ctrl, graph);356357FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);358Balance2Way(ctrl, graph, ntpwgts);359FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);360Balance2Way(ctrl, graph, ntpwgts);361FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);362363if (inbfs == 0 || bestcut >= graph->mincut) {364bestcut = graph->mincut;365icopy(nvtxs, where, bestwhere);366if (bestcut == 0)367break;368}369}370371graph->mincut = bestcut;372icopy(nvtxs, bestwhere, where);373374WCOREPOP;375}376377378/*************************************************************************/379/*! This function takes a multi-constraint graph and produces a bisection380by using a region growing algorithm. The resulting partition is381returned in graph->where.382*/383/*************************************************************************/384void McGrowBisection(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,385idx_t niparts)386{387idx_t i, j, k, nvtxs, ncon, from, bestcut=0, mincut, inbfs;388idx_t *bestwhere, *where;389390WCOREPUSH;391392nvtxs = graph->nvtxs;393394Allocate2WayPartitionMemory(ctrl, graph);395where = graph->where;396397bestwhere = iwspacemalloc(ctrl, nvtxs);398399for (inbfs=0; inbfs<2*niparts; inbfs++) {400iset(nvtxs, 1, where);401where[irandInRange(nvtxs)] = 0;402403Compute2WayPartitionParams(ctrl, graph);404405Balance2Way(ctrl, graph, ntpwgts);406FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);407Balance2Way(ctrl, graph, ntpwgts);408FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);409410if (inbfs == 0 || bestcut >= graph->mincut) {411bestcut = graph->mincut;412icopy(nvtxs, where, bestwhere);413if (bestcut == 0)414break;415}416}417418graph->mincut = bestcut;419icopy(nvtxs, bestwhere, where);420421WCOREPOP;422}423424425/*************************************************************************/426/* This function takes a graph and produces a tri-section into left, right,427and separator using a region growing algorithm. The resulting separator428is refined using node FM.429The resulting partition is returned in graph->where.430*/431/**************************************************************************/432void GrowBisectionNode(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,433idx_t niparts)434{435idx_t i, j, k, nvtxs, drain, nleft, first, last, pwgts[2], oneminpwgt,436onemaxpwgt, from, me, bestcut=0, icut, mincut, inbfs;437idx_t *xadj, *vwgt, *adjncy, *adjwgt, *where, *bndind;438idx_t *queue, *touched, *gain, *bestwhere;439440WCOREPUSH;441442nvtxs = graph->nvtxs;443xadj = graph->xadj;444vwgt = graph->vwgt;445adjncy = graph->adjncy;446adjwgt = graph->adjwgt;447448bestwhere = iwspacemalloc(ctrl, nvtxs);449queue = iwspacemalloc(ctrl, nvtxs);450touched = iwspacemalloc(ctrl, nvtxs);451452onemaxpwgt = ctrl->ubfactors[0]*graph->tvwgt[0]*0.5;453oneminpwgt = (1.0/ctrl->ubfactors[0])*graph->tvwgt[0]*0.5;454455456/* Allocate refinement memory. Allocate sufficient memory for both edge and node */457graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts");458graph->where = imalloc(nvtxs, "GrowBisectionNode: where");459graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr");460graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind");461graph->id = imalloc(nvtxs, "GrowBisectionNode: id");462graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed");463graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo");464465where = graph->where;466bndind = graph->bndind;467468for (inbfs=0; inbfs<niparts; inbfs++) {469iset(nvtxs, 1, where);470iset(nvtxs, 0, touched);471472pwgts[1] = graph->tvwgt[0];473pwgts[0] = 0;474475queue[0] = irandInRange(nvtxs);476touched[queue[0]] = 1;477first = 0; last = 1;478nleft = nvtxs-1;479drain = 0;480481/* Start the BFS from queue to get a partition */482for (;;) {483if (first == last) { /* Empty. Disconnected graph! */484if (nleft == 0 || drain)485break;486487k = irandInRange(nleft);488for (i=0; i<nvtxs; i++) { /* select the kth untouched vertex */489if (touched[i] == 0) {490if (k == 0)491break;492else493k--;494}495}496497queue[0] = i;498touched[i] = 1;499first = 0;500last = 1;501nleft--;502}503504i = queue[first++];505if (pwgts[1]-vwgt[i] < oneminpwgt) {506drain = 1;507continue;508}509510where[i] = 0;511INC_DEC(pwgts[0], pwgts[1], vwgt[i]);512if (pwgts[1] <= onemaxpwgt)513break;514515drain = 0;516for (j=xadj[i]; j<xadj[i+1]; j++) {517k = adjncy[j];518if (touched[k] == 0) {519queue[last++] = k;520touched[k] = 1;521nleft--;522}523}524}525526/*************************************************************527* Do some partition refinement528**************************************************************/529Compute2WayPartitionParams(ctrl, graph);530Balance2Way(ctrl, graph, ntpwgts);531FM_2WayRefine(ctrl, graph, ntpwgts, 4);532533/* Construct and refine the vertex separator */534for (i=0; i<graph->nbnd; i++) {535j = bndind[i];536if (xadj[j+1]-xadj[j] > 0) /* ignore islands */537where[j] = 2;538}539540Compute2WayNodePartitionParams(ctrl, graph);541FM_2WayNodeRefine2Sided(ctrl, graph, 1);542FM_2WayNodeRefine1Sided(ctrl, graph, 4);543544/*545printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n",546inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut);547*/548549if (inbfs == 0 || bestcut > graph->mincut) {550bestcut = graph->mincut;551icopy(nvtxs, where, bestwhere);552}553}554555graph->mincut = bestcut;556icopy(nvtxs, bestwhere, where);557558WCOREPOP;559}560561562/*************************************************************************/563/* This function takes a graph and produces a tri-section into left, right,564and separator using a region growing algorithm. The resulting separator565is refined using node FM.566The resulting partition is returned in graph->where.567*/568/**************************************************************************/569void GrowBisectionNode2(ctrl_t *ctrl, graph_t *graph, real_t *ntpwgts,570idx_t niparts)571{572idx_t i, j, k, nvtxs, bestcut=0, mincut, inbfs;573idx_t *xadj, *where, *bndind, *bestwhere;574575WCOREPUSH;576577nvtxs = graph->nvtxs;578xadj = graph->xadj;579580/* Allocate refinement memory. Allocate sufficient memory for both edge and node */581graph->pwgts = imalloc(3, "GrowBisectionNode: pwgts");582graph->where = imalloc(nvtxs, "GrowBisectionNode: where");583graph->bndptr = imalloc(nvtxs, "GrowBisectionNode: bndptr");584graph->bndind = imalloc(nvtxs, "GrowBisectionNode: bndind");585graph->id = imalloc(nvtxs, "GrowBisectionNode: id");586graph->ed = imalloc(nvtxs, "GrowBisectionNode: ed");587graph->nrinfo = (nrinfo_t *)gk_malloc(nvtxs*sizeof(nrinfo_t), "GrowBisectionNode: nrinfo");588589bestwhere = iwspacemalloc(ctrl, nvtxs);590591where = graph->where;592bndind = graph->bndind;593594for (inbfs=0; inbfs<niparts; inbfs++) {595iset(nvtxs, 1, where);596if (inbfs > 0)597where[irandInRange(nvtxs)] = 0;598599Compute2WayPartitionParams(ctrl, graph);600General2WayBalance(ctrl, graph, ntpwgts);601FM_2WayRefine(ctrl, graph, ntpwgts, ctrl->niter);602603/* Construct and refine the vertex separator */604for (i=0; i<graph->nbnd; i++) {605j = bndind[i];606if (xadj[j+1]-xadj[j] > 0) /* ignore islands */607where[j] = 2;608}609610Compute2WayNodePartitionParams(ctrl, graph);611FM_2WayNodeRefine2Sided(ctrl, graph, 4);612613/*614printf("ISep: [%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"] %"PRIDX"\n",615inbfs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2], bestcut);616*/617618if (inbfs == 0 || bestcut > graph->mincut) {619bestcut = graph->mincut;620icopy(nvtxs, where, bestwhere);621}622}623624graph->mincut = bestcut;625icopy(nvtxs, bestwhere, where);626627WCOREPOP;628}629630631632