#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Data Structures | |
struct | NodeData |
Defines | |
#define | DBL_MAX_EXP 1024 |
#define | DEFAULT_PAGE_SIZE 2048 |
#define | DEFAULT_NODE_DATA_PAGE_SIZE 1024 |
#define | INITIAL_PAGES 128 |
Typedefs | |
typedef struct NodeData | NodeData_t |
Functions | |
static void ResizeNodeDataPages | ARGS (()) |
static double SubsetCountMintermAux | ARGS ((DdNode *node, double max, st_table *table)) |
static st_table *SubsetCountMinterm | ARGS ((DdNode *node, int nvars)) |
static int SubsetCountNodesAux | ARGS ((DdNode *node, st_table *table, double max)) |
static int SubsetCountNodes | ARGS ((DdNode *node, st_table *table, int nvars)) |
static void StoreNodes | ARGS ((st_table *storeTable, DdManager *dd, DdNode *node)) |
static DdNode *BuildSubsetBdd | ARGS ((DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable)) |
DdNode * | Cudd_SubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold) |
DdNode * | Cudd_SupersetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold) |
DdNode * | cuddSubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold) |
static void | ResizeNodeDataPages () |
static void | ResizeCountMintermPages () |
static void | ResizeCountNodePages () |
static double | SubsetCountMintermAux (DdNode *node, double max, st_table *table) |
static st_table * | SubsetCountMinterm (DdNode *node, int nvars) |
static int | SubsetCountNodesAux (DdNode *node, st_table *table, double max) |
static int | SubsetCountNodes (DdNode *node, st_table *table, int nvars) |
static void | StoreNodes (st_table *storeTable, DdManager *dd, DdNode *node) |
static DdNode * | BuildSubsetBdd (DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" |
static int | memOut |
static DdNode * | zero |
static DdNode * | one |
static double ** | mintermPages |
static int ** | nodePages |
static int ** | lightNodePages |
static double * | currentMintermPage |
static double | max |
static int * | currentNodePage |
static int * | currentLightNodePage |
static int | pageIndex |
static int | page |
static int | pageSize = DEFAULT_PAGE_SIZE |
static int | maxPages |
static NodeData_t * | currentNodeDataPage |
static int | nodeDataPage |
static int | nodeDataPageIndex |
static NodeData_t ** | nodeDataPages |
static int | nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE |
static int | maxNodeDataPages |
#define DBL_MAX_EXP 1024 |
CFile***********************************************************************
FileName [cuddSubsetHB.c]
PackageName [cudd]
Synopsis [Procedure to subset the given BDD by choosing the heavier branches]
Description [External procedures provided by this module:
Internal procedures included in this module:
Static procedures included in this module:
]
SeeAlso [cuddSubsetSP.c]
Author [Kavita Ravi]
Copyright [This file was created at the University of Colorado at Boulder. The University of Colorado at Boulder makes no warranty about the suitability of this software for any purpose. It is presented on an AS IS basis.]
Definition at line 47 of file cuddSubsetHB.c.
#define DEFAULT_NODE_DATA_PAGE_SIZE 1024 |
Definition at line 57 of file cuddSubsetHB.c.
#define DEFAULT_PAGE_SIZE 2048 |
Definition at line 56 of file cuddSubsetHB.c.
#define INITIAL_PAGES 128 |
Definition at line 58 of file cuddSubsetHB.c.
typedef struct NodeData NodeData_t |
Definition at line 82 of file cuddSubsetHB.c.
static DdNode* BuildSubsetBdd ARGS | ( | (DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable) | ) | [static] |
static void ResizeNodeDataPages ARGS | ( | () | ) | [static] |
AutomaticStart
static DdNode* BuildSubsetBdd | ( | DdManager * | dd, | |
DdNode * | node, | |||
int * | size, | |||
st_table * | visitedTable, | |||
int | threshold, | |||
st_table * | storeTable, | |||
st_table * | approxTable | |||
) | [static] |
Function********************************************************************
Synopsis [Builds the subset BDD using the heavy branch method.]
Description [The procedure carries out the building of the subset BDD starting at the root. Using the three different counts labelling each node, the procedure chooses the heavier branch starting from the root and keeps track of the number of nodes it discards at each step, thus keeping count of the size of the subset BDD dynamically. Once the threshold is satisfied, the procedure then calls ITE to build the BDD.]
SideEffects [None]
SeeAlso []
Definition at line 1135 of file cuddSubsetHB.c.
01143 { 01144 01145 DdNode *Nv, *Nnv, *N, *topv, *neW; 01146 double minNv, minNnv; 01147 NodeData_t *currNodeQual; 01148 NodeData_t *currNodeQualT; 01149 NodeData_t *currNodeQualE; 01150 DdNode *ThenBranch, *ElseBranch; 01151 unsigned int topid; 01152 char *dummy; 01153 01154 #ifdef DEBUG 01155 num_calls++; 01156 #endif 01157 /*If the size of the subset is below the threshold, dont do 01158 anything. */ 01159 if ((*size) <= threshold) { 01160 /* store nodes below this, so we can recombine if possible */ 01161 StoreNodes(storeTable, dd, node); 01162 return(node); 01163 } 01164 01165 if (Cudd_IsConstant(node)) 01166 return(node); 01167 01168 /* Look up minterm count for this node. */ 01169 if (!st_lookup(visitedTable, (char *)node, (char **)&currNodeQual)) { 01170 fprintf(dd->err, 01171 "Something is wrong, ought to be in node quality table\n"); 01172 } 01173 01174 /* Get children. */ 01175 N = Cudd_Regular(node); 01176 Nv = Cudd_T(N); 01177 Nnv = Cudd_E(N); 01178 01179 /* complement if necessary */ 01180 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 01181 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 01182 01183 if (!Cudd_IsConstant(Nv)) { 01184 /* find out minterms and nodes contributed by then child */ 01185 if (!st_lookup(visitedTable, (char *)Nv, 01186 (char **)&currNodeQualT)) { 01187 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); 01188 dd->errorCode = CUDD_INTERNAL_ERROR; 01189 return(NULL); 01190 } 01191 else { 01192 minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer); 01193 } 01194 } else { 01195 if (Nv == zero) { 01196 minNv = 0; 01197 } else { 01198 minNv = max; 01199 } 01200 } 01201 if (!Cudd_IsConstant(Nnv)) { 01202 /* find out minterms and nodes contributed by else child */ 01203 if (!st_lookup(visitedTable, (char *)Nnv, (char **)&currNodeQualE)) { 01204 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); 01205 dd->errorCode = CUDD_INTERNAL_ERROR; 01206 return(NULL); 01207 } else { 01208 minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer); 01209 } 01210 } else { 01211 if (Nnv == zero) { 01212 minNnv = 0; 01213 } else { 01214 minNnv = max; 01215 } 01216 } 01217 01218 /* keep track of size of subset by subtracting the number of 01219 * differential nodes contributed by lighter child 01220 */ 01221 *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer); 01222 if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes 01223 the Then branch in case of a tie */ 01224 01225 /* recur with the Then branch */ 01226 ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size, 01227 visitedTable, threshold, storeTable, approxTable); 01228 if (ThenBranch == NULL) { 01229 return(NULL); 01230 } 01231 cuddRef(ThenBranch); 01232 /* The Else branch is either a node that already exists in the 01233 * subset, or one whose approximation has been computed, or 01234 * Zero. 01235 */ 01236 if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), (char **)&dummy)) { 01237 ElseBranch = Nnv; 01238 cuddRef(ElseBranch); 01239 } else { 01240 if (st_lookup(approxTable, (char *)Nnv, (char **)&dummy)) { 01241 ElseBranch = (DdNode *)dummy; 01242 cuddRef(ElseBranch); 01243 } else { 01244 ElseBranch = zero; 01245 cuddRef(ElseBranch); 01246 } 01247 } 01248 01249 } 01250 else { 01251 /* recur with the Else branch */ 01252 ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size, 01253 visitedTable, threshold, storeTable, approxTable); 01254 if (ElseBranch == NULL) { 01255 return(NULL); 01256 } 01257 cuddRef(ElseBranch); 01258 /* The Then branch is either a node that already exists in the 01259 * subset, or one whose approximation has been computed, or 01260 * Zero. 01261 */ 01262 if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), (char **)&dummy)) { 01263 ThenBranch = Nv; 01264 cuddRef(ThenBranch); 01265 } else { 01266 if (st_lookup(approxTable, (char *)Nv, (char **)&dummy)) { 01267 ThenBranch = (DdNode *)dummy; 01268 cuddRef(ThenBranch); 01269 } else { 01270 ThenBranch = zero; 01271 cuddRef(ThenBranch); 01272 } 01273 } 01274 } 01275 01276 /* construct the Bdd with the top variable and the two children */ 01277 topid = Cudd_NodeReadIndex(N); 01278 topv = Cudd_ReadVars(dd, topid); 01279 cuddRef(topv); 01280 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); 01281 if (neW != NULL) { 01282 cuddRef(neW); 01283 } 01284 Cudd_RecursiveDeref(dd, topv); 01285 Cudd_RecursiveDeref(dd, ThenBranch); 01286 Cudd_RecursiveDeref(dd, ElseBranch); 01287 01288 01289 if (neW == NULL) 01290 return(NULL); 01291 else { 01292 /* store this node in the store table */ 01293 if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), (char **)&dummy)) { 01294 cuddRef(neW); 01295 st_insert(storeTable, (char *)Cudd_Regular(neW), (char *)NIL(char)); 01296 01297 } 01298 /* store the approximation for this node */ 01299 if (N != Cudd_Regular(neW)) { 01300 if (st_lookup(approxTable, (char *)node, (char **)&dummy)) { 01301 fprintf(dd->err, "This node should not be in the approximated table\n"); 01302 } else { 01303 cuddRef(neW); 01304 st_insert(approxTable, (char *)node, (char *)neW); 01305 } 01306 } 01307 cuddDeref(neW); 01308 return(neW); 01309 } 01310 } /* end of BuildSubsetBdd */
AutomaticEnd Function********************************************************************
Synopsis [Extracts a dense subset from a BDD with the heavy branch heuristic.]
Description [Extracts a dense subset from a BDD. This procedure builds a subset by throwing away one of the children of each node, starting from the root, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.]
SideEffects [None]
SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
Definition at line 178 of file cuddSubsetHB.c.
Function********************************************************************
Synopsis [Extracts a dense superset from a BDD with the heavy branch heuristic.]
Description [Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure builds a superset by throwing away one of the children of each node starting from the root of the complement function, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.]
SideEffects [None]
SeeAlso [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
Definition at line 228 of file cuddSubsetHB.c.
00233 { 00234 DdNode *subset, *g; 00235 00236 g = Cudd_Not(f); 00237 memOut = 0; 00238 do { 00239 dd->reordered = 0; 00240 subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold); 00241 } while ((dd->reordered == 1) && (!memOut)); 00242 00243 return(Cudd_NotCond(subset, (subset != NULL))); 00244 00245 } /* end of Cudd_SupersetHeavyBranch */
Function********************************************************************
Synopsis [The main procedure that returns a subset by choosing the heavier branch in the BDD.]
Description [Here a subset BDD is built by throwing away one of the children. Starting at root, annotate each node with the number of minterms (in terms of the total number of variables specified - numVars), number of nodes taken by the DAG rooted at this node and number of additional nodes taken by the child that has the lesser minterms. The child with the lower number of minterms is thrown away and a dyanmic count of the nodes of the subset is kept. Once the threshold is reached the subset is returned to the calling procedure.]
SideEffects [None]
SeeAlso [Cudd_SubsetHeavyBranch]
Definition at line 274 of file cuddSubsetHB.c.
00279 { 00280 00281 int i, *size; 00282 st_table *visitedTable; 00283 int numNodes; 00284 NodeData_t *currNodeQual; 00285 DdNode *subset; 00286 double minN; 00287 st_table *storeTable, *approxTable; 00288 char *key, *value; 00289 st_generator *stGen; 00290 00291 if (f == NULL) { 00292 fprintf(dd->err, "Cannot subset, nil object\n"); 00293 dd->errorCode = CUDD_INVALID_ARG; 00294 return(NULL); 00295 } 00296 00297 one = Cudd_ReadOne(dd); 00298 zero = Cudd_Not(one); 00299 00300 /* If user does not know numVars value, set it to the maximum 00301 * exponent that the pow function can take. The -1 is due to the 00302 * discrepancy in the value that pow takes and the value that 00303 * log gives. 00304 */ 00305 if (numVars == 0) { 00306 /* set default value */ 00307 numVars = DBL_MAX_EXP - 1; 00308 } 00309 00310 if (Cudd_IsConstant(f)) { 00311 return(f); 00312 } 00313 00314 max = pow(2.0, (double)numVars); 00315 00316 /* Create visited table where structures for node data are allocated and 00317 stored in a st_table */ 00318 visitedTable = SubsetCountMinterm(f, numVars); 00319 if ((visitedTable == NULL) || memOut) { 00320 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00321 dd->errorCode = CUDD_MEMORY_OUT; 00322 return(0); 00323 } 00324 numNodes = SubsetCountNodes(f, visitedTable, numVars); 00325 if (memOut) { 00326 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00327 dd->errorCode = CUDD_MEMORY_OUT; 00328 return(0); 00329 } 00330 00331 if (st_lookup(visitedTable, (char *)f, (char **)&currNodeQual)) { 00332 minN = *(((NodeData_t *)currNodeQual)->mintermPointer); 00333 } else { 00334 fprintf(dd->err, 00335 "Something is wrong, ought to be node quality table\n"); 00336 dd->errorCode = CUDD_INTERNAL_ERROR; 00337 } 00338 00339 size = ALLOC(int, 1); 00340 if (size == NULL) { 00341 dd->errorCode = CUDD_MEMORY_OUT; 00342 return(NULL); 00343 } 00344 *size = numNodes; 00345 00346 #ifdef DEBUG 00347 num_calls = 0; 00348 #endif 00349 /* table to store nodes being created. */ 00350 storeTable = st_init_table(st_ptrcmp, st_ptrhash); 00351 /* insert the constant */ 00352 cuddRef(one); 00353 if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == 00354 ST_OUT_OF_MEM) { 00355 fprintf(dd->out, "Something wrong, st_table insert failed\n"); 00356 } 00357 /* table to store approximations of nodes */ 00358 approxTable = st_init_table(st_ptrcmp, st_ptrhash); 00359 subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, 00360 storeTable, approxTable); 00361 if (subset != NULL) { 00362 cuddRef(subset); 00363 } 00364 00365 stGen = st_init_gen(approxTable); 00366 if (stGen == NULL) { 00367 st_free_table(approxTable); 00368 return(NULL); 00369 } 00370 while(st_gen(stGen, (char **)&key, (char **)&value)) { 00371 Cudd_RecursiveDeref(dd, (DdNode *)value); 00372 } 00373 st_free_gen(stGen); stGen = NULL; 00374 st_free_table(approxTable); 00375 00376 stGen = st_init_gen(storeTable); 00377 if (stGen == NULL) { 00378 st_free_table(storeTable); 00379 return(NULL); 00380 } 00381 while(st_gen(stGen, (char **)&key, (char **)&value)) { 00382 Cudd_RecursiveDeref(dd, (DdNode *)key); 00383 } 00384 st_free_gen(stGen); stGen = NULL; 00385 st_free_table(storeTable); 00386 00387 for (i = 0; i <= page; i++) { 00388 FREE(mintermPages[i]); 00389 } 00390 FREE(mintermPages); 00391 for (i = 0; i <= page; i++) { 00392 FREE(nodePages[i]); 00393 } 00394 FREE(nodePages); 00395 for (i = 0; i <= page; i++) { 00396 FREE(lightNodePages[i]); 00397 } 00398 FREE(lightNodePages); 00399 for (i = 0; i <= nodeDataPage; i++) { 00400 FREE(nodeDataPages[i]); 00401 } 00402 FREE(nodeDataPages); 00403 st_free_table(visitedTable); 00404 FREE(size); 00405 #if 0 00406 (void) Cudd_DebugCheck(dd); 00407 (void) Cudd_CheckKeys(dd); 00408 #endif 00409 00410 if (subset != NULL) { 00411 #ifdef DD_DEBUG 00412 if (!Cudd_bddLeq(dd, subset, f)) { 00413 fprintf(dd->err, "Wrong subset\n"); 00414 dd->errorCode = CUDD_INTERNAL_ERROR; 00415 return(NULL); 00416 } 00417 #endif 00418 cuddDeref(subset); 00419 return(subset); 00420 } else { 00421 return(NULL); 00422 } 00423 } /* end of cuddSubsetHeavyBranch */
static void ResizeCountMintermPages | ( | ) | [static] |
Function********************************************************************
Synopsis [Resize the number of pages allocated to store the minterm counts. ]
Description [Resize the number of pages allocated to store the minterm counts. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.]
SideEffects [Changes the size of minterm pages, page, page index, maximum number of pages freeing stuff in case of memory out. ]
SeeAlso []
Definition at line 506 of file cuddSubsetHB.c.
00508 { 00509 int i; 00510 double **newMintermPages; 00511 00512 page++; 00513 /* If the current page index is larger than the number of pages 00514 * allocated, allocate a new page array. Page numbers are incremented by 00515 * INITIAL_PAGES 00516 */ 00517 if (page == maxPages) { 00518 newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES); 00519 if (newMintermPages == NULL) { 00520 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00521 FREE(mintermPages); 00522 memOut = 1; 00523 return; 00524 } else { 00525 for (i = 0; i < maxPages; i++) { 00526 newMintermPages[i] = mintermPages[i]; 00527 } 00528 /* Increase total page count */ 00529 maxPages += INITIAL_PAGES; 00530 FREE(mintermPages); 00531 mintermPages = newMintermPages; 00532 } 00533 } 00534 /* Allocate a new page */ 00535 currentMintermPage = mintermPages[page] = ALLOC(double,pageSize); 00536 if (currentMintermPage == NULL) { 00537 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00538 FREE(mintermPages); 00539 memOut = 1; 00540 return; 00541 } 00542 /* reset page index */ 00543 pageIndex = 0; 00544 return; 00545 00546 } /* end of ResizeCountMintermPages */
static void ResizeCountNodePages | ( | ) | [static] |
Function********************************************************************
Synopsis [Resize the number of pages allocated to store the node counts.]
Description [Resize the number of pages allocated to store the node counts. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.]
SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out.]
SeeAlso []
Definition at line 564 of file cuddSubsetHB.c.
00566 { 00567 int i; 00568 int **newNodePages; 00569 00570 page++; 00571 00572 /* If the current page index is larger than the number of pages 00573 * allocated, allocate a new page array. The number of pages is incremented 00574 * by INITIAL_PAGES. 00575 */ 00576 if (page == maxPages) { 00577 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); 00578 if (newNodePages == NULL) { 00579 for (i = 0; i < page; i++) FREE(nodePages[i]); 00580 FREE(nodePages); 00581 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00582 FREE(lightNodePages); 00583 memOut = 1; 00584 return; 00585 } else { 00586 for (i = 0; i < maxPages; i++) { 00587 newNodePages[i] = nodePages[i]; 00588 } 00589 FREE(nodePages); 00590 nodePages = newNodePages; 00591 } 00592 00593 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); 00594 if (newNodePages == NULL) { 00595 for (i = 0; i < page; i++) FREE(nodePages[i]); 00596 FREE(nodePages); 00597 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00598 FREE(lightNodePages); 00599 memOut = 1; 00600 return; 00601 } else { 00602 for (i = 0; i < maxPages; i++) { 00603 newNodePages[i] = lightNodePages[i]; 00604 } 00605 FREE(lightNodePages); 00606 lightNodePages = newNodePages; 00607 } 00608 /* Increase total page count */ 00609 maxPages += INITIAL_PAGES; 00610 } 00611 /* Allocate a new page */ 00612 currentNodePage = nodePages[page] = ALLOC(int,pageSize); 00613 if (currentNodePage == NULL) { 00614 for (i = 0; i < page; i++) FREE(nodePages[i]); 00615 FREE(nodePages); 00616 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00617 FREE(lightNodePages); 00618 memOut = 1; 00619 return; 00620 } 00621 /* Allocate a new page */ 00622 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); 00623 if (currentLightNodePage == NULL) { 00624 for (i = 0; i <= page; i++) FREE(nodePages[i]); 00625 FREE(nodePages); 00626 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00627 FREE(lightNodePages); 00628 memOut = 1; 00629 return; 00630 } 00631 /* reset page index */ 00632 pageIndex = 0; 00633 return; 00634 00635 } /* end of ResizeCountNodePages */
static void ResizeNodeDataPages | ( | ) | [static] |
Function********************************************************************
Synopsis [Resize the number of pages allocated to store the node data.]
Description [Resize the number of pages allocated to store the node data The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.]
SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out. ]
SeeAlso []
Definition at line 446 of file cuddSubsetHB.c.
00448 { 00449 int i; 00450 NodeData_t **newNodeDataPages; 00451 00452 nodeDataPage++; 00453 /* If the current page index is larger than the number of pages 00454 * allocated, allocate a new page array. Page numbers are incremented by 00455 * INITIAL_PAGES 00456 */ 00457 if (nodeDataPage == maxNodeDataPages) { 00458 newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); 00459 if (newNodeDataPages == NULL) { 00460 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00461 FREE(nodeDataPages); 00462 memOut = 1; 00463 return; 00464 } else { 00465 for (i = 0; i < maxNodeDataPages; i++) { 00466 newNodeDataPages[i] = nodeDataPages[i]; 00467 } 00468 /* Increase total page count */ 00469 maxNodeDataPages += INITIAL_PAGES; 00470 FREE(nodeDataPages); 00471 nodeDataPages = newNodeDataPages; 00472 } 00473 } 00474 /* Allocate a new page */ 00475 currentNodeDataPage = nodeDataPages[nodeDataPage] = 00476 ALLOC(NodeData_t ,nodeDataPageSize); 00477 if (currentNodeDataPage == NULL) { 00478 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00479 FREE(nodeDataPages); 00480 memOut = 1; 00481 return; 00482 } 00483 /* reset page index */ 00484 nodeDataPageIndex = 0; 00485 return; 00486 00487 } /* end of ResizeNodeDataPages */
Function********************************************************************
Synopsis [Procedure to recursively store nodes that are retained in the subset.]
Description [rocedure to recursively store nodes that are retained in the subset.]
SideEffects [None]
SeeAlso [StoreNodes]
Definition at line 1089 of file cuddSubsetHB.c.
01093 { 01094 char *dummy; 01095 DdNode *N, *Nt, *Ne; 01096 if (Cudd_IsConstant(dd)) { 01097 return; 01098 } 01099 N = Cudd_Regular(node); 01100 if (st_lookup(storeTable, (char *)N, (char **)&dummy)) { 01101 return; 01102 } 01103 cuddRef(N); 01104 if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) { 01105 fprintf(dd->err,"Something wrong, st_table insert failed\n"); 01106 } 01107 01108 Nt = Cudd_T(N); 01109 Ne = Cudd_E(N); 01110 01111 StoreNodes(storeTable, dd, Nt); 01112 StoreNodes(storeTable, dd, Ne); 01113 return; 01114 01115 }
Function********************************************************************
Synopsis [Counts minterms of each node in the DAG]
Description [Counts minterms of each node in the DAG. Similar to the Cudd_CountMinterm procedure except this returns the minterm count for all the nodes in the bdd in an st_table.]
SideEffects [none]
SeeAlso [SubsetCountMintermAux]
Definition at line 766 of file cuddSubsetHB.c.
00769 { 00770 st_table *table; 00771 double num; 00772 int i; 00773 00774 00775 #ifdef DEBUG 00776 num_calls = 0; 00777 #endif 00778 00779 max = pow(2.0,(double) nvars); 00780 table = st_init_table(st_ptrcmp,st_ptrhash); 00781 if (table == NULL) goto OUT_OF_MEM; 00782 maxPages = INITIAL_PAGES; 00783 mintermPages = ALLOC(double *,maxPages); 00784 if (mintermPages == NULL) { 00785 st_free_table(table); 00786 goto OUT_OF_MEM; 00787 } 00788 page = 0; 00789 currentMintermPage = ALLOC(double,pageSize); 00790 mintermPages[page] = currentMintermPage; 00791 if (currentMintermPage == NULL) { 00792 FREE(mintermPages); 00793 st_free_table(table); 00794 goto OUT_OF_MEM; 00795 } 00796 pageIndex = 0; 00797 maxNodeDataPages = INITIAL_PAGES; 00798 nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages); 00799 if (nodeDataPages == NULL) { 00800 for (i = 0; i <= page ; i++) FREE(mintermPages[i]); 00801 FREE(mintermPages); 00802 st_free_table(table); 00803 goto OUT_OF_MEM; 00804 } 00805 nodeDataPage = 0; 00806 currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize); 00807 nodeDataPages[nodeDataPage] = currentNodeDataPage; 00808 if (currentNodeDataPage == NULL) { 00809 for (i = 0; i <= page ; i++) FREE(mintermPages[i]); 00810 FREE(mintermPages); 00811 FREE(nodeDataPages); 00812 st_free_table(table); 00813 goto OUT_OF_MEM; 00814 } 00815 nodeDataPageIndex = 0; 00816 00817 num = SubsetCountMintermAux(node,max,table); 00818 if (memOut) goto OUT_OF_MEM; 00819 return(table); 00820 00821 OUT_OF_MEM: 00822 memOut = 1; 00823 return(NULL); 00824 00825 } /* end of SubsetCountMinterm */
Function********************************************************************
Synopsis [Recursively counts minterms of each node in the DAG.]
Description [Recursively counts minterms of each node in the DAG. Similar to the cuddCountMintermAux which recursively counts the number of minterms for the dag rooted at each node in terms of the total number of variables (max). This procedure creates the node data structure and stores the minterm count as part of the node data structure. ]
SideEffects [Creates structures of type node quality and fills the st_table]
SeeAlso [SubsetCountMinterm]
Definition at line 655 of file cuddSubsetHB.c.
00659 { 00660 00661 DdNode *N,*Nv,*Nnv; /* nodes to store cofactors */ 00662 double min,*pmin; /* minterm count */ 00663 double min1, min2; /* minterm count */ 00664 NodeData_t *dummy; 00665 NodeData_t *newEntry; 00666 int i; 00667 00668 #ifdef DEBUG 00669 num_calls++; 00670 #endif 00671 00672 /* Constant case */ 00673 if (Cudd_IsConstant(node)) { 00674 if (node == zero) { 00675 return(0.0); 00676 } else { 00677 return(max); 00678 } 00679 } else { 00680 00681 /* check if entry for this node exists */ 00682 if (st_lookup(table,(char *)node, (char **)&dummy)) { 00683 min = *(dummy->mintermPointer); 00684 return(min); 00685 } 00686 00687 /* Make the node regular to extract cofactors */ 00688 N = Cudd_Regular(node); 00689 00690 /* store the cofactors */ 00691 Nv = Cudd_T(N); 00692 Nnv = Cudd_E(N); 00693 00694 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 00695 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 00696 00697 min1 = SubsetCountMintermAux(Nv, max,table)/2.0; 00698 if (memOut) return(0.0); 00699 min2 = SubsetCountMintermAux(Nnv,max,table)/2.0; 00700 if (memOut) return(0.0); 00701 min = (min1+min2); 00702 00703 /* if page index is at the bottom, then create a new page */ 00704 if (pageIndex == pageSize) ResizeCountMintermPages(); 00705 if (memOut) { 00706 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00707 FREE(nodeDataPages); 00708 st_free_table(table); 00709 return(0.0); 00710 } 00711 00712 /* point to the correct location in the page */ 00713 pmin = currentMintermPage+pageIndex; 00714 pageIndex++; 00715 00716 /* store the minterm count of this node in the page */ 00717 *pmin = min; 00718 00719 /* Note I allocate the struct here. Freeing taken care of later */ 00720 if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages(); 00721 if (memOut) { 00722 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00723 FREE(mintermPages); 00724 st_free_table(table); 00725 return(0.0); 00726 } 00727 00728 newEntry = currentNodeDataPage + nodeDataPageIndex; 00729 nodeDataPageIndex++; 00730 00731 /* points to the correct location in the page */ 00732 newEntry->mintermPointer = pmin; 00733 /* initialize this field of the Node Quality structure */ 00734 newEntry->nodesPointer = NULL; 00735 00736 /* insert entry for the node in the table */ 00737 if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) { 00738 memOut = 1; 00739 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00740 FREE(mintermPages); 00741 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00742 FREE(nodeDataPages); 00743 st_free_table(table); 00744 return(0.0); 00745 } 00746 return(min); 00747 } 00748 00749 } /* end of SubsetCountMintermAux */
Function********************************************************************
Synopsis [Counts the nodes under the current node and its lighter child]
Description [Counts the nodes under the current node and its lighter child. Calls a recursive procedure to count the number of nodes of a DAG rooted at a particular node and the number of nodes taken by its lighter child.]
SideEffects [None]
SeeAlso [SubsetCountNodesAux]
Definition at line 1012 of file cuddSubsetHB.c.
01016 { 01017 int num; 01018 int i; 01019 01020 #ifdef DEBUG 01021 num_calls = 0; 01022 #endif 01023 01024 max = pow(2.0,(double) nvars); 01025 maxPages = INITIAL_PAGES; 01026 nodePages = ALLOC(int *,maxPages); 01027 if (nodePages == NULL) { 01028 goto OUT_OF_MEM; 01029 } 01030 01031 lightNodePages = ALLOC(int *,maxPages); 01032 if (lightNodePages == NULL) { 01033 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 01034 FREE(mintermPages); 01035 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 01036 FREE(nodeDataPages); 01037 FREE(nodePages); 01038 goto OUT_OF_MEM; 01039 } 01040 01041 page = 0; 01042 currentNodePage = nodePages[page] = ALLOC(int,pageSize); 01043 if (currentNodePage == NULL) { 01044 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 01045 FREE(mintermPages); 01046 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 01047 FREE(nodeDataPages); 01048 FREE(lightNodePages); 01049 FREE(nodePages); 01050 goto OUT_OF_MEM; 01051 } 01052 01053 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); 01054 if (currentLightNodePage == NULL) { 01055 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 01056 FREE(mintermPages); 01057 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 01058 FREE(nodeDataPages); 01059 FREE(currentNodePage); 01060 FREE(lightNodePages); 01061 FREE(nodePages); 01062 goto OUT_OF_MEM; 01063 } 01064 01065 pageIndex = 0; 01066 num = SubsetCountNodesAux(node,table,max); 01067 if (memOut) goto OUT_OF_MEM; 01068 return(num); 01069 01070 OUT_OF_MEM: 01071 memOut = 1; 01072 return(0); 01073 01074 } /* end of SubsetCountNodes */
Function********************************************************************
Synopsis [Recursively counts the number of nodes under the dag. Also counts the number of nodes under the lighter child of this node.]
Description [Recursively counts the number of nodes under the dag. Also counts the number of nodes under the lighter child of this node. . Note that the same dag may be the lighter child of two different nodes and have different counts. As with the minterm counts, the node counts are stored in pages to be space efficient and the address for these node counts are stored in an st_table associated to each node. ]
SideEffects [Updates the node data table with node counts]
SeeAlso [SubsetCountNodes]
Definition at line 848 of file cuddSubsetHB.c.
00852 { 00853 int tval, eval, i; 00854 DdNode *N, *Nv, *Nnv; 00855 double minNv, minNnv; 00856 NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar; 00857 int *pmin, *pminBar, *val; 00858 00859 if ((node == NULL) || Cudd_IsConstant(node)) 00860 return(0); 00861 00862 /* if this node has been processed do nothing */ 00863 if (st_lookup(table, (char *)node, (char **)&dummyN) == 1) { 00864 val = dummyN->nodesPointer; 00865 if (val != NULL) 00866 return(0); 00867 } else { 00868 return(0); 00869 } 00870 00871 N = Cudd_Regular(node); 00872 Nv = Cudd_T(N); 00873 Nnv = Cudd_E(N); 00874 00875 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 00876 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 00877 00878 /* find the minterm counts for the THEN and ELSE branches */ 00879 if (Cudd_IsConstant(Nv)) { 00880 if (Nv == zero) { 00881 minNv = 0.0; 00882 } else { 00883 minNv = max; 00884 } 00885 } else { 00886 if (st_lookup(table, (char *)Nv, (char **)&dummyNv) == 1) 00887 minNv = *(dummyNv->mintermPointer); 00888 else { 00889 return(0); 00890 } 00891 } 00892 if (Cudd_IsConstant(Nnv)) { 00893 if (Nnv == zero) { 00894 minNnv = 0.0; 00895 } else { 00896 minNnv = max; 00897 } 00898 } else { 00899 if (st_lookup(table, (char *)Nnv, (char **)&dummyNnv) == 1) { 00900 minNnv = *(dummyNnv->mintermPointer); 00901 } 00902 else { 00903 return(0); 00904 } 00905 } 00906 00907 00908 /* recur based on which has larger minterm, */ 00909 if (minNv >= minNnv) { 00910 tval = SubsetCountNodesAux(Nv, table, max); 00911 if (memOut) return(0); 00912 eval = SubsetCountNodesAux(Nnv, table, max); 00913 if (memOut) return(0); 00914 00915 /* store the node count of the lighter child. */ 00916 if (pageIndex == pageSize) ResizeCountNodePages(); 00917 if (memOut) { 00918 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00919 FREE(mintermPages); 00920 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00921 FREE(nodeDataPages); 00922 st_free_table(table); 00923 return(0); 00924 } 00925 pmin = currentLightNodePage + pageIndex; 00926 *pmin = eval; /* Here the ELSE child is lighter */ 00927 dummyN->lightChildNodesPointer = pmin; 00928 00929 } else { 00930 eval = SubsetCountNodesAux(Nnv, table, max); 00931 if (memOut) return(0); 00932 tval = SubsetCountNodesAux(Nv, table, max); 00933 if (memOut) return(0); 00934 00935 /* store the node count of the lighter child. */ 00936 if (pageIndex == pageSize) ResizeCountNodePages(); 00937 if (memOut) { 00938 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00939 FREE(mintermPages); 00940 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00941 FREE(nodeDataPages); 00942 st_free_table(table); 00943 return(0); 00944 } 00945 pmin = currentLightNodePage + pageIndex; 00946 *pmin = tval; /* Here the THEN child is lighter */ 00947 dummyN->lightChildNodesPointer = pmin; 00948 00949 } 00950 /* updating the page index for node count storage. */ 00951 pmin = currentNodePage + pageIndex; 00952 *pmin = tval + eval + 1; 00953 dummyN->nodesPointer = pmin; 00954 00955 /* pageIndex is parallel page index for count_nodes and count_lightNodes */ 00956 pageIndex++; 00957 00958 /* if this node has been reached first, it belongs to a heavier 00959 branch. Its complement will be reached later on a lighter branch. 00960 Hence the complement has zero node count. */ 00961 00962 if (st_lookup(table, (char *)Cudd_Not(node), (char **)&dummyNBar) == 1) { 00963 if (pageIndex == pageSize) ResizeCountNodePages(); 00964 if (memOut) { 00965 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00966 FREE(mintermPages); 00967 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00968 FREE(nodeDataPages); 00969 st_free_table(table); 00970 return(0); 00971 } 00972 pminBar = currentLightNodePage + pageIndex; 00973 *pminBar = 0; 00974 dummyNBar->lightChildNodesPointer = pminBar; 00975 /* The lighter child has less nodes than the parent. 00976 * So if parent 0 then lighter child zero 00977 */ 00978 if (pageIndex == pageSize) ResizeCountNodePages(); 00979 if (memOut) { 00980 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00981 FREE(mintermPages); 00982 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00983 FREE(nodeDataPages); 00984 st_free_table(table); 00985 return(0); 00986 } 00987 pminBar = currentNodePage + pageIndex; 00988 *pminBar = 0; 00989 dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */ 00990 00991 pageIndex++; 00992 } 00993 return(*pmin); 00994 } /*end of SubsetCountNodesAux */
int* currentLightNodePage [static] |
Definition at line 108 of file cuddSubsetHB.c.
double* currentMintermPage [static] |
Definition at line 101 of file cuddSubsetHB.c.
NodeData_t* currentNodeDataPage [static] |
Definition at line 115 of file cuddSubsetHB.c.
int* currentNodePage [static] |
Definition at line 106 of file cuddSubsetHB.c.
char rcsid [] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static] |
Definition at line 89 of file cuddSubsetHB.c.
int** lightNodePages [static] |
Definition at line 100 of file cuddSubsetHB.c.
double max [static] |
Definition at line 103 of file cuddSubsetHB.c.
int maxNodeDataPages [static] |
Definition at line 122 of file cuddSubsetHB.c.
int maxPages [static] |
Definition at line 113 of file cuddSubsetHB.c.
int memOut [static] |
Definition at line 92 of file cuddSubsetHB.c.
double** mintermPages [static] |
Definition at line 98 of file cuddSubsetHB.c.
int nodeDataPage [static] |
Definition at line 117 of file cuddSubsetHB.c.
int nodeDataPageIndex [static] |
Definition at line 118 of file cuddSubsetHB.c.
NodeData_t** nodeDataPages [static] |
Definition at line 119 of file cuddSubsetHB.c.
int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE [static] |
Definition at line 120 of file cuddSubsetHB.c.
int** nodePages [static] |
Definition at line 99 of file cuddSubsetHB.c.
Definition at line 97 of file cuddSubsetHB.c.
int page [static] |
Definition at line 111 of file cuddSubsetHB.c.
int pageIndex [static] |
Definition at line 110 of file cuddSubsetHB.c.
int pageSize = DEFAULT_PAGE_SIZE [static] |
Definition at line 112 of file cuddSubsetHB.c.
Definition at line 97 of file cuddSubsetHB.c.