#include "util.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 (void) |
static void | ResizeCountMintermPages (void) |
static void | ResizeCountNodePages (void) |
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) |
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) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio 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 [Copyright (c) 1995-2004, Regents of the University of Colorado
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the University of Colorado nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.]
Definition at line 74 of file cuddSubsetHB.c.
#define DEFAULT_NODE_DATA_PAGE_SIZE 1024 |
Definition at line 84 of file cuddSubsetHB.c.
#define DEFAULT_PAGE_SIZE 2048 |
Definition at line 83 of file cuddSubsetHB.c.
#define INITIAL_PAGES 128 |
Definition at line 85 of file cuddSubsetHB.c.
typedef struct NodeData NodeData_t |
Definition at line 109 of file cuddSubsetHB.c.
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 1154 of file cuddSubsetHB.c.
01162 { 01163 01164 DdNode *Nv, *Nnv, *N, *topv, *neW; 01165 double minNv, minNnv; 01166 NodeData_t *currNodeQual; 01167 NodeData_t *currNodeQualT; 01168 NodeData_t *currNodeQualE; 01169 DdNode *ThenBranch, *ElseBranch; 01170 unsigned int topid; 01171 char *dummy; 01172 01173 #ifdef DEBUG 01174 num_calls++; 01175 #endif 01176 /*If the size of the subset is below the threshold, dont do 01177 anything. */ 01178 if ((*size) <= threshold) { 01179 /* store nodes below this, so we can recombine if possible */ 01180 StoreNodes(storeTable, dd, node); 01181 return(node); 01182 } 01183 01184 if (Cudd_IsConstant(node)) 01185 return(node); 01186 01187 /* Look up minterm count for this node. */ 01188 if (!st_lookup(visitedTable, node, &currNodeQual)) { 01189 fprintf(dd->err, 01190 "Something is wrong, ought to be in node quality table\n"); 01191 } 01192 01193 /* Get children. */ 01194 N = Cudd_Regular(node); 01195 Nv = Cudd_T(N); 01196 Nnv = Cudd_E(N); 01197 01198 /* complement if necessary */ 01199 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 01200 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 01201 01202 if (!Cudd_IsConstant(Nv)) { 01203 /* find out minterms and nodes contributed by then child */ 01204 if (!st_lookup(visitedTable, Nv, &currNodeQualT)) { 01205 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); 01206 dd->errorCode = CUDD_INTERNAL_ERROR; 01207 return(NULL); 01208 } 01209 else { 01210 minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer); 01211 } 01212 } else { 01213 if (Nv == zero) { 01214 minNv = 0; 01215 } else { 01216 minNv = max; 01217 } 01218 } 01219 if (!Cudd_IsConstant(Nnv)) { 01220 /* find out minterms and nodes contributed by else child */ 01221 if (!st_lookup(visitedTable, Nnv, &currNodeQualE)) { 01222 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n"); 01223 dd->errorCode = CUDD_INTERNAL_ERROR; 01224 return(NULL); 01225 } else { 01226 minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer); 01227 } 01228 } else { 01229 if (Nnv == zero) { 01230 minNnv = 0; 01231 } else { 01232 minNnv = max; 01233 } 01234 } 01235 01236 /* keep track of size of subset by subtracting the number of 01237 * differential nodes contributed by lighter child 01238 */ 01239 *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer); 01240 if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes 01241 the Then branch in case of a tie */ 01242 01243 /* recur with the Then branch */ 01244 ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size, 01245 visitedTable, threshold, storeTable, approxTable); 01246 if (ThenBranch == NULL) { 01247 return(NULL); 01248 } 01249 cuddRef(ThenBranch); 01250 /* The Else branch is either a node that already exists in the 01251 * subset, or one whose approximation has been computed, or 01252 * Zero. 01253 */ 01254 if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), &dummy)) { 01255 ElseBranch = Nnv; 01256 cuddRef(ElseBranch); 01257 } else { 01258 if (st_lookup(approxTable, (char *)Nnv, &dummy)) { 01259 ElseBranch = (DdNode *)dummy; 01260 cuddRef(ElseBranch); 01261 } else { 01262 ElseBranch = zero; 01263 cuddRef(ElseBranch); 01264 } 01265 } 01266 01267 } 01268 else { 01269 /* recur with the Else branch */ 01270 ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size, 01271 visitedTable, threshold, storeTable, approxTable); 01272 if (ElseBranch == NULL) { 01273 return(NULL); 01274 } 01275 cuddRef(ElseBranch); 01276 /* The Then branch is either a node that already exists in the 01277 * subset, or one whose approximation has been computed, or 01278 * Zero. 01279 */ 01280 if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), &dummy)) { 01281 ThenBranch = Nv; 01282 cuddRef(ThenBranch); 01283 } else { 01284 if (st_lookup(approxTable, (char *)Nv, &dummy)) { 01285 ThenBranch = (DdNode *)dummy; 01286 cuddRef(ThenBranch); 01287 } else { 01288 ThenBranch = zero; 01289 cuddRef(ThenBranch); 01290 } 01291 } 01292 } 01293 01294 /* construct the Bdd with the top variable and the two children */ 01295 topid = Cudd_NodeReadIndex(N); 01296 topv = Cudd_ReadVars(dd, topid); 01297 cuddRef(topv); 01298 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); 01299 if (neW != NULL) { 01300 cuddRef(neW); 01301 } 01302 Cudd_RecursiveDeref(dd, topv); 01303 Cudd_RecursiveDeref(dd, ThenBranch); 01304 Cudd_RecursiveDeref(dd, ElseBranch); 01305 01306 01307 if (neW == NULL) 01308 return(NULL); 01309 else { 01310 /* store this node in the store table */ 01311 if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), &dummy)) { 01312 cuddRef(neW); 01313 if (!st_insert(storeTable, (char *)Cudd_Regular(neW), NIL(char))) 01314 return (NULL); 01315 } 01316 /* store the approximation for this node */ 01317 if (N != Cudd_Regular(neW)) { 01318 if (st_lookup(approxTable, (char *)node, &dummy)) { 01319 fprintf(dd->err, "This node should not be in the approximated table\n"); 01320 } else { 01321 cuddRef(neW); 01322 if (!st_insert(approxTable, (char *)node, (char *)neW)) 01323 return(NULL); 01324 } 01325 } 01326 cuddDeref(neW); 01327 return(neW); 01328 } 01329 } /* 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 205 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 255 of file cuddSubsetHB.c.
00260 { 00261 DdNode *subset, *g; 00262 00263 g = Cudd_Not(f); 00264 memOut = 0; 00265 do { 00266 dd->reordered = 0; 00267 subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold); 00268 } while ((dd->reordered == 1) && (!memOut)); 00269 00270 return(Cudd_NotCond(subset, (subset != NULL))); 00271 00272 } /* 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 301 of file cuddSubsetHB.c.
00306 { 00307 00308 int i, *size; 00309 st_table *visitedTable; 00310 int numNodes; 00311 NodeData_t *currNodeQual; 00312 DdNode *subset; 00313 st_table *storeTable, *approxTable; 00314 char *key, *value; 00315 st_generator *stGen; 00316 00317 if (f == NULL) { 00318 fprintf(dd->err, "Cannot subset, nil object\n"); 00319 dd->errorCode = CUDD_INVALID_ARG; 00320 return(NULL); 00321 } 00322 00323 one = Cudd_ReadOne(dd); 00324 zero = Cudd_Not(one); 00325 00326 /* If user does not know numVars value, set it to the maximum 00327 * exponent that the pow function can take. The -1 is due to the 00328 * discrepancy in the value that pow takes and the value that 00329 * log gives. 00330 */ 00331 if (numVars == 0) { 00332 /* set default value */ 00333 numVars = DBL_MAX_EXP - 1; 00334 } 00335 00336 if (Cudd_IsConstant(f)) { 00337 return(f); 00338 } 00339 00340 max = pow(2.0, (double)numVars); 00341 00342 /* Create visited table where structures for node data are allocated and 00343 stored in a st_table */ 00344 visitedTable = SubsetCountMinterm(f, numVars); 00345 if ((visitedTable == NULL) || memOut) { 00346 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00347 dd->errorCode = CUDD_MEMORY_OUT; 00348 return(0); 00349 } 00350 numNodes = SubsetCountNodes(f, visitedTable, numVars); 00351 if (memOut) { 00352 (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n"); 00353 dd->errorCode = CUDD_MEMORY_OUT; 00354 return(0); 00355 } 00356 00357 if (st_lookup(visitedTable, f, &currNodeQual) == 0) { 00358 fprintf(dd->err, 00359 "Something is wrong, ought to be node quality table\n"); 00360 dd->errorCode = CUDD_INTERNAL_ERROR; 00361 } 00362 00363 size = ALLOC(int, 1); 00364 if (size == NULL) { 00365 dd->errorCode = CUDD_MEMORY_OUT; 00366 return(NULL); 00367 } 00368 *size = numNodes; 00369 00370 #ifdef DEBUG 00371 num_calls = 0; 00372 #endif 00373 /* table to store nodes being created. */ 00374 storeTable = st_init_table(st_ptrcmp, st_ptrhash); 00375 /* insert the constant */ 00376 cuddRef(one); 00377 if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) == 00378 ST_OUT_OF_MEM) { 00379 fprintf(dd->out, "Something wrong, st_table insert failed\n"); 00380 } 00381 /* table to store approximations of nodes */ 00382 approxTable = st_init_table(st_ptrcmp, st_ptrhash); 00383 subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold, 00384 storeTable, approxTable); 00385 if (subset != NULL) { 00386 cuddRef(subset); 00387 } 00388 00389 stGen = st_init_gen(approxTable); 00390 if (stGen == NULL) { 00391 st_free_table(approxTable); 00392 return(NULL); 00393 } 00394 while(st_gen(stGen, (char **)&key, (char **)&value)) { 00395 Cudd_RecursiveDeref(dd, (DdNode *)value); 00396 } 00397 st_free_gen(stGen); stGen = NULL; 00398 st_free_table(approxTable); 00399 00400 stGen = st_init_gen(storeTable); 00401 if (stGen == NULL) { 00402 st_free_table(storeTable); 00403 return(NULL); 00404 } 00405 while(st_gen(stGen, (char **)&key, (char **)&value)) { 00406 Cudd_RecursiveDeref(dd, (DdNode *)key); 00407 } 00408 st_free_gen(stGen); stGen = NULL; 00409 st_free_table(storeTable); 00410 00411 for (i = 0; i <= page; i++) { 00412 FREE(mintermPages[i]); 00413 } 00414 FREE(mintermPages); 00415 for (i = 0; i <= page; i++) { 00416 FREE(nodePages[i]); 00417 } 00418 FREE(nodePages); 00419 for (i = 0; i <= page; i++) { 00420 FREE(lightNodePages[i]); 00421 } 00422 FREE(lightNodePages); 00423 for (i = 0; i <= nodeDataPage; i++) { 00424 FREE(nodeDataPages[i]); 00425 } 00426 FREE(nodeDataPages); 00427 st_free_table(visitedTable); 00428 FREE(size); 00429 #if 0 00430 (void) Cudd_DebugCheck(dd); 00431 (void) Cudd_CheckKeys(dd); 00432 #endif 00433 00434 if (subset != NULL) { 00435 #ifdef DD_DEBUG 00436 if (!Cudd_bddLeq(dd, subset, f)) { 00437 fprintf(dd->err, "Wrong subset\n"); 00438 dd->errorCode = CUDD_INTERNAL_ERROR; 00439 return(NULL); 00440 } 00441 #endif 00442 cuddDeref(subset); 00443 return(subset); 00444 } else { 00445 return(NULL); 00446 } 00447 } /* end of cuddSubsetHeavyBranch */
static void ResizeCountMintermPages | ( | void | ) | [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 529 of file cuddSubsetHB.c.
00530 { 00531 int i; 00532 double **newMintermPages; 00533 00534 page++; 00535 /* If the current page index is larger than the number of pages 00536 * allocated, allocate a new page array. Page numbers are incremented by 00537 * INITIAL_PAGES 00538 */ 00539 if (page == maxPages) { 00540 newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES); 00541 if (newMintermPages == NULL) { 00542 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00543 FREE(mintermPages); 00544 memOut = 1; 00545 return; 00546 } else { 00547 for (i = 0; i < maxPages; i++) { 00548 newMintermPages[i] = mintermPages[i]; 00549 } 00550 /* Increase total page count */ 00551 maxPages += INITIAL_PAGES; 00552 FREE(mintermPages); 00553 mintermPages = newMintermPages; 00554 } 00555 } 00556 /* Allocate a new page */ 00557 currentMintermPage = mintermPages[page] = ALLOC(double,pageSize); 00558 if (currentMintermPage == NULL) { 00559 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00560 FREE(mintermPages); 00561 memOut = 1; 00562 return; 00563 } 00564 /* reset page index */ 00565 pageIndex = 0; 00566 return; 00567 00568 } /* end of ResizeCountMintermPages */
static void ResizeCountNodePages | ( | void | ) | [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 586 of file cuddSubsetHB.c.
00587 { 00588 int i; 00589 int **newNodePages; 00590 00591 page++; 00592 00593 /* If the current page index is larger than the number of pages 00594 * allocated, allocate a new page array. The number of pages is incremented 00595 * by INITIAL_PAGES. 00596 */ 00597 if (page == maxPages) { 00598 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); 00599 if (newNodePages == NULL) { 00600 for (i = 0; i < page; i++) FREE(nodePages[i]); 00601 FREE(nodePages); 00602 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00603 FREE(lightNodePages); 00604 memOut = 1; 00605 return; 00606 } else { 00607 for (i = 0; i < maxPages; i++) { 00608 newNodePages[i] = nodePages[i]; 00609 } 00610 FREE(nodePages); 00611 nodePages = newNodePages; 00612 } 00613 00614 newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES); 00615 if (newNodePages == NULL) { 00616 for (i = 0; i < page; i++) FREE(nodePages[i]); 00617 FREE(nodePages); 00618 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00619 FREE(lightNodePages); 00620 memOut = 1; 00621 return; 00622 } else { 00623 for (i = 0; i < maxPages; i++) { 00624 newNodePages[i] = lightNodePages[i]; 00625 } 00626 FREE(lightNodePages); 00627 lightNodePages = newNodePages; 00628 } 00629 /* Increase total page count */ 00630 maxPages += INITIAL_PAGES; 00631 } 00632 /* Allocate a new page */ 00633 currentNodePage = nodePages[page] = ALLOC(int,pageSize); 00634 if (currentNodePage == NULL) { 00635 for (i = 0; i < page; i++) FREE(nodePages[i]); 00636 FREE(nodePages); 00637 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00638 FREE(lightNodePages); 00639 memOut = 1; 00640 return; 00641 } 00642 /* Allocate a new page */ 00643 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); 00644 if (currentLightNodePage == NULL) { 00645 for (i = 0; i <= page; i++) FREE(nodePages[i]); 00646 FREE(nodePages); 00647 for (i = 0; i < page; i++) FREE(lightNodePages[i]); 00648 FREE(lightNodePages); 00649 memOut = 1; 00650 return; 00651 } 00652 /* reset page index */ 00653 pageIndex = 0; 00654 return; 00655 00656 } /* end of ResizeCountNodePages */
static void ResizeNodeDataPages | ( | void | ) | [static] |
AutomaticStart
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 470 of file cuddSubsetHB.c.
00471 { 00472 int i; 00473 NodeData_t **newNodeDataPages; 00474 00475 nodeDataPage++; 00476 /* If the current page index is larger than the number of pages 00477 * allocated, allocate a new page array. Page numbers are incremented by 00478 * INITIAL_PAGES 00479 */ 00480 if (nodeDataPage == maxNodeDataPages) { 00481 newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES); 00482 if (newNodeDataPages == NULL) { 00483 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00484 FREE(nodeDataPages); 00485 memOut = 1; 00486 return; 00487 } else { 00488 for (i = 0; i < maxNodeDataPages; i++) { 00489 newNodeDataPages[i] = nodeDataPages[i]; 00490 } 00491 /* Increase total page count */ 00492 maxNodeDataPages += INITIAL_PAGES; 00493 FREE(nodeDataPages); 00494 nodeDataPages = newNodeDataPages; 00495 } 00496 } 00497 /* Allocate a new page */ 00498 currentNodeDataPage = nodeDataPages[nodeDataPage] = 00499 ALLOC(NodeData_t ,nodeDataPageSize); 00500 if (currentNodeDataPage == NULL) { 00501 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00502 FREE(nodeDataPages); 00503 memOut = 1; 00504 return; 00505 } 00506 /* reset page index */ 00507 nodeDataPageIndex = 0; 00508 return; 00509 00510 } /* 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 1109 of file cuddSubsetHB.c.
01113 { 01114 DdNode *N, *Nt, *Ne; 01115 if (Cudd_IsConstant(dd)) { 01116 return; 01117 } 01118 N = Cudd_Regular(node); 01119 if (st_lookup(storeTable, (char *)N, NIL(char *))) { 01120 return; 01121 } 01122 cuddRef(N); 01123 if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) { 01124 fprintf(dd->err,"Something wrong, st_table insert failed\n"); 01125 } 01126 01127 Nt = Cudd_T(N); 01128 Ne = Cudd_E(N); 01129 01130 StoreNodes(storeTable, dd, Nt); 01131 StoreNodes(storeTable, dd, Ne); 01132 return; 01133 01134 }
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 787 of file cuddSubsetHB.c.
00790 { 00791 st_table *table; 00792 int i; 00793 00794 00795 #ifdef DEBUG 00796 num_calls = 0; 00797 #endif 00798 00799 max = pow(2.0,(double) nvars); 00800 table = st_init_table(st_ptrcmp,st_ptrhash); 00801 if (table == NULL) goto OUT_OF_MEM; 00802 maxPages = INITIAL_PAGES; 00803 mintermPages = ALLOC(double *,maxPages); 00804 if (mintermPages == NULL) { 00805 st_free_table(table); 00806 goto OUT_OF_MEM; 00807 } 00808 page = 0; 00809 currentMintermPage = ALLOC(double,pageSize); 00810 mintermPages[page] = currentMintermPage; 00811 if (currentMintermPage == NULL) { 00812 FREE(mintermPages); 00813 st_free_table(table); 00814 goto OUT_OF_MEM; 00815 } 00816 pageIndex = 0; 00817 maxNodeDataPages = INITIAL_PAGES; 00818 nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages); 00819 if (nodeDataPages == NULL) { 00820 for (i = 0; i <= page ; i++) FREE(mintermPages[i]); 00821 FREE(mintermPages); 00822 st_free_table(table); 00823 goto OUT_OF_MEM; 00824 } 00825 nodeDataPage = 0; 00826 currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize); 00827 nodeDataPages[nodeDataPage] = currentNodeDataPage; 00828 if (currentNodeDataPage == NULL) { 00829 for (i = 0; i <= page ; i++) FREE(mintermPages[i]); 00830 FREE(mintermPages); 00831 FREE(nodeDataPages); 00832 st_free_table(table); 00833 goto OUT_OF_MEM; 00834 } 00835 nodeDataPageIndex = 0; 00836 00837 (void) SubsetCountMintermAux(node,max,table); 00838 if (memOut) goto OUT_OF_MEM; 00839 return(table); 00840 00841 OUT_OF_MEM: 00842 memOut = 1; 00843 return(NULL); 00844 00845 } /* 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 676 of file cuddSubsetHB.c.
00680 { 00681 00682 DdNode *N,*Nv,*Nnv; /* nodes to store cofactors */ 00683 double min,*pmin; /* minterm count */ 00684 double min1, min2; /* minterm count */ 00685 NodeData_t *dummy; 00686 NodeData_t *newEntry; 00687 int i; 00688 00689 #ifdef DEBUG 00690 num_calls++; 00691 #endif 00692 00693 /* Constant case */ 00694 if (Cudd_IsConstant(node)) { 00695 if (node == zero) { 00696 return(0.0); 00697 } else { 00698 return(max); 00699 } 00700 } else { 00701 00702 /* check if entry for this node exists */ 00703 if (st_lookup(table, node, &dummy)) { 00704 min = *(dummy->mintermPointer); 00705 return(min); 00706 } 00707 00708 /* Make the node regular to extract cofactors */ 00709 N = Cudd_Regular(node); 00710 00711 /* store the cofactors */ 00712 Nv = Cudd_T(N); 00713 Nnv = Cudd_E(N); 00714 00715 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 00716 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 00717 00718 min1 = SubsetCountMintermAux(Nv, max,table)/2.0; 00719 if (memOut) return(0.0); 00720 min2 = SubsetCountMintermAux(Nnv,max,table)/2.0; 00721 if (memOut) return(0.0); 00722 min = (min1+min2); 00723 00724 /* if page index is at the bottom, then create a new page */ 00725 if (pageIndex == pageSize) ResizeCountMintermPages(); 00726 if (memOut) { 00727 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00728 FREE(nodeDataPages); 00729 st_free_table(table); 00730 return(0.0); 00731 } 00732 00733 /* point to the correct location in the page */ 00734 pmin = currentMintermPage+pageIndex; 00735 pageIndex++; 00736 00737 /* store the minterm count of this node in the page */ 00738 *pmin = min; 00739 00740 /* Note I allocate the struct here. Freeing taken care of later */ 00741 if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages(); 00742 if (memOut) { 00743 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00744 FREE(mintermPages); 00745 st_free_table(table); 00746 return(0.0); 00747 } 00748 00749 newEntry = currentNodeDataPage + nodeDataPageIndex; 00750 nodeDataPageIndex++; 00751 00752 /* points to the correct location in the page */ 00753 newEntry->mintermPointer = pmin; 00754 /* initialize this field of the Node Quality structure */ 00755 newEntry->nodesPointer = NULL; 00756 00757 /* insert entry for the node in the table */ 00758 if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) { 00759 memOut = 1; 00760 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00761 FREE(mintermPages); 00762 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00763 FREE(nodeDataPages); 00764 st_free_table(table); 00765 return(0.0); 00766 } 00767 return(min); 00768 } 00769 00770 } /* 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 1032 of file cuddSubsetHB.c.
01036 { 01037 int num; 01038 int i; 01039 01040 #ifdef DEBUG 01041 num_calls = 0; 01042 #endif 01043 01044 max = pow(2.0,(double) nvars); 01045 maxPages = INITIAL_PAGES; 01046 nodePages = ALLOC(int *,maxPages); 01047 if (nodePages == NULL) { 01048 goto OUT_OF_MEM; 01049 } 01050 01051 lightNodePages = ALLOC(int *,maxPages); 01052 if (lightNodePages == NULL) { 01053 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 01054 FREE(mintermPages); 01055 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 01056 FREE(nodeDataPages); 01057 FREE(nodePages); 01058 goto OUT_OF_MEM; 01059 } 01060 01061 page = 0; 01062 currentNodePage = nodePages[page] = ALLOC(int,pageSize); 01063 if (currentNodePage == NULL) { 01064 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 01065 FREE(mintermPages); 01066 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 01067 FREE(nodeDataPages); 01068 FREE(lightNodePages); 01069 FREE(nodePages); 01070 goto OUT_OF_MEM; 01071 } 01072 01073 currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize); 01074 if (currentLightNodePage == NULL) { 01075 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 01076 FREE(mintermPages); 01077 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 01078 FREE(nodeDataPages); 01079 FREE(currentNodePage); 01080 FREE(lightNodePages); 01081 FREE(nodePages); 01082 goto OUT_OF_MEM; 01083 } 01084 01085 pageIndex = 0; 01086 num = SubsetCountNodesAux(node,table,max); 01087 if (memOut) goto OUT_OF_MEM; 01088 return(num); 01089 01090 OUT_OF_MEM: 01091 memOut = 1; 01092 return(0); 01093 01094 } /* 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 868 of file cuddSubsetHB.c.
00872 { 00873 int tval, eval, i; 00874 DdNode *N, *Nv, *Nnv; 00875 double minNv, minNnv; 00876 NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar; 00877 int *pmin, *pminBar, *val; 00878 00879 if ((node == NULL) || Cudd_IsConstant(node)) 00880 return(0); 00881 00882 /* if this node has been processed do nothing */ 00883 if (st_lookup(table, node, &dummyN) == 1) { 00884 val = dummyN->nodesPointer; 00885 if (val != NULL) 00886 return(0); 00887 } else { 00888 return(0); 00889 } 00890 00891 N = Cudd_Regular(node); 00892 Nv = Cudd_T(N); 00893 Nnv = Cudd_E(N); 00894 00895 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 00896 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 00897 00898 /* find the minterm counts for the THEN and ELSE branches */ 00899 if (Cudd_IsConstant(Nv)) { 00900 if (Nv == zero) { 00901 minNv = 0.0; 00902 } else { 00903 minNv = max; 00904 } 00905 } else { 00906 if (st_lookup(table, Nv, &dummyNv) == 1) 00907 minNv = *(dummyNv->mintermPointer); 00908 else { 00909 return(0); 00910 } 00911 } 00912 if (Cudd_IsConstant(Nnv)) { 00913 if (Nnv == zero) { 00914 minNnv = 0.0; 00915 } else { 00916 minNnv = max; 00917 } 00918 } else { 00919 if (st_lookup(table, Nnv, &dummyNnv) == 1) { 00920 minNnv = *(dummyNnv->mintermPointer); 00921 } 00922 else { 00923 return(0); 00924 } 00925 } 00926 00927 00928 /* recur based on which has larger minterm, */ 00929 if (minNv >= minNnv) { 00930 tval = SubsetCountNodesAux(Nv, table, max); 00931 if (memOut) return(0); 00932 eval = SubsetCountNodesAux(Nnv, 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 = eval; /* Here the ELSE child is lighter */ 00947 dummyN->lightChildNodesPointer = pmin; 00948 00949 } else { 00950 eval = SubsetCountNodesAux(Nnv, table, max); 00951 if (memOut) return(0); 00952 tval = SubsetCountNodesAux(Nv, table, max); 00953 if (memOut) return(0); 00954 00955 /* store the node count of the lighter child. */ 00956 if (pageIndex == pageSize) ResizeCountNodePages(); 00957 if (memOut) { 00958 for (i = 0; i <= page; i++) FREE(mintermPages[i]); 00959 FREE(mintermPages); 00960 for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]); 00961 FREE(nodeDataPages); 00962 st_free_table(table); 00963 return(0); 00964 } 00965 pmin = currentLightNodePage + pageIndex; 00966 *pmin = tval; /* Here the THEN child is lighter */ 00967 dummyN->lightChildNodesPointer = pmin; 00968 00969 } 00970 /* updating the page index for node count storage. */ 00971 pmin = currentNodePage + pageIndex; 00972 *pmin = tval + eval + 1; 00973 dummyN->nodesPointer = pmin; 00974 00975 /* pageIndex is parallel page index for count_nodes and count_lightNodes */ 00976 pageIndex++; 00977 00978 /* if this node has been reached first, it belongs to a heavier 00979 branch. Its complement will be reached later on a lighter branch. 00980 Hence the complement has zero node count. */ 00981 00982 if (st_lookup(table, Cudd_Not(node), &dummyNBar) == 1) { 00983 if (pageIndex == pageSize) ResizeCountNodePages(); 00984 if (memOut) { 00985 for (i = 0; i < page; i++) FREE(mintermPages[i]); 00986 FREE(mintermPages); 00987 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 00988 FREE(nodeDataPages); 00989 st_free_table(table); 00990 return(0); 00991 } 00992 pminBar = currentLightNodePage + pageIndex; 00993 *pminBar = 0; 00994 dummyNBar->lightChildNodesPointer = pminBar; 00995 /* The lighter child has less nodes than the parent. 00996 * So if parent 0 then lighter child zero 00997 */ 00998 if (pageIndex == pageSize) ResizeCountNodePages(); 00999 if (memOut) { 01000 for (i = 0; i < page; i++) FREE(mintermPages[i]); 01001 FREE(mintermPages); 01002 for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]); 01003 FREE(nodeDataPages); 01004 st_free_table(table); 01005 return(0); 01006 } 01007 pminBar = currentNodePage + pageIndex; 01008 *pminBar = 0; 01009 dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */ 01010 01011 pageIndex++; 01012 } 01013 return(*pmin); 01014 } /*end of SubsetCountNodesAux */
int* currentLightNodePage [static] |
Definition at line 135 of file cuddSubsetHB.c.
double* currentMintermPage [static] |
Definition at line 128 of file cuddSubsetHB.c.
NodeData_t* currentNodeDataPage [static] |
Definition at line 142 of file cuddSubsetHB.c.
int* currentNodePage [static] |
Definition at line 133 of file cuddSubsetHB.c.
char rcsid [] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio Exp $" [static] |
Definition at line 116 of file cuddSubsetHB.c.
int** lightNodePages [static] |
Definition at line 127 of file cuddSubsetHB.c.
double max [static] |
Definition at line 130 of file cuddSubsetHB.c.
int maxNodeDataPages [static] |
Definition at line 149 of file cuddSubsetHB.c.
int maxPages [static] |
Definition at line 140 of file cuddSubsetHB.c.
int memOut [static] |
Definition at line 119 of file cuddSubsetHB.c.
double** mintermPages [static] |
Definition at line 125 of file cuddSubsetHB.c.
int nodeDataPage [static] |
Definition at line 144 of file cuddSubsetHB.c.
int nodeDataPageIndex [static] |
Definition at line 145 of file cuddSubsetHB.c.
NodeData_t** nodeDataPages [static] |
Definition at line 146 of file cuddSubsetHB.c.
int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE [static] |
Definition at line 147 of file cuddSubsetHB.c.
int** nodePages [static] |
Definition at line 126 of file cuddSubsetHB.c.
Definition at line 124 of file cuddSubsetHB.c.
int page [static] |
Definition at line 138 of file cuddSubsetHB.c.
int pageIndex [static] |
Definition at line 137 of file cuddSubsetHB.c.
int pageSize = DEFAULT_PAGE_SIZE [static] |
Definition at line 139 of file cuddSubsetHB.c.
Definition at line 124 of file cuddSubsetHB.c.