00001
00011 #include "metislib.h"
00012
00013
00014
00015
00016
00017
00018
00019
00020 void Greedy_KWayOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter,
00021 real_t ffactor, idx_t omode)
00022 {
00023 switch (ctrl->objtype) {
00024 case METIS_OBJTYPE_CUT:
00025 if (graph->ncon == 1)
00026 Greedy_KWayCutOptimize(ctrl, graph, niter, ffactor, omode);
00027 else
00028 Greedy_McKWayCutOptimize(ctrl, graph, niter, ffactor, omode);
00029 break;
00030
00031 case METIS_OBJTYPE_VOL:
00032 if (graph->ncon == 1)
00033 Greedy_KWayVolOptimize(ctrl, graph, niter, ffactor, omode);
00034 else
00035 Greedy_McKWayVolOptimize(ctrl, graph, niter, ffactor, omode);
00036 break;
00037
00038 default:
00039 gk_errexit(SIGERR, "Unknown objtype of %d\n", ctrl->objtype);
00040 }
00041 }
00042
00043
00044
00059
00060 void Greedy_KWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter,
00061 real_t ffactor, idx_t omode)
00062 {
00063
00064 idx_t i, ii, iii, j, k, l, pass, nvtxs, nparts, gain;
00065 idx_t from, me, to, oldcut, vwgt;
00066 idx_t *xadj, *adjncy, *adjwgt;
00067 idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts;
00068 idx_t nmoved, nupd, *vstatus, *updptr, *updind;
00069 idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL;
00070 idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL;
00071 idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE);
00072
00073
00074 idx_t nbnd, oldnnbrs;
00075 rpq_t *queue;
00076 real_t rgain;
00077 ckrinfo_t *myrinfo;
00078 cnbr_t *mynbrs;
00079
00080 WCOREPUSH;
00081
00082
00083 nvtxs = graph->nvtxs;
00084 xadj = graph->xadj;
00085 adjncy = graph->adjncy;
00086 adjwgt = graph->adjwgt;
00087
00088 bndind = graph->bndind;
00089 bndptr = graph->bndptr;
00090
00091 where = graph->where;
00092 pwgts = graph->pwgts;
00093
00094 nparts = ctrl->nparts;
00095
00096
00097 minwgt = iwspacemalloc(ctrl, nparts);
00098 maxwgt = iwspacemalloc(ctrl, nparts);
00099 itpwgts = iwspacemalloc(ctrl, nparts);
00100
00101 for (i=0; i<nparts; i++) {
00102 itpwgts[i] = ctrl->tpwgts[i]*graph->tvwgt[0];
00103 maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0];
00104 minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]);
00105 }
00106
00107 perm = iwspacemalloc(ctrl, nvtxs);
00108
00109
00110
00111
00112
00113
00114 safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts));
00115
00116 if (ctrl->minconn) {
00117 ComputeSubDomainGraph(ctrl, graph);
00118
00119 nads = ctrl->nads;
00120 adids = ctrl->adids;
00121 adwgts = ctrl->adwgts;
00122 doms = iset(nparts, 0, ctrl->pvec1);
00123 }
00124
00125
00126
00127
00128 vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs));
00129 updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
00130 updind = iwspacemalloc(ctrl, nvtxs);
00131
00132 if (ctrl->contig) {
00133
00134 bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00135 bfsind = iwspacemalloc(ctrl, nvtxs);
00136 bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00137 }
00138
00139 if (ctrl->dbglvl&METIS_DBG_REFINE) {
00140 printf("%s: [%6"PRIDX" %6"PRIDX"]-[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL","
00141 " Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %6"PRIDX,
00142 (omode == OMODE_REFINE ? "GRC" : "GBC"),
00143 pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), minwgt[0], maxwgt[0],
00144 ComputeLoadImbalance(graph, nparts, ctrl->pijbm),
00145 graph->nvtxs, graph->nbnd, graph->mincut);
00146 if (ctrl->minconn)
00147 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
00148 printf("\n");
00149 }
00150
00151 queue = rpqCreate(nvtxs);
00152
00153
00154
00155
00156 for (pass=0; pass<niter; pass++) {
00157 ASSERT(ComputeCut(graph, where) == graph->mincut);
00158
00159 if (omode == OMODE_BALANCE) {
00160
00161 for (i=0; i<nparts; i++) {
00162 if (pwgts[i] > maxwgt[i])
00163 break;
00164 }
00165 if (i == nparts)
00166 break;
00167 }
00168
00169 oldcut = graph->mincut;
00170 nbnd = graph->nbnd;
00171 nupd = 0;
00172
00173 if (ctrl->minconn)
00174 maxndoms = imax(nparts, nads);
00175
00176
00177 irandArrayPermute(nbnd, perm, nbnd/4, 1);
00178 for (ii=0; ii<nbnd; ii++) {
00179 i = bndind[perm[ii]];
00180 rgain = (graph->ckrinfo[i].nnbrs > 0 ?
00181 1.0*graph->ckrinfo[i].ed/sqrt(graph->ckrinfo[i].nnbrs) : 0.0)
00182 - graph->ckrinfo[i].id;
00183 rpqInsert(queue, i, rgain);
00184 vstatus[i] = VPQSTATUS_PRESENT;
00185 ListInsert(nupd, updind, updptr, i);
00186 }
00187
00188
00189 for (nmoved=0, iii=0;;iii++) {
00190 if ((i = rpqGetTop(queue)) == -1)
00191 break;
00192 vstatus[i] = VPQSTATUS_EXTRACTED;
00193
00194 myrinfo = graph->ckrinfo+i;
00195 mynbrs = ctrl->cnbrpool + myrinfo->inbr;
00196
00197 from = where[i];
00198 vwgt = graph->vwgt[i];
00199
00200
00201 if (omode == OMODE_REFINE) {
00202 if (myrinfo->id > 0 && pwgts[from]-vwgt < minwgt[from])
00203 continue;
00204 }
00205 else {
00206 if (pwgts[from]-vwgt < minwgt[from])
00207 continue;
00208 }
00209
00210 if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk))
00211 continue;
00212
00213 if (ctrl->minconn)
00214 SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms);
00215
00216
00217 if (omode == OMODE_REFINE) {
00218 for (k=myrinfo->nnbrs-1; k>=0; k--) {
00219 if (!safetos[to=mynbrs[k].pid])
00220 continue;
00221 gain = mynbrs[k].ed-myrinfo->id;
00222 if (gain >= 0 && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain)
00223 break;
00224 }
00225 if (k < 0)
00226 continue;
00227
00228 for (j=k-1; j>=0; j--) {
00229 if (!safetos[to=mynbrs[j].pid])
00230 continue;
00231 gain = mynbrs[j].ed-myrinfo->id;
00232 if ((mynbrs[j].ed > mynbrs[k].ed && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain)
00233 ||
00234 (mynbrs[j].ed == mynbrs[k].ed &&
00235 itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid]))
00236 k = j;
00237 }
00238
00239 to = mynbrs[k].pid;
00240
00241 gain = mynbrs[k].ed-myrinfo->id;
00242 if (!(gain > 0
00243 || (gain == 0
00244 && (pwgts[from] >= maxwgt[from]
00245 || itpwgts[to]*pwgts[from] > itpwgts[from]*(pwgts[to]+vwgt)
00246 || (iii%2 == 0 && safetos[to] == 2)
00247 )
00248 )
00249 )
00250 )
00251 continue;
00252 }
00253 else {
00254 for (k=myrinfo->nnbrs-1; k>=0; k--) {
00255 if (!safetos[to=mynbrs[k].pid])
00256 continue;
00257 if (pwgts[to]+vwgt <= maxwgt[to] ||
00258 itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from])
00259 break;
00260 }
00261 if (k < 0)
00262 continue;
00263
00264 for (j=k-1; j>=0; j--) {
00265 if (!safetos[to=mynbrs[j].pid])
00266 continue;
00267 if (itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid])
00268 k = j;
00269 }
00270
00271 to = mynbrs[k].pid;
00272
00273 if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] &&
00274 mynbrs[k].ed-myrinfo->id < 0)
00275 continue;
00276 }
00277
00278
00279
00280
00281
00282
00283 graph->mincut -= mynbrs[k].ed-myrinfo->id;
00284 nmoved++;
00285
00286 IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
00287 printf("\t\tMoving %6"PRIDX" to %3"PRIDX". Gain: %4"PRIDX". Cut: %6"PRIDX"\n",
00288 i, to, mynbrs[k].ed-myrinfo->id, graph->mincut));
00289
00290
00291 if (ctrl->minconn) {
00292
00293 UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, &maxndoms);
00294
00295
00296 for (j=xadj[i]; j<xadj[i+1]; j++) {
00297 me = where[adjncy[j]];
00298 if (me != from && me != to) {
00299 UpdateEdgeSubDomainGraph(ctrl, from, me, -adjwgt[j], &maxndoms);
00300 UpdateEdgeSubDomainGraph(ctrl, to, me, adjwgt[j], &maxndoms);
00301 }
00302 }
00303 }
00304
00305
00306 INC_DEC(pwgts[to], pwgts[from], vwgt);
00307 UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where, nbnd,
00308 bndptr, bndind, bndtype);
00309
00310
00311 for (j=xadj[i]; j<xadj[i+1]; j++) {
00312 ii = adjncy[j];
00313 me = where[ii];
00314 myrinfo = graph->ckrinfo+ii;
00315
00316 oldnnbrs = myrinfo->nnbrs;
00317
00318 UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me,
00319 from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, bndtype);
00320
00321 UpdateQueueInfo(queue, vstatus, ii, me, from, to, myrinfo, oldnnbrs,
00322 nupd, updptr, updind, bndtype);
00323
00324 ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]);
00325 }
00326 }
00327
00328 graph->nbnd = nbnd;
00329
00330
00331 for (i=0; i<nupd; i++) {
00332 ASSERT(updptr[updind[i]] != -1);
00333 ASSERT(vstatus[updind[i]] != VPQSTATUS_NOTPRESENT);
00334 vstatus[updind[i]] = VPQSTATUS_NOTPRESENT;
00335 updptr[updind[i]] = -1;
00336 }
00337
00338 if (ctrl->dbglvl&METIS_DBG_REFINE) {
00339 printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"."
00340 " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX,
00341 pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts),
00342 ComputeLoadImbalance(graph, nparts, ctrl->pijbm),
00343 graph->nbnd, nmoved, graph->mincut, ComputeVolume(graph, where));
00344 if (ctrl->minconn)
00345 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
00346 printf("\n");
00347 }
00348
00349 if (nmoved == 0 || (omode == OMODE_REFINE && graph->mincut == oldcut))
00350 break;
00351 }
00352
00353 rpqDestroy(queue);
00354
00355 WCOREPOP;
00356 }
00357
00358
00359
00369
00370 void Greedy_KWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter,
00371 real_t ffactor, idx_t omode)
00372 {
00373
00374 idx_t i, ii, iii, j, k, l, pass, nvtxs, nparts, gain;
00375 idx_t from, me, to, oldcut, vwgt;
00376 idx_t *xadj, *adjncy;
00377 idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt, *itpwgts;
00378 idx_t nmoved, nupd, *vstatus, *updptr, *updind;
00379 idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL;
00380 idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL;
00381 idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE);
00382
00383
00384 ipq_t *queue;
00385 idx_t oldvol, xgain;
00386 idx_t *vmarker, *pmarker, *modind;
00387 vkrinfo_t *myrinfo;
00388 vnbr_t *mynbrs;
00389
00390 WCOREPUSH;
00391
00392
00393 nvtxs = graph->nvtxs;
00394 xadj = graph->xadj;
00395 adjncy = graph->adjncy;
00396 bndptr = graph->bndptr;
00397 bndind = graph->bndind;
00398 where = graph->where;
00399 pwgts = graph->pwgts;
00400
00401 nparts = ctrl->nparts;
00402
00403
00404 minwgt = iwspacemalloc(ctrl, nparts);
00405 maxwgt = iwspacemalloc(ctrl, nparts);
00406 itpwgts = iwspacemalloc(ctrl, nparts);
00407
00408 for (i=0; i<nparts; i++) {
00409 itpwgts[i] = ctrl->tpwgts[i]*graph->tvwgt[0];
00410 maxwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*ctrl->ubfactors[0];
00411 minwgt[i] = ctrl->tpwgts[i]*graph->tvwgt[0]*(1.0/ctrl->ubfactors[0]);
00412 }
00413
00414 perm = iwspacemalloc(ctrl, nvtxs);
00415
00416
00417
00418
00419
00420
00421 safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts));
00422
00423 if (ctrl->minconn) {
00424 ComputeSubDomainGraph(ctrl, graph);
00425
00426 nads = ctrl->nads;
00427 adids = ctrl->adids;
00428 adwgts = ctrl->adwgts;
00429 doms = iset(nparts, 0, ctrl->pvec1);
00430 }
00431
00432
00433
00434
00435 vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs));
00436 updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
00437 updind = iwspacemalloc(ctrl, nvtxs);
00438
00439 if (ctrl->contig) {
00440
00441 bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00442 bfsind = iwspacemalloc(ctrl, nvtxs);
00443 bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00444 }
00445
00446
00447 modind = iwspacemalloc(ctrl, nvtxs);
00448 vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00449 pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
00450
00451 if (ctrl->dbglvl&METIS_DBG_REFINE) {
00452 printf("%s: [%6"PRIDX" %6"PRIDX"]-[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL
00453 ", Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %5"PRIDX", Vol: %5"PRIDX,
00454 (omode == OMODE_REFINE ? "GRV" : "GBV"),
00455 pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts), minwgt[0], maxwgt[0],
00456 ComputeLoadImbalance(graph, nparts, ctrl->pijbm),
00457 graph->nvtxs, graph->nbnd, graph->mincut, graph->minvol);
00458 if (ctrl->minconn)
00459 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
00460 printf("\n");
00461 }
00462
00463 queue = ipqCreate(nvtxs);
00464
00465
00466
00467
00468
00469 for (pass=0; pass<niter; pass++) {
00470 ASSERT(ComputeVolume(graph, where) == graph->minvol);
00471
00472 if (omode == OMODE_BALANCE) {
00473
00474 for (i=0; i<nparts; i++) {
00475 if (pwgts[i] > maxwgt[i])
00476 break;
00477 }
00478 if (i == nparts)
00479 break;
00480 }
00481
00482 oldcut = graph->mincut;
00483 oldvol = graph->minvol;
00484 nupd = 0;
00485
00486 if (ctrl->minconn)
00487 maxndoms = imax(nparts, nads);
00488
00489
00490 irandArrayPermute(graph->nbnd, perm, graph->nbnd/4, 1);
00491 for (ii=0; ii<graph->nbnd; ii++) {
00492 i = bndind[perm[ii]];
00493 ipqInsert(queue, i, graph->vkrinfo[i].gv);
00494 vstatus[i] = VPQSTATUS_PRESENT;
00495 ListInsert(nupd, updind, updptr, i);
00496 }
00497
00498
00499 for (nmoved=0, iii=0;;iii++) {
00500 if ((i = ipqGetTop(queue)) == -1)
00501 break;
00502 vstatus[i] = VPQSTATUS_EXTRACTED;
00503
00504 myrinfo = graph->vkrinfo+i;
00505 mynbrs = ctrl->vnbrpool + myrinfo->inbr;
00506
00507 from = where[i];
00508 vwgt = graph->vwgt[i];
00509
00510
00511 if (omode == OMODE_REFINE) {
00512 if (myrinfo->nid > 0 && pwgts[from]-vwgt < minwgt[from])
00513 continue;
00514 }
00515 else {
00516 if (pwgts[from]-vwgt < minwgt[from])
00517 continue;
00518 }
00519
00520 if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk))
00521 continue;
00522
00523 if (ctrl->minconn)
00524 SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms);
00525
00526 xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? graph->vsize[i] : 0);
00527
00528
00529 if (omode == OMODE_REFINE) {
00530 for (k=myrinfo->nnbrs-1; k>=0; k--) {
00531 if (!safetos[to=mynbrs[k].pid])
00532 continue;
00533 gain = mynbrs[k].gv + xgain;
00534 if (gain >= 0 && pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain)
00535 break;
00536 }
00537 if (k < 0)
00538 continue;
00539
00540 for (j=k-1; j>=0; j--) {
00541 if (!safetos[to=mynbrs[j].pid])
00542 continue;
00543 gain = mynbrs[j].gv + xgain;
00544 if ((mynbrs[j].gv > mynbrs[k].gv &&
00545 pwgts[to]+vwgt <= maxwgt[to]+ffactor*gain)
00546 ||
00547 (mynbrs[j].gv == mynbrs[k].gv &&
00548 mynbrs[j].ned > mynbrs[k].ned &&
00549 pwgts[to]+vwgt <= maxwgt[to])
00550 ||
00551 (mynbrs[j].gv == mynbrs[k].gv &&
00552 mynbrs[j].ned == mynbrs[k].ned &&
00553 itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid])
00554 )
00555 k = j;
00556 }
00557 to = mynbrs[k].pid;
00558
00559 ASSERT(xgain+mynbrs[k].gv >= 0);
00560
00561 j = 0;
00562 if (xgain+mynbrs[k].gv > 0 || mynbrs[k].ned-myrinfo->nid > 0)
00563 j = 1;
00564 else if (mynbrs[k].ned-myrinfo->nid == 0) {
00565 if ((iii%2 == 0 && safetos[to] == 2) ||
00566 pwgts[from] >= maxwgt[from] ||
00567 itpwgts[from]*(pwgts[to]+vwgt) < itpwgts[to]*pwgts[from])
00568 j = 1;
00569 }
00570 if (j == 0)
00571 continue;
00572 }
00573 else {
00574 for (k=myrinfo->nnbrs-1; k>=0; k--) {
00575 if (!safetos[to=mynbrs[k].pid])
00576 continue;
00577 if (pwgts[to]+vwgt <= maxwgt[to] ||
00578 itpwgts[from]*(pwgts[to]+vwgt) <= itpwgts[to]*pwgts[from])
00579 break;
00580 }
00581 if (k < 0)
00582 continue;
00583
00584 for (j=k-1; j>=0; j--) {
00585 if (!safetos[to=mynbrs[j].pid])
00586 continue;
00587 if (itpwgts[mynbrs[k].pid]*pwgts[to] < itpwgts[to]*pwgts[mynbrs[k].pid])
00588 k = j;
00589 }
00590 to = mynbrs[k].pid;
00591
00592 if (pwgts[from] < maxwgt[from] && pwgts[to] > minwgt[to] &&
00593 (xgain+mynbrs[k].gv < 0 ||
00594 (xgain+mynbrs[k].gv == 0 && mynbrs[k].ned-myrinfo->nid < 0))
00595 )
00596 continue;
00597 }
00598
00599
00600
00601
00602
00603 INC_DEC(pwgts[to], pwgts[from], vwgt);
00604 graph->mincut -= mynbrs[k].ned-myrinfo->nid;
00605 graph->minvol -= (xgain+mynbrs[k].gv);
00606 where[i] = to;
00607 nmoved++;
00608
00609 IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
00610 printf("\t\tMoving %6"PRIDX" from %3"PRIDX" to %3"PRIDX". "
00611 "Gain: [%4"PRIDX" %4"PRIDX"]. Cut: %6"PRIDX", Vol: %6"PRIDX"\n",
00612 i, from, to, xgain+mynbrs[k].gv, mynbrs[k].ned-myrinfo->nid,
00613 graph->mincut, graph->minvol));
00614
00615
00616 if (ctrl->minconn) {
00617
00618 UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->nid-mynbrs[k].ned, &maxndoms);
00619
00620
00621 for (j=xadj[i]; j<xadj[i+1]; j++) {
00622 me = where[adjncy[j]];
00623 if (me != from && me != to) {
00624 UpdateEdgeSubDomainGraph(ctrl, from, me, -1, &maxndoms);
00625 UpdateEdgeSubDomainGraph(ctrl, to, me, 1, &maxndoms);
00626 }
00627 }
00628 }
00629
00630
00631 KWayVolUpdate(ctrl, graph, i, from, to, queue, vstatus, &nupd, updptr,
00632 updind, bndtype, vmarker, pmarker, modind);
00633
00634
00635 }
00636
00637
00638
00639 for (i=0; i<nupd; i++) {
00640 ASSERT(updptr[updind[i]] != -1);
00641 ASSERT(vstatus[updind[i]] != VPQSTATUS_NOTPRESENT);
00642 vstatus[updind[i]] = VPQSTATUS_NOTPRESENT;
00643 updptr[updind[i]] = -1;
00644 }
00645
00646 if (ctrl->dbglvl&METIS_DBG_REFINE) {
00647 printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"."
00648 " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX,
00649 pwgts[iargmin(nparts, pwgts)], imax(nparts, pwgts),
00650 ComputeLoadImbalance(graph, nparts, ctrl->pijbm),
00651 graph->nbnd, nmoved, graph->mincut, graph->minvol);
00652 if (ctrl->minconn)
00653 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
00654 printf("\n");
00655 }
00656
00657 if (nmoved == 0 ||
00658 (omode == OMODE_REFINE && graph->minvol == oldvol && graph->mincut == oldcut))
00659 break;
00660 }
00661
00662 ipqDestroy(queue);
00663
00664 WCOREPOP;
00665 }
00666
00667
00668
00683
00684 void Greedy_McKWayCutOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter,
00685 real_t ffactor, idx_t omode)
00686 {
00687
00688 idx_t i, ii, iii, j, k, l, pass, nvtxs, ncon, nparts, gain;
00689 idx_t from, me, to, cto, oldcut;
00690 idx_t *xadj, *vwgt, *adjncy, *adjwgt;
00691 idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt;
00692 idx_t nmoved, nupd, *vstatus, *updptr, *updind;
00693 idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL;
00694 idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL;
00695 idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE);
00696 real_t *ubfactors, *pijbm;
00697 real_t origbal;
00698
00699
00700 idx_t nbnd, oldnnbrs;
00701 rpq_t *queue;
00702 real_t rgain;
00703 ckrinfo_t *myrinfo;
00704 cnbr_t *mynbrs;
00705
00706 WCOREPUSH;
00707
00708
00709 nvtxs = graph->nvtxs;
00710 ncon = graph->ncon;
00711 xadj = graph->xadj;
00712 vwgt = graph->vwgt;
00713 adjncy = graph->adjncy;
00714 adjwgt = graph->adjwgt;
00715
00716 bndind = graph->bndind;
00717 bndptr = graph->bndptr;
00718
00719 where = graph->where;
00720 pwgts = graph->pwgts;
00721
00722 nparts = ctrl->nparts;
00723 pijbm = ctrl->pijbm;
00724
00725
00726
00727
00728
00729
00730 ubfactors = rwspacemalloc(ctrl, ncon);
00731 ComputeLoadImbalanceVec(graph, nparts, pijbm, ubfactors);
00732 origbal = rvecmaxdiff(ncon, ubfactors, ctrl->ubfactors);
00733 if (omode == OMODE_BALANCE) {
00734 rcopy(ncon, ctrl->ubfactors, ubfactors);
00735 }
00736 else {
00737 for (i=0; i<ncon; i++)
00738 ubfactors[i] = (ubfactors[i] > ctrl->ubfactors[i] ? ubfactors[i] : ctrl->ubfactors[i]);
00739 }
00740
00741
00742
00743 minwgt = iwspacemalloc(ctrl, nparts*ncon);
00744 maxwgt = iwspacemalloc(ctrl, nparts*ncon);
00745
00746 for (i=0; i<nparts; i++) {
00747 for (j=0; j<ncon; j++) {
00748 maxwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*ubfactors[j];
00749
00750 minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*.2;
00751 }
00752 }
00753
00754 perm = iwspacemalloc(ctrl, nvtxs);
00755
00756
00757
00758
00759
00760
00761 safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts));
00762
00763 if (ctrl->minconn) {
00764 ComputeSubDomainGraph(ctrl, graph);
00765
00766 nads = ctrl->nads;
00767 adids = ctrl->adids;
00768 adwgts = ctrl->adwgts;
00769 doms = iset(nparts, 0, ctrl->pvec1);
00770 }
00771
00772
00773
00774
00775 vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs));
00776 updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
00777 updind = iwspacemalloc(ctrl, nvtxs);
00778
00779 if (ctrl->contig) {
00780
00781 bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00782 bfsind = iwspacemalloc(ctrl, nvtxs);
00783 bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
00784 }
00785
00786 if (ctrl->dbglvl&METIS_DBG_REFINE) {
00787 printf("%s: [%6"PRIDX" %6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"(%.3"PRREAL"),"
00788 " Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %6"PRIDX", (%"PRIDX")",
00789 (omode == OMODE_REFINE ? "GRC" : "GBC"),
00790 imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), imax(nparts*ncon, maxwgt),
00791 ComputeLoadImbalance(graph, nparts, pijbm), origbal,
00792 graph->nvtxs, graph->nbnd, graph->mincut, niter);
00793 if (ctrl->minconn)
00794 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
00795 printf("\n");
00796 }
00797
00798 queue = rpqCreate(nvtxs);
00799
00800
00801
00802
00803
00804 for (pass=0; pass<niter; pass++) {
00805 ASSERT(ComputeCut(graph, where) == graph->mincut);
00806
00807
00808 if (omode == OMODE_BALANCE && IsBalanced(ctrl, graph, 0))
00809 break;
00810
00811 oldcut = graph->mincut;
00812 nbnd = graph->nbnd;
00813 nupd = 0;
00814
00815 if (ctrl->minconn)
00816 maxndoms = imax(nparts, nads);
00817
00818
00819 irandArrayPermute(nbnd, perm, nbnd/4, 1);
00820 for (ii=0; ii<nbnd; ii++) {
00821 i = bndind[perm[ii]];
00822 rgain = (graph->ckrinfo[i].nnbrs > 0 ?
00823 1.0*graph->ckrinfo[i].ed/sqrt(graph->ckrinfo[i].nnbrs) : 0.0)
00824 - graph->ckrinfo[i].id;
00825 rpqInsert(queue, i, rgain);
00826 vstatus[i] = VPQSTATUS_PRESENT;
00827 ListInsert(nupd, updind, updptr, i);
00828 }
00829
00830
00831 for (nmoved=0, iii=0;;iii++) {
00832 if ((i = rpqGetTop(queue)) == -1)
00833 break;
00834 vstatus[i] = VPQSTATUS_EXTRACTED;
00835
00836 myrinfo = graph->ckrinfo+i;
00837 mynbrs = ctrl->cnbrpool + myrinfo->inbr;
00838
00839 from = where[i];
00840
00841
00842 if (omode == OMODE_REFINE) {
00843 if (myrinfo->id > 0 &&
00844 !ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon))
00845 continue;
00846 }
00847 else {
00848 if (!ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon))
00849 continue;
00850 }
00851
00852 if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk))
00853 continue;
00854
00855 if (ctrl->minconn)
00856 SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms);
00857
00858
00859 if (omode == OMODE_REFINE) {
00860 for (k=myrinfo->nnbrs-1; k>=0; k--) {
00861 if (!safetos[to=mynbrs[k].pid])
00862 continue;
00863 gain = mynbrs[k].ed-myrinfo->id;
00864 if (gain >= 0 && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon))
00865 break;
00866 }
00867 if (k < 0)
00868 continue;
00869
00870 cto = to;
00871 for (j=k-1; j>=0; j--) {
00872 if (!safetos[to=mynbrs[j].pid])
00873 continue;
00874 if ((mynbrs[j].ed > mynbrs[k].ed &&
00875 ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon))
00876 ||
00877 (mynbrs[j].ed == mynbrs[k].ed &&
00878 BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
00879 1, pwgts+cto*ncon, pijbm+cto*ncon,
00880 1, pwgts+to*ncon, pijbm+to*ncon))) {
00881 k = j;
00882 cto = to;
00883 }
00884 }
00885 to = cto;
00886
00887 gain = mynbrs[k].ed-myrinfo->id;
00888 if (!(gain > 0
00889 || (gain == 0
00890 && (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
00891 -1, pwgts+from*ncon, pijbm+from*ncon,
00892 +1, pwgts+to*ncon, pijbm+to*ncon)
00893 || (iii%2 == 0 && safetos[to] == 2)
00894 )
00895 )
00896 )
00897 )
00898 continue;
00899 }
00900 else {
00901 for (k=myrinfo->nnbrs-1; k>=0; k--) {
00902 if (!safetos[to=mynbrs[k].pid])
00903 continue;
00904 if (ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon) ||
00905 BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
00906 -1, pwgts+from*ncon, pijbm+from*ncon,
00907 +1, pwgts+to*ncon, pijbm+to*ncon))
00908 break;
00909 }
00910 if (k < 0)
00911 continue;
00912
00913 cto = to;
00914 for (j=k-1; j>=0; j--) {
00915 if (!safetos[to=mynbrs[j].pid])
00916 continue;
00917 if (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
00918 1, pwgts+cto*ncon, pijbm+cto*ncon,
00919 1, pwgts+to*ncon, pijbm+to*ncon)) {
00920 k = j;
00921 cto = to;
00922 }
00923 }
00924 to = cto;
00925
00926 if (mynbrs[k].ed-myrinfo->id < 0 &&
00927 !BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
00928 -1, pwgts+from*ncon, pijbm+from*ncon,
00929 +1, pwgts+to*ncon, pijbm+to*ncon))
00930 continue;
00931 }
00932
00933
00934
00935
00936
00937
00938 graph->mincut -= mynbrs[k].ed-myrinfo->id;
00939 nmoved++;
00940
00941 IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
00942 printf("\t\tMoving %6"PRIDX" to %3"PRIDX". Gain: %4"PRIDX". Cut: %6"PRIDX"\n",
00943 i, to, mynbrs[k].ed-myrinfo->id, graph->mincut));
00944
00945
00946 if (ctrl->minconn) {
00947
00948 UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->id-mynbrs[k].ed, &maxndoms);
00949
00950
00951 for (j=xadj[i]; j<xadj[i+1]; j++) {
00952 me = where[adjncy[j]];
00953 if (me != from && me != to) {
00954 UpdateEdgeSubDomainGraph(ctrl, from, me, -adjwgt[j], &maxndoms);
00955 UpdateEdgeSubDomainGraph(ctrl, to, me, adjwgt[j], &maxndoms);
00956 }
00957 }
00958 }
00959
00960
00961 iaxpy(ncon, 1, vwgt+i*ncon, 1, pwgts+to*ncon, 1);
00962 iaxpy(ncon, -1, vwgt+i*ncon, 1, pwgts+from*ncon, 1);
00963 UpdateMovedVertexInfoAndBND(i, from, k, to, myrinfo, mynbrs, where,
00964 nbnd, bndptr, bndind, bndtype);
00965
00966
00967 for (j=xadj[i]; j<xadj[i+1]; j++) {
00968 ii = adjncy[j];
00969 me = where[ii];
00970 myrinfo = graph->ckrinfo+ii;
00971
00972 oldnnbrs = myrinfo->nnbrs;
00973
00974 UpdateAdjacentVertexInfoAndBND(ctrl, ii, xadj[ii+1]-xadj[ii], me,
00975 from, to, myrinfo, adjwgt[j], nbnd, bndptr, bndind, bndtype);
00976
00977 UpdateQueueInfo(queue, vstatus, ii, me, from, to, myrinfo, oldnnbrs,
00978 nupd, updptr, updind, bndtype);
00979
00980 ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]);
00981 }
00982 }
00983
00984 graph->nbnd = nbnd;
00985
00986
00987 for (i=0; i<nupd; i++) {
00988 ASSERT(updptr[updind[i]] != -1);
00989 ASSERT(vstatus[updind[i]] != VPQSTATUS_NOTPRESENT);
00990 vstatus[updind[i]] = VPQSTATUS_NOTPRESENT;
00991 updptr[updind[i]] = -1;
00992 }
00993
00994 if (ctrl->dbglvl&METIS_DBG_REFINE) {
00995 printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"."
00996 " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX,
00997 imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts),
00998 ComputeLoadImbalance(graph, nparts, pijbm),
00999 graph->nbnd, nmoved, graph->mincut, ComputeVolume(graph, where));
01000 if (ctrl->minconn)
01001 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
01002 printf("\n");
01003 }
01004
01005 if (nmoved == 0 || (omode == OMODE_REFINE && graph->mincut == oldcut))
01006 break;
01007 }
01008
01009 rpqDestroy(queue);
01010
01011 WCOREPOP;
01012 }
01013
01014
01015
01025
01026 void Greedy_McKWayVolOptimize(ctrl_t *ctrl, graph_t *graph, idx_t niter,
01027 real_t ffactor, idx_t omode)
01028 {
01029
01030 idx_t i, ii, iii, j, k, l, pass, nvtxs, ncon, nparts, gain;
01031 idx_t from, me, to, cto, oldcut;
01032 idx_t *xadj, *vwgt, *adjncy;
01033 idx_t *where, *pwgts, *perm, *bndptr, *bndind, *minwgt, *maxwgt;
01034 idx_t nmoved, nupd, *vstatus, *updptr, *updind;
01035 idx_t maxndoms, *safetos=NULL, *nads=NULL, *doms=NULL, **adids=NULL, **adwgts=NULL;
01036 idx_t *bfslvl=NULL, *bfsind=NULL, *bfsmrk=NULL;
01037 idx_t bndtype = (omode == OMODE_REFINE ? BNDTYPE_REFINE : BNDTYPE_BALANCE);
01038 real_t *ubfactors, *pijbm;
01039 real_t origbal;
01040
01041
01042 ipq_t *queue;
01043 idx_t oldvol, xgain;
01044 idx_t *vmarker, *pmarker, *modind;
01045 vkrinfo_t *myrinfo;
01046 vnbr_t *mynbrs;
01047
01048 WCOREPUSH;
01049
01050
01051 nvtxs = graph->nvtxs;
01052 ncon = graph->ncon;
01053 xadj = graph->xadj;
01054 vwgt = graph->vwgt;
01055 adjncy = graph->adjncy;
01056 bndptr = graph->bndptr;
01057 bndind = graph->bndind;
01058 where = graph->where;
01059 pwgts = graph->pwgts;
01060
01061 nparts = ctrl->nparts;
01062 pijbm = ctrl->pijbm;
01063
01064
01065
01066
01067
01068
01069 ubfactors = rwspacemalloc(ctrl, ncon);
01070 ComputeLoadImbalanceVec(graph, nparts, pijbm, ubfactors);
01071 origbal = rvecmaxdiff(ncon, ubfactors, ctrl->ubfactors);
01072 if (omode == OMODE_BALANCE) {
01073 rcopy(ncon, ctrl->ubfactors, ubfactors);
01074 }
01075 else {
01076 for (i=0; i<ncon; i++)
01077 ubfactors[i] = (ubfactors[i] > ctrl->ubfactors[i] ? ubfactors[i] : ctrl->ubfactors[i]);
01078 }
01079
01080
01081
01082 minwgt = iwspacemalloc(ctrl, nparts*ncon);
01083 maxwgt = iwspacemalloc(ctrl, nparts*ncon);
01084
01085 for (i=0; i<nparts; i++) {
01086 for (j=0; j<ncon; j++) {
01087 maxwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*ubfactors[j];
01088
01089 minwgt[i*ncon+j] = ctrl->tpwgts[i*ncon+j]*graph->tvwgt[j]*.2;
01090 }
01091 }
01092
01093 perm = iwspacemalloc(ctrl, nvtxs);
01094
01095
01096
01097
01098
01099
01100 safetos = iset(nparts, 2, iwspacemalloc(ctrl, nparts));
01101
01102 if (ctrl->minconn) {
01103 ComputeSubDomainGraph(ctrl, graph);
01104
01105 nads = ctrl->nads;
01106 adids = ctrl->adids;
01107 adwgts = ctrl->adwgts;
01108 doms = iset(nparts, 0, ctrl->pvec1);
01109 }
01110
01111
01112
01113
01114 vstatus = iset(nvtxs, VPQSTATUS_NOTPRESENT, iwspacemalloc(ctrl, nvtxs));
01115 updptr = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
01116 updind = iwspacemalloc(ctrl, nvtxs);
01117
01118 if (ctrl->contig) {
01119
01120 bfslvl = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
01121 bfsind = iwspacemalloc(ctrl, nvtxs);
01122 bfsmrk = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
01123 }
01124
01125
01126 modind = iwspacemalloc(ctrl, nvtxs);
01127 vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
01128 pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
01129
01130 if (ctrl->dbglvl&METIS_DBG_REFINE) {
01131 printf("%s: [%6"PRIDX" %6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL"(%.3"PRREAL"),"
01132 ", Nv-Nb[%6"PRIDX" %6"PRIDX"], Cut: %5"PRIDX", Vol: %5"PRIDX", (%"PRIDX")",
01133 (omode == OMODE_REFINE ? "GRV" : "GBV"),
01134 imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts), imax(nparts*ncon, maxwgt),
01135 ComputeLoadImbalance(graph, nparts, pijbm), origbal,
01136 graph->nvtxs, graph->nbnd, graph->mincut, graph->minvol, niter);
01137 if (ctrl->minconn)
01138 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
01139 printf("\n");
01140 }
01141
01142 queue = ipqCreate(nvtxs);
01143
01144
01145
01146
01147
01148 for (pass=0; pass<niter; pass++) {
01149 ASSERT(ComputeVolume(graph, where) == graph->minvol);
01150
01151
01152 if (omode == OMODE_BALANCE && IsBalanced(ctrl, graph, 0))
01153 break;
01154
01155 oldcut = graph->mincut;
01156 oldvol = graph->minvol;
01157 nupd = 0;
01158
01159 if (ctrl->minconn)
01160 maxndoms = imax(nparts, nads);
01161
01162
01163 irandArrayPermute(graph->nbnd, perm, graph->nbnd/4, 1);
01164 for (ii=0; ii<graph->nbnd; ii++) {
01165 i = bndind[perm[ii]];
01166 ipqInsert(queue, i, graph->vkrinfo[i].gv);
01167 vstatus[i] = VPQSTATUS_PRESENT;
01168 ListInsert(nupd, updind, updptr, i);
01169 }
01170
01171
01172 for (nmoved=0, iii=0;;iii++) {
01173 if ((i = ipqGetTop(queue)) == -1)
01174 break;
01175 vstatus[i] = VPQSTATUS_EXTRACTED;
01176
01177 myrinfo = graph->vkrinfo+i;
01178 mynbrs = ctrl->vnbrpool + myrinfo->inbr;
01179
01180 from = where[i];
01181
01182
01183 if (omode == OMODE_REFINE) {
01184 if (myrinfo->nid > 0 &&
01185 !ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon))
01186 continue;
01187 }
01188 else {
01189 if (!ivecaxpygez(ncon, -1, vwgt+i*ncon, pwgts+from*ncon, minwgt+from*ncon))
01190 continue;
01191 }
01192
01193 if (ctrl->contig && IsArticulationNode(i, xadj, adjncy, where, bfslvl, bfsind, bfsmrk))
01194 continue;
01195
01196 if (ctrl->minconn)
01197 SelectSafeTargetSubdomains(myrinfo, mynbrs, nads, adids, maxndoms, safetos, doms);
01198
01199 xgain = (myrinfo->nid == 0 && myrinfo->ned > 0 ? graph->vsize[i] : 0);
01200
01201
01202 if (omode == OMODE_REFINE) {
01203 for (k=myrinfo->nnbrs-1; k>=0; k--) {
01204 if (!safetos[to=mynbrs[k].pid])
01205 continue;
01206 gain = mynbrs[k].gv + xgain;
01207 if (gain >= 0 && ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon))
01208 break;
01209 }
01210 if (k < 0)
01211 continue;
01212
01213 cto = to;
01214 for (j=k-1; j>=0; j--) {
01215 if (!safetos[to=mynbrs[j].pid])
01216 continue;
01217 gain = mynbrs[j].gv + xgain;
01218 if ((mynbrs[j].gv > mynbrs[k].gv &&
01219 ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon))
01220 ||
01221 (mynbrs[j].gv == mynbrs[k].gv &&
01222 mynbrs[j].ned > mynbrs[k].ned &&
01223 ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon))
01224 ||
01225 (mynbrs[j].gv == mynbrs[k].gv &&
01226 mynbrs[j].ned == mynbrs[k].ned &&
01227 BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
01228 1, pwgts+cto*ncon, pijbm+cto*ncon,
01229 1, pwgts+to*ncon, pijbm+to*ncon))) {
01230 k = j;
01231 cto = to;
01232 }
01233 }
01234 to = cto;
01235
01236 j = 0;
01237 if (xgain+mynbrs[k].gv > 0 || mynbrs[k].ned-myrinfo->nid > 0)
01238 j = 1;
01239 else if (mynbrs[k].ned-myrinfo->nid == 0) {
01240 if ((iii%2 == 0 && safetos[to] == 2) ||
01241 BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
01242 -1, pwgts+from*ncon, pijbm+from*ncon,
01243 +1, pwgts+to*ncon, pijbm+to*ncon))
01244 j = 1;
01245 }
01246 if (j == 0)
01247 continue;
01248 }
01249 else {
01250 for (k=myrinfo->nnbrs-1; k>=0; k--) {
01251 if (!safetos[to=mynbrs[k].pid])
01252 continue;
01253 if (ivecaxpylez(ncon, 1, vwgt+i*ncon, pwgts+to*ncon, maxwgt+to*ncon) ||
01254 BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
01255 -1, pwgts+from*ncon, pijbm+from*ncon,
01256 +1, pwgts+to*ncon, pijbm+to*ncon))
01257 break;
01258 }
01259 if (k < 0)
01260 continue;
01261
01262 cto = to;
01263 for (j=k-1; j>=0; j--) {
01264 if (!safetos[to=mynbrs[j].pid])
01265 continue;
01266 if (BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
01267 1, pwgts+cto*ncon, pijbm+cto*ncon,
01268 1, pwgts+to*ncon, pijbm+to*ncon)) {
01269 k = j;
01270 cto = to;
01271 }
01272 }
01273 to = cto;
01274
01275 if ((xgain+mynbrs[k].gv < 0 ||
01276 (xgain+mynbrs[k].gv == 0 && mynbrs[k].ned-myrinfo->nid < 0))
01277 &&
01278 !BetterBalanceKWay(ncon, vwgt+i*ncon, ubfactors,
01279 -1, pwgts+from*ncon, pijbm+from*ncon,
01280 +1, pwgts+to*ncon, pijbm+to*ncon))
01281 continue;
01282 }
01283
01284
01285
01286
01287
01288 graph->mincut -= mynbrs[k].ned-myrinfo->nid;
01289 graph->minvol -= (xgain+mynbrs[k].gv);
01290 where[i] = to;
01291 nmoved++;
01292
01293 IFSET(ctrl->dbglvl, METIS_DBG_MOVEINFO,
01294 printf("\t\tMoving %6"PRIDX" from %3"PRIDX" to %3"PRIDX". "
01295 "Gain: [%4"PRIDX" %4"PRIDX"]. Cut: %6"PRIDX", Vol: %6"PRIDX"\n",
01296 i, from, to, xgain+mynbrs[k].gv, mynbrs[k].ned-myrinfo->nid,
01297 graph->mincut, graph->minvol));
01298
01299
01300 if (ctrl->minconn) {
01301
01302 UpdateEdgeSubDomainGraph(ctrl, from, to, myrinfo->nid-mynbrs[k].ned, &maxndoms);
01303
01304
01305 for (j=xadj[i]; j<xadj[i+1]; j++) {
01306 me = where[adjncy[j]];
01307 if (me != from && me != to) {
01308 UpdateEdgeSubDomainGraph(ctrl, from, me, -1, &maxndoms);
01309 UpdateEdgeSubDomainGraph(ctrl, to, me, 1, &maxndoms);
01310 }
01311 }
01312 }
01313
01314
01315 iaxpy(ncon, 1, vwgt+i*ncon, 1, pwgts+to*ncon, 1);
01316 iaxpy(ncon, -1, vwgt+i*ncon, 1, pwgts+from*ncon, 1);
01317
01318
01319 KWayVolUpdate(ctrl, graph, i, from, to, queue, vstatus, &nupd, updptr,
01320 updind, bndtype, vmarker, pmarker, modind);
01321
01322
01323 }
01324
01325
01326
01327 for (i=0; i<nupd; i++) {
01328 ASSERT(updptr[updind[i]] != -1);
01329 ASSERT(vstatus[updind[i]] != VPQSTATUS_NOTPRESENT);
01330 vstatus[updind[i]] = VPQSTATUS_NOTPRESENT;
01331 updptr[updind[i]] = -1;
01332 }
01333
01334 if (ctrl->dbglvl&METIS_DBG_REFINE) {
01335 printf("\t[%6"PRIDX" %6"PRIDX"], Bal: %5.3"PRREAL", Nb: %6"PRIDX"."
01336 " Nmoves: %5"PRIDX", Cut: %6"PRIDX", Vol: %6"PRIDX,
01337 imin(nparts*ncon, pwgts), imax(nparts*ncon, pwgts),
01338 ComputeLoadImbalance(graph, nparts, pijbm),
01339 graph->nbnd, nmoved, graph->mincut, graph->minvol);
01340 if (ctrl->minconn)
01341 printf(", Doms: [%3"PRIDX" %4"PRIDX"]", imax(nparts, nads), isum(nparts, nads,1));
01342 printf("\n");
01343 }
01344
01345 if (nmoved == 0 ||
01346 (omode == OMODE_REFINE && graph->minvol == oldvol && graph->mincut == oldcut))
01347 break;
01348 }
01349
01350 ipqDestroy(queue);
01351
01352 WCOREPOP;
01353 }
01354
01355
01356
01360
01361 idx_t IsArticulationNode(idx_t i, idx_t *xadj, idx_t *adjncy, idx_t *where,
01362 idx_t *bfslvl, idx_t *bfsind, idx_t *bfsmrk)
01363 {
01364 idx_t ii, j, k=0, head, tail, nhits, tnhits, from, BFSDEPTH=5;
01365
01366 from = where[i];
01367
01368
01369 for (tnhits=0, j=xadj[i]; j<xadj[i+1]; j++) {
01370 if (where[adjncy[j]] == from) {
01371 ASSERT(bfsmrk[adjncy[j]] == 0);
01372 ASSERT(bfslvl[adjncy[j]] == 0);
01373 bfsmrk[k=adjncy[j]] = 1;
01374 tnhits++;
01375 }
01376 }
01377
01378
01379 if (tnhits == 0)
01380 return 0;
01381 if (tnhits == 1) {
01382 bfsmrk[k] = 0;
01383 return 0;
01384 }
01385
01386 ASSERT(bfslvl[i] == 0);
01387 bfslvl[i] = 1;
01388
01389 bfsind[0] = k;
01390 bfslvl[k] = 1;
01391 bfsmrk[k] = 0;
01392 head = 0;
01393 tail = 1;
01394
01395
01396 for (nhits=1; head<tail; ) {
01397 ii = bfsind[head++];
01398 for (j=xadj[ii]; j<xadj[ii+1]; j++) {
01399 if (where[k=adjncy[j]] == from) {
01400 if (bfsmrk[k]) {
01401 bfsmrk[k] = 0;
01402 if (++nhits == tnhits)
01403 break;
01404 }
01405 if (bfslvl[k] == 0 && bfslvl[ii] < BFSDEPTH) {
01406 bfsind[tail++] = k;
01407 bfslvl[k] = bfslvl[ii]+1;
01408 }
01409 }
01410 }
01411 if (nhits == tnhits)
01412 break;
01413 }
01414
01415
01416 bfslvl[i] = 0;
01417 for (j=0; j<tail; j++)
01418 bfslvl[bfsind[j]] = 0;
01419
01420
01421
01422 if (nhits < tnhits) {
01423 for (j=xadj[i]; j<xadj[i+1]; j++)
01424 if (where[adjncy[j]] == from)
01425 bfsmrk[adjncy[j]] = 0;
01426 }
01427
01428 return (nhits != tnhits);
01429 }
01430
01431
01432
01459
01460 void KWayVolUpdate(ctrl_t *ctrl, graph_t *graph, idx_t v, idx_t from,
01461 idx_t to, ipq_t *queue, idx_t *vstatus, idx_t *r_nupd, idx_t *updptr,
01462 idx_t *updind, idx_t bndtype, idx_t *vmarker, idx_t *pmarker,
01463 idx_t *modind)
01464 {
01465 idx_t i, ii, iii, j, jj, k, kk, l, u, nmod, other, me, myidx;
01466 idx_t *xadj, *vsize, *adjncy, *where;
01467 vkrinfo_t *myrinfo, *orinfo;
01468 vnbr_t *mynbrs, *onbrs;
01469
01470 xadj = graph->xadj;
01471 adjncy = graph->adjncy;
01472 vsize = graph->vsize;
01473 where = graph->where;
01474
01475 myrinfo = graph->vkrinfo+v;
01476 mynbrs = ctrl->vnbrpool + myrinfo->inbr;
01477
01478
01479
01480
01481
01482 for (k=0; k<myrinfo->nnbrs; k++)
01483 pmarker[mynbrs[k].pid] = k;
01484 pmarker[from] = k;
01485
01486 myidx = pmarker[to];
01487
01488 for (j=xadj[v]; j<xadj[v+1]; j++) {
01489 ii = adjncy[j];
01490 other = where[ii];
01491 orinfo = graph->vkrinfo+ii;
01492 onbrs = ctrl->vnbrpool + orinfo->inbr;
01493
01494 if (other == from) {
01495 for (k=0; k<orinfo->nnbrs; k++) {
01496 if (pmarker[onbrs[k].pid] == -1)
01497 onbrs[k].gv += vsize[v];
01498 }
01499 }
01500 else {
01501 ASSERT(pmarker[other] != -1);
01502
01503 if (mynbrs[pmarker[other]].ned > 1) {
01504 for (k=0; k<orinfo->nnbrs; k++) {
01505 if (pmarker[onbrs[k].pid] == -1)
01506 onbrs[k].gv += vsize[v];
01507 }
01508 }
01509 else {
01510 for (k=0; k<orinfo->nnbrs; k++) {
01511 if (pmarker[onbrs[k].pid] != -1)
01512 onbrs[k].gv -= vsize[v];
01513 }
01514 }
01515 }
01516 }
01517
01518 for (k=0; k<myrinfo->nnbrs; k++)
01519 pmarker[mynbrs[k].pid] = -1;
01520 pmarker[from] = -1;
01521
01522
01523
01524
01525
01526 if (myidx == -1) {
01527 myidx = myrinfo->nnbrs++;
01528 ASSERT(myidx < xadj[v+1]-xadj[v]);
01529 mynbrs[myidx].ned = 0;
01530 }
01531 myrinfo->ned += myrinfo->nid-mynbrs[myidx].ned;
01532 SWAP(myrinfo->nid, mynbrs[myidx].ned, j);
01533 if (mynbrs[myidx].ned == 0)
01534 mynbrs[myidx] = mynbrs[--myrinfo->nnbrs];
01535 else
01536 mynbrs[myidx].pid = from;
01537
01538
01539
01540
01541
01542 vmarker[v] = 1;
01543 modind[0] = v;
01544 nmod = 1;
01545 for (j=xadj[v]; j<xadj[v+1]; j++) {
01546 ii = adjncy[j];
01547 me = where[ii];
01548
01549 if (!vmarker[ii]) {
01550 vmarker[ii] = 2;
01551 modind[nmod++] = ii;
01552 }
01553
01554 myrinfo = graph->vkrinfo+ii;
01555 if (myrinfo->inbr == -1)
01556 myrinfo->inbr = vnbrpoolGetNext(ctrl, xadj[ii+1]-xadj[ii]+1);
01557 mynbrs = ctrl->vnbrpool + myrinfo->inbr;
01558
01559 if (me == from) {
01560 INC_DEC(myrinfo->ned, myrinfo->nid, 1);
01561 }
01562 else if (me == to) {
01563 INC_DEC(myrinfo->nid, myrinfo->ned, 1);
01564 }
01565
01566
01567 if (me != from) {
01568 for (k=0; k<myrinfo->nnbrs; k++) {
01569 if (mynbrs[k].pid == from) {
01570 if (mynbrs[k].ned == 1) {
01571 mynbrs[k] = mynbrs[--myrinfo->nnbrs];
01572 vmarker[ii] = 1;
01573
01574
01575 for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {
01576 u = adjncy[jj];
01577 other = where[u];
01578 orinfo = graph->vkrinfo+u;
01579 onbrs = ctrl->vnbrpool + orinfo->inbr;
01580
01581 for (kk=0; kk<orinfo->nnbrs; kk++) {
01582 if (onbrs[kk].pid == from) {
01583 onbrs[kk].gv -= vsize[ii];
01584 if (!vmarker[u]) {
01585 vmarker[u] = 2;
01586 modind[nmod++] = u;
01587 }
01588 break;
01589 }
01590 }
01591 }
01592 }
01593 else {
01594 mynbrs[k].ned--;
01595
01596
01597 if (mynbrs[k].ned == 1) {
01598
01599 for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {
01600 u = adjncy[jj];
01601 other = where[u];
01602
01603 if (other == from) {
01604 orinfo = graph->vkrinfo+u;
01605 onbrs = ctrl->vnbrpool + orinfo->inbr;
01606
01607
01608
01609
01610
01611
01612 for (kk=0; kk<orinfo->nnbrs; kk++)
01613 onbrs[kk].gv += vsize[ii];
01614
01615 if (!vmarker[u]) {
01616 vmarker[u] = 2;
01617 modind[nmod++] = u;
01618 }
01619 break;
01620 }
01621 }
01622 }
01623 }
01624 break;
01625 }
01626 }
01627 }
01628
01629
01630
01631 if (me != to) {
01632 for (k=0; k<myrinfo->nnbrs; k++) {
01633 if (mynbrs[k].pid == to) {
01634 mynbrs[k].ned++;
01635
01636
01637 if (mynbrs[k].ned == 2) {
01638
01639 for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {
01640 u = adjncy[jj];
01641 other = where[u];
01642
01643 if (u != v && other == to) {
01644 orinfo = graph->vkrinfo+u;
01645 onbrs = ctrl->vnbrpool + orinfo->inbr;
01646 for (kk=0; kk<orinfo->nnbrs; kk++)
01647 onbrs[kk].gv -= vsize[ii];
01648
01649 if (!vmarker[u]) {
01650 vmarker[u] = 2;
01651 modind[nmod++] = u;
01652 }
01653 break;
01654 }
01655 }
01656 }
01657 break;
01658 }
01659 }
01660
01661 if (k == myrinfo->nnbrs) {
01662 mynbrs[myrinfo->nnbrs].pid = to;
01663 mynbrs[myrinfo->nnbrs++].ned = 1;
01664 vmarker[ii] = 1;
01665
01666
01667 for (jj=xadj[ii]; jj<xadj[ii+1]; jj++) {
01668 u = adjncy[jj];
01669 other = where[u];
01670 orinfo = graph->vkrinfo+u;
01671 onbrs = ctrl->vnbrpool + orinfo->inbr;
01672
01673 for (kk=0; kk<orinfo->nnbrs; kk++) {
01674 if (onbrs[kk].pid == to) {
01675 onbrs[kk].gv += vsize[ii];
01676 if (!vmarker[u]) {
01677 vmarker[u] = 2;
01678 modind[nmod++] = u;
01679 }
01680 break;
01681 }
01682 }
01683 }
01684 }
01685 }
01686
01687 ASSERT(myrinfo->nnbrs <= xadj[ii+1]-xadj[ii]);
01688 }
01689
01690
01691
01692
01693
01694 myrinfo = graph->vkrinfo+v;
01695 mynbrs = ctrl->vnbrpool + myrinfo->inbr;
01696 for (k=0; k<myrinfo->nnbrs; k++)
01697 pmarker[mynbrs[k].pid] = k;
01698 pmarker[to] = k;
01699
01700 for (j=xadj[v]; j<xadj[v+1]; j++) {
01701 ii = adjncy[j];
01702 other = where[ii];
01703 orinfo = graph->vkrinfo+ii;
01704 onbrs = ctrl->vnbrpool + orinfo->inbr;
01705
01706 if (other == to) {
01707 for (k=0; k<orinfo->nnbrs; k++) {
01708 if (pmarker[onbrs[k].pid] == -1)
01709 onbrs[k].gv -= vsize[v];
01710 }
01711 }
01712 else {
01713 ASSERT(pmarker[other] != -1);
01714
01715 if (mynbrs[pmarker[other]].ned > 1) {
01716 for (k=0; k<orinfo->nnbrs; k++) {
01717 if (pmarker[onbrs[k].pid] == -1)
01718 onbrs[k].gv -= vsize[v];
01719 }
01720 }
01721 else {
01722 for (k=0; k<orinfo->nnbrs; k++) {
01723 if (pmarker[onbrs[k].pid] != -1)
01724 onbrs[k].gv += vsize[v];
01725 }
01726 }
01727 }
01728 }
01729 for (k=0; k<myrinfo->nnbrs; k++)
01730 pmarker[mynbrs[k].pid] = -1;
01731 pmarker[to] = -1;
01732
01733
01734
01735
01736
01737
01738 for (iii=0; iii<nmod; iii++) {
01739 i = modind[iii];
01740 me = where[i];
01741
01742 myrinfo = graph->vkrinfo+i;
01743 mynbrs = ctrl->vnbrpool + myrinfo->inbr;
01744
01745 if (vmarker[i] == 1) {
01746 for (k=0; k<myrinfo->nnbrs; k++)
01747 mynbrs[k].gv = 0;
01748
01749 for (j=xadj[i]; j<xadj[i+1]; j++) {
01750 ii = adjncy[j];
01751 other = where[ii];
01752 orinfo = graph->vkrinfo+ii;
01753 onbrs = ctrl->vnbrpool + orinfo->inbr;
01754
01755 for (kk=0; kk<orinfo->nnbrs; kk++)
01756 pmarker[onbrs[kk].pid] = kk;
01757 pmarker[other] = 1;
01758
01759 if (me == other) {
01760
01761 for (k=0; k<myrinfo->nnbrs; k++) {
01762 if (pmarker[mynbrs[k].pid] == -1)
01763 mynbrs[k].gv -= vsize[ii];
01764 }
01765 }
01766 else {
01767 ASSERT(pmarker[me] != -1);
01768
01769
01770 if (onbrs[pmarker[me]].ned == 1) {
01771
01772 for (k=0; k<myrinfo->nnbrs; k++) {
01773 if (pmarker[mynbrs[k].pid] != -1)
01774 mynbrs[k].gv += vsize[ii];
01775 }
01776 }
01777 else {
01778
01779 for (k=0; k<myrinfo->nnbrs; k++) {
01780 if (pmarker[mynbrs[k].pid] == -1)
01781 mynbrs[k].gv -= vsize[ii];
01782 }
01783 }
01784 }
01785
01786 for (kk=0; kk<orinfo->nnbrs; kk++)
01787 pmarker[onbrs[kk].pid] = -1;
01788 pmarker[other] = -1;
01789
01790 }
01791 }
01792
01793
01794 myrinfo->gv = IDX_MIN;
01795 for (k=0; k<myrinfo->nnbrs; k++) {
01796 if (mynbrs[k].gv > myrinfo->gv)
01797 myrinfo->gv = mynbrs[k].gv;
01798 }
01799
01800
01801 if (myrinfo->ned > 0 && myrinfo->nid == 0)
01802 myrinfo->gv += vsize[i];
01803
01804
01805
01806
01807
01808 if (bndtype == BNDTYPE_REFINE) {
01809 if (myrinfo->gv >= 0 && graph->bndptr[i] == -1)
01810 BNDInsert(graph->nbnd, graph->bndind, graph->bndptr, i);
01811
01812 if (myrinfo->gv < 0 && graph->bndptr[i] != -1)
01813 BNDDelete(graph->nbnd, graph->bndind, graph->bndptr, i);
01814 }
01815 else {
01816 if (myrinfo->ned > 0 && graph->bndptr[i] == -1)
01817 BNDInsert(graph->nbnd, graph->bndind, graph->bndptr, i);
01818
01819 if (myrinfo->ned == 0 && graph->bndptr[i] != -1)
01820 BNDDelete(graph->nbnd, graph->bndind, graph->bndptr, i);
01821 }
01822
01823
01824
01825
01826
01827 if (queue != NULL) {
01828 if (vstatus[i] != VPQSTATUS_EXTRACTED) {
01829 if (graph->bndptr[i] != -1) {
01830 if (vstatus[i] == VPQSTATUS_PRESENT) {
01831 ipqUpdate(queue, i, myrinfo->gv);
01832 }
01833 else {
01834 ipqInsert(queue, i, myrinfo->gv);
01835 vstatus[i] = VPQSTATUS_PRESENT;
01836 ListInsert(*r_nupd, updind, updptr, i);
01837 }
01838 }
01839 else {
01840 if (vstatus[i] == VPQSTATUS_PRESENT) {
01841 ipqDelete(queue, i);
01842 vstatus[i] = VPQSTATUS_NOTPRESENT;
01843 ListDelete(*r_nupd, updind, updptr, i);
01844 }
01845 }
01846 }
01847 }
01848
01849 vmarker[i] = 0;
01850 }
01851 }
01852