/* ------------------------------------------------- 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) ; }
/* ------------------------------------------------------------ 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) ; }
/* ----------------------------------------------------------------- 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) ; }