Esempio n. 1
0
idx_t IsConnected(graph_t *graph, idx_t report) {
    idx_t ncmps;

    ncmps = FindPartitionInducedComponents(graph, NULL, NULL, NULL);

    if (ncmps != 1 && report) {
        printf("The graph is not connected. It has %"PRIDX" connected components.\n", ncmps);
    }

    return (ncmps == 1);
}
void RefineKWay(ctrl_t *ctrl, graph_t *orggraph, graph_t *graph)
{
  idx_t i, nlevels, contig=ctrl->contig;
  graph_t *ptr;

  IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->UncoarsenTmr));

  /* Determine how many levels are there */
  for (ptr=graph, nlevels=0; ptr!=orggraph; ptr=ptr->finer, nlevels++); 

  /* Compute the parameters of the coarsest graph */
  ComputeKWayPartitionParams(ctrl, graph);

  /* Try to minimize the sub-domain connectivity */
  if (ctrl->minconn) 
    EliminateSubDomainEdges(ctrl, graph);
  
  /* Deal with contiguity constraints at the beginning */
  if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) { 
    EliminateComponents(ctrl, graph);

    ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
    Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); 

    ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
    Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); 

    ctrl->contig = 0;
  }

  /* Refine each successively finer graph */
  for (i=0; ;i++) {
    if (ctrl->minconn && i == nlevels/2) 
      EliminateSubDomainEdges(ctrl, graph);

    IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->RefTmr));

    if (2*i >= nlevels && !IsBalanced(ctrl, graph, .02)) {
      ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
      Greedy_KWayOptimize(ctrl, graph, 1, 0, OMODE_BALANCE); 
      ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
    }

    Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 5.0, OMODE_REFINE); 

    IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->RefTmr));

    /* Deal with contiguity constraints in the middle */
    if (contig && i == nlevels/2) {
      if (FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) {
        EliminateComponents(ctrl, graph);

        if (!IsBalanced(ctrl, graph, .02)) {
          ctrl->contig = 1;
          ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
          Greedy_KWayOptimize(ctrl, graph, 5, 0, OMODE_BALANCE); 
  
          ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
          Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); 
          ctrl->contig = 0;
        }
      }
    }

    if (graph == orggraph)
      break;

    graph = graph->finer;

    IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startcputimer(ctrl->ProjectTmr));
    ASSERT(graph->vwgt != NULL);

    ProjectKWayPartition(ctrl, graph);
    IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->ProjectTmr));
  }

  /* Deal with contiguity requirement at the end */
  ctrl->contig = contig;
  if (contig && FindPartitionInducedComponents(graph, graph->where, NULL, NULL) > ctrl->nparts) 
    EliminateComponents(ctrl, graph);

  if (!IsBalanced(ctrl, graph, 0.0)) {
    ComputeKWayBoundary(ctrl, graph, BNDTYPE_BALANCE);
    Greedy_KWayOptimize(ctrl, graph, 10, 0, OMODE_BALANCE); 

    ComputeKWayBoundary(ctrl, graph, BNDTYPE_REFINE);
    Greedy_KWayOptimize(ctrl, graph, ctrl->niter, 0, OMODE_REFINE); 
  }

  if (ctrl->contig) 
    ASSERT(FindPartitionInducedComponents(graph, graph->where, NULL, NULL) == ctrl->nparts);

  IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopcputimer(ctrl->UncoarsenTmr));
}
Esempio n. 3
0
void EliminateComponents(ctrl_t *ctrl, graph_t *graph) {
    idx_t i, ii, j, jj, k, me, nparts, nvtxs, ncon, ncmps, other,
        ncand, target;
    idx_t *xadj, *adjncy, *vwgt, *adjwgt, *where, *pwgts;
    idx_t *cptr, *cind, *cpvec, *pcptr, *pcind, *cwhere;
    idx_t cid, bestcid, *cwgt, *bestcwgt;
    idx_t ntodo, oldntodo, *todo;
    rkv_t *cand;
    real_t *tpwgts;
    idx_t *vmarker = NULL, *pmarker = NULL, *modind = NULL;  /* volume specific work arrays */

    WCOREPUSH;

    nvtxs = graph->nvtxs;
    ncon = graph->ncon;
    xadj = graph->xadj;
    adjncy = graph->adjncy;
    vwgt = graph->vwgt;
    adjwgt = (ctrl->objtype == METIS_OBJTYPE_VOL ? NULL : graph->adjwgt);

    where = graph->where;
    pwgts = graph->pwgts;

    nparts = ctrl->nparts;
    tpwgts = ctrl->tpwgts;

    cptr = iwspacemalloc(ctrl, nvtxs + 1);
    cind = iwspacemalloc(ctrl, nvtxs);

    ncmps = FindPartitionInducedComponents(graph, where, cptr, cind);

    IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO,
          printf("I found %"PRIDX" components, for this %"PRIDX"-way partition\n",
                 ncmps, nparts));

    /* There are more components than partitions */
    if (ncmps > nparts) {
        cwgt = iwspacemalloc(ctrl, ncon);
        bestcwgt = iwspacemalloc(ctrl, ncon);
        cpvec = iwspacemalloc(ctrl, nparts);
        pcptr = iset(nparts + 1, 0, iwspacemalloc(ctrl, nparts + 1));
        pcind = iwspacemalloc(ctrl, ncmps);
        cwhere = iset(nvtxs, -1, iwspacemalloc(ctrl, nvtxs));
        todo = iwspacemalloc(ctrl, ncmps);
        cand = (rkv_t *) wspacemalloc(ctrl, nparts * sizeof(rkv_t));

        if (ctrl->objtype == METIS_OBJTYPE_VOL) {
            /* Vol-refinement specific working arrays */
            modind = iwspacemalloc(ctrl, nvtxs);
            vmarker = iset(nvtxs, 0, iwspacemalloc(ctrl, nvtxs));
            pmarker = iset(nparts, -1, iwspacemalloc(ctrl, nparts));
        }


        /* Get a CSR representation of the components-2-partitions mapping */
        for (i = 0; i < ncmps; i++) {
            pcptr[where[cind[cptr[i]]]]++;
        }
        MAKECSR(i, nparts, pcptr);
        for (i = 0; i < ncmps; i++) {
            pcind[pcptr[where[cind[cptr[i]]]]++] = i;
        }
        SHIFTCSR(i, nparts, pcptr);

        /* Assign the heaviest component of each partition to its original partition */
        for (ntodo = 0, i = 0; i < nparts; i++) {
            if (pcptr[i + 1] - pcptr[i] == 1) {
                bestcid = pcind[pcptr[i]];
            } else {
                for (bestcid = -1, j = pcptr[i]; j < pcptr[i + 1]; j++) {
                    cid = pcind[j];
                    iset(ncon, 0, cwgt);
                    for (ii = cptr[cid]; ii < cptr[cid + 1]; ii++) {
                        iaxpy(ncon, 1, vwgt + cind[ii] * ncon, 1, cwgt, 1);
                    }
                    if (bestcid == -1 || isum(ncon, bestcwgt, 1) < isum(ncon, cwgt, 1)) {
                        bestcid = cid;
                        icopy(ncon, cwgt, bestcwgt);
                    }
                }
                /* Keep track of those that need to be dealt with */
                for (j = pcptr[i]; j < pcptr[i + 1]; j++) {
                    if (pcind[j] != bestcid) {
                        todo[ntodo++] = pcind[j];
                    }
                }
            }

            for (j = cptr[bestcid]; j < cptr[bestcid + 1]; j++) {
                ASSERT(where[cind[j]] == i);
                cwhere[cind[j]] = i;
            }
        }

        while (ntodo > 0) {
            oldntodo = ntodo;
            for (i = 0; i < ntodo; i++) {
                cid = todo[i];
                me = where[cind[cptr[cid]]];  /* Get the domain of this component */

                /* Determine the weight of the block to be moved */
                iset(ncon, 0, cwgt);
                for (j = cptr[cid]; j < cptr[cid + 1]; j++) {
                    iaxpy(ncon, 1, vwgt + cind[j] * ncon, 1, cwgt, 1);
                }

                IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO,
                      printf("Trying to move %"PRIDX" [%"PRIDX"] from %"PRIDX"\n",
                             cid, isum(ncon, cwgt, 1), me));

                /* Determine the connectivity */
                iset(nparts, 0, cpvec);
                for (j = cptr[cid]; j < cptr[cid + 1]; j++) {
                    ii = cind[j];
                    for (jj = xadj[ii]; jj < xadj[ii + 1]; jj++) {
                        if (cwhere[adjncy[jj]] != -1) {
                            cpvec[cwhere[adjncy[jj]]] += (adjwgt ? adjwgt[jj] : 1);
                        }
                    }
                }

                /* Put the neighbors into a cand[] array for sorting */
                for (ncand = 0, j = 0; j < nparts; j++) {
                    if (cpvec[j] > 0) {
                        cand[ncand].key = cpvec[j];
                        cand[ncand++].val = j;
                    }
                }
                if (ncand == 0) {
                    continue;
                }

                rkvsortd(ncand, cand);

                /* Limit the moves to only the top candidates, which are defined as
                   those with connectivity at least 50% of the best.
                   This applies only when ncon=1, as for multi-constraint, balancing
                   will be hard. */
                if (ncon == 1) {
                    for (j = 1; j < ncand; j++) {
                        if (cand[j].key < .5 * cand[0].key) {
                            break;
                        }
                    }
                    ncand = j;
                }

                /* Now among those, select the one with the best balance */
                target = cand[0].val;
                for (j = 1; j < ncand; j++) {
                    if (BetterBalanceKWay(ncon, cwgt, ctrl->ubfactors,
                                          1, pwgts + target * ncon, ctrl->pijbm + target * ncon,
                                          1, pwgts + cand[j].val * ncon, ctrl->pijbm + cand[j].val * ncon)) {
                                              target = cand[j].val;
                    }
                }

                IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO,
                      printf("\tMoving it to %"PRIDX" [%"PRIDX"] [%"PRIDX"]\n", target, cpvec[target], ncand));

                /* Note that as a result of a previous movement, a connected component may
                   now will like to stay to its original partition */
                if (target != me) {
                    switch (ctrl->objtype) {
                        case METIS_OBJTYPE_CUT:MoveGroupContigForCut(ctrl, graph, target, cid, cptr, cind);
                            break;

                        case METIS_OBJTYPE_VOL:
                            MoveGroupContigForVol(ctrl, graph, target, cid, cptr, cind,
                                                  vmarker, pmarker, modind);
                            break;

                        default:gk_errexit(SIGERR, "Unknown objtype %d\n", ctrl->objtype);
                    }
                }

                /* Update the cwhere vector */
                for (j = cptr[cid]; j < cptr[cid + 1]; j++) {
                    cwhere[cind[j]] = target;
                }

                todo[i] = todo[--ntodo];
            }
            if (oldntodo == ntodo) {
                IFSET(ctrl->dbglvl, METIS_DBG_CONTIGINFO, printf("Stopped at ntodo: %"PRIDX"\n", ntodo));
                break;
            }
        }

        for (i = 0; i < nvtxs; i++) {
            ASSERT(where[i] == cwhere[i]);
        }

    }

    WCOREPOP;
}