Beispiel #1
0
/*
   -------------------------------------------------
   expand an ETree object by splitting a large front 
   into a chain of smaller fronts.

   created -- 96jun27, cca
   -------------------------------------------------
*/
ETree *
ETree_splitFronts (
   ETree   *etree,
   int     vwghts[],
   int     maxfrontsize,
   int     seed
) {
ETree   *etree2 ;
int     count, front, ii, I, Inew, J, Jnew, nbnd, newsize, nint, nfront,
        nfront2, nsplit, nvtx, prev, size, sizeJ, v, vwght ;
int     *bndwghts, *fch, *head, *indices, *link, *newbndwghts, *newmap, 
        *newnodwghts, *newpar, *nodwghts, *roots, *sib, *vtxToFront ;
Tree    *tree ;
/*
   ---------------
   check the input
   ---------------
*/
if ( etree == NULL
   || (nfront = etree->nfront) <= 0
   || (nvtx = etree->nvtx) <= 0
   || maxfrontsize <= 0 ) {
   fprintf(stderr, "\n fatal error in ETree_splitFronts(%p,%p,%d,%d)"
           "\n bad input\n", etree, vwghts, maxfrontsize, seed) ;
   spoolesFatal();
}
tree       = etree->tree ;
fch        = tree->fch ;
sib        = tree->sib ;
nodwghts   = IV_entries(etree->nodwghtsIV) ;
bndwghts   = IV_entries(etree->bndwghtsIV) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
   --------------------------
   set up the working storage
   --------------------------
*/
newpar      = IVinit(nvtx,   -1) ;
roots       = IVinit(nfront, -1) ;
newmap      = IVinit(nvtx,   -1) ;
newnodwghts = IVinit(nvtx,   -1) ;
newbndwghts = IVinit(nvtx,   -1) ;
head        = IVinit(nfront, -1) ;
link        = IVinit(nvtx,   -1) ;
indices     = IVinit(nvtx,   -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
   front = vtxToFront[v] ;
   link[v] = head[front] ;
   head[front] = v ;
}
/*
   ------------------------------------------------
   execute a post-order traversal of the front tree
   ------------------------------------------------
*/
nfront2 = 0 ;
for ( J = Tree_postOTfirst(tree) ;
      J != -1 ;
      J = Tree_postOTnext(tree, J) ) {
   sizeJ = 0 ;
   for ( v = head[J], count = 0 ; v != -1 ; v = link[v] ) {
      indices[count++] = v ;
      vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
      sizeJ += vwght ;
   }
   if ( sizeJ != nodwghts[J] ) {
      fprintf(stderr, "\n fatal error in ETree_splitFronts(%p,%p,%d,%d)"
             "\n J = %d, sizeJ = %d, nodwght = %d\n", 
             etree, vwghts, maxfrontsize, seed, J, sizeJ, nodwghts[J]) ;
      spoolesFatal();
   }
#if MYDEBUG > 0
   fprintf(stdout, "\n\n checking out front %d, size %d", J, sizeJ) ;
#endif
   if ( sizeJ <= maxfrontsize || fch[J] == -1 ) {
/*
      -------------------------------------------
      this front is small enough (or is a domain)
      -------------------------------------------
*/
      Jnew = nfront2++ ;
      for ( ii = 0 ; ii < count ; ii++ ) {
         v = indices[ii] ;
         newmap[v] = Jnew ;
#if MYDEBUG > 1
            fprintf(stdout, "\n   mapping vertex %d into new front %d",
                    v, Jnew) ;
#endif
      }
      for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
         Inew = roots[I] ;
         newpar[Inew] = Jnew ;
      }
      newnodwghts[Jnew] = nodwghts[J] ;
      newbndwghts[Jnew] = bndwghts[J] ;
      roots[J] = Jnew ;
#if MYDEBUG > 0
      fprintf(stdout, "\n    front is small enough, Jnew = %d", Jnew) ;
#endif
   } else {
/*
      ------------------------------------------
      this front is too large, split into pieces 
      whose size differs by one vertex
      ------------------------------------------
*/
      nsplit  = (sizeJ + maxfrontsize - 1)/maxfrontsize ;
      newsize = sizeJ / nsplit ;
      if ( sizeJ % nsplit != 0 ) {
         newsize++ ;
      }
#if MYDEBUG > 0
      fprintf(stdout, 
         "\n    front is too large, %d target fronts, target size = %d",
         nsplit, newsize) ;
#endif
      prev    = -1 ;
      nint    = nodwghts[J] ;
      nbnd    = nint + bndwghts[J] ;
      if ( seed > 0 ) {
         IVshuffle(count, indices, seed) ;
      }
      ii = 0 ;
      while ( ii < count ) {
         Jnew = nfront2++ ;
         size = 0 ;
         while ( ii < count ) {
            v = indices[ii] ;
            vwght = (vwghts != NULL) ? vwghts[v] : 1 ;
#if MYDEBUG > 0
            fprintf(stdout, 
                "\n   ii = %d, v = %d, vwght = %d, size = %d",
                ii, v, vwght, size) ;
#endif
/*
   -----------------------------------------------
   97aug28, cca
   bug fix. front is created even if it is too big
   -----------------------------------------------
*/
            if ( newsize >= size + vwght || size == 0 ) {
               newmap[v] = Jnew ;
               size += vwght ;
#if MYDEBUG > 0
               fprintf(stdout, 
                "\n   mapping vertex %d into new front %d, size = %d",
                v, Jnew, size) ;
#endif
               ii++ ;
            } else {
               break ;
            }
         }
         if ( prev == -1 ) {
            for ( I = fch[J] ; I != -1 ; I = sib[I] ) {
               Inew = roots[I] ;
               newpar[Inew] = Jnew ;
            }
         } else {
            newpar[prev] = Jnew ;
         }
         prev = Jnew ;
         newnodwghts[Jnew] = size ;
         nbnd = nbnd - size ;
         newbndwghts[Jnew] = nbnd ;
#if MYDEBUG > 0
         fprintf(stdout, "\n    new front %d, size %d, bnd %d",
                 Jnew, newnodwghts[Jnew], newbndwghts[Jnew]) ;
#endif
      }
      roots[J] = Jnew ;
   }
}
/*
   ---------------------------
   create the new ETree object
   ---------------------------
*/
etree2 = ETree_new() ;
ETree_init1(etree2, nfront2, nvtx) ;
IVcopy(nfront2, etree2->tree->par, newpar) ;
Tree_setFchSibRoot(etree2->tree) ;
IVcopy(nvtx, IV_entries(etree2->vtxToFrontIV), newmap) ;
IVcopy(nfront2, IV_entries(etree2->nodwghtsIV), newnodwghts) ;
IVcopy(nfront2, IV_entries(etree2->bndwghtsIV), newbndwghts) ;
/*
   ------------------------
   free the working storage
   ------------------------
*/
IVfree(newpar) ;
IVfree(roots)  ;
IVfree(newmap) ;
IVfree(newnodwghts) ;
IVfree(newbndwghts) ;
IVfree(head) ;
IVfree(link) ;
IVfree(indices) ;

