// --------------------------------------------------------------------
// repartitionHMetis()
//
/// \brief Repartitions the two subpartitions using the hMetis min-cut library.
///
/// The number of cut nets between the two partitions will be minimized.
//
// --------------------------------------------------------------------
void repartitionHMetis(Partition *parent) {
#if defined(NO_HMETIS)
  printf("QPAR_02 : \t\tERROR: hMetis not available.  Ignoring.\n");
#else

  int n,c,t, i;
  float area;
  int *edgeConnections = NULL;
  int *partitionAssignment = (int *)calloc(g_place_numCells, sizeof(int));
  int *vertexWeights = (int *)calloc(g_place_numCells, sizeof(int));
  int *edgeDegree = (int *)malloc(sizeof(int)*(g_place_numNets+1));
  int numConnections = 0;
  int numEdges = 0;
  float initial_cut;
  int targets = 0;
  ConcreteCell *cell = NULL;
  int options[9];
  int afterCuts = 0;

  assert(parent);
  assert(parent->m_sub1);
  assert(parent->m_sub2);

  printf("QPAR-02 : \t\trepartitioning with hMetis\n");

  // count edges
  edgeDegree[0] = 0;
  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n])
    if (g_place_concreteNets[n]->m_numTerms > 1) {
      numConnections += g_place_concreteNets[n]->m_numTerms;
      edgeDegree[++numEdges] = numConnections;
    }
  
  if (parent->m_vertical) {
    // vertical
    initial_cut = parent->m_sub2->m_bounds.x;
    
    // initialize all cells
    for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
      if (g_place_concreteCells[c]->m_x < initial_cut)
        partitionAssignment[c] = 0;
      else
        partitionAssignment[c] = 1;
    }
  
    // initialize cells in partition 1
    for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
      cell = parent->m_sub1->m_members[t];
      vertexWeights[cell->m_id] = getCellArea(cell);
      // pay attention to cells that are close to the cut
      if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
        targets++;
        partitionAssignment[cell->m_id] = -1;
      }
    }
    
    // initialize cells in partition 2
    for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
      cell = parent->m_sub2->m_members[t];
      vertexWeights[cell->m_id] = getCellArea(cell);
      // pay attention to cells that are close to the cut
      if (abs(cell->m_x-initial_cut) < parent->m_bounds.w*REPARTITION_TARGET_FRACTION) {
        targets++;
        partitionAssignment[cell->m_id] = -1;
      }		
    }
    
  } else {
    // horizontal
    initial_cut = parent->m_sub2->m_bounds.y;
    
    // initialize all cells
    for(c=0; c<g_place_numCells; c++) if (g_place_concreteCells[c]) {
      if (g_place_concreteCells[c]->m_y < initial_cut)
        partitionAssignment[c] = 0;
      else
        partitionAssignment[c] = 1;
    }
    
    // initialize cells in partition 1
    for(t=0; t<parent->m_sub1->m_numMembers; t++) if (parent->m_sub1->m_members[t]) {
      cell = parent->m_sub1->m_members[t];
      vertexWeights[cell->m_id] = getCellArea(cell);
      // pay attention to cells that are close to the cut
      if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
        targets++;
        partitionAssignment[cell->m_id] = -1;
      }
    }
    
    // initialize cells in partition 2
    for(t=0; t<parent->m_sub2->m_numMembers; t++) if (parent->m_sub2->m_members[t]) {
      cell = parent->m_sub2->m_members[t];
      vertexWeights[cell->m_id] = getCellArea(cell);
      // pay attention to cells that are close to the cut
      if (abs(cell->m_y-initial_cut) < parent->m_bounds.h*REPARTITION_TARGET_FRACTION) {
        targets++;
        partitionAssignment[cell->m_id] = -1;
      }		
    }
  }

  options[0] = 1;  // any non-default values?
  options[1] = 3; // num bisections
  options[2] = 1;  // grouping scheme
  options[3] = 1;  // refinement scheme
  options[4] = 1;  // cycle refinement scheme
  options[5] = 0;  // reconstruction scheme
  options[6] = 0;  // fixed assignments?
  options[7] = 12261980; // random seed
  options[8] = 0;  // debugging level

  edgeConnections = (int *)malloc(sizeof(int)*numConnections);

  i = 0;
  for(n=0; n<g_place_numNets; n++) if (g_place_concreteNets[n]) {
    if (g_place_concreteNets[n]->m_numTerms > 1)
      for(t=0; t<g_place_concreteNets[n]->m_numTerms; t++)
        edgeConnections[i++] = g_place_concreteNets[n]->m_terms[t]->m_id;
  }

  HMETIS_PartRecursive(g_place_numCells, numEdges, vertexWeights,
		       edgeDegree, edgeConnections, NULL,
		       2, (int)(100*MAX_PARTITION_NONSYMMETRY),
		       options, partitionAssignment, &afterCuts);
	
  /*
  printf("HMET-20 : \t\t\tbalance before %d / %d ... ", parent->m_sub1->m_numMembers,
         parent->m_sub2->m_numMembers);
  */

  // reassign members to subpartitions
  parent->m_sub1->m_numMembers = 0;
  parent->m_sub1->m_area = 0;
  parent->m_sub2->m_numMembers = 0;
  parent->m_sub2->m_area = 0;
  parent->m_sub1->m_members = (ConcreteCell**)realloc(parent->m_sub1->m_members, 
       sizeof(ConcreteCell*)*parent->m_numMembers); 
  parent->m_sub2->m_members = (ConcreteCell**)realloc(parent->m_sub2->m_members, 
       sizeof(ConcreteCell*)*parent->m_numMembers); 
 
  for(t=0; t<parent->m_numMembers; t++) if (parent->m_members[t]) {
    cell = parent->m_members[t];
    area = getCellArea(cell);
    if (partitionAssignment[cell->m_id] == 0) {
      parent->m_sub1->m_members[parent->m_sub1->m_numMembers++] = cell;
      parent->m_sub1->m_area += area;
    }
    else {
      parent->m_sub2->m_members[parent->m_sub2->m_numMembers++] = cell;
      parent->m_sub2->m_area += area;
    }
  }
  /*
  printf("after %d / %d\n", parent->m_sub1->m_numMembers,
         parent->m_sub2->m_numMembers);
  */

  // cout << "HMET-21 : \t\t\tloc: " << initial_cut <<  " targetting: " << targets*100/parent->m_members.length() << "%" << endl;
  // cout << "HMET-22 : \t\t\tstarting cuts= " << beforeCuts << " final cuts= " << afterCuts << endl;

  free(edgeConnections);
  free(vertexWeights);
  free(edgeDegree);
  free(partitionAssignment);
