/* ----------------------------------------- purpose -- eliminate vertex v 1) create v's boundary list 2) merge boundary list onto reach list 3) for each vertex in the boundary 3.1) add v to the subtree list created -- 96feb25, cca ----------------------------------------- */ void MSMD_eliminateVtx ( MSMD *msmd, MSMDvtx *v, MSMDinfo *info ) { int i, ierr, j, nadj, nbnd, nedge, uid, wid, wght ; int *adj, *bnd, *edges ; IP *ip, *ip2, *prev ; IV *reachIV ; MSMDvtx *u, *w ; /* --------------- check the input --------------- */ if ( msmd == NULL || v == NULL || info == NULL ) { fprintf(stderr, "\n fatal error in MSMD_eliminateVtx(%p,%p,%p)" "\n bad input\n", msmd, v, info) ; exit(-1) ; } adj = IV_entries(&msmd->ivtmpIV) ; reachIV = &msmd->reachIV ; /* ----------------------------- create the boundary set for v ----------------------------- */ v->mark = 'X' ; if ( v->subtrees == NULL ) { /* -------------------------------------------------------- v is a leaf, look at its uncovered edge list, move v and any indistinguishable vertices to the end of the list -------------------------------------------------------- */ if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n vertex %d is a leaf", v->id) ; fflush(info->msgFile) ; } v->status = 'L' ; nedge = v->nadj ; edges = v->adj ; i = 0 ; j = nedge - 1 ; while ( i <= j ) { wid = edges[i] ; w = msmd->vertices + wid ; if ( w == v || w->status == 'I' ) { edges[i] = edges[j] ; edges[j] = wid ; j-- ; } else { w->mark = 'X' ; i++ ; } } v->nadj = j + 1 ; } else { /* ---------------------------------------------------- v is not a leaf, merge its subtrees' boundaries with its uncovered edge list to get the new boundary ---------------------------------------------------- */ if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n vertex %d is not a leaf", v->id) ; fprintf(info->msgFile, "\n vertex %d, subtrees :", v->id) ; IP_fp80(info->msgFile, v->subtrees, 20) ; fflush(info->msgFile) ; } v->status = 'E' ; nadj = 0 ; while ( (ip = v->subtrees) != NULL ) { if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n subtree %d, ip(%p)<%d,%p>", ip->val, ip, ip->val, ip->next) ; fflush(info->msgFile) ; } uid = ip->val ; u = msmd->vertices + uid ; u->par = v ; nbnd = u->nadj ; bnd = u->adj ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n bnd of adj subtree %d :", u->id) ; IVfp80(info->msgFile, nbnd, bnd, 25, &ierr) ; fflush(info->msgFile) ; } for ( i = 0 ; i < nbnd ; i++ ) { wid = bnd[i] ; w = msmd->vertices + wid ; if ( w->mark == 'O' && w->status != 'I' ) { w->mark = 'X' ; adj[nadj++] = wid ; } } if ( u->status == 'E' ) { /* ------------------------------------------ u is not a leaf, free its boundary storage ------------------------------------------ */ IVfree(u->adj) ; info->nbytes -= u->nadj * sizeof(int) ; } u->adj = NULL ; u->nadj = 0 ; /* -------------------------------------- put this IP structure on the free list -------------------------------------- */ v->subtrees = ip->next ; ip->val = -1 ; ip->next = msmd->freeIP ; msmd->freeIP = ip ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n v->subtrees = %p, msmd->freeIP = %p", v->subtrees, msmd->freeIP) ; fflush(info->msgFile) ; } } /* ------------------------------------------------ merge all uncovered edges into the boundary list ------------------------------------------------ */ nedge = v->nadj ; edges = v->adj ; for ( i = 0 ; i < nedge ; i++ ) { wid = edges[i] ; w = msmd->vertices + wid ; if ( w->mark == 'O' && w->status != 'I' ) { w->mark = 'X' ; adj[nadj++] = wid ; } } /* ---------------------------------------------------------- if boundary is not empty, allocate new storage for entries ---------------------------------------------------------- */ v->nadj = nadj ; if ( nadj > 0 ) { v->adj = IVinit(nadj, -1) ; IVcopy(nadj, v->adj, adj) ; info->nbytes += nadj*sizeof(int) ; if ( info->maxnbytes < info->nbytes ) { info->maxnbytes = info->nbytes ; } } else { v->adj = NULL ; } } if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n bnd(%d) :", v->id) ; if ( v->nadj > 0 ) { IVfp80(info->msgFile, v->nadj, v->adj, 17, &ierr) ; } fflush(info->msgFile) ; } /* ---------------------------------------------- for each boundary vertex 1. add v to subtree list 2. put v on reach set if not already there 3. unmark and add weight to boundary weight ---------------------------------------------- */ nbnd = v->nadj ; bnd = v->adj ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n %d's bnd :", v->id) ; IVfp80(info->msgFile, nbnd, bnd, 12, &ierr) ; fflush(info->msgFile) ; } wght = 0 ; for ( i = 0 ; i < nbnd ; i++ ) { wid = bnd[i] ; w = msmd->vertices + wid ; if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n adjacent vertex %d", w->id) ; fflush(info->msgFile) ; } /* ------------------------------- add v to the subtree list for w ------------------------------- */ if ( (ip = msmd->freeIP) == NULL ) { if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n need to get more IP objects") ; fflush(info->msgFile) ; } /* ------------------------------------------------- no more free IP structures, allocate more storage ------------------------------------------------- */ if ( (ip = IP_init(msmd->incrIP, IP_FORWARD)) == NULL ) { fprintf(stderr, "\n fatal error in MSMD_eliminateVtx%p,%p,%p)" "\n unable to allocate more IP objects", msmd, v, info) ; exit(-1) ; } if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n old baseIP = %p", msmd->baseIP) ; fprintf(info->msgFile, "\n new baseIP = %p", ip) ; fflush(info->msgFile) ; } ip->next = msmd->baseIP ; msmd->baseIP = ip ; info->nbytes += msmd->incrIP*sizeof(struct _IP) ; if ( info->maxnbytes < info->nbytes ) { info->maxnbytes = info->nbytes ; } ip = msmd->freeIP = msmd->baseIP + 1 ; if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n all set") ; fflush(info->msgFile) ; } } msmd->freeIP = ip->next ; ip->val = v->id ; ip->next = NULL ; for ( ip2 = w->subtrees, prev = NULL ; ip2 != NULL && ip2->val > ip->val ; ip2 = ip2->next ) { prev = ip2 ; } if ( prev == NULL ) { w->subtrees = ip ; } else { prev->next = ip ; } ip->next = ip2 ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n %d's subtrees :", w->id) ; IP_fp80(info->msgFile, w->subtrees, 15) ; fflush(info->msgFile) ; } /* -------------------------------- add w to reach list if necessary -------------------------------- */ if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n status[%d] = %c", wid, w->status) ; fflush(info->msgFile) ; } switch ( w->status ) { case 'D' : if ( info->msglvl > 4 ) { fprintf(info->msgFile, ", remove from heap") ; fflush(info->msgFile) ; } IIheap_remove(msmd->heap, wid) ; case 'O' : case 'B' : if ( info->msglvl > 4 ) { fprintf(info->msgFile, ", add to reach set, nreach = %d", IV_size(reachIV) + 1) ; fflush(info->msgFile) ; } IV_push(reachIV, wid) ; w->status = 'R' ; case 'R' : break ; case 'I' : break ; default : fprintf(stderr, "\n error in MSMD_eliminateVtx(%p,%p,%p)" "\n status[%d] = '%c'\n", msmd, v, info, wid, w->status) ; fprintf(stderr, "\n msmd->nvtx = %d", msmd->nvtx) ; exit(-1) ; } /* -------------------------------- unmark the boundary vertices and store the weight of the boundary -------------------------------- */ w->mark = 'O' ; wght += w->wght ; } /* ------------------------------------ unmark v and set its boundary weight ------------------------------------ */ v->mark = 'O' ; v->bndwght = wght ; return ; }
/* ------------------------------------------------------------------ purpose -- to initialize the semi-implicit matrix using as input a FrontMtx and a map from fronts to domains (map[J] != 0) or the schur complement (map[J] = 0) return value -- 1 -- normal return -1 -- semimtx is NULL -2 -- frontmtx is NULL -3 -- inpmtx is NULL -4 -- frontmapIV is NULL -5 -- frontmapIV is invalid -6 -- unable to create domains' front matrix -7 -- unable to create schur complement front matrix created -- 98oct17, cca ------------------------------------------------------------------ */ int SemiImplMtx_initFromFrontMtx ( SemiImplMtx *semimtx, FrontMtx *frontmtx, InpMtx *inpmtx, IV *frontmapIV, int msglvl, FILE *msgFile ) { FrontMtx *domMtx, *schurMtx ; InpMtx *A12, *A21 ; int ii, J, ncol, nfront, nrow, rc, size ; int *cols, *frontmap, *rows ; IV *domColsIV, *domidsIV, *domRowsIV, *schurColsIV, *schuridsIV, *schurRowsIV ; /* -------------- check the data -------------- */ if ( semimtx == NULL ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n semimtx is NULL\n") ; return(-1) ; } if ( frontmtx == NULL ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n frontmtx is NULL\n") ; return(-2) ; } if ( inpmtx == NULL ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n inpmtx is NULL\n") ; return(-3) ; } if ( frontmapIV == NULL ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n frontmapIV is NULL\n") ; return(-4) ; } nfront = FrontMtx_nfront(frontmtx) ; IV_sizeAndEntries(frontmapIV, &size, &frontmap) ; if ( nfront != size ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n nfront %d, size of front map %d\n", nfront, size) ; return(-5) ; } domidsIV = IV_new() ; schuridsIV = IV_new() ; for ( J = 0 ; J < nfront ; J++ ) { if ( frontmap[J] == 0 ) { IV_push(schuridsIV, J) ; } else if ( frontmap[J] > 0 ) { IV_push(domidsIV, J) ; } else { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n frontmap[%d] = %d, invalid\n", J, frontmap[J]) ; IV_free(domidsIV) ; IV_free(schuridsIV) ; return(-5) ; } } /* ----------------------------------------------------------- clear the data for the semi-implicit matrix and set scalars ----------------------------------------------------------- */ SemiImplMtx_clearData(semimtx) ; semimtx->neqns = frontmtx->neqns ; semimtx->type = frontmtx->type ; semimtx->symmetryflag = frontmtx->symmetryflag ; /* ---------------------------------------------- get the front matrix that contains the domains ---------------------------------------------- */ if ( msglvl > 4 ) { fprintf(msgFile, "\n\n working on domain front matrix") ; fflush(msgFile) ; } domMtx = semimtx->domainMtx = FrontMtx_new() ; domRowsIV = semimtx->domRowsIV = IV_new() ; domColsIV = semimtx->domColsIV = IV_new() ; rc = FrontMtx_initFromSubmatrix(domMtx, frontmtx, domidsIV, domRowsIV, domColsIV, msglvl, msgFile) ; if ( rc != 1 ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n unable to initialize the domains' front matrix" "\n error return = %d\n", rc) ; return(-6) ; } semimtx->ndomeqns = IV_size(domRowsIV) ; if ( msglvl > 4 ) { fprintf(msgFile, "\n\n---------------------------------------- ") ; fprintf(msgFile, "\n\n submatrix for domains") ; FrontMtx_writeForHumanEye(domMtx, msgFile) ; fflush(msgFile) ; } if ( msglvl > 4 ) { FrontMtx_writeForMatlab(domMtx, "L11", "D11", "U11", msgFile) ; IV_writeForMatlab(domRowsIV, "domrows", msgFile) ; IV_writeForMatlab(domColsIV, "domcols", msgFile) ; fflush(msgFile) ; } /* ------------------------------------------------------- get the front matrix that contains the schur complement ------------------------------------------------------- */ if ( msglvl > 4 ) { fprintf(msgFile, "\n\n working on domain front matrix") ; fflush(msgFile) ; } schurMtx = semimtx->schurMtx = FrontMtx_new() ; schurRowsIV = semimtx->schurRowsIV = IV_new() ; schurColsIV = semimtx->schurColsIV = IV_new() ; rc = FrontMtx_initFromSubmatrix(schurMtx, frontmtx, schuridsIV, schurRowsIV, schurColsIV, msglvl, msgFile) ; if ( rc != 1 ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n unable to initialize the schur complement front matrix" "\n error return = %d\n", rc) ; return(-6) ; } semimtx->nschureqns = IV_size(schurRowsIV) ; if ( msglvl > 4 ) { fprintf(msgFile, "\n\n---------------------------------------- ") ; fprintf(msgFile, "\n\n submatrix for schur complement") ; FrontMtx_writeForHumanEye(schurMtx, msgFile) ; fflush(msgFile) ; } if ( msglvl > 4 ) { FrontMtx_writeForMatlab(schurMtx, "L22", "D22", "U22", msgFile) ; IV_writeForMatlab(schurRowsIV, "schurrows", msgFile) ; IV_writeForMatlab(schurColsIV, "schurcols", msgFile) ; fflush(msgFile) ; } /* ------------------------- get the A12 InpMtx object ------------------------- */ A12 = semimtx->A12 = InpMtx_new() ; rc = InpMtx_initFromSubmatrix(A12, inpmtx, domRowsIV, schurColsIV, semimtx->symmetryflag, msglvl, msgFile) ; if ( rc != 1 ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n unable to create A21 matrix" "\n error return = %d\n", rc) ; return(-6) ; } InpMtx_changeCoordType(A12, INPMTX_BY_ROWS) ; InpMtx_changeStorageMode(A12, INPMTX_BY_VECTORS) ; if ( msglvl > 4 ) { fprintf(msgFile, "\n\n---------------------------------------- ") ; fprintf(msgFile, "\n\n domRowsIV ") ; IV_writeForHumanEye(domRowsIV, msgFile) ; fprintf(msgFile, "\n\n schurColsIV ") ; IV_writeForHumanEye(schurColsIV, msgFile) ; fprintf(msgFile, "\n\n A12 matrix") ; InpMtx_writeForHumanEye(A12, msgFile) ; fflush(msgFile) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n A12 = zeros(%d,%d) ;", IV_size(domRowsIV), IV_size(schurColsIV)) ; InpMtx_writeForMatlab(A12, "A12", msgFile) ; fflush(msgFile) ; } if ( FRONTMTX_IS_NONSYMMETRIC(frontmtx) ) { /* ------------------------- get the A21 InpMtx object ------------------------- */ A21 = semimtx->A21 = InpMtx_new() ; rc = InpMtx_initFromSubmatrix(A21, inpmtx, schurRowsIV, domColsIV, semimtx->symmetryflag, msglvl, msgFile) ; if ( rc != 1 ) { fprintf(stderr, "\n error in SemiImplMtx_initFromFrontMtx()" "\n unable to create A21 matrix" "\n error return = %d\n", rc) ; return(-6) ; } InpMtx_changeCoordType(A21, INPMTX_BY_COLUMNS) ; InpMtx_changeStorageMode(A21, INPMTX_BY_VECTORS) ; if ( msglvl > 4 ) { fprintf(msgFile, "\n\n--------------------------------------- ") ; fprintf(msgFile, "\n\n schurRowsIV ") ; IV_writeForHumanEye(schurRowsIV, msgFile) ; fprintf(msgFile, "\n\n domColsIV ") ; IV_writeForHumanEye(domColsIV, msgFile) ; fprintf(msgFile, "\n\n A21 matrix") ; InpMtx_writeForHumanEye(A21, msgFile) ; fflush(msgFile) ; } if ( msglvl > 4 ) { fprintf(msgFile, "\n\n A21 = zeros(%d,%d) ;", IV_size(schurRowsIV), IV_size(domColsIV)) ; InpMtx_writeForMatlab(A21, "A21", msgFile) ; fflush(msgFile) ; } } /* ------------------------ free the working storage ------------------------ */ IV_free(domidsIV) ; IV_free(schuridsIV) ; return(1) ; }
/* --------------------------------------------------------------------- eliminate all nodes in a stage created -- 96feb25, cca --------------------------------------------------------------------- */ void MSMD_eliminateStage ( MSMD *msmd, MSMDinfo *info ) { int ierr, ii, jj, iv, nelim, nreach, stage, step ; int *reach ; IV *reachIV ; MSMDvtx *v ; /* --------------- check the input --------------- */ if ( msmd == NULL || info == NULL ) { fprintf(stderr, "\n fatal error in MSMD_eliminateStage(%p,%p)" "\n bad input\n", msmd, info) ; exit(-1) ; } stage = info->istage ; /* ----------------------------------------------- load the reach set with all nodes in this stage ----------------------------------------------- */ reachIV = &msmd->reachIV ; IV_setSize(reachIV, 0) ; for ( iv = 0, v = msmd->vertices ; iv < msmd->nvtx ; iv++, v++ ) { if ( v->status != 'I' ) { if ( v->stage == stage ) { IV_push(reachIV, v->id) ; v->status = 'R' ; } else if ( v->stage > stage || v->stage < 0 ) { v->status = 'B' ; } } } if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n after loading reach set") ; IV_fp80(reachIV, info->msgFile, 80, &ierr) ; fflush(info->msgFile) ; } if ( info->seed > 0 ) { IV_shuffle(reachIV, info->seed) ; } if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n reach set at stage %d", stage) ; IV_fp80(reachIV, info->msgFile, 80, &ierr) ; fflush(info->msgFile) ; } /* ------------------------------------ do an initial update of the vertices ------------------------------------ */ MSMD_update(msmd, info) ; if ( info->msglvl > 4 ) { fprintf(info->msgFile, "\n\n after initial update") ; fflush(info->msgFile) ; } IV_setSize(reachIV, 0) ; /* ----------- elimination ----------- */ step = 0 ; while ( 1 ) { if ( info->msglvl > 1 ) { fprintf(info->msgFile, "\n\n ##### stage %d, elimination step %d", stage, step) ; fflush(info->msgFile) ; } nelim = MSMD_eliminateStep(msmd, info) ; if ( nelim == 0 ) { break ; } /* ----------------------------------------- for each node in the reach set, clean its subtree list and list of uncovered edges ----------------------------------------- */ if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n calling MSMD_cleanReachSet()") ; fprintf(info->msgFile, "\n reach set") ; IV_fp80(reachIV, info->msgFile, 80, &ierr) ; fflush(info->msgFile) ; } MSMD_cleanReachSet(msmd, info) ; if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n return from MSMD_cleanReachSet()") ; fflush(info->msgFile) ; } /* ------------------ compress the graph ------------------ */ MSMD_findInodes(msmd, info) ; /* ---------------------------------------------- clean the reach set of indistinguishable nodes and any nodes not on the present stage ---------------------------------------------- */ nreach = IV_size(reachIV) ; reach = IV_entries(reachIV) ; for ( ii = jj = 0 ; ii < nreach ; ii++ ) { if ( reach[ii] < 0 || reach[ii] >= msmd->nvtx ) { fprintf(stderr, "\n fatal error in MSMD_eliminateStage()" "\n reach[%d] = %d", ii, reach[ii]) ; exit(-1) ; } v = msmd->vertices + reach[ii] ; if ( v->status == 'I' ) { continue ; } else if ( v->stage != stage ) { v->status = 'B' ; } else { reach[jj++] = v->id ; } } IV_setSize(reachIV, jj) ; if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n after cleaning reach set, nreach = %d", IV_size(reachIV)) ; fprintf(info->msgFile, "\n reach :") ; IV_fp80(reachIV, info->msgFile, 8, &ierr) ; fflush(info->msgFile) ; } /* ---------------------------------- update the nodes on the reach set ---------------------------------- */ MSMD_update(msmd, info) ; if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n return from update") ; fflush(info->msgFile) ; } IV_setSize(reachIV, 0) ; /* ------------------------------ increment the elimination step ------------------------------ */ step++ ; } if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n stage %d over, %d steps", stage, step) ; fflush(info->msgFile) ; } /* -------------------------------------- set the number of steps for this stage -------------------------------------- */ info->stageInfo->nstep = step ; return ; }
/* --------------------------------------------------------------------- purpose -- to order the graph using multi-stage minimum degree g -- Graph object stages -- stage vector for vertices, if NULL then all vertices on stage zero. otherwise vertices with stage istage are eliminated before any vertices with stage > istage working storage is free'd, statistics can be accessed through their variables or printed via the void MSMD_printStats(MSMD*,FILE*) method. created -- 96feb25, cca --------------------------------------------------------------------- */ void MSMD_order ( MSMD *msmd, Graph *g, int stages[], MSMDinfo *info ) { double t0, t1, t2, t3 ; int istage, iv, nstage, nvtx ; IP *ip ; MSMDstageInfo *now, *total ; MSMDvtx *v ; /* --------------- check the input --------------- */ MARKTIME(t0) ; if ( msmd == NULL || g == NULL || info == NULL ) { fprintf(stderr, "\n fatal error in MSMD_order(%p,%p,%p,%p)" "\n bad input\n", msmd, g, stages, info) ; exit(-1) ; } if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n inside MSMD_order()") ; if ( stages != NULL ) { int ierr ; fprintf(info->msgFile, "\n stages[%d]", g->nvtx) ; IVfp80(info->msgFile, g->nvtx, stages, 80, &ierr) ; } fflush(info->msgFile) ; } /* ------------------------------- check the information structure ------------------------------- */ if ( MSMDinfo_isValid(info) != 1 ) { fprintf(stderr, "\n fatal error in MSMD_order(%p,%p,%p,%p)" "\n bad MSMDinfo object\n", msmd, g, stages, info) ; exit(-1) ; } /* --------------------- initialize the object --------------------- */ if ( info->msglvl > 3 ) { fprintf(info->msgFile, "\n\n trying to initialize MSMD object ") ; Graph_writeForHumanEye(g, info->msgFile) ; fflush(info->msgFile) ; } MSMD_init(msmd, g, stages, info) ; nvtx = g->nvtx ; nstage = info->nstage ; if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n MSMD object initialized, %d stages", nstage) ; fflush(info->msgFile) ; } /* ------------------------------------ load the reach set with all vertices ------------------------------------ */ if ( info->compressFlag / 4 >= 1 ) { /* ------------------ compress the graph ------------------ */ if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n initial compression") ; fflush(info->msgFile) ; } IV_setSize(&msmd->reachIV, nvtx) ; IV_ramp(&msmd->reachIV, 0, 1) ; MSMD_findInodes(msmd, info) ; if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n %d checked, %d found indistinguishable", info->stageInfo->ncheck, info->stageInfo->nindst) ; fflush(info->msgFile) ; } MSMD_cleanReachSet(msmd, info) ; /* for ( iv = 0, v = msmd->vertices ; iv < nvtx ; iv++, v++ ) { MSMD_cleanEdgeList(msmd, v, info) ; } */ } IV_setSize(&msmd->reachIV, 0) ; /* -------------------- loop over the stages -------------------- */ for ( info->istage = 0 ; info->istage <= nstage ; info->istage++ ) { if ( info->msglvl > 2 ) { fprintf(info->msgFile, "\n\n ##### elimination stage %d", info->istage) ; fflush(info->msgFile) ; } /* if ( info->istage == nstage ) { info->msglvl = 5 ; } */ MARKTIME(t1) ; MSMD_eliminateStage(msmd, info) ; MARKTIME(t2) ; info->stageInfo->cpu = t2 - t1 ; info->stageInfo++ ; } /* ------------- final cleanup ------------- */ { MSMDvtx *first, *last, *v ; IV_setSize(&msmd->reachIV, 0) ; first = msmd->vertices ; last = first + nvtx - 1 ; for ( v = first ; v <= last ; v++ ) { switch ( v->status ) { case 'E' : case 'L' : case 'I' : break ; default : IV_push(&msmd->reachIV, v->id) ; break ; } } /* fprintf(stdout, "\n reach set, %d entries", IV_size(&msmd->reachIV)) ; IV_writeForHumanEye(&msmd->reachIV, stdout) ; */ MSMD_findInodes(msmd, info) ; } /* --------------------------------------------------------- make info->stagInfo point back to beginning of the stages --------------------------------------------------------- */ info->stageInfo -= nstage + 1 ; /* ------------------------ get the total statistics ------------------------ */ for ( istage = 0, now = info->stageInfo, total = info->stageInfo + nstage + 1 ; istage <= nstage ; istage++, now++ ) { total->nstep += now->nstep ; total->nfront += now->nfront ; total->welim += now->welim ; total->nfind += now->nfind ; total->nzf += now->nzf ; total->ops += now->ops ; total->nexact2 += now->nexact2 ; total->nexact3 += now->nexact3 ; total->napprox += now->napprox ; total->ncheck += now->ncheck ; total->nindst += now->nindst ; total->noutmtch += now->noutmtch ; } /* ----------------------------------------------------- free some working storage (leave the MSMDvtx objects so the user can extract the permutations and/or ETree ----------------------------------------------------- */ IIheap_free(msmd->heap) ; msmd->heap = NULL ; IV_clearData(&msmd->ivtmpIV) ; IV_clearData(&msmd->reachIV) ; /* while ( (ip = msmd->baseIP) != NULL ) { msmd->baseIP = ip->next ; IP_free(ip) ; } */ MARKTIME(t3) ; info->totalCPU = t3 - t0 ; return ; }