/**Function******************************************************************** Synopsis [Reads the variable group tree from a file.] Description [Reads the variable group tree from a file. Returns 1 if successful; 0 otherwise.] SideEffects [None] SeeAlso [] *****************************************************************************/ static int ntrReadTree( DdManager * dd, char * treefile, int nvars) { FILE *fp; MtrNode *root; if (treefile == NULL) { return(1); } if ((fp = fopen(treefile,"r")) == NULL) { (void) fprintf(stderr,"Unable to open %s\n",treefile); return(0); } root = Mtr_ReadGroups(fp,ddMax(Cudd_ReadSize(dd),nvars)); if (root == NULL) { return(0); } Cudd_SetTree(dd,root); return(1); } /* end of ntrReadTree */
/**Function******************************************************************** Synopsis [Creates a new ZDD variable group.] Description [Creates a new ZDD variable group. The group starts at variable and contains size variables. The parameter low is the index of the first variable. If the variable already exists, its current position in the order is known to the manager. If the variable does not exist yet, the position is assumed to be the same as the index. The group tree is created if it does not exist yet. Returns a pointer to the group if successful; NULL otherwise.] SideEffects [The ZDD variable tree is changed.] SeeAlso [Cudd_MakeTreeNode] ******************************************************************************/ MtrNode * Cudd_MakeZddTreeNode( DdManager * dd /* manager */, unsigned int low /* index of the first group variable */, unsigned int size /* number of variables in the group */, unsigned int type /* MTR_DEFAULT or MTR_FIXED */) { MtrNode *group; MtrNode *tree; unsigned int level; /* If the variable does not exist yet, the position is assumed to be ** the same as the index. Therefore, applications that rely on ** Cudd_bddNewVarAtLevel or Cudd_addNewVarAtLevel to create new ** variables have to create the variables before they group them. */ level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low; if (level + size - 1> (int) MTR_MAXHIGH) return(NULL); /* If the tree does not exist yet, create it. */ tree = dd->treeZ; if (tree == NULL) { dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ); if (tree == NULL) return(NULL); tree->index = dd->invpermZ[0]; } /* Extend the upper bound of the tree if necessary. This allows the ** application to create groups even before the variables are created. */ tree->size = ddMax(tree->size, level + size); /* Create the group. */ group = Mtr_MakeGroup(tree, level, size, type); if (group == NULL) return(NULL); /* Initialize the index field to the index of the variable currently ** in position low. This field will be updated by the reordering ** procedure to provide a handle to the group once it has been moved. */ group->index = (MtrHalfWord) low; return(group); } /* end of Cudd_MakeZddTreeNode */
/**Function******************************************************************** Synopsis [Reads in a matrix in the format of the Harwell-Boeing benchmark suite.] Description [Reads in a matrix in the format of the Harwell-Boeing benchmark suite. The variables are ordered as follows: <blockquote> x\[0\] y\[0\] x\[1\] y\[1\] ... </blockquote> 0 is the most significant bit. On input, nx and ny hold the numbers of row and column variables already in existence. On output, they hold the numbers of row and column variables actually used by the matrix. m and n are set to the numbers of rows and columns of the matrix. Their values on input are immaterial. Returns 1 on success; 0 otherwise. The ADD for the sparse matrix is returned in E, and its reference count is > 0.] SideEffects [None] SeeAlso [Cudd_addRead Cudd_bddRead] ******************************************************************************/ int Cudd_addHarwell( FILE * fp /* pointer to the input file */, DdManager * dd /* DD manager */, DdNode ** E /* characteristic function of the graph */, DdNode *** x /* array of row variables */, DdNode *** y /* array of column variables */, DdNode *** xn /* array of complemented row variables */, DdNode *** yn_ /* array of complemented column variables */, int * nx /* number or row variables */, int * ny /* number or column variables */, int * m /* number of rows */, int * n /* number of columns */, int bx /* first index of row variables */, int sx /* step of row variables */, int by /* first index of column variables */, int sy /* step of column variables */, int pr /* verbosity level */) { DdNode *one, *zero; DdNode *w; DdNode *cubex, *cubey, *minterm1; int u, v, err, i, j, nv; double val; DdNode **lx, **ly, **lxn, **lyn; /* local copies of x, y, xn, yn_ */ int lnx, lny; /* local copies of nx and ny */ char title[73], key[9], mxtype[4], rhstyp[4]; int totcrd, ptrcrd, indcrd, valcrd, rhscrd, nrow, ncol, nnzero, neltvl, nrhs, nrhsix; int *colptr, *rowind; #if 0 int nguess, nexact; int *rhsptr, *rhsind; #endif if (*nx < 0 || *ny < 0) return(0); one = DD_ONE(dd); zero = DD_ZERO(dd); /* Read the header */ err = fscanf(fp, "%72c %8c", title, key); if (err == EOF) { return(0); } else if (err != 2) { return(0); } title[72] = (char) 0; key[8] = (char) 0; err = fscanf(fp, "%d %d %d %d %d", &totcrd, &ptrcrd, &indcrd, &valcrd, &rhscrd); if (err == EOF) { return(0); } else if (err != 5) { return(0); } err = fscanf(fp, "%3s %d %d %d %d", mxtype, &nrow, &ncol, &nnzero, &neltvl); if (err == EOF) { return(0); } else if (err != 5) { return(0); } /* Skip FORTRAN formats */ if (rhscrd == 0) { err = fscanf(fp, "%*s %*s %*s \n"); } else { err = fscanf(fp, "%*s %*s %*s %*s \n"); } if (err == EOF) { return(0); } else if (err != 0) { return(0); } /* Print out some stuff if requested to be verbose */ if (pr>0) { (void) fprintf(dd->out,"%s: type %s, %d rows, %d columns, %d entries\n", key, mxtype, nrow, ncol, nnzero); if (pr>1) (void) fprintf(dd->out,"%s\n", title); } /* Check matrix type */ if (mxtype[0] != 'R' || mxtype[1] != 'U' || mxtype[2] != 'A') { (void) fprintf(dd->err,"%s: Illegal matrix type: %s\n", key, mxtype); return(0); } if (neltvl != 0) return(0); /* Read optional 5-th line */ if (rhscrd != 0) { err = fscanf(fp, "%3c %d %d", rhstyp, &nrhs, &nrhsix); if (err == EOF) { return(0); } else if (err != 3) { return(0); } rhstyp[3] = (char) 0; if (rhstyp[0] != 'F') { (void) fprintf(dd->err, "%s: Sparse right-hand side not yet supported\n", key); return(0); } if (pr>0) (void) fprintf(dd->out,"%d right-hand side(s)\n", nrhs); } else { nrhs = 0; } /* Compute the number of variables */ /* row and column numbers start from 0 */ u = nrow - 1; for (i=0; u > 0; i++) { u >>= 1; } lnx = i; if (nrhs == 0) { v = ncol - 1; } else { v = 2* (ddMax(ncol, nrhs) - 1); } for (i=0; v > 0; i++) { v >>= 1; } lny = i; /* Allocate or reallocate arrays for variables as needed */ if (*nx == 0) { if (lnx > 0) { *x = lx = ALLOC(DdNode *,lnx); if (lx == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } *xn = lxn = ALLOC(DdNode *,lnx); if (lxn == NULL) { dd->errorCode = CUDD_MEMORY_OUT; return(0); } } else {
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void reoReorderArray( reo_man * p, DdManager * dd, DdNode * Funcs[], DdNode * FuncsRes[], int nFuncs, int * pOrder ) { int Counter, i; // set the initial parameters p->dd = dd; p->pOrder = pOrder; p->nTops = nFuncs; // get the initial number of nodes p->nNodesBeg = Cudd_SharingSize( Funcs, nFuncs ); // resize the internal data structures of the manager if necessary reoResizeStructures( p, ddMax(dd->size,dd->sizeZ), p->nNodesBeg, nFuncs ); // compute the support p->pSupp = Extra_VectorSupportArray( dd, Funcs, nFuncs, p->pSupp ); // get the number of support variables p->nSupp = 0; for ( i = 0; i < dd->size; i++ ) p->nSupp += p->pSupp[i]; // if it is the constant function, no need to reorder if ( p->nSupp == 0 ) { for ( i = 0; i < nFuncs; i++ ) { FuncsRes[i] = Funcs[i]; Cudd_Ref( FuncsRes[i] ); } return; } // create the internal variable maps // go through variable levels in the manager Counter = 0; for ( i = 0; i < dd->size; i++ ) if ( p->pSupp[ dd->invperm[i] ] ) { p->pMapToPlanes[ dd->invperm[i] ] = Counter; p->pMapToDdVarsOrig[Counter] = dd->invperm[i]; if ( !p->fRemapUp ) p->pMapToDdVarsFinal[Counter] = dd->invperm[i]; else p->pMapToDdVarsFinal[Counter] = dd->invperm[Counter]; p->pOrderInt[Counter] = Counter; Counter++; } // set the initial parameters p->nUnitsUsed = 0; p->nNodesCur = 0; p->fThisIsAdd = 0; p->Signature++; // transfer the function from the CUDD package into REO"s internal data structure for ( i = 0; i < nFuncs; i++ ) p->pTops[i] = reoTransferNodesToUnits_rec( p, Funcs[i] ); assert( p->nNodesBeg == p->nNodesCur ); if ( !p->fThisIsAdd && p->fMinWidth ) { printf( "An important message from the REO reordering engine:\n" ); printf( "The BDD given to the engine for reordering contains complemented edges.\n" ); printf( "Currently, such BDDs cannot be reordered for the minimum width.\n" ); printf( "Therefore, minimization for the number of BDD nodes is performed.\n" ); fflush( stdout ); p->fMinApl = 0; p->fMinWidth = 0; } if ( p->fMinWidth ) reoProfileWidthStart(p); else if ( p->fMinApl ) reoProfileAplStart(p); else reoProfileNodesStart(p); if ( p->fVerbose ) { printf( "INITIAL: " ); if ( p->fMinWidth ) reoProfileWidthPrint(p); else if ( p->fMinApl ) reoProfileAplPrint(p); else reoProfileNodesPrint(p); } /////////////////////////////////////////////////////////////////// // performs the reordering p->nSwaps = 0; p->nNISwaps = 0; for ( i = 0; i < p->nIters; i++ ) { reoReorderSift( p ); // print statistics after each iteration if ( p->fVerbose ) { printf( "ITER #%d: ", i+1 ); if ( p->fMinWidth ) reoProfileWidthPrint(p); else if ( p->fMinApl ) reoProfileAplPrint(p); else reoProfileNodesPrint(p); } // if the cost function did not change, stop iterating if ( p->fMinWidth ) { p->nWidthEnd = p->nWidthCur; assert( p->nWidthEnd <= p->nWidthBeg ); if ( p->nWidthEnd == p->nWidthBeg ) break; } else if ( p->fMinApl ) { p->nAplEnd = p->nAplCur; assert( p->nAplEnd <= p->nAplBeg ); if ( p->nAplEnd == p->nAplBeg ) break; } else { p->nNodesEnd = p->nNodesCur; assert( p->nNodesEnd <= p->nNodesBeg ); if ( p->nNodesEnd == p->nNodesBeg ) break; } } assert( reoCheckLevels( p ) ); /////////////////////////////////////////////////////////////////// s_AplBefore = p->nAplBeg; s_AplAfter = p->nAplEnd; // set the initial parameters p->nRefNodes = 0; p->nNodesCur = 0; p->Signature++; // transfer the BDDs from REO's internal data structure to CUDD for ( i = 0; i < nFuncs; i++ ) { FuncsRes[i] = reoTransferUnitsToNodes_rec( p, p->pTops[i] ); Cudd_Ref( FuncsRes[i] ); } // undo the DDs referenced for storing in the cache for ( i = 0; i < p->nRefNodes; i++ ) Cudd_RecursiveDeref( dd, p->pRefNodes[i] ); // verify zero refs of the terminal nodes for ( i = 0; i < nFuncs; i++ ) { assert( reoRecursiveDeref( p->pTops[i] ) ); } assert( reoCheckZeroRefs( &(p->pPlanes[p->nSupp]) ) ); // prepare the variable map to return to the user if ( p->pOrder ) { // i is the current level in the planes data structure // p->pOrderInt[i] is the original level in the planes data structure // p->pMapToDdVarsOrig[i] is the variable, into which we remap when we construct the BDD from planes // p->pMapToDdVarsOrig[ p->pOrderInt[i] ] is the original BDD variable corresponding to this level // Therefore, p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ] // creates the permutation, which remaps the resulting BDD variable into the original BDD variable for ( i = 0; i < p->nSupp; i++ ) p->pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; } if ( p->fVerify ) { int fVerification; DdNode * FuncRemapped; int * pOrder; if ( p->pOrder == NULL ) { pOrder = ABC_ALLOC( int, p->nSupp ); for ( i = 0; i < p->nSupp; i++ ) pOrder[ p->pMapToDdVarsFinal[i] ] = p->pMapToDdVarsOrig[ p->pOrderInt[i] ]; }