return(etree2) ; }
Beispiel #2
0
/*
   ------------------------------------------------------------
   create and return an ETree object that holds the front tree.

   created  -- 96jun23, cca
   ------------------------------------------------------------
*/
ETree *
MSMD_frontETree (
   MSMD   *msmd
) {
ETree     *etree ;
int       front, iv, nfront, nvtx, root ;
int       *bndwghts, *fch, *nodwghts, *par, *sib, *vtxToFront ;
MSMDvtx   *v, *w ;
/*
   ---------------
   check the input
   ---------------
*/
if ( msmd == NULL ) {
   fprintf(stderr, "\n fatal error in MSMD_frontETree(%p)"
           "\n bad input\n", msmd) ;
   exit(-1) ;
}
nvtx = msmd->nvtx ;
/*
   --------------------------
   count the number of fronts
   --------------------------
*/
nfront = 0 ;
fch = IVinit(nvtx, -1) ;
sib = IVinit(nvtx, -1) ;
root = -1 ;
for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) {
#if MYDEBUG > 0
   fprintf(stdout, "\n vertex %d, status %c, wght %d",
           v->id, v->status, v->wght) ;
/*
   MSMDvtx_print(v, stdout) ;
*/
   fflush(stdout) ;
#endif
   switch ( v->status ) {
   case 'L' :
   case 'E' :
      if ( (w = v->par) != NULL ) {
         sib[v->id] = fch[w->id] ;
         fch[w->id] = v->id ;
      } else {
         sib[v->id] = root ;
         root = v->id ;
      }
#if MYDEBUG > 0
   fprintf(stdout, ", new front %d", nfront) ;
   fflush(stdout) ;
#endif
      nfront++ ;
      break ;
   default :
      break ;
   }
}
#if MYDEBUG > 0
fprintf(stdout, "\n %d fronts", nfront) ;
fflush(stdout) ;
#endif
/*
   ---------------------------
   initialize the ETree object
   ---------------------------
*/
etree = ETree_new() ;
ETree_init1(etree, nfront, nvtx) ;
nodwghts   = IV_entries(etree->nodwghtsIV) ;
bndwghts   = IV_entries(etree->bndwghtsIV) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
/*
   ----------------------------------------------
   fill the vtxToFront[] vector so representative 
   vertices are mapped in a post-order traversal
   ----------------------------------------------
*/
nfront = 0 ;
iv = root ;
while ( iv != -1 ) {
   while ( fch[iv] != -1 ) {
       iv = fch[iv] ;
   }
   v = msmd->vertices + iv ;
   vtxToFront[iv] = nfront++ ;
#if MYDEBUG > 0
   fprintf(stdout, "\n v = %d, vwght = %d, vtxToFront[%d] = %d", 
           v->id, v->wght, iv, vtxToFront[iv]) ;
   fflush(stdout) ;
#endif
   while ( sib[iv] == -1 && v->par != NULL ) {
      v = v->par ;
      iv = v->id ;
      vtxToFront[iv] = nfront++ ;
#if MYDEBUG > 0
      fprintf(stdout, "\n v = %d, vwght = %d, vtxToFront[%d] = %d", 
              v->id, v->wght, iv, vtxToFront[iv]) ;
      fflush(stdout) ;
#endif
   }
   iv = sib[iv] ;
}
IVfree(fch) ;
IVfree(sib) ;
/*
   --------------------------------------------------------------
   fill in the vertex-to-front map for indistinguishable vertices
   --------------------------------------------------------------
*/
for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) {
#if MYDEBUG > 0
   fprintf(stdout, "\n v %d, wght = %d, status %c", 
           v->id, v->wght, v->status) ;
   fflush(stdout) ;
#endif
   switch ( v->status ) {
   case 'I' :
#if MYDEBUG > 0
      fprintf(stdout, "\n I : v %d", v->id) ;
      fflush(stdout) ;
#endif
      w = v ;
      while ( w->par != NULL && w->status == 'I' ) {
         w = w->par ;
#if MYDEBUG > 0
/*
         fprintf(stdout, " --> %d", w->id) ;
*/
         fprintf(stdout, " %d", w->id) ;
         fflush(stdout) ;
#endif
      }
#if MYDEBUG > 0
      fprintf(stdout, ", w %d, status %c", w->id, w->status) ;
      fflush(stdout) ;
#endif
      switch ( w->status ) {
      case 'L' :
      case 'E' :
         vtxToFront[v->id] = vtxToFront[w->id] ;
#if MYDEBUG > 0
         fprintf(stdout, "\n I: vtxToFront[%d] = %d", 
                 iv, vtxToFront[iv]) ;
         fflush(stdout) ;
#endif
         break ;
      default :
#if MYDEBUG > 0
         fprintf(stdout, "\n wow, v->rootpar = %d, status %c",
                 w->id, w->status) ;
         fflush(stdout) ;
#endif
         break ;
      }
   }
}
/*
   ------------------------------------------------------------
   now fill in the parent Tree field, node and boundary weights 
   ------------------------------------------------------------
*/
par = etree->tree->par ;
for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) {
#if MYDEBUG > 0
   fprintf(stdout, "\n v %d, status %c", v->id, v->status) ;
   fflush(stdout) ;
#endif
   switch ( v->status ) {
   case 'L' :
   case 'E' :
      front = vtxToFront[iv] ;
#if MYDEBUG > 0
      fprintf(stdout, ", front %d", front) ;
      fflush(stdout) ;
#endif
      if ( (w = v->par) != NULL ) {
         par[vtxToFront[v->id]] = vtxToFront[w->id] ;
#if MYDEBUG > 0
         fprintf(stdout, ", par[%d] = %d", front, par[front]) ;
         fflush(stdout) ;
#endif
      }
      bndwghts[front] = v->bndwght ;
      nodwghts[front] = v->wght    ;
      break ;
   default :
      break ;
   }
}
/*
   -------------------------
   set the other tree fields
   -------------------------
*/
Tree_setFchSibRoot(etree->tree) ;

