Пример #1
0
void MlevelNestedDissectionCC(ctrl_t *ctrl, graph_t *graph, idx_t *order, 
         idx_t lastvtx)
{
  idx_t i, j, nvtxs, nbnd, ncmps, rnvtxs, snvtxs;
  idx_t *label, *bndind;
  idx_t *cptr, *cind;
  graph_t **sgraphs;

  nvtxs = graph->nvtxs;

  MlevelNodeBisectionMultiple(ctrl, graph);

  IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, 
      printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", 
        graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]));

  /* Order the nodes in the separator */
  nbnd   = graph->nbnd;
  bndind = graph->bndind;
  label  = graph->label;
  for (i=0; i<nbnd; i++) 
    order[label[bndind[i]]] = --lastvtx;

  WCOREPUSH;
  cptr  = iwspacemalloc(ctrl, nvtxs+1);
  cind  = iwspacemalloc(ctrl, nvtxs);
  ncmps = FindSepInducedComponents(ctrl, graph, cptr, cind);

  if (ctrl->dbglvl&METIS_DBG_INFO) {
    if (ncmps > 2)
      printf("  Bisection resulted in %"PRIDX" connected components\n", ncmps);
  }
  
  sgraphs = SplitGraphOrderCC(ctrl, graph, ncmps, cptr, cind);

  WCOREPOP;

  /* Free the memory of the top level graph */
  FreeGraph(&graph);

  /* Go and process the subgraphs */
  for (rnvtxs=i=0; i<ncmps; i++) {
    /* Save the number of vertices in sgraphs[i] because sgraphs[i] is freed 
       inside MlevelNestedDissectionCC, and as such it will be undefined. */
    snvtxs = sgraphs[i]->nvtxs;

    if (sgraphs[i]->nvtxs > MMDSWITCH && sgraphs[i]->nedges > 0) {
      MlevelNestedDissectionCC(ctrl, sgraphs[i], order, lastvtx-rnvtxs);
    }
    else {
      MMDOrder(ctrl, sgraphs[i], order, lastvtx-rnvtxs);
      FreeGraph(&sgraphs[i]);
    }
    rnvtxs += snvtxs;
  }

  gk_free((void **)&sgraphs, LTERM);
}
Пример #2
0
int main(int argc, char *argv[]) {
    graph_t *graph, *fgraph;
    char filename[256];
    idx_t wgtflag;
    params_t params;

    if (argc != 2 && argc != 3) {
        printf("Usage: %s <GraphFile> [FixedGraphFile (for storing the fixed graph)]\n", argv[0]);
        exit(0);
    }

    memset((void *) &params, 0, sizeof(params_t));
    params.filename = gk_strdup(argv[1]);

    graph = ReadGraph(&params);
    if (graph->nvtxs == 0) {
        printf("Empty graph!\n");
        exit(0);
    }

    printf("**********************************************************************\n");
    printf("%s", METISTITLE);
    printf(" (HEAD: %s, Built on: %s, %s)\n", SVNINFO, __DATE__, __TIME__);
    printf(" size of idx_t: %zubits, real_t: %zubits, idx_t *: %zubits\n",
           8 * sizeof(idx_t), 8 * sizeof(real_t), 8 * sizeof(idx_t * ));
    printf("\n");
    printf("Graph Information ---------------------------------------------------\n");
    printf("  Name: %s, #Vertices: %"PRIDX", #Edges: %"PRIDX"\n\n",
           params.filename, graph->nvtxs, graph->nedges / 2);
    printf("Checking Graph... ---------------------------------------------------\n");

    if (CheckGraph(graph, 1, 1)) {
        printf("   The format of the graph is correct!\n");
    } else {
        printf("   The format of the graph is incorrect!\n");
        if (argc == 3) {
            fgraph = FixGraph(graph);
            WriteGraph(fgraph, argv[2]);
            FreeGraph(&fgraph);
            printf("   A corrected version was stored at %s\n", argv[2]);
        }
    }

    printf("\n**********************************************************************\n");

    FreeGraph(&graph);
    gk_free((void **) &params.filename, &params.tpwgtsfile, &params.tpwgts, LTERM);
}  
Пример #3
0
/*F GenerateSingleMolecule(bind)
**
**  DESCRIPTION
**    bind: The bind structure (for molecule and reaction data)
**
**  REMARKS
**
**   Top routine to generate a single molecule from a 
**   specification
**
**
**  REFERENCES
**
**  SEE ALSO
**
**  HEADERFILE
**
*/
extern INT GenerateSetOfMolecules(BindStructure *bind) {
     CommandMaster *commandmaster;
     GenerateStructureMaster *specmaster;
     INT num,i;
     SetOfGraphs *set;
     MoleculeSet *mols;
     MoleculeSet *molecules,*newmols;
     BaseArgumentType *currentvalue;
     Graph *graph,*graphelement;

     molecules = GetBoundStructure(bind,BIND_CURRENT_MOLECULES);
     commandmaster = GetBoundStructure(bind,BIND_COMMANDMASTER);
     specmaster = GetBoundStructure(bind,BIND_GENERATE);

     currentvalue = GetCurrentArgument("NumberOfMolecules",commandmaster);
     num = currentvalue->Integer_Value;
     set = AllocateSetOfGraphs;
     CreateSetOfGraphs(set,commandmaster->ID,commandmaster->Name,
		       num,0);

     graphelement = set->Graphs;
     for(i=0;i<num;i++) {
       graph = GenerateSingleMoleculeAsGraph(specmaster);
       CopyFullGraph(graphelement,graph);
       FreeGraph(graph);
       graphelement++;
     }
     mols = TransferSetOfGraphsToMoleculeSet(set);
     newmols = MergeMoleculeSets(mols,molecules);

     ReplaceBindMoleculeSet(newmols,bind);
  return(SYSTEM_NORMAL_RETURN);
}
Пример #4
0
/*************************************************************************
* This function takes a graph and produces a bisection of it
**************************************************************************/
idxtype MlevelKWayPartitioning(CtrlType *ctrl, GraphType *graph, idxtype nparts, idxtype *part, float *tpwgts, float ubfactor)
{
  idxtype i, j, nvtxs, tvwgt, tpwgts2[2];
  GraphType *cgraph;
  idxtype wgtflag=3, numflag=0, options[10], edgecut;

  cgraph = Coarsen2Way(ctrl, graph);

  IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
  AllocateKWayPartitionMemory(ctrl, cgraph, nparts);

  options[0] = 1; 
  options[OPTION_CTYPE] = MTYPE_SHEMKWAY;
  options[OPTION_ITYPE] = ITYPE_GGPKL;
  options[OPTION_RTYPE] = RTYPE_FM;
  options[OPTION_DBGLVL] = 0;

  METIS_WPartGraphRecursive(&cgraph->nvtxs, cgraph->xadj, cgraph->adjncy, cgraph->vwgt, 
                            cgraph->adjwgt, &wgtflag, &numflag, &nparts, tpwgts, options, 
                            &edgecut, cgraph->where);

  IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
  IFSET(ctrl->dbglvl, DBG_IPART, mprintf("Initial %D-way partitioning cut: %D\n", nparts, edgecut));

  IFSET(ctrl->dbglvl, DBG_KWAYPINFO, ComputePartitionInfo(cgraph, nparts, cgraph->where));

  RefineKWay(ctrl, graph, cgraph, nparts, tpwgts, ubfactor);

  idxcopy(graph->nvtxs, graph->where, part);

  FreeGraph(graph, 0);

  return graph->mincut;

}
Пример #5
0
void Project2WayNodePartition(ctrl_t *ctrl, graph_t *graph)
{
  idx_t i, j, nvtxs;
  idx_t *cmap, *where, *cwhere;
  graph_t *cgraph;

  cgraph = graph->coarser;
  cwhere = cgraph->where;

  nvtxs = graph->nvtxs;
  cmap  = graph->cmap;

  Allocate2WayNodePartitionMemory(ctrl, graph);
  where = graph->where;
  
  /* Project the partition */
  for (i=0; i<nvtxs; i++) {
    where[i] = cwhere[cmap[i]];
    ASSERTP(where[i] >= 0 && where[i] <= 2, ("%"PRIDX" %"PRIDX" %"PRIDX" %"PRIDX"\n", 
          i, cmap[i], where[i], cwhere[cmap[i]]));
  }

  FreeGraph(&graph->coarser);
  graph->coarser = NULL;

  Compute2WayNodePartitionParams(ctrl, graph);
}
Пример #6
0
void METIS_NodeRefine(int nvtxs, idxtype *xadj, idxtype *vwgt, idxtype *adjncy, 
           idxtype *adjwgt, idxtype *where, idxtype *hmarker, float ubfactor)
{
  GraphType *graph;
  CtrlType ctrl;

  ctrl.dbglvl    = ONMETIS_DBGLVL;
  ctrl.optype    = OP_ONMETIS;

  graph = CreateGraph();
  SetUpGraph(graph, OP_ONMETIS, nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3);

  AllocateWorkSpace(&ctrl, graph, 2);

  Allocate2WayNodePartitionMemory(&ctrl, graph);
  idxcopy(nvtxs, where, graph->where);

  Compute2WayNodePartitionParams(&ctrl, graph);

  FM_2WayNodeRefine_OneSidedP(&ctrl, graph, hmarker, ubfactor, 10); 
  /* FM_2WayNodeRefine_TwoSidedP(&ctrl, graph, hmarker, ubfactor, 10); */

  FreeWorkSpace(&ctrl, graph);

  idxcopy(nvtxs, graph->where, where);

  FreeGraph(graph);

}
Пример #7
0
/******************************************************************************
* This function takes a graph and its partition vector and creates a new
* graph corresponding to the one after the movement
*******************************************************************************/
void TestMoveGraph(graph_t *ograph, graph_t *omgraph, idx_t *part, MPI_Comm comm)
{
  idx_t npes, mype;
  ctrl_t *ctrl;
  graph_t *graph, *mgraph;
  idx_t options[5] = {0, 0, 1, 0, 0};

  gkMPI_Comm_size(comm, &npes);
  ctrl = SetupCtrl(PARMETIS_OP_KMETIS, NULL, 1, npes, NULL, NULL, comm); 
  mype = ctrl->mype;

  ctrl->CoarsenTo = 1;  /* Needed by SetUpGraph, otherwise we can FP errors */
  graph = TestSetUpGraph(ctrl, ograph->vtxdist, ograph->xadj, NULL, ograph->adjncy, NULL, 0);
  AllocateWSpace(ctrl, 0);

  CommSetup(ctrl, graph);
  graph->where = part;
  graph->ncon  = 1;
  mgraph = MoveGraph(ctrl, graph);

  omgraph->gnvtxs  = mgraph->gnvtxs;
  omgraph->nvtxs   = mgraph->nvtxs;
  omgraph->nedges  = mgraph->nedges;
  omgraph->vtxdist = mgraph->vtxdist;
  omgraph->xadj    = mgraph->xadj;
  omgraph->adjncy  = mgraph->adjncy;
  mgraph->vtxdist  = NULL;
  mgraph->xadj     = NULL;
  mgraph->adjncy   = NULL;
  FreeGraph(mgraph);

  graph->where = NULL;
  FreeInitialGraphAndRemap(graph);
  FreeCtrl(&ctrl);
}  
Пример #8
0
void FreeParameters(Parameters *parameters)
{
   FreeGraph(parameters->posGraph);
   FreeLabelList(parameters->labelList);
   free(parameters->posEgsVertexIndices);
   free(parameters->log2Factorial);
   free(parameters);
}
Пример #9
0
void EvaluateSub(Substructure *sub, Parameters *parameters)
{
   double sizeOfSub;
   double sizeOfPosGraph;
   double sizeOfCompressedPosGraph;
   double subValue = 0.0;
   Graph *compressedGraph;
   ULONG numLabels;
   ULONG posEgsCovered;

   // parameters used
   Graph *posGraph              = parameters->posGraph;
   double posGraphDL            = parameters->posGraphDL;
   ULONG numPosEgs              = parameters->numPosEgs;
   LabelList *labelList         = parameters->labelList;
   BOOLEAN allowInstanceOverlap = parameters->allowInstanceOverlap;
   ULONG evalMethod             = parameters->evalMethod;

   // calculate number of examples covered by this substructure
   sub->numExamples = PosExamplesCovered(sub, parameters);

   switch(evalMethod) 
   {
      case EVAL_MDL:
         numLabels = labelList->numLabels;
         sizeOfSub = MDL(sub->definition, numLabels, parameters);
         sizeOfPosGraph = posGraphDL; // cached at beginning
         compressedGraph = CompressGraph(posGraph, sub->instances, parameters);
         numLabels++; // add one for new "SUB" vertex label
         if ((allowInstanceOverlap) && (InstancesOverlap(sub->instances)))
            numLabels++; // add one for new "OVERLAP" edge label
         sizeOfCompressedPosGraph = MDL(compressedGraph, numLabels, parameters);
         // add extra bits to describe where external edges connect to instances
         sizeOfCompressedPosGraph +=
            ExternalEdgeBits(compressedGraph,sub->definition,sub->numInstances);
         subValue = sizeOfPosGraph / (sizeOfSub + sizeOfCompressedPosGraph);
         FreeGraph(compressedGraph);
      break;

      case EVAL_SIZE:
         sizeOfSub = (double) GraphSize(sub->definition);
         sizeOfPosGraph = (double) GraphSize(posGraph);
         sizeOfCompressedPosGraph =
           (double) SizeOfCompressedGraph(posGraph, sub->instances,
                                          parameters, POS);
         subValue = sizeOfPosGraph / (sizeOfSub + sizeOfCompressedPosGraph);

      break;

      case EVAL_SETCOVER:
         posEgsCovered = PosExamplesCovered(sub, parameters);
         subValue = ((double) (posEgsCovered)) / ((double) (numPosEgs));
         break;
   }

   sub->value = subValue;

}
Пример #10
0
void FreeParkingLot(ParkingLot * parkinglot)
{
  FreeDecoder( GetDecoder( parkinglot ), GetVertices( parkinglot ) );
  FreeGraph( GetGraph( parkinglot ) ) ;
  freeLinkedList( GetAccesses( parkinglot) );
  freeLinkedList( GetQueueHead(parkinglot) );
  FreeParkedCars( GetParkedListHead(parkinglot) );
  free(parkinglot);
}
Пример #11
0
Graph *ReadGraph(char *filename, LabelList *labelList, BOOLEAN directed)
{
   Graph *graph;
   FILE *graphFile;
   ULONG lineNo;             // Line number counter for graph file
   char token[TOKEN_LEN];
   ULONG vertexListSize = 0; // Size of currently-allocated vertex array
   ULONG edgeListSize = 0;   // Size of currently-allocated edge array
   ULONG vertexOffset = 0;   // Dummy argument to ReadVertex and ReadEdge

   // Allocate graph
   graph = AllocateGraph(0,0);

   // Open graph file
   graphFile = fopen(filename,"r");
   if (graphFile == NULL) 
   {
      fprintf(stderr, "Unable to open graph file %s.\n", filename);
      exit(1);
   }

   // Parse graph file
   lineNo = 1;
   while (ReadToken(token, graphFile, &lineNo) != 0) 
   {
      if (strcmp(token, "v") == 0)         // read vertex
         ReadVertex(graph, graphFile, labelList, &vertexListSize, &lineNo,
                    vertexOffset);

      else if (strcmp(token, "e") == 0)    // read 'e' edge
         ReadEdge(graph, graphFile, labelList, &edgeListSize, &lineNo, directed,
                  vertexOffset);

      else if (strcmp(token, "u") == 0)    // read undirected edge
         ReadEdge(graph, graphFile, labelList, &edgeListSize, &lineNo, FALSE,
                  vertexOffset);

      else if (strcmp(token, "d") == 0)    // read directed edge
         ReadEdge(graph, graphFile, labelList, &edgeListSize, &lineNo, TRUE,
                  vertexOffset);

      else 
      {
         fclose(graphFile);
         FreeGraph(graph);
         fprintf(stderr, "Unknown token %s in line %lu of graph file %s.\n",
                 token, lineNo, filename);
         exit(1);
      }
   }
   fclose(graphFile);

   //***** trim vertex, edge and label lists

   return graph;
}
Пример #12
0
/*F AddStructureNext(currentstructure,element)
**
**  DESCRIPTION
**    currentstructure: The current structure to add to
**    element: The structural element to add
**
**  REMARKS
**
**   This connects the current structure with the structural element
**   to form a new currentstructure
**
**
**  REFERENCES
**
**  SEE ALSO
**
**  HEADERFILE
**
*/
static void AddStructureNext(CurrentStructure *currentstructure,
			 FullStructuralElement *element){
  INT currentattach, structureattach,replacepoint,replacepointC;
  CombinedGraph *combined,*newcombined;
  AttachmentRemoved *currentR,*elementR;
  CurrentStructure *elementcurrent;
  INT a1,a2,offset;
  Neighbor *n1,*n2;

  currentattach = PickPoint(currentstructure->Attachments->NumberOfPoints);
  structureattach = PickPoint(element->Connections->NumberOfPoints);

  elementcurrent = AllocateCurrentStructure;
  CreateCurrentStructure(elementcurrent,currentstructure->ID,currentstructure->Name,
			 0,element->MoleculeGraph,element->Connections);
  
  /*
  PrintPrettyGraph("current: ",stdout,currentstructure->Structure);
  PrintPrettyDataSubSet(stdout,"Attachments: ",currentstructure->Attachments);
  PrintPrettyGraph("element: ",stdout,element->MoleculeGraph);
  PrintPrettyDataSubSet(stdout,"Attachments: ",elementcurrent->Attachments);
  */
  replacepoint = *(elementcurrent->Attachments->Points + structureattach);
  replacepointC = *(currentstructure->Attachments->Points + currentattach);
  printf("Remove: Element (%d,%d,%d),  Current(%d,%d,%d)\n",
	 replacepoint,structureattach,element->Connections->NumberOfPoints,
	 replacepointC,currentattach,currentstructure->Attachments->NumberOfPoints);
  currentR = RemoveAttachment(currentstructure,currentattach);
  elementR = RemoveAttachment(elementcurrent,structureattach);
  /*  PrintPrettyGraph("currentR: ",stdout,currentR->Structure);
  PrintPrettyGraph("elementR: ",stdout,elementR->Structure);
  */
  offset = currentR->Structure->NumberOfNodes;
  combined = AllocateCombinedGraph;
  CreateCombinedGraph(combined,currentstructure->ID,currentstructure->Name,
		      currentR->Structure,
		      1,0);
  *(combined->Begins) = 0;

  newcombined = AddGraphToCombined(elementR->Structure,combined);

  a1 = currentR->Attachment;
  a2 = elementR->Attachment + offset;
  n1 = newcombined->Combined->Neighbors + a1;
  n2 = newcombined->Combined->Neighbors + a2;
  AddElementToNeighbor(a1,n2);
  AddElementToNeighbor(a2,n1);
  FreeGraph(currentstructure->Structure);
  CopyFullGraph(currentstructure->Structure,newcombined->Combined);

  /*
  PrintPrettyGraph("newcombined with bond: ",stdout,currentstructure->Structure);
  */
  offset = *(newcombined->Begins +1);
  AdjustAttachmentPointsOfNewElement(offset,replacepoint,replacepointC,elementcurrent,currentstructure);  
}
Пример #13
0
void FreeSub(Substructure *sub)
{
   if (sub != NULL) 
   {
      FreeGraph(sub->definition);
      FreeInstanceList(sub->instances);
      FreeInstanceList(sub->negInstances);
      free(sub);
   }
}
Пример #14
0
void MlevelNestedDissection(ctrl_t *ctrl, graph_t *graph, idx_t *order, 
         idx_t lastvtx)
{
  idx_t i, j, nvtxs, nbnd;
  idx_t *label, *bndind;
  graph_t *lgraph, *rgraph;

  nvtxs = graph->nvtxs;

  MlevelNodeBisectionMultiple(ctrl, graph);

  IFSET(ctrl->dbglvl, METIS_DBG_SEPINFO, 
      printf("Nvtxs: %6"PRIDX", [%6"PRIDX" %6"PRIDX" %6"PRIDX"]\n", 
        graph->nvtxs, graph->pwgts[0], graph->pwgts[1], graph->pwgts[2]));


  /* Order the nodes in the separator */
  nbnd   = graph->nbnd;
  bndind = graph->bndind;
  label  = graph->label;
  for (i=0; i<nbnd; i++) 
    order[label[bndind[i]]] = --lastvtx;

  SplitGraphOrder(ctrl, graph, &lgraph, &rgraph);

  /* Free the memory of the top level graph */
  FreeGraph(&graph);

  /* Recurse on lgraph first, as its lastvtx depends on rgraph->nvtxs, which
     will not be defined upon return from MlevelNestedDissection. */
  if (lgraph->nvtxs > MMDSWITCH && lgraph->nedges > 0) 
    MlevelNestedDissection(ctrl, lgraph, order, lastvtx-rgraph->nvtxs);
  else {
    MMDOrder(ctrl, lgraph, order, lastvtx-rgraph->nvtxs); 
    FreeGraph(&lgraph);
  }
  if (rgraph->nvtxs > MMDSWITCH && rgraph->nedges > 0) 
    MlevelNestedDissection(ctrl, rgraph, order, lastvtx);
  else {
    MMDOrder(ctrl, rgraph, order, lastvtx); 
    FreeGraph(&rgraph);
  }
}
Пример #15
0
/*************************************************************************
* This function is the entry point for ONWMETIS. It requires weights on the
* vertices. It is for the case that the matrix has been pre-compressed.
**************************************************************************/
void METIS_EdgeComputeSeparator(idxtype *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, 
           idxtype *adjwgt, idxtype *options, idxtype *sepsize, idxtype *part) 
{
  idxtype i, j, tvwgt, tpwgts[2];
  GraphType graph;
  CtrlType ctrl;

  SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3);
  tvwgt = idxsum(*nvtxs, graph.vwgt, 1);

  if (options[0] == 0) {  /* Use the default parameters */
    ctrl.CType = ONMETIS_CTYPE;
    ctrl.IType = ONMETIS_ITYPE;
    ctrl.RType = ONMETIS_RTYPE;
    ctrl.dbglvl = ONMETIS_DBGLVL;
  }
  else {
    ctrl.CType = options[OPTION_CTYPE];
    ctrl.IType = options[OPTION_ITYPE];
    ctrl.RType = options[OPTION_RTYPE];
    ctrl.dbglvl = options[OPTION_DBGLVL];
  }

  ctrl.oflags  = 0;
  ctrl.pfactor = 0;
  ctrl.nseps = 1;
  ctrl.optype = OP_OEMETIS;
  ctrl.CoarsenTo = amin(100, *nvtxs-1);
  ctrl.maxvwgt = 1.5*tvwgt/ctrl.CoarsenTo;

  InitRandom(options[7]);

  AllocateWorkSpace(&ctrl, &graph, 2);

  /*============================================================
   * Perform the bisection
   *============================================================*/ 
  tpwgts[0] = tvwgt/2;
  tpwgts[1] = tvwgt-tpwgts[0];

  MlevelEdgeBisection(&ctrl, &graph, tpwgts, 1.05);
  ConstructMinCoverSeparator(&ctrl, &graph, 1.05);

  *sepsize = graph.pwgts[2];
  idxcopy(*nvtxs, graph.where, part);

  FreeGraph(&graph, 0);

  FreeWorkSpace(&ctrl, &graph);
}
Пример #16
0
/*************************************************************************
* Let the game begin
**************************************************************************/
int main(int argc, char *argv[])
{
  idx_t i;
  idx_t *perm, *iperm;
  graph_t *graph;
  params_t params;
  size_t maxlnz, opc;

  if (argc != 3) {
    printf("Usage: %s <GraphFile> <PermFile\n", argv[0]);
    exit(0);
  }
    
  params.filename = gk_strdup(argv[1]);
  graph = ReadGraph(&params);
  if (graph->nvtxs <= 0) {
    printf("Empty graph. Nothing to do.\n");
    exit(0);
  }
  if (graph->ncon != 1) {
    printf("Ordering can only be applied to graphs with one constraint.\n");
    exit(0);
  }


  /* Read the external iperm vector */
  perm  = imalloc(graph->nvtxs, "main: perm");
  iperm = imalloc(graph->nvtxs, "main: iperm");
  ReadPOVector(graph, argv[2], iperm);

  for (i=0; i<graph->nvtxs; i++)
    perm[iperm[i]] = i;

  printf("**********************************************************************\n");
  printf("%s", METISTITLE);
  printf("Graph Information ---------------------------------------------------\n");
  printf("  Name: %s, #Vertices: %"PRIDX", #Edges: %"PRIDX"\n\n", argv[1], 
      graph->nvtxs, graph->nedges/2);
  printf("Fillin... -----------------------------------------------------------\n");

  ComputeFillIn(graph, perm, iperm, &maxlnz, &opc);
  
  printf("  Nonzeros: %6.3le \tOperation Count: %6.3le\n", (double)maxlnz, (double)opc);


  printf("**********************************************************************\n");

  FreeGraph(&graph);
}  
Пример #17
0
/*************************************************************************
* This function takes a graph and produces a bisection of it
**************************************************************************/
idxtype MCMlevelKWayPartitioning(CtrlType *ctrl, GraphType *graph, idxtype nparts, idxtype *part, 
      float *rubvec)
{
  idxtype i, j, nvtxs;
  GraphType *cgraph;
  idxtype options[10], edgecut;

  cgraph = MCCoarsen2Way(ctrl, graph);

  IFSET(ctrl->dbglvl, DBG_TIME, gk_startcputimer(ctrl->InitPartTmr));
  MocAllocateKWayPartitionMemory(ctrl, cgraph, nparts);

  options[0] = 1; 
  options[OPTION_CTYPE] = MTYPE_SBHEM_INFNORM;
  options[OPTION_ITYPE] = ITYPE_RANDOM;
  options[OPTION_RTYPE] = RTYPE_FM;
  options[OPTION_DBGLVL] = 0;

  /* Determine what you will use as the initial partitioner, based on tolerances */
  for (i=0; i<graph->ncon; i++) {
    if (rubvec[i] > 1.2)
      break;
  }
  if (i == graph->ncon)
    METIS_mCPartGraphRecursiveInternal(&cgraph->nvtxs, &cgraph->ncon, 
          cgraph->xadj, cgraph->adjncy, cgraph->nvwgt, cgraph->adjwgt, &nparts, 
          options, &edgecut, cgraph->where);
  else
    METIS_mCHPartGraphRecursiveInternal(&cgraph->nvtxs, &cgraph->ncon, 
          cgraph->xadj, cgraph->adjncy, cgraph->nvwgt, cgraph->adjwgt, &nparts, 
          rubvec, options, &edgecut, cgraph->where);


  IFSET(ctrl->dbglvl, DBG_TIME, gk_stopcputimer(ctrl->InitPartTmr));
  IFSET(ctrl->dbglvl, DBG_IPART, mprintf("Initial %D-way partitioning cut: %D\n", nparts, edgecut));

  IFSET(ctrl->dbglvl, DBG_KWAYPINFO, ComputePartitionInfo(cgraph, nparts, cgraph->where));

  MocRefineKWayHorizontal(ctrl, graph, cgraph, nparts, rubvec);

  idxcopy(graph->nvtxs, graph->where, part);

  FreeGraph(graph, 0);

  return graph->mincut;

}
Пример #18
0
InstanceList *FilterInstances(Graph *subGraph, InstanceList *instanceList,
                              Graph *graph, Parameters *parameters)
{
   InstanceListNode *instanceListNode;
   Instance *instance;
   InstanceList *newInstanceList;
   Graph *instanceGraph;
   double thresholdLimit;
   double matchCost;

   newInstanceList = AllocateInstanceList();
   if (instanceList != NULL) 
   {
      instanceListNode = instanceList->head;
      while (instanceListNode != NULL) 
      {
         if (instanceListNode->instance != NULL) 
         {
            instance = instanceListNode->instance;
            if (parameters->allowInstanceOverlap ||
                (! InstanceListOverlap(instance, newInstanceList))) 
            {
               thresholdLimit = parameters->threshold *
                                (instance->numVertices + instance->numEdges);
               instanceGraph = InstanceToGraph(instance, graph);
               if (GraphMatch(subGraph, instanceGraph, parameters->labelList,
                              thresholdLimit, & matchCost, NULL)) 
               {
                  if (matchCost < instance->minMatchCost)
                     instance->minMatchCost = matchCost;
                  InstanceListInsert(instance, newInstanceList, FALSE);
               }
               FreeGraph(instanceGraph);
            }
         }
         instanceListNode = instanceListNode->next;
      }
   }
   FreeInstanceList(instanceList);
   return newInstanceList;
}
Пример #19
0
/******************************************************************************
* This function takes a graph and its partition vector and creates a new
* graph corresponding to the one after the movement
*******************************************************************************/
void TestMoveGraph(GraphType *ograph, GraphType *omgraph, idxtype *part, MPI_Comm comm)
{
  int npes, mype;
  CtrlType ctrl;
  WorkSpaceType wspace;
  GraphType *graph, *mgraph;
  int options[5] = {0, 0, 1, 0, 0};

  MPI_Comm_size(comm, &npes);
  MPI_Comm_rank(comm, &mype);

  SetUpCtrl(&ctrl, npes, 0, comm); 
  ctrl.CoarsenTo = 1;  /* Needed by SetUpGraph, otherwise we can FP errors */
  graph = SetUpGraph(&ctrl, ograph->vtxdist, ograph->xadj, NULL, ograph->adjncy, NULL, 0);
  AllocateWSpace(&ctrl, graph, &wspace);

  SetUp(&ctrl, graph, &wspace);
  graph->where = part;
  graph->ncon = 1;
  mgraph = Mc_MoveGraph(&ctrl, graph, &wspace);

  omgraph->gnvtxs = mgraph->gnvtxs;
  omgraph->nvtxs = mgraph->nvtxs;
  omgraph->nedges = mgraph->nedges;
  omgraph->vtxdist = mgraph->vtxdist;
  omgraph->xadj = mgraph->xadj;
  omgraph->adjncy = mgraph->adjncy;
  mgraph->vtxdist = NULL;
  mgraph->xadj = NULL;
  mgraph->adjncy = NULL;
  FreeGraph(mgraph);

  graph->where = NULL;
  FreeInitialGraphAndRemap(graph, 0, 1);
  FreeWSpace(&wspace);
}  
void ProjectKWayPartition(ctrl_t *ctrl, graph_t *graph)
{
  idx_t i, j, k, nvtxs, nbnd, nparts, me, other, istart, iend, tid, ted;
  idx_t *xadj, *adjncy, *adjwgt;
  idx_t *cmap, *where, *bndptr, *bndind, *cwhere, *htable;
  graph_t *cgraph;

  WCOREPUSH;

  nparts = ctrl->nparts;

  cgraph = graph->coarser;
  cwhere = cgraph->where;

  nvtxs   = graph->nvtxs;
  cmap    = graph->cmap;
  xadj    = graph->xadj;
  adjncy  = graph->adjncy;
  adjwgt  = graph->adjwgt;

  AllocateKWayPartitionMemory(ctrl, graph);

  where  = graph->where;
  bndind = graph->bndind;
  bndptr = iset(nvtxs, -1, graph->bndptr);

  htable = iset(nparts, -1, iwspacemalloc(ctrl, nparts));

  /* Compute the required info for refinement */
  switch (ctrl->objtype) {
    case METIS_OBJTYPE_CUT:
      ASSERT(CheckBnd2(cgraph));
      {
        ckrinfo_t *myrinfo;
        cnbr_t *mynbrs;

        /* go through and project partition and compute id/ed for the nodes */
        for (i=0; i<nvtxs; i++) {
          k        = cmap[i];
          where[i] = cwhere[k];
          cmap[i]  = cgraph->ckrinfo[k].ed;  /* For optimization */
        }

        memset(graph->ckrinfo, 0, sizeof(ckrinfo_t)*nvtxs);
        cnbrpoolReset(ctrl);

        for (nbnd=0, i=0; i<nvtxs; i++) {
          istart = xadj[i];
          iend   = xadj[i+1];

          myrinfo = graph->ckrinfo+i;

          if (cmap[i] == 0) { /* Interior node. Note that cmap[i] = crinfo[cmap[i]].ed */
            for (tid=0, j=istart; j<iend; j++) 
              tid += adjwgt[j];

            myrinfo->id   = tid;
            myrinfo->inbr = -1;
          }
          else { /* Potentially an interface node */
            myrinfo->inbr = cnbrpoolGetNext(ctrl, iend-istart+1);
            mynbrs        = ctrl->cnbrpool + myrinfo->inbr;

            me = where[i];
            for (tid=0, ted=0, j=istart; j<iend; j++) {
              other = where[adjncy[j]];
              if (me == other) {
                tid += adjwgt[j];
              }
              else {
                ted += adjwgt[j];
                if ((k = htable[other]) == -1) {
                  htable[other]               = myrinfo->nnbrs;
                  mynbrs[myrinfo->nnbrs].pid  = other;
                  mynbrs[myrinfo->nnbrs++].ed = adjwgt[j];
                }
                else {
                  mynbrs[k].ed += adjwgt[j];
                }
              }
            }
            myrinfo->id = tid;
            myrinfo->ed = ted;
      
            /* Remove space for edegrees if it was interior */
            if (ted == 0) { 
              ctrl->nbrpoolcpos -= iend-istart+1;
              myrinfo->inbr      = -1;
            }
            else {
              if (ted-tid >= 0) 
                BNDInsert(nbnd, bndind, bndptr, i); 
      
              for (j=0; j<myrinfo->nnbrs; j++)
                htable[mynbrs[j].pid] = -1;
            }
          }
        }
      
        graph->nbnd = nbnd;

      }
      ASSERT(CheckBnd2(graph));
      break;

    case METIS_OBJTYPE_VOL:
      {
        vkrinfo_t *myrinfo;
        vnbr_t *mynbrs;

        ASSERT(cgraph->minvol == ComputeVolume(cgraph, cgraph->where));

        /* go through and project partition and compute id/ed for the nodes */
        for (i=0; i<nvtxs; i++) {
          k        = cmap[i];
          where[i] = cwhere[k];
          cmap[i]  = cgraph->vkrinfo[k].ned;  /* For optimization */
        }

        memset(graph->vkrinfo, 0, sizeof(vkrinfo_t)*nvtxs);
        vnbrpoolReset(ctrl);

        for (i=0; i<nvtxs; i++) {
          istart = xadj[i];
          iend   = xadj[i+1];
          myrinfo = graph->vkrinfo+i;

          if (cmap[i] == 0) { /* Note that cmap[i] = crinfo[cmap[i]].ed */
            myrinfo->nid  = iend-istart;
            myrinfo->inbr = -1;
          }
          else { /* Potentially an interface node */
            myrinfo->inbr = vnbrpoolGetNext(ctrl, iend-istart+1);
            mynbrs        = ctrl->vnbrpool + myrinfo->inbr;

            me = where[i];
            for (tid=0, ted=0, j=istart; j<iend; j++) {
              other = where[adjncy[j]];
              if (me == other) {
                tid++;
              }
              else {
                ted++;
                if ((k = htable[other]) == -1) {
                  htable[other]                = myrinfo->nnbrs;
                  mynbrs[myrinfo->nnbrs].gv    = 0;
                  mynbrs[myrinfo->nnbrs].pid   = other;
                  mynbrs[myrinfo->nnbrs++].ned = 1;
                }
                else {
                  mynbrs[k].ned++;
                }
              }
            }
            myrinfo->nid = tid;
            myrinfo->ned = ted;
      
            /* Remove space for edegrees if it was interior */
            if (ted == 0) { 
              ctrl->nbrpoolcpos -= iend-istart+1;
              myrinfo->inbr = -1;
            }
            else {
              for (j=0; j<myrinfo->nnbrs; j++)
                htable[mynbrs[j].pid] = -1;
            }
          }
        }
      
        ComputeKWayVolGains(ctrl, graph);

        ASSERT(graph->minvol == ComputeVolume(graph, graph->where));
      }
      break;

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

  graph->mincut = cgraph->mincut;
  icopy(nparts*graph->ncon, cgraph->pwgts, graph->pwgts);

  FreeGraph(&graph->coarser);
  graph->coarser = NULL;

  WCOREPOP;
}
Пример #21
0
/*************************************************************************
* This function is the entry point of the initial partition algorithm
* that does recursive bissection.
* This algorithm assembles the graph to all the processors and preceeds
* by parallelizing the recursive bisection step.
**************************************************************************/
void InitPartition(ctrl_t *ctrl, graph_t *graph)
{
  idx_t i, j, ncon, mype, npes, gnvtxs, ngroups;
  idx_t *xadj, *adjncy, *adjwgt, *vwgt;
  idx_t *part, *gwhere0, *gwhere1;
  idx_t *tmpwhere, *tmpvwgt, *tmpxadj, *tmpadjncy, *tmpadjwgt;
  graph_t *agraph;
  idx_t lnparts, fpart, fpe, lnpes; 
  idx_t twoparts=2, moptions[METIS_NOPTIONS], edgecut, max_cut;
  real_t *tpwgts, *tpwgts2, *lbvec, lbsum, min_lbsum, wsum;
  MPI_Comm ipcomm;
  struct {
    double sum;
    int rank;
  } lpesum, gpesum;

  WCOREPUSH;

  ncon = graph->ncon;

  ngroups = gk_max(gk_min(RIP_SPLIT_FACTOR, ctrl->npes), 1);

  IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->comm));
  IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->InitPartTmr));

  lbvec = rwspacemalloc(ctrl, ncon);

  /* assemble the graph to all the processors */
  agraph = AssembleAdaptiveGraph(ctrl, graph);
  gnvtxs = agraph->nvtxs;

  /* make a copy of the graph's structure for later */
  xadj   = icopy(gnvtxs+1, agraph->xadj, iwspacemalloc(ctrl, gnvtxs+1));
  vwgt   = icopy(gnvtxs*ncon, agraph->vwgt, iwspacemalloc(ctrl, gnvtxs*ncon));
  adjncy = icopy(agraph->nedges, agraph->adjncy, iwspacemalloc(ctrl, agraph->nedges));
  adjwgt = icopy(agraph->nedges, agraph->adjwgt, iwspacemalloc(ctrl, agraph->nedges));
  part   = iwspacemalloc(ctrl, gnvtxs);

  /* create different processor groups */
  gkMPI_Comm_split(ctrl->gcomm, ctrl->mype % ngroups, 0, &ipcomm);
  gkMPI_Comm_rank(ipcomm, &mype);
  gkMPI_Comm_size(ipcomm, &npes);


  /* Go into the recursive bisection */
  METIS_SetDefaultOptions(moptions);
  moptions[METIS_OPTION_SEED] = ctrl->sync + (ctrl->mype % ngroups) + 1;

  tpwgts  = ctrl->tpwgts;
  tpwgts2 = rwspacemalloc(ctrl, 2*ncon);

  lnparts = ctrl->nparts;
  fpart = fpe = 0;
  lnpes = npes;
  while (lnpes > 1 && lnparts > 1) {
    /* determine the weights of the two partitions as a function of the 
       weight of the target partition weights */
    for (j=(lnparts>>1), i=0; i<ncon; i++) {
      tpwgts2[i]      = rsum(j, tpwgts+fpart*ncon+i, ncon);
      tpwgts2[ncon+i] = rsum(lnparts-j, tpwgts+(fpart+j)*ncon+i, ncon);
      wsum            = 1.0/(tpwgts2[i] + tpwgts2[ncon+i]);
      tpwgts2[i]      *= wsum;
      tpwgts2[ncon+i] *= wsum;
    }

    METIS_PartGraphRecursive(&agraph->nvtxs, &ncon, agraph->xadj, agraph->adjncy, 
          agraph->vwgt, NULL, agraph->adjwgt, &twoparts, tpwgts2, NULL, moptions, 
          &edgecut, part);

    /* pick one of the branches */
    if (mype < fpe+lnpes/2) {
      KeepPart(ctrl, agraph, part, 0);
      lnpes   = lnpes/2;
      lnparts = lnparts/2;
    }
    else {
      KeepPart(ctrl, agraph, part, 1);
      fpart   = fpart + lnparts/2;
      fpe     = fpe + lnpes/2;
      lnpes   = lnpes - lnpes/2;
      lnparts = lnparts - lnparts/2;
    }
  }

  gwhere0 = iset(gnvtxs, 0, iwspacemalloc(ctrl, gnvtxs));
  gwhere1 = iwspacemalloc(ctrl, gnvtxs);

  if (lnparts == 1) { /* Case npes is greater than or equal to nparts */
    /* Only the first process will assign labels (for the reduction to work) */
    if (mype == fpe) {
      for (i=0; i<agraph->nvtxs; i++) 
        gwhere0[agraph->label[i]] = fpart;
    }
  }
  else { /* Case in which npes is smaller than nparts */
    /* create the normalized tpwgts for the lnparts from ctrl->tpwgts */
    tpwgts = rwspacemalloc(ctrl, lnparts*ncon);
    for (j=0; j<ncon; j++) {
      for (wsum=0.0, i=0; i<lnparts; i++) {
        tpwgts[i*ncon+j] = ctrl->tpwgts[(fpart+i)*ncon+j];
        wsum += tpwgts[i*ncon+j];
      }
      for (wsum=1.0/wsum, i=0; i<lnparts; i++) 
        tpwgts[i*ncon+j] *= wsum;
    }

    METIS_PartGraphKway(&agraph->nvtxs, &ncon, agraph->xadj, agraph->adjncy, 
          agraph->vwgt, NULL, agraph->adjwgt, &lnparts, tpwgts, NULL, moptions, 
          &edgecut, part);

    for (i=0; i<agraph->nvtxs; i++) 
      gwhere0[agraph->label[i]] = fpart + part[i];
  }

  gkMPI_Allreduce((void *)gwhere0, (void *)gwhere1, gnvtxs, IDX_T, MPI_SUM, ipcomm);

  if (ngroups > 1) {
    tmpxadj   = agraph->xadj;
    tmpadjncy = agraph->adjncy;
    tmpadjwgt = agraph->adjwgt;
    tmpvwgt   = agraph->vwgt;
    tmpwhere  = agraph->where;

    agraph->xadj   = xadj;
    agraph->adjncy = adjncy;
    agraph->adjwgt = adjwgt;
    agraph->vwgt   = vwgt;
    agraph->where  = gwhere1;
    agraph->vwgt   = vwgt;
    agraph->nvtxs  = gnvtxs;

    edgecut = ComputeSerialEdgeCut(agraph);
    ComputeSerialBalance(ctrl, agraph, gwhere1, lbvec);
    lbsum = rsum(ncon, lbvec, 1);

    gkMPI_Allreduce((void *)&edgecut, (void *)&max_cut,   1, IDX_T,  MPI_MAX, ctrl->gcomm);
    gkMPI_Allreduce((void *)&lbsum,   (void *)&min_lbsum, 1, REAL_T, MPI_MIN, ctrl->gcomm);

    lpesum.sum = lbsum;
    if (min_lbsum < UNBALANCE_FRACTION*ncon) {
      if (lbsum < UNBALANCE_FRACTION*ncon)
        lpesum.sum = edgecut;
      else
        lpesum.sum = max_cut;
    } 
    lpesum.rank = ctrl->mype;
    
    gkMPI_Allreduce((void *)&lpesum, (void *)&gpesum, 1, MPI_DOUBLE_INT,
        MPI_MINLOC, ctrl->gcomm);
    gkMPI_Bcast((void *)gwhere1, gnvtxs, IDX_T, gpesum.rank, ctrl->gcomm);

    agraph->xadj   = tmpxadj;
    agraph->adjncy = tmpadjncy;
    agraph->adjwgt = tmpadjwgt;
    agraph->vwgt   = tmpvwgt;
    agraph->where  = tmpwhere;
  }

  icopy(graph->nvtxs, gwhere1+graph->vtxdist[ctrl->mype], graph->where);

  FreeGraph(agraph);
  gkMPI_Comm_free(&ipcomm);

  IFSET(ctrl->dbglvl, DBG_TIME, gkMPI_Barrier(ctrl->comm));
  IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->InitPartTmr));

  WCOREPOP;
}
Пример #22
0
idx_t MlevelKWayPartitioning(ctrl_t *ctrl, graph_t *graph, idx_t *part)
{
  idx_t i, objval=0, curobj=0, bestobj=0;
  real_t curbal=0.0, bestbal=0.0;
  graph_t *cgraph;


  for (i=0; i<ctrl->ncuts; i++) {
    cgraph = CoarsenGraph(ctrl, graph);

    IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_startwctimer(ctrl->InitPartTmr));
    AllocateKWayPartitionMemory(ctrl, cgraph);

    /* Compute the initial partitioning */
    switch (ctrl->iptype) {
      case METIS_IPTYPE_METISRB:
        FreeWorkSpace(ctrl); /* Release the work space, for the recursive metis call */
        InitKWayPartitioningRB(ctrl, cgraph);
        AllocateWorkSpace(ctrl, graph); /* Re-allocate the work space */
        break;

      case METIS_IPTYPE_GROW:
        AllocateRefinementWorkSpace(ctrl, 2*cgraph->nedges);
        InitKWayPartitioningGrow(ctrl, cgraph);
        break;

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

    IFSET(ctrl->dbglvl, METIS_DBG_TIME, gk_stopwctimer(ctrl->InitPartTmr));
    IFSET(ctrl->dbglvl, METIS_DBG_IPART, printf("Initial %"PRIDX \
          "-way partitioning cut: %"PRIDX"\n", ctrl->nparts, objval));

    RefineKWay(ctrl, graph, cgraph);

    switch (ctrl->objtype) {
      case METIS_OBJTYPE_CUT:
        curobj = graph->mincut;
        break;

      case METIS_OBJTYPE_VOL:
        curobj = graph->minvol;
        break;

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

    curbal = ComputeLoadImbalanceDiff(graph, ctrl->nparts, ctrl->pijbm, ctrl->ubfactors);

    if (i == 0 
        || (curbal <= 0.0005 && bestobj > curobj)
        || (bestbal > 0.0005 && curbal < bestbal)) {
      icopy(graph->nvtxs, graph->where, part);
      bestobj = curobj;
      bestbal = curbal;
    }

    FreeRData(graph);

    if (bestobj == 0)
      break;
  }

  FreeGraph(&graph);

  return bestobj;
}
Пример #23
0
/*************************************************************************
* This function is the entry point of the initial partition algorithm
* that does recursive bissection.
* This algorithm assembles the graph to all the processors and preceeds
* by parallelizing the recursive bisection step.
**************************************************************************/
void Mc_InitPartition_RB(CtrlType *ctrl, GraphType *graph, WorkSpaceType *wspace)
{
    int i, j;
    int ncon, mype, npes, gnvtxs, ngroups;
    idxtype *xadj, *adjncy, *adjwgt, *vwgt;
    idxtype *part, *gwhere0, *gwhere1;
    idxtype *tmpwhere, *tmpvwgt, *tmpxadj, *tmpadjncy, *tmpadjwgt;
    GraphType *agraph;
    int lnparts, fpart, fpe, lnpes;
    int twoparts=2, numflag = 0, wgtflag = 3, moptions[10], edgecut, max_cut;
    float *mytpwgts, mytpwgts2[2], lbvec[MAXNCON], lbsum, min_lbsum, wsum;
    MPI_Comm ipcomm;
    struct {
        float sum;
        int rank;
    } lpesum, gpesum;

    ncon = graph->ncon;
    ngroups = amax(amin(RIP_SPLIT_FACTOR, ctrl->npes), 1);

    IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
    IFSET(ctrl->dbglvl, DBG_TIME, starttimer(ctrl->InitPartTmr));

    agraph = Mc_AssembleAdaptiveGraph(ctrl, graph, wspace);
    part = idxmalloc(agraph->nvtxs, "Mc_IP_RB: part");
    xadj = idxmalloc(agraph->nvtxs+1, "Mc_IP_RB: xadj");
    adjncy = idxmalloc(agraph->nedges, "Mc_IP_RB: adjncy");
    adjwgt = idxmalloc(agraph->nedges, "Mc_IP_RB: adjwgt");
    vwgt = idxmalloc(agraph->nvtxs*ncon, "Mc_IP_RB: vwgt");

    idxcopy(agraph->nvtxs*ncon, agraph->vwgt, vwgt);
    idxcopy(agraph->nvtxs+1, agraph->xadj, xadj);
    idxcopy(agraph->nedges, agraph->adjncy, adjncy);
    idxcopy(agraph->nedges, agraph->adjwgt, adjwgt);

    MPI_Comm_split(ctrl->gcomm, ctrl->mype % ngroups, 0, &ipcomm);
    MPI_Comm_rank(ipcomm, &mype);
    MPI_Comm_size(ipcomm, &npes);

    gnvtxs = agraph->nvtxs;

    gwhere0 = idxsmalloc(gnvtxs, 0, "Mc_IP_RB: gwhere0");
    gwhere1 = idxmalloc(gnvtxs, "Mc_IP_RB: gwhere1");

    /* ADD: this assumes that tpwgts for all constraints is the same */
    /* ADD: this is necessary because serial metis does not support the general case */
    mytpwgts = fsmalloc(ctrl->nparts, 0.0, "mytpwgts");
    for (i=0; i<ctrl->nparts; i++)
        for (j=0; j<ncon; j++)
            mytpwgts[i] += ctrl->tpwgts[i*ncon+j];
    for (i=0; i<ctrl->nparts; i++)
        mytpwgts[i] /= (float)ncon;

    /* Go into the recursive bisection */
    /* ADD: consider changing this to breadth-first type bisection */
    moptions[0] = 0;
    moptions[7] = ctrl->sync + (ctrl->mype % ngroups) + 1;

    lnparts = ctrl->nparts;
    fpart = fpe = 0;
    lnpes = npes;
    while (lnpes > 1 && lnparts > 1) {
        /* Determine the weights of the partitions */
        mytpwgts2[0] = ssum(lnparts/2, mytpwgts+fpart);
        mytpwgts2[1] = 1.0-mytpwgts2[0];

        if (ncon == 1)
            METIS_WPartGraphKway2(&agraph->nvtxs, agraph->xadj, agraph->adjncy,
                                  agraph->vwgt, agraph->adjwgt, &wgtflag, &numflag, &twoparts, mytpwgts2,
                                  moptions, &edgecut, part);
        else {
            METIS_mCPartGraphRecursive2(&agraph->nvtxs, &ncon, agraph->xadj,
                                        agraph->adjncy, agraph->vwgt, agraph->adjwgt, &wgtflag, &numflag,
                                        &twoparts, mytpwgts2, moptions, &edgecut, part);
        }

        wsum = ssum(lnparts/2, mytpwgts+fpart);
        sscale(lnparts/2, 1.0/wsum, mytpwgts+fpart);
        sscale(lnparts-lnparts/2, 1.0/(1.0-wsum), mytpwgts+fpart+lnparts/2);

        /* I'm picking the left branch */
        if (mype < fpe+lnpes/2) {
            Mc_KeepPart(agraph, wspace, part, 0);
            lnpes = lnpes/2;
            lnparts = lnparts/2;
        }
        else {
            Mc_KeepPart(agraph, wspace, part, 1);
            fpart = fpart + lnparts/2;
            fpe = fpe + lnpes/2;
            lnpes = lnpes - lnpes/2;
            lnparts = lnparts - lnparts/2;
        }
    }

    /* In case npes is greater than or equal to nparts */
    if (lnparts == 1) {
        /* Only the first process will assign labels (for the reduction to work) */
        if (mype == fpe) {
            for (i=0; i<agraph->nvtxs; i++)
                gwhere0[agraph->label[i]] = fpart;
        }
    }
    /* In case npes is smaller than nparts */
    else {
        if (ncon == 1)
            METIS_WPartGraphKway2(&agraph->nvtxs, agraph->xadj, agraph->adjncy,
                                  agraph->vwgt, agraph->adjwgt, &wgtflag, &numflag, &lnparts, mytpwgts+fpart,
                                  moptions, &edgecut, part);
        else
            METIS_mCPartGraphRecursive2(&agraph->nvtxs, &ncon, agraph->xadj,
                                        agraph->adjncy, agraph->vwgt, agraph->adjwgt, &wgtflag, &numflag,
                                        &lnparts, mytpwgts+fpart, moptions, &edgecut, part);

        for (i=0; i<agraph->nvtxs; i++)
            gwhere0[agraph->label[i]] = fpart + part[i];
    }

    MPI_Allreduce((void *)gwhere0, (void *)gwhere1, gnvtxs, IDX_DATATYPE, MPI_SUM, ipcomm);

    if (ngroups > 1) {
        tmpxadj = agraph->xadj;
        tmpadjncy = agraph->adjncy;
        tmpadjwgt = agraph->adjwgt;
        tmpvwgt = agraph->vwgt;
        tmpwhere = agraph->where;
        agraph->xadj = xadj;
        agraph->adjncy = adjncy;
        agraph->adjwgt = adjwgt;
        agraph->vwgt = vwgt;
        agraph->where = gwhere1;
        agraph->vwgt = vwgt;
        agraph->nvtxs = gnvtxs;
        Mc_ComputeSerialBalance(ctrl, agraph, gwhere1, lbvec);
        lbsum = ssum(ncon, lbvec);

        edgecut = ComputeSerialEdgeCut(agraph);
        MPI_Allreduce((void *)&edgecut, (void *)&max_cut, 1, MPI_INT, MPI_MAX, ctrl->gcomm);
        MPI_Allreduce((void *)&lbsum, (void *)&min_lbsum, 1, MPI_FLOAT, MPI_MIN, ctrl->gcomm);

        lpesum.sum = lbsum;
        if (min_lbsum < UNBALANCE_FRACTION * (float)(ncon)) {
            if (lbsum < UNBALANCE_FRACTION * (float)(ncon))
                lpesum.sum = (float) (edgecut);
            else
                lpesum.sum = (float) (max_cut);
        }

        MPI_Comm_rank(ctrl->gcomm, &(lpesum.rank));
        MPI_Allreduce((void *)&lpesum, (void *)&gpesum, 1, MPI_FLOAT_INT, MPI_MINLOC, ctrl->gcomm);
        MPI_Bcast((void *)gwhere1, gnvtxs, IDX_DATATYPE, gpesum.rank, ctrl->gcomm);

        agraph->xadj = tmpxadj;
        agraph->adjncy = tmpadjncy;
        agraph->adjwgt = tmpadjwgt;
        agraph->vwgt = tmpvwgt;
        agraph->where = tmpwhere;
    }

    idxcopy(graph->nvtxs, gwhere1+graph->vtxdist[ctrl->mype], graph->where);

    FreeGraph(agraph);
    MPI_Comm_free(&ipcomm);
    GKfree((void **)&gwhere0, (void **)&gwhere1, (void **)&mytpwgts, (void **)&part, (void **)&xadj, (void **)&adjncy, (void **)&adjwgt, (void **)&vwgt, LTERM);

    IFSET(ctrl->dbglvl, DBG_TIME, MPI_Barrier(ctrl->comm));
    IFSET(ctrl->dbglvl, DBG_TIME, stoptimer(ctrl->InitPartTmr));

}
Пример #24
0
//---------------------------------------------------------------------------
//
// NAME: AddNegInstancesToSub
//
// INPUTS: (Substructure *sub) - substructure to collect instances
//         (Instance *subInstance) - instance of substructure
//         (InstanceList *instanceList) - instances to collect from in
//                                        negative graph
//         (Parameters *parameters)
//
// RETURN: (void)
//
// PURPOSE: Add instance from instanceList to sub's negative
// instances if the instance matches sub's definition.  If
// allowInstanceOverlap=FALSE, then instances added only if they do
// not overlap with existing instances.
//---------------------------------------------------------------------------
void AddNegInstancesToSub(Substructure *sub, Instance *subInstance,
                           InstanceList *instanceList, Parameters *parameters)
{
   InstanceListNode *instanceListNode;
   Instance *instance;
   Graph *instanceGraph;
   double thresholdLimit;
   double matchCost;

   // parameters used
   Graph *negGraph              = parameters->negGraph;
   LabelList *labelList         = parameters->labelList;
   BOOLEAN allowInstanceOverlap = parameters->allowInstanceOverlap;
   double threshold             = parameters->threshold;

   // collect negative instances of substructure
   if (instanceList != NULL) 
   {
      sub->negInstances = AllocateInstanceList();
      instanceListNode = instanceList->head;
      while (instanceListNode != NULL) 
      {
         if (instanceListNode->instance != NULL) 
         {
            instance = instanceListNode->instance;
            if (allowInstanceOverlap ||
                (! InstanceListOverlap(instance, sub->negInstances))) 
            {
               thresholdLimit = threshold *
                                (instance->numVertices + instance->numEdges);
               instanceGraph = InstanceToGraph(instance, negGraph);
               //
               // First, if the threshold is 0.0, see if we can match on
               // just the new edge that was added.
               //
               if (threshold == 0.0)
               {
                  // If instance has already been added to another substructure's
                  // list of instances, we can skip it
                  if (!instance->used)
                  {
                     if (NewEdgeMatch (sub->definition, subInstance, instanceGraph, 
                                       instance, parameters, thresholdLimit, 
                                       & matchCost))
                     {
                        if (matchCost < instance->minMatchCost)
                           instance->minMatchCost = matchCost;
                        instance->used = TRUE;
                        InstanceListInsert(instance, sub->negInstances, FALSE);
                        sub->numNegInstances++;
                     }
                  }
               } 
               else 
               {
                  if (GraphMatch(sub->definition, instanceGraph, labelList,
                                 thresholdLimit, & matchCost, NULL))
                  {
                     if (matchCost < instance->minMatchCost)
                        instance->minMatchCost = matchCost;
                     InstanceListInsert(instance, sub->negInstances, FALSE);
                     sub->numNegInstances++;
                  }
               }
               FreeGraph(instanceGraph);
            }
         }
         instanceListNode = instanceListNode->next;
      }
   }
}
Пример #25
0
/*************************************************************************
* This function projects a partition, and at the same time computes the
* parameters for refinement.
**************************************************************************/
void MocProject2WayPartition(CtrlType *ctrl, GraphType *graph)
{
    int i, j, k, nvtxs, nbnd, me;
    idxtype *xadj, *adjncy, *adjwgt, *adjwgtsum;
    idxtype *cmap, *where, *id, *ed, *bndptr, *bndind;
    idxtype *cwhere, *cid, *ced, *cbndptr;
    GraphType *cgraph;

    cgraph = graph->coarser;
    cwhere = cgraph->where;
    cid = cgraph->id;
    ced = cgraph->ed;
    cbndptr = cgraph->bndptr;

    nvtxs = graph->nvtxs;
    cmap = graph->cmap;
    xadj = graph->xadj;
    adjncy = graph->adjncy;
    adjwgt = graph->adjwgt;
    adjwgtsum = graph->adjwgtsum;

    MocAllocate2WayPartitionMemory(ctrl, graph);

    where = graph->where;
    id = idxset(nvtxs, 0, graph->id);
    ed = idxset(nvtxs, 0, graph->ed);
    bndptr = idxset(nvtxs, -1, graph->bndptr);
    bndind = graph->bndind;


    /* Go through and project partition and compute id/ed for the nodes */
    for (i=0; i<nvtxs; i++) {
        k = cmap[i];
        where[i] = cwhere[k];
        cmap[i] = cbndptr[k];
    }

    for (nbnd=0, i=0; i<nvtxs; i++) {
        me = where[i];

        id[i] = adjwgtsum[i];

        if (xadj[i] == xadj[i+1]) {
            bndptr[i] = nbnd;
            bndind[nbnd++] = i;
        }
        else {
            if (cmap[i] != -1) { /* If it is an interface node. Note that cmap[i] = cbndptr[cmap[i]] */
                for (j=xadj[i]; j<xadj[i+1]; j++) {
                    if (me != where[adjncy[j]])
                        ed[i] += adjwgt[j];
                }
                id[i] -= ed[i];

                if (ed[i] > 0 || xadj[i] == xadj[i+1]) {
                    bndptr[i] = nbnd;
                    bndind[nbnd++] = i;
                }
            }
        }
    }

    graph->mincut = cgraph->mincut;
    graph->nbnd = nbnd;
    scopy(2*graph->ncon, cgraph->npwgts, graph->npwgts);

    FreeGraph(graph->coarser);
    graph->coarser = NULL;

}
Пример #26
0
//---------------------------------------------------------------------------
//
// NAME: AddPosInstancesToSub
//
// INPUTS: (Substructure *sub) - substructure to collect instances
//         (Instance *subInstance) - instance of substructure
//         (InstanceList *instanceList) - instances to collect from in
//                                        positive graph
//         (Parameters *parameters)
//         (ULONG index) - index of substructure into instance list
//
// RETURN: (void)
//
// PURPOSE: Add instance from instanceList to sub's positive
// instances if the instance matches sub's definition.  If
// allowInstanceOverlap=FALSE, then instances added only if they do
// not overlap with existing instances.
//---------------------------------------------------------------------------
void AddPosInstancesToSub(Substructure *sub, Instance *subInstance,
                           InstanceList *instanceList, Parameters *parameters,
                           ULONG index)
{
   InstanceListNode *instanceListNode;
   Instance *instance;
   Graph *instanceGraph;
   double thresholdLimit;
   double matchCost;
   ULONG counter = 0;

   // parameters used
   Graph *posGraph              = parameters->posGraph;
   LabelList *labelList         = parameters->labelList;
   BOOLEAN allowInstanceOverlap = parameters->allowInstanceOverlap;
   double threshold             = parameters->threshold;

   // collect positive instances of substructure
   if (instanceList != NULL) 
   {
      sub->instances = AllocateInstanceList();
      //
      // Go ahead an insert the subInstance onto the list of instances for the
      // substructure, as it is obviously an instance.
      //
      subInstance->used = TRUE;
      InstanceListInsert(subInstance, sub->instances, FALSE);
      sub->numInstances++;
      instanceListNode = instanceList->head;
      while (instanceListNode != NULL) 
      {
         if (instanceListNode->instance != NULL) 
         {
            instance = instanceListNode->instance;
            if (allowInstanceOverlap ||
               (! InstanceListOverlap(instance, sub->instances))) 
            {
               thresholdLimit = threshold *
                                (instance->numVertices + instance->numEdges);
               instanceGraph = InstanceToGraph(instance, posGraph);
               //
               // First, if the threshold is 0.0, see if we can match on
               // just the new edge that was added.
               //
               if (threshold == 0.0)
               {
                  //
                  // To avoid processing duplicates, skip all entries
                  // before this instance (because they have been checked
                  // before in a previous call), and skip itself (because
                  // there is no point in comparing it to itself).
                  //
                  // Also, skip processing this instance if it is already
                  // matched with another substructure.
                  //
                  if ((counter > index) && (!instance->used))
                  {
                     if (NewEdgeMatch (sub->definition, subInstance, instanceGraph, 
                                       instance, parameters, thresholdLimit, 
                                       & matchCost))
                     {
                        if (matchCost < instance->minMatchCost)
                           instance->minMatchCost = matchCost;
                        instance->used = TRUE;
                        InstanceListInsert(instance, sub->instances, FALSE);
                        sub->numInstances++;
                     }
                  }
               }
               else
               {
                  if (GraphMatch(sub->definition, instanceGraph, labelList,
                                 thresholdLimit, & matchCost, NULL))
                  {
                     if (matchCost < instance->minMatchCost)
                        instance->minMatchCost = matchCost;
                     InstanceListInsert(instance, sub->instances, FALSE);
                     sub->numInstances++;
                  }
               }
               FreeGraph(instanceGraph);
            }
            counter++;
         }
         instanceListNode = instanceListNode->next;
      }
   }
}
Пример #27
0
void Test(char *subsFileName, char *graphFileName, Parameters *parameters,
          ULONG *TPp, ULONG *TNp, ULONG *FPp, ULONG *FNp)
{
   FILE *graphFile;
   LabelList *labelList;
   BOOLEAN directed;
   Graph **subGraphs;
   ULONG numSubGraphs;
   Graph *graph;
   BOOLEAN positive1;
   BOOLEAN positive2;
   ULONG vertexOffset = 0;
   ULONG lineNo = 1;
   char token[TOKEN_LEN];
   ULONG FP = 0;
   ULONG FN = 0;
   ULONG TP = 0;
   ULONG TN = 0;
   ULONG i;

   labelList = parameters->labelList;
   directed = parameters->directed;

   // read substructures
   subGraphs = ReadSubGraphsFromFile(subsFileName, SUB_TOKEN, &numSubGraphs,
                                     parameters);
   fprintf(stdout, "Read %lu substructures from file %s.\n",
           numSubGraphs, subsFileName);

   // open example graphs file and compute stats
   graphFile = fopen(graphFileName, "r");
   if (graphFile == NULL) 
   {
      fprintf(stderr, "Unable to open graph file %s.\n", graphFileName);
      exit(1);
   }

   graph = NULL;
   positive1 = TRUE;
   while (ReadToken(token, graphFile, &lineNo) != 0) 
   {
      if (strcmp(token, POS_EG_TOKEN) == 0) 
      { // reading positive eg
         if (graph != NULL) 
         {
            // test last graph
            positive2 = PositiveExample(graph, subGraphs, numSubGraphs,
                                        parameters);
            // increment appropriate counter
            if (positive1 && positive2) TP++;
            if (positive1 && (! positive2)) FN++;
            if ((! positive1) && positive2) FP++;
            if ((! positive1) && (! positive2)) TN++;
            FreeGraph(graph);
         }
         graph = AllocateGraph(0,0);
         positive1 = TRUE;
      }
      else if (strcmp(token, NEG_EG_TOKEN) == 0) 
      { // reading negative eg
         if (graph != NULL) 
         {
            // test last graph
            positive2 = PositiveExample(graph, subGraphs, numSubGraphs,
                                        parameters);
            // increment appropriate counter
            if (positive1 && positive2) TP++;
            if (positive1 && (! positive2)) FN++;
            if ((! positive1) && positive2) FP++;
            if ((! positive1) && (! positive2)) TN++;
            FreeGraph(graph);
         }
         graph = AllocateGraph(0,0);
         positive1 = FALSE;
      }
      else if (strcmp(token, "v") == 0) 
      {  // read vertex
         if (positive1 && (graph == NULL)) 
         {
            // first graph starts without positive token, so assumed positive
            graph = AllocateGraph(0,0);
         }
         ReadVertex(graph, graphFile, labelList, &lineNo, vertexOffset);
      }
      else if (strcmp(token, "e") == 0)    // read 'e' edge
         ReadEdge(graph, graphFile, labelList, &lineNo, directed, vertexOffset);

      else if (strcmp(token, "u") == 0)    // read undirected edge
         ReadEdge(graph, graphFile, labelList, &lineNo, FALSE, vertexOffset);

      else if (strcmp(token, "d") == 0)    // read directed edge
         ReadEdge(graph, graphFile, labelList, &lineNo, TRUE, vertexOffset);

      else 
      {
         fclose(graphFile);
         fprintf(stderr, "Unknown token %s in line %lu of input file %s.\n",
                 token, lineNo, graphFileName);
         exit(1);
      }
   }
   // test last graph
   if (graph != NULL) 
   {
      positive2 = PositiveExample(graph, subGraphs, numSubGraphs,
                                  parameters);
      // increment appropriate counter
      if (positive1 && positive2) TP++;
      if (positive1 && (! positive2)) FN++;
      if ((! positive1) && positive2) FP++;
      if ((! positive1) && (! positive2)) TN++;
      FreeGraph(graph);
   }

   fclose(graphFile);

   // free substructure graphs
   for (i = 0; i < numSubGraphs; i++)
      FreeGraph(subGraphs[i]);
   free(subGraphs);

   *TPp = TP;
   *TNp = TN;
   *FPp = FP;
   *FNp = FN;
}
Пример #28
0
/*************************************************************************
* This function projects a partition, and at the same time computes the
* parameters for refinement.
**************************************************************************/
void ProjectKWayPartition(CtrlType *ctrl, GraphType *graph, int nparts)
{
  int i, j, k, nvtxs, nbnd, me, other, istart, iend, ndegrees;
  idxtype *xadj, *adjncy, *adjwgt, *adjwgtsum;
  idxtype *cmap, *where, *bndptr, *bndind;
  idxtype *cwhere;
  GraphType *cgraph;
  RInfoType *crinfo, *rinfo, *myrinfo;
  EDegreeType *myedegrees;
  idxtype *htable;

  cgraph = graph->coarser;
  cwhere = cgraph->where;
  crinfo = cgraph->rinfo;

  nvtxs = graph->nvtxs;
  cmap = graph->cmap;
  xadj = graph->xadj;
  adjncy = graph->adjncy;
  adjwgt = graph->adjwgt;
  adjwgtsum = graph->adjwgtsum;

  AllocateKWayPartitionMemory(ctrl, graph, nparts);
  where = graph->where;
  rinfo = graph->rinfo;
  bndind = graph->bndind;
  bndptr = idxset(nvtxs, -1, graph->bndptr);

  /* Go through and project partition and compute id/ed for the nodes */
  for (i=0; i<nvtxs; i++) {
    k = cmap[i];
    where[i] = cwhere[k];
    cmap[i] = crinfo[k].ed;  /* For optimization */
  }

  htable = idxset(nparts, -1, idxwspacemalloc(ctrl, nparts));

  ctrl->wspace.cdegree = 0;
  for (nbnd=0, i=0; i<nvtxs; i++) {
    me = where[i];

    myrinfo = rinfo+i;
    myrinfo->id = myrinfo->ed = myrinfo->ndegrees = 0;
    myrinfo->edegrees = NULL;

    myrinfo->id = adjwgtsum[i];

    if (cmap[i] > 0) { /* If it is an interface node. Note cmap[i] = crinfo[cmap[i]].ed */
      istart = xadj[i];
      iend = xadj[i+1];

      myedegrees = myrinfo->edegrees = ctrl->wspace.edegrees+ctrl->wspace.cdegree;
      ctrl->wspace.cdegree += iend-istart;

      ndegrees = 0;
      for (j=istart; j<iend; j++) {
        other = where[adjncy[j]];
        if (me != other) {
          myrinfo->ed += adjwgt[j];
          if ((k = htable[other]) == -1) {
            htable[other] = ndegrees;
            myedegrees[ndegrees].pid = other;
            myedegrees[ndegrees++].ed = adjwgt[j];
          }
          else {
            myedegrees[k].ed += adjwgt[j];
          }
        }
      }
      myrinfo->id -= myrinfo->ed;

      /* Remove space for edegrees if it was interior */
      if (myrinfo->ed == 0) { 
        myrinfo->edegrees = NULL;
        ctrl->wspace.cdegree -= iend-istart;
      }
      else {
        if (myrinfo->ed-myrinfo->id >= 0) 
          BNDInsert(nbnd, bndind, bndptr, i); 

        myrinfo->ndegrees = ndegrees;

        for (j=0; j<ndegrees; j++)
          htable[myedegrees[j].pid] = -1;
      }
    }
  }

  idxcopy(nparts, cgraph->pwgts, graph->pwgts);
  graph->mincut = cgraph->mincut;
  graph->nbnd = nbnd;

  FreeGraph(graph->coarser);
  graph->coarser = NULL;

  idxwspacefree(ctrl, nparts);

  ASSERT(CheckBnd2(graph));

}
Пример #29
0
/***********************************************************************************
* This function is the entry point of the parallel ordering algorithm.
* This function assumes that the graph is already nice partitioned among the 
* processors and then proceeds to perform recursive bisection.
************************************************************************************/
void ParMETIS_V3_NodeND(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy, int *numflag,
              int *options, idxtype *order, idxtype *sizes, MPI_Comm *comm)
{
  int i, j;
  int ltvwgts[MAXNCON];
  int nparts, npes, mype, wgtflag = 0, seed = GLOBAL_SEED;
  CtrlType ctrl;
  WorkSpaceType wspace;
  GraphType *graph, *mgraph;
  idxtype *morder;
  int minnvtxs;

  MPI_Comm_size(*comm, &npes);
  MPI_Comm_rank(*comm, &mype);
  nparts = npes;

  if (!ispow2(npes)) {
    if (mype == 0)
      printf("Error: The number of processors must be a power of 2!\n");
    return;
  }

  if (vtxdist[npes] < (int)((float)(npes*npes)*1.2)) {
    if (mype == 0)
      printf("Error: Too many processors for this many vertices.\n");
    return;
  }

  minnvtxs = vtxdist[1]-vtxdist[0];
  for (i=0; i<npes; i++)
    minnvtxs = (minnvtxs < vtxdist[i+1]-vtxdist[i]) ? minnvtxs : vtxdist[i+1]-vtxdist[i];

  if (minnvtxs < (int)((float)npes*1.1)) {
    if (mype == 0)
      printf("Error: vertices are not distributed equally.\n");
    return;
  }
 

  if (*numflag == 1) 
    ChangeNumbering(vtxdist, xadj, adjncy, order, npes, mype, 1);

  SetUpCtrl(&ctrl, nparts, options[PMV3_OPTION_DBGLVL], *comm);
  ctrl.CoarsenTo = amin(vtxdist[npes]+1, 25*npes);

  ctrl.CoarsenTo = amin(vtxdist[npes]+1, 25*amax(npes, nparts));
  ctrl.seed = mype;
  ctrl.sync = seed;
  ctrl.partType = STATIC_PARTITION;
  ctrl.ps_relation = -1;
  ctrl.tpwgts = fsmalloc(nparts, 1.0/(float)(nparts), "tpwgts");
  ctrl.ubvec[0] = 1.03;

  graph = Moc_SetUpGraph(&ctrl, 1, vtxdist, xadj, NULL, adjncy, NULL, &wgtflag);

  PreAllocateMemory(&ctrl, graph, &wspace);

  /*=======================================================
   * Compute the initial k-way partitioning 
   =======================================================*/
  IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));

  Moc_Global_Partition(&ctrl, graph, &wspace);

  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
  IFSET(ctrl.dbglvl, DBG_TIME, PrintTimingInfo(&ctrl));

  /*=======================================================
   * Move the graph according to the partitioning
   =======================================================*/
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.MoveTmr));

  MALLOC_CHECK(NULL);
  graph->ncon = 1;
  mgraph = Moc_MoveGraph(&ctrl, graph, &wspace);
  MALLOC_CHECK(NULL);

  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.MoveTmr));

  /*=======================================================
   * Now compute an ordering of the moved graph
   =======================================================*/
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));

  FreeWSpace(&wspace);
  PreAllocateMemory(&ctrl, mgraph, &wspace);

  ctrl.ipart = ISEP_NODE;
  ctrl.CoarsenTo = amin(vtxdist[npes]+1, amax(20*npes, 1000));

  /* compute tvwgts */
  for (j=0; j<mgraph->ncon; j++)
    ltvwgts[j] = 0;

  for (i=0; i<mgraph->nvtxs; i++)
    for (j=0; j<mgraph->ncon; j++)
      ltvwgts[j] += mgraph->vwgt[i*mgraph->ncon+j];

  for (j=0; j<mgraph->ncon; j++)
    ctrl.tvwgts[j] = GlobalSESum(&ctrl, ltvwgts[j]);

  mgraph->nvwgt = fmalloc(mgraph->nvtxs*mgraph->ncon, "mgraph->nvwgt");
  for (i=0; i<mgraph->nvtxs; i++)
    for (j=0; j<mgraph->ncon; j++)
      mgraph->nvwgt[i*mgraph->ncon+j] = (float)(mgraph->vwgt[i*mgraph->ncon+j]) / (float)(ctrl.tvwgts[j]);


  morder = idxmalloc(mgraph->nvtxs, "PAROMETIS: morder");
  MultilevelOrder(&ctrl, mgraph, morder, sizes, &wspace);

  MALLOC_CHECK(NULL);

  /* Invert the ordering back to the original graph */
  ProjectInfoBack(&ctrl, graph, order, morder, &wspace);

  MALLOC_CHECK(NULL);

  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
  IFSET(ctrl.dbglvl, DBG_TIME, PrintTimingInfo(&ctrl));
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));

  free(ctrl.tpwgts);
  free(morder);
  FreeGraph(mgraph);
  FreeInitialGraphAndRemap(graph, 0);
  FreeWSpace(&wspace);
  FreeCtrl(&ctrl);

  if (*numflag == 1) 
    ChangeNumbering(vtxdist, xadj, adjncy, order, npes, mype, 0);

  MALLOC_CHECK(NULL);
}
Пример #30
0
/***********************************************************************************
* This function is the entry point of the parallel kmetis algorithm that uses
* coordinates to compute an initial graph distribution.
************************************************************************************/
void ParMETIS_V3_PartGeomKway(idxtype *vtxdist, idxtype *xadj, idxtype *adjncy,
              idxtype *vwgt, idxtype *adjwgt, int *wgtflag, int *numflag, int *ndims, 
	      float *xyz, int *ncon, int *nparts, float *tpwgts, float *ubvec, 
	      int *options, int *edgecut, idxtype *part, MPI_Comm *comm)
{
  int h, i, j;
  int nvtxs = -1, npes, mype;
  int uwgtflag, cut, gcut, maxnvtxs;
  int ltvwgts[MAXNCON];
  int moptions[10];
  CtrlType ctrl;
  idxtype *uvwgt;
  WorkSpaceType wspace;
  GraphType *graph, *mgraph;
  float avg, maximb, balance, *mytpwgts;
  int seed, dbglvl = 0;
  int iwgtflag, inumflag, incon, inparts, ioptions[10];
  float *itpwgts, iubvec[MAXNCON];

  MPI_Comm_size(*comm, &npes);
  MPI_Comm_rank(*comm, &mype);

  /********************************/
  /* Try and take care bad inputs */
  /********************************/
  if (options != NULL && options[0] == 1)
    dbglvl = options[PMV3_OPTION_DBGLVL];

  CheckInputs(STATIC_PARTITION, npes, dbglvl, wgtflag, &iwgtflag, numflag, &inumflag,
              ncon, &incon, nparts, &inparts, tpwgts, &itpwgts, ubvec, iubvec, 
	      NULL, NULL, options, ioptions, part, comm);


  /*********************************/
  /* Take care the nparts = 1 case */
  /*********************************/
  if (inparts <= 1) {
    idxset(vtxdist[mype+1]-vtxdist[mype], 0, part);
    *edgecut = 0;
    return;
  }

  /******************************/
  /* Take care of npes = 1 case */
  /******************************/
  if (npes == 1 && inparts > 1) {
    moptions[0] = 0;
    nvtxs = vtxdist[1];

    if (incon == 1) {
      METIS_WPartGraphKway(&nvtxs, xadj, adjncy, vwgt, adjwgt, &iwgtflag, &inumflag, 
            &inparts, itpwgts, moptions, edgecut, part);
    }
    else {
      /* ADD: this is because METIS does not support tpwgts for all constraints */
      mytpwgts = fmalloc(inparts, "mytpwgts");
      for (i=0; i<inparts; i++)
        mytpwgts[i] = itpwgts[i*incon];

      moptions[7] = -1;
      METIS_mCPartGraphRecursive2(&nvtxs, &incon, xadj, adjncy, vwgt, adjwgt, &iwgtflag, 
            &inumflag, &inparts, mytpwgts, moptions, edgecut, part);

      free(mytpwgts);
    }

    return;
  }


  if (inumflag == 1)
    ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 1);

  /*****************************/
  /* Set up control structures */
  /*****************************/
  if (ioptions[0] == 1) {
    dbglvl = ioptions[PMV3_OPTION_DBGLVL];
    seed = ioptions[PMV3_OPTION_SEED];
  }
  else {
    dbglvl = GLOBAL_DBGLVL;
    seed = GLOBAL_SEED;
  }
  SetUpCtrl(&ctrl, npes, dbglvl, *comm);
  ctrl.CoarsenTo = amin(vtxdist[npes]+1, 25*incon*amax(npes, inparts));
  ctrl.seed = (seed == 0) ? mype : seed*mype;
  ctrl.sync = GlobalSEMax(&ctrl, seed);
  ctrl.partType = STATIC_PARTITION;
  ctrl.ps_relation = -1;
  ctrl.tpwgts = itpwgts;
  scopy(incon, iubvec, ctrl.ubvec);

  uwgtflag = iwgtflag|2;
  uvwgt = idxsmalloc(vtxdist[mype+1]-vtxdist[mype], 1, "uvwgt");
  graph = Moc_SetUpGraph(&ctrl, 1, vtxdist, xadj, uvwgt, adjncy, adjwgt, &uwgtflag);
  free(graph->nvwgt); graph->nvwgt = NULL;

  PreAllocateMemory(&ctrl, graph, &wspace);

  /*=================================================================
   * Compute the initial npes-way partitioning geometric partitioning
   =================================================================*/
  IFSET(ctrl.dbglvl, DBG_TIME, InitTimers(&ctrl));
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));

  Coordinate_Partition(&ctrl, graph, *ndims, xyz, 1, &wspace);

  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));
  IFSET(ctrl.dbglvl, DBG_TIME, PrintTimingInfo(&ctrl));

  /*=================================================================
   * Move the graph according to the partitioning
   =================================================================*/
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.MoveTmr));

  free(uvwgt);
  graph->vwgt = ((iwgtflag&2) != 0) ? vwgt : idxsmalloc(graph->nvtxs*incon, 1, "vwgt");
  graph->ncon = incon;
  j = ctrl.nparts;
  ctrl.nparts = ctrl.npes;
  mgraph = Moc_MoveGraph(&ctrl, graph, &wspace);
  ctrl.nparts = j;

  /**********************************************************/
  /* Do the same functionality as Moc_SetUpGraph for mgraph */
  /**********************************************************/
  /* compute tvwgts */
  for (j=0; j<incon; j++)
    ltvwgts[j] = 0;

  for (i=0; i<graph->nvtxs; i++)
    for (j=0; j<incon; j++)
      ltvwgts[j] += mgraph->vwgt[i*incon+j];

  for (j=0; j<incon; j++)
    ctrl.tvwgts[j] = GlobalSESum(&ctrl, ltvwgts[j]);

  /* check for zero wgt constraints */
  for (i=0; i<incon; i++) {
    /* ADD: take care of the case in which tvwgts is zero */
    if (ctrl.tvwgts[i] == 0) {
      if (ctrl.mype == 0) printf("ERROR: sum weight for constraint %d is zero\n", i);
      MPI_Finalize();
      exit(-1);
    }
  }

  /* compute nvwgt */
  mgraph->nvwgt = fmalloc(mgraph->nvtxs*incon, "mgraph->nvwgt");
  for (i=0; i<mgraph->nvtxs; i++)
    for (j=0; j<incon; j++)
      mgraph->nvwgt[i*incon+j] = (float)(mgraph->vwgt[i*incon+j]) / (float)(ctrl.tvwgts[j]);


  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.MoveTmr));

  if (ctrl.dbglvl&DBG_INFO) {
    cut = 0;
    for (i=0; i<graph->nvtxs; i++)
      for (j=graph->xadj[i]; j<graph->xadj[i+1]; j++)
        if (graph->where[i] != graph->where[graph->adjncy[j]])
          cut += graph->adjwgt[j];
    gcut = GlobalSESum(&ctrl, cut)/2;
    maxnvtxs = GlobalSEMax(&ctrl, mgraph->nvtxs);
    balance = (float)(maxnvtxs)/((float)(graph->gnvtxs)/(float)(npes));
    rprintf(&ctrl, "XYZ Cut: %6d \tBalance: %6.3f [%d %d %d]\n",
      gcut, balance, maxnvtxs, graph->gnvtxs, npes);

  }

  /*=================================================================
   * Set up the newly moved graph
   =================================================================*/
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, starttimer(ctrl.TotalTmr));

  ctrl.nparts = inparts;
  FreeWSpace(&wspace);
  PreAllocateMemory(&ctrl, mgraph, &wspace);

  /*=======================================================
   * Now compute the partition of the moved graph
   =======================================================*/
  if (vtxdist[npes] < SMALLGRAPH || vtxdist[npes] < npes*20 || GlobalSESum(&ctrl, mgraph->nedges) == 0) {
    IFSET(ctrl.dbglvl, DBG_INFO, rprintf(&ctrl, "Partitioning a graph of size %d serially\n", vtxdist[npes]));
    PartitionSmallGraph(&ctrl, mgraph, &wspace);
  }
  else {
    Moc_Global_Partition(&ctrl, mgraph, &wspace);
  }
  ParallelReMapGraph(&ctrl, mgraph, &wspace);

  /* Invert the ordering back to the original graph */
  ctrl.nparts = npes;
  ProjectInfoBack(&ctrl, graph, part, mgraph->where, &wspace);

  *edgecut = mgraph->mincut;

  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));
  IFSET(ctrl.dbglvl, DBG_TIME, stoptimer(ctrl.TotalTmr));

  /*******************/
  /* Print out stats */
  /*******************/
  IFSET(ctrl.dbglvl, DBG_TIME, PrintTimingInfo(&ctrl));
  IFSET(ctrl.dbglvl, DBG_TIME, MPI_Barrier(ctrl.gcomm));

  if (ctrl.dbglvl&DBG_INFO) {
    rprintf(&ctrl, "Final %d-way CUT: %6d \tBalance: ", inparts, mgraph->mincut);
    avg = 0.0;
    for (h=0; h<incon; h++) {
      maximb = 0.0;
      for (i=0; i<inparts; i++)
        maximb = amax(maximb, mgraph->gnpwgts[i*incon+h]/itpwgts[i*incon+h]);
      avg += maximb;
      rprintf(&ctrl, "%.3f ", maximb);
    }
    rprintf(&ctrl, "  avg: %.3f\n", avg/(float)incon);
  }

  GKfree((void **)&itpwgts, LTERM);
  FreeGraph(mgraph);
  FreeInitialGraphAndRemap(graph, iwgtflag);
  FreeWSpace(&wspace);
  FreeCtrl(&ctrl);

  if (inumflag == 1)
    ChangeNumbering(vtxdist, xadj, adjncy, part, npes, mype, 0);

}