#endif
}
Beispiel #2
0
/* May 30th, Weinan: one problem I have just found is that I need to 
 * establish a kind of checking table to connect my global vertex 
 * number with local vertex number to be used in the HMETIS_PartRecursive
 * function calling.
 */
static int cutNode(struct node * source, struct node * left, struct node * right, int ub){
  int nvtxs, nhedges;
  int * vwgts = NULL;
  int * eptr = NULL;
  int * eind = NULL;
  int * hewgts = NULL;
  int nparts;
  int ubfactor;
  int * options = NULL;
  int * part = NULL;
  int * edgecut = NULL;

  int tmp, i, j, k, l, tmpNO, flag, found, group0, group1, index0, index1;
  /* this is the table used to correspond global vertice number with 
   * local vertice number.
   */
  int * checkTable;

  /* number of vertices */
  nvtxs = source->numberPoints;
  checkTable = (int *)calloc(nvtxs, sizeof(int));
  if(checkTable == NULL)
    {
      printf("cannot allocate memory for checkTable! \n");
      return -1;
    }
  /* load the vertice's number into the checkTable */
  for(i=0; i<nvtxs; i++){
    checkTable[i] = source->points[i];
  }/* end for */

  /* number of edges */
  tmp=0;
  for(i=0; i<nvtxs; i++){
    for(j=0; j<points[source->points[i]].length; j++){
      /* decide a point whether belongs to a node */
      if(belongs(source, points[source->points[i]].edges[j].pointNO)==1) /* !!!!!! */
	tmp++;
    }/* end for j*/
  }/* end for i*/
  nhedges = tmp;

  /* weight of the vertices, because 
   * the vertices are not weighted, so
   * according to p13 of the hMETIS manual,
   * vwgts can be NULL.
   */
  vwgts = NULL;

  /* eptr and eind */
  /* because all my edges are of
   * size 2, so it makes things 
   * easier.
   */
  tmp = nhedges+1;
  eptr = (int *)calloc(tmp, sizeof(int));
  if(eptr == NULL)
    {
      printf("cannot allocate memory for eptr! \n");
      return -1;
    }
  for(i=0; i<tmp; i++)
    eptr[i]=i*2;

  /* when loading eind, need to check the checkTable */
  eind = (int *)calloc(2*tmp, sizeof(int));
  if(eind == 0)
    {
      printf("cannot allocate memory for eind! \n");
      return -1;
    }
  k = 0;
  for(i=0; i<nvtxs; i++){
    for(j=0; j<points[source->points[i]].length; j++){
      /* decide a point whether belongs to a node */
      if(belongs(source, points[source->points[i]].edges[j].pointNO)==1){
	/* eind[k] = source->points[i];*/
	eind[k] = i;
	k++;
	/* eind[k] = points[source->points[i]].edges[j].pointNO; */
	tmpNO =  points[source->points[i]].edges[j].pointNO;
	flag = 0;
	for(l=0; l<nvtxs; l++){
	  if (tmpNO == checkTable[l]){
	    flag = 1;
	    found = l;
	    break;
	  }
	}
	if(flag == 1)
	  eind[k] = found;
	else
	  {
	    printf("some thing wrong with checkTable! \n");
	    return -1;
	  }/* end if...else... */
	k++;      
      }/* end if */
    }/* end for j*/
  }/* end for i*/
  if(k != 2*nhedges){
    printf("some thing wrong with eind! \n");
    return -1;
  }/* end if */

  /* hewgts: an array of size nhedges that stores the weight
   * of the hyperedges.
   */
  hewgts = (int *)calloc(nhedges, sizeof(int));
  if(hewgts == 0)
    {
      printf("cannot allocate memory for hewgts! \n");
      return -1;
    }
  k = 0;
  for(i=0; i<nvtxs; i++){
    for(j=0; j<points[source->points[i]].length; j++){
      /* decide a point whether belongs to a node */
      if(belongs(source, points[source->points[i]].edges[j].pointNO)==1){
	/*!!!!!! here I have to do a cast becasue now similarity is a double */
	hewgts[k] = (int)(points[source->points[i]].edges[j].similarity*DIAG);
	k++;      
      }/* end if */
    }/* end for j*/
  }/* end for i*/
  if(k != nhedges){
    printf("some thing wrong with hewgts! \n");
    return -1;
  }/* end if */

  /* nparts: number of desired partitions */
  nparts = 2;

  /* ubfactor: relative imbalance factor */
  ubfactor = ub;

  /* options */
  /* note that is options[0]=0,
   * then default values are used.
   */
  options =  (int *)calloc(9, sizeof(int));
  if(options == 0)
    {
      printf("cannot allocate memory for options! \n");
      return -1;
    }
  options[0] = 0;

  /* part */
  part =  (int *)calloc(nvtxs, sizeof(int));
  if(part == 0)
    {
      printf("cannot allocate memory for part! \n");
      return -1;
    }

  /* edgecut */
  edgecut = (int *)calloc(1, sizeof(int));
  if(edgecut == 0)
    {
      printf("cannot allocate memory for edgecut! \n");
      return -1;
    }


  HMETIS_PartRecursive(nvtxs, nhedges, vwgts, eptr, eind, hewgts, 
		       nparts, ubfactor, options, part, edgecut);

  group0 = 0;
  group1 = 0;
  for(i=0; i<nvtxs; i++){
    if(part[i] == 0)
      group0++;
    else if(part[i] == 1)
      group1++;
    else
      {
	printf("something wrong with part. \n");
	return -1;
      }/* end if..else...*/
  }/* end for */

  left->numberPoints = group0;
  right->numberPoints = group1;
  left->points = (int *)calloc(group0, sizeof(int));
  if(left->points == NULL)
    {
      printf("cannot allocate memory for left->points \n");
      return -1;
    }
  right->points = (int *)calloc(group1, sizeof(int));
  if(right->points == NULL)
    {
      printf("cannot allocate memory for right->points \n");
      return -1;
    }
  left->left = NULL;
  left->right = NULL;
  right->left = NULL;
  right->right = NULL;

  index0 = 0;
  index1 = 0;
  for(i=0; i<nvtxs; i++){
    if(part[i] == 0)
      {
	left->points[index0] = checkTable[i];
	index0++;
      }
    else if(part[i] == 1)
     {
	right->points[index1] = checkTable[i];
	index1++;
      }
    else
      {
	printf("something wrong with part. \n");
	return -1;
      }/* end if..else...*/
  }/* end for */
  if(index0!=group0 || index1!=group1)
    {
      printf("some thing wrong with index0-1. \n");
      return -1;
    }

  free(vwgts);
  free(eptr);
  free(eind);
  free(hewgts);
  free(options);
  free(part);
  free(edgecut);

  free(checkTable);

  return 1;

}/* end cutNode */