return(etree) ; }
Beispiel #3
0
/*
   -----------------------------------------------------------------
   compress a tree based on a map from old vertices to new vertices.
   the restriction on the map is that the set {u | map[u] = U} must
   be connected for all U.

   created  -- 95nov15, cca
   modified -- 96jan04, cca
      bug fixed, N computed incorrectly
   modified -- 96jun23, cca
      in calling sequence, int map[] converted to IV *mapIV 
   -----------------------------------------------------------------
*/
Tree *
Tree_compress (
   Tree   *tree,
   IV     *mapIV
) {
int    n, N, u, U, v, V ;
int    *head, *link, *map ;
Tree   *tree2 ;
/*
   ---------------
   check the input
   ---------------
*/
if (  tree == NULL 
   || (n = tree->n) <= 0 
   || mapIV == NULL 
   || n != IV_size(mapIV)
   || (map = IV_entries(mapIV)) == NULL ) {
   fprintf(stderr, "\n fatal error in Tree_compress(%p,%p)"
           "\n bad input\n", tree, mapIV) ;
   exit(-1) ;
}
/*
   -----------------------
   initialize the new tree
   -----------------------
*/
N = 1 + IV_max(mapIV) ;
tree2 = Tree_new() ;
Tree_init1(tree2, N) ;
/*
   -----------------------------------------------------------
   get the head/link construct to map old nodes into new nodes
   -----------------------------------------------------------
*/
head = IVinit(N, -1) ;
link = IVinit(n, -1) ;
for ( v = 0 ; v < n ; v++ ) {
   if ( (V = map[v]) < 0 || V >= N ) {
      fprintf(stderr, "\n fatal error in Tree_compress(%p,%p)"
              "\n map[%d] = %d, N = %d\n", tree, map, v, V, N) ;
      exit(-1) ;
   }
   link[v] = head[V] ;
   head[V] =    v    ;
}
/*
   ---------------------
   fill the tree vectors
   ---------------------
*/
for ( U = 0 ; U < N ; U++ ) {
   for ( u = head[U] ; u != -1 ; u = link[u] ) {
      if ( (v = tree->par[u]) == -1 ) {
         tree2->par[U] = -1 ;
         break ;
      } else if ( (V = map[v]) != U ) {
         tree2->par[U] = V ;
         break ;
      }
   }
}
Tree_setFchSibRoot(tree2) ;
/*
   ------------------------
   free the working storage
   ------------------------
*/
IVfree(head) ;
IVfree(link) ;
 
return(tree2) ; }