#include "util_hack.h"
#include "cuddInt.h"
Go to the source code of this file.
Data Structures | |
struct | NodeDist |
struct | AssortedInfo |
Defines | |
#define | DEFAULT_PAGE_SIZE 2048 |
#define | DEFAULT_NODE_DIST_PAGE_SIZE 2048 |
#define | MAXSHORTINT ((DdHalfWord) ~0) |
#define | INITIAL_PAGES 128 |
Typedefs | |
typedef struct NodeDist | NodeDist_t |
Functions | |
static void ResizeNodeDistPages | ARGS (()) |
static void CreateTopDist | ARGS ((st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp)) |
static int CreateBotDist | ARGS ((DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp)) |
static st_table *CreatePathTable | ARGS ((DdNode *node, unsigned int *pathLengthArray, FILE *fp)) |
static unsigned int AssessPathLength | ARGS ((unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp)) |
static DdNode *BuildSubsetBdd | ARGS ((DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable)) |
static enum st_retval stPathTableDdFree | ARGS ((char *key, char *value, char *arg)) |
DdNode * | Cudd_SubsetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit) |
DdNode * | Cudd_SupersetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit) |
DdNode * | cuddSubsetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit) |
static void | ResizeNodeDistPages () |
static void | ResizeQueuePages () |
static void | CreateTopDist (st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp) |
static int | CreateBotDist (DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp) |
static st_table * | CreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp) |
static unsigned int | AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp) |
static DdNode * | BuildSubsetBdd (DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable) |
static enum st_retval | stPathTableDdFree (char *key, char *value, char *arg) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" |
static int | memOut |
static DdNode * | zero |
static DdNode * | one |
static NodeDist_t ** | nodeDistPages |
static int | nodeDistPageIndex |
static int | nodeDistPage |
static int | nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE |
static int | maxNodeDistPages |
static NodeDist_t * | currentNodeDistPage |
static DdNode *** | queuePages |
static int | queuePageIndex |
static int | queuePage |
static int | queuePageSize = DEFAULT_PAGE_SIZE |
static int | maxQueuePages |
static DdNode ** | currentQueuePage |
#define DEFAULT_NODE_DIST_PAGE_SIZE 2048 |
Definition at line 52 of file cuddSubsetSP.c.
#define DEFAULT_PAGE_SIZE 2048 |
CFile***********************************************************************
FileName [cuddSubsetSP.c]
PackageName [cudd]
Synopsis [Procedure to subset the given BDD choosing the shortest paths (largest cubes) in the BDD.]
Description [External procedures included in this module:
Internal procedures included in this module:
Static procedures included in this module:
]
SeeAlso [cuddSubsetHB.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 51 of file cuddSubsetSP.c.
#define INITIAL_PAGES 128 |
Definition at line 58 of file cuddSubsetSP.c.
#define MAXSHORTINT ((DdHalfWord) ~0) |
Definition at line 53 of file cuddSubsetSP.c.
typedef struct NodeDist NodeDist_t |
Definition at line 91 of file cuddSubsetSP.c.
static DdNode* BuildSubsetBdd ARGS | ( | (DdManager *dd, st_table *pathTable, DdNode *node, struct AssortedInfo *info, st_table *subsetNodeTable) | ) | [static] |
static unsigned int AssessPathLength ARGS | ( | (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp) | ) | [static] |
static st_table* CreatePathTable ARGS | ( | (DdNode *node, unsigned int *pathLengthArray, FILE *fp) | ) | [static] |
static int CreateBotDist ARGS | ( | (DdNode *node, st_table *pathTable, unsigned int *pathLengthArray, FILE *fp) | ) | [static] |
static void CreateTopDist ARGS | ( | (st_table *pathTable, int parentPage, int parentQueueIndex, int topLen, DdNode **childPage, int childQueueIndex, int numParents, FILE *fp) | ) | [static] |
static void ResizeNodeDistPages ARGS | ( | () | ) | [static] |
AutomaticStart
static unsigned int AssessPathLength | ( | unsigned int * | pathLengthArray, | |
int | threshold, | |||
int | numVars, | |||
unsigned int * | excess, | |||
FILE * | fp | |||
) | [static] |
Function********************************************************************
Synopsis [Chooses the maximum allowable path length of nodes under the threshold.]
Description [Chooses the maximum allowable path length under each node. The corner cases are when the threshold is larger than the number of nodes in the BDD iself, in which case 'numVars + 1' is returned. If all nodes of a particular path length are needed, then the maxpath returned is the next one with excess nodes = 0;]
SideEffects [None]
SeeAlso []
Definition at line 1134 of file cuddSubsetSP.c.
01140 { 01141 unsigned int i, maxpath; 01142 int temp; 01143 01144 temp = threshold; 01145 i = 0; 01146 maxpath = 0; 01147 /* quit loop if i reaches max number of variables or if temp reaches 01148 * below zero 01149 */ 01150 while ((i < (unsigned) numVars+1) && (temp > 0)) { 01151 if (pathLengthArray[i] > 0) { 01152 maxpath = i; 01153 temp = temp - pathLengthArray[i]; 01154 } 01155 i++; 01156 } 01157 /* if all nodes of max path are needed */ 01158 if (temp >= 0) { 01159 maxpath++; /* now maxpath becomes the next maxppath or max number 01160 of variables */ 01161 *excess = 0; 01162 } else { /* normal case when subset required is less than size of 01163 original BDD */ 01164 *excess = temp + pathLengthArray[maxpath]; 01165 } 01166 01167 if (maxpath == 0) { 01168 fprintf(fp, "Path Length array seems to be all zeroes, check\n"); 01169 } 01170 return(maxpath); 01171 01172 } /* end of AssessPathLength */
static DdNode* BuildSubsetBdd | ( | DdManager * | dd, | |
st_table * | pathTable, | |||
DdNode * | node, | |||
struct AssortedInfo * | info, | |||
st_table * | subsetNodeTable | |||
) | [static] |
Function********************************************************************
Synopsis [Builds the BDD with nodes labeled with path length less than or equal to maxpath]
Description [Builds the BDD with nodes labeled with path length under maxpath and as many nodes labeled maxpath as determined by the threshold. The procedure uses the path table to determine which nodes in the original bdd need to be retained. This procedure picks a shortest path (tie break decided by taking the child with the shortest distance to the constant) and recurs down the path till it reaches the constant. the procedure then starts building the subset upward from the constant. All nodes labeled by path lengths less than the given maxpath are used to build the subset. However, in the case of nodes that have label equal to maxpath, as many are chosen as required by the threshold. This number is stored in the info structure in the field thresholdReached. This field is decremented whenever a node labeled maxpath is encountered and the nodes labeled maxpath are aggregated in a maxpath table. As soon as the thresholdReached count goes to 0, the shortest path from this node to the constant is found. The extraction of nodes with the above labeling is based on the fact that each node, labeled with a path length, P, has at least one child labeled P or less. So extracting all nodes labeled a given path length P ensures complete paths between the root and the constant. Extraction of a partial number of nodes with a given path length may result in incomplete paths and hence the additional number of nodes are grabbed to complete the path. Since the Bdd is built bottom-up, other nodes labeled maxpath do lie on complete paths. The procedure may cause the subset to have a larger or smaller number of nodes than the specified threshold. The increase in the number of nodes is caused by the building of a subset and the reduction by recombination. However in most cases, the recombination overshadows the increase and the procedure returns a result with lower number of nodes than specified. The subsetNodeTable is NIL when there is no hard limit on the number of nodes. Further efforts towards keeping the subset closer to the threshold number were abandoned in favour of keeping the procedure simple and fast.]
SideEffects [SubsetNodeTable is changed if it is not NIL.]
SeeAlso []
Definition at line 1218 of file cuddSubsetSP.c.
01224 { 01225 DdNode *N, *Nv, *Nnv; 01226 DdNode *ThenBranch, *ElseBranch, *childBranch; 01227 DdNode *child, *regChild, *regNnv, *regNv; 01228 NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; 01229 DdNode *neW, *topv, *regNew; 01230 char *entry; 01231 unsigned int topid; 01232 unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength; 01233 unsigned int NvBotDist, NnvBotDist; 01234 int tiebreakChild; 01235 int processingDone, thenDone, elseDone; 01236 01237 01238 #ifdef DD_DEBUG 01239 numCalls++; 01240 #endif 01241 if (Cudd_IsConstant(node)) 01242 return(node); 01243 01244 N = Cudd_Regular(node); 01245 /* Find node in table. */ 01246 if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { 01247 (void) fprintf(dd->err, "Something wrong, node must be in table \n"); 01248 dd->errorCode = CUDD_INTERNAL_ERROR; 01249 return(NULL); 01250 } 01251 /* If the node in the table has been visited, then return the corresponding 01252 ** Dd. Since a node can become a subset of itself, its 01253 ** complement (that is te same node reached by a different parity) will 01254 ** become a superset of the original node and result in some minterms 01255 ** that were not in the original set. Hence two different results are 01256 ** maintained, corresponding to the odd and even parities. 01257 */ 01258 01259 /* If this node is reached with an odd parity, get odd parity results. */ 01260 if (Cudd_IsComplement(node)) { 01261 if (nodeStat->compResult != NULL) { 01262 #ifdef DD_DEBUG 01263 hits++; 01264 #endif 01265 return(nodeStat->compResult); 01266 } 01267 } else { 01268 /* if this node is reached with an even parity, get even parity 01269 * results 01270 */ 01271 if (nodeStat->regResult != NULL) { 01272 #ifdef DD_DEBUG 01273 hits++; 01274 #endif 01275 return(nodeStat->regResult); 01276 } 01277 } 01278 01279 01280 /* get children */ 01281 Nv = Cudd_T(N); 01282 Nnv = Cudd_E(N); 01283 01284 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 01285 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 01286 01287 /* no child processed */ 01288 processingDone = 0; 01289 /* then child not processed */ 01290 thenDone = 0; 01291 ThenBranch = NULL; 01292 /* else child not processed */ 01293 elseDone = 0; 01294 ElseBranch = NULL; 01295 /* if then child constant, branch is the child */ 01296 if (Cudd_IsConstant(Nv)) { 01297 /*shortest path found */ 01298 if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) { 01299 info->findShortestPath = 0; 01300 } 01301 01302 ThenBranch = Nv; 01303 cuddRef(ThenBranch); 01304 if (ThenBranch == NULL) { 01305 return(NULL); 01306 } 01307 01308 thenDone++; 01309 processingDone++; 01310 NvBotDist = MAXSHORTINT; 01311 } else { 01312 /* Derive regular child for table lookup. */ 01313 regNv = Cudd_Regular(Nv); 01314 /* Get node data for shortest path length. */ 01315 if (!st_lookup(pathTable, (char *)regNv, (char **)&nodeStatNv) ) { 01316 (void) fprintf(dd->err, "Something wrong, node must be in table\n"); 01317 dd->errorCode = CUDD_INTERNAL_ERROR; 01318 return(NULL); 01319 } 01320 /* Derive shortest path length for child. */ 01321 if ((nodeStatNv->oddTopDist != MAXSHORTINT) && 01322 (nodeStatNv->oddBotDist != MAXSHORTINT)) { 01323 oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist); 01324 } else { 01325 oddLen = MAXSHORTINT; 01326 } 01327 01328 if ((nodeStatNv->evenTopDist != MAXSHORTINT) && 01329 (nodeStatNv->evenBotDist != MAXSHORTINT)) { 01330 evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist); 01331 } else { 01332 evenLen = MAXSHORTINT; 01333 } 01334 01335 NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; 01336 NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist: 01337 nodeStatNv->evenBotDist; 01338 } 01339 /* if else child constant, branch is the child */ 01340 if (Cudd_IsConstant(Nnv)) { 01341 /*shortest path found */ 01342 if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) { 01343 info->findShortestPath = 0; 01344 } 01345 01346 ElseBranch = Nnv; 01347 cuddRef(ElseBranch); 01348 if (ElseBranch == NULL) { 01349 return(NULL); 01350 } 01351 01352 elseDone++; 01353 processingDone++; 01354 NnvBotDist = MAXSHORTINT; 01355 } else { 01356 /* Derive regular child for table lookup. */ 01357 regNnv = Cudd_Regular(Nnv); 01358 /* Get node data for shortest path length. */ 01359 if (!st_lookup(pathTable, (char *)regNnv, (char **)&nodeStatNnv) ) { 01360 (void) fprintf(dd->err, "Something wrong, node must be in table\n"); 01361 dd->errorCode = CUDD_INTERNAL_ERROR; 01362 return(NULL); 01363 } 01364 /* Derive shortest path length for child. */ 01365 if ((nodeStatNnv->oddTopDist != MAXSHORTINT) && 01366 (nodeStatNnv->oddBotDist != MAXSHORTINT)) { 01367 oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist); 01368 } else { 01369 oddLen = MAXSHORTINT; 01370 } 01371 01372 if ((nodeStatNnv->evenTopDist != MAXSHORTINT) && 01373 (nodeStatNnv->evenBotDist != MAXSHORTINT)) { 01374 evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist); 01375 } else { 01376 evenLen = MAXSHORTINT; 01377 } 01378 01379 NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; 01380 NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist : 01381 nodeStatNnv->evenBotDist; 01382 } 01383 01384 tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0; 01385 /* while both children not processed */ 01386 while (processingDone != 2) { 01387 if (!processingDone) { 01388 /* if no child processed */ 01389 /* pick the child with shortest path length and record which one 01390 * picked 01391 */ 01392 if ((NvPathLength < NnvPathLength) || 01393 ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) { 01394 child = Nv; 01395 regChild = regNv; 01396 thenDone = 1; 01397 childPathLength = NvPathLength; 01398 } else { 01399 child = Nnv; 01400 regChild = regNnv; 01401 elseDone = 1; 01402 childPathLength = NnvPathLength; 01403 } /* then path length less than else path length */ 01404 } else { 01405 /* if one child processed, process the other */ 01406 if (thenDone) { 01407 child = Nnv; 01408 regChild = regNnv; 01409 elseDone = 1; 01410 childPathLength = NnvPathLength; 01411 } else { 01412 child = Nv; 01413 regChild = regNv; 01414 thenDone = 1; 01415 childPathLength = NvPathLength; 01416 } /* end of else pick the Then child if ELSE child processed */ 01417 } /* end of else one child has been processed */ 01418 01419 /* ignore (replace with constant 0) all nodes which lie on paths larger 01420 * than the maximum length of the path required 01421 */ 01422 if (childPathLength > info->maxpath) { 01423 /* record nodes visited */ 01424 childBranch = zero; 01425 } else { 01426 if (childPathLength < info->maxpath) { 01427 if (info->findShortestPath) { 01428 info->findShortestPath = 0; 01429 } 01430 childBranch = BuildSubsetBdd(dd, pathTable, child, info, 01431 subsetNodeTable); 01432 01433 } else { /* Case: path length of node = maxpath */ 01434 /* If the node labeled with maxpath is found in the 01435 ** maxpathTable, use it to build the subset BDD. */ 01436 if (st_lookup(info->maxpathTable, (char *)regChild, 01437 (char **)&entry)) { 01438 /* When a node that is already been chosen is hit, 01439 ** the quest for a complete path is over. */ 01440 if (info->findShortestPath) { 01441 info->findShortestPath = 0; 01442 } 01443 childBranch = BuildSubsetBdd(dd, pathTable, child, info, 01444 subsetNodeTable); 01445 } else { 01446 /* If node is not found in the maxpathTable and 01447 ** the threshold has been reached, then if the 01448 ** path needs to be completed, continue. Else 01449 ** replace the node with a zero. */ 01450 if (info->thresholdReached <= 0) { 01451 if (info->findShortestPath) { 01452 if (st_insert(info->maxpathTable, (char *)regChild, 01453 (char *)NIL(char)) == ST_OUT_OF_MEM) { 01454 memOut = 1; 01455 (void) fprintf(dd->err, "OUT of memory\n"); 01456 info->thresholdReached = 0; 01457 childBranch = zero; 01458 } else { 01459 info->thresholdReached--; 01460 childBranch = BuildSubsetBdd(dd, pathTable, 01461 child, info,subsetNodeTable); 01462 } 01463 } else { /* not find shortest path, we dont need this 01464 node */ 01465 childBranch = zero; 01466 } 01467 } else { /* Threshold hasn't been reached, 01468 ** need the node. */ 01469 if (st_insert(info->maxpathTable, (char *)regChild, 01470 (char *)NIL(char)) == ST_OUT_OF_MEM) { 01471 memOut = 1; 01472 (void) fprintf(dd->err, "OUT of memory\n"); 01473 info->thresholdReached = 0; 01474 childBranch = zero; 01475 } else { 01476 info->thresholdReached--; 01477 if (info->thresholdReached <= 0) { 01478 info->findShortestPath = 1; 01479 } 01480 childBranch = BuildSubsetBdd(dd, pathTable, 01481 child, info, subsetNodeTable); 01482 01483 } /* end of st_insert successful */ 01484 } /* end of threshold hasnt been reached yet */ 01485 } /* end of else node not found in maxpath table */ 01486 } /* end of if (path length of node = maxpath) */ 01487 } /* end if !(childPathLength > maxpath) */ 01488 if (childBranch == NULL) { 01489 /* deref other stuff incase reordering has taken place */ 01490 if (ThenBranch != NULL) { 01491 Cudd_RecursiveDeref(dd, ThenBranch); 01492 ThenBranch = NULL; 01493 } 01494 if (ElseBranch != NULL) { 01495 Cudd_RecursiveDeref(dd, ElseBranch); 01496 ElseBranch = NULL; 01497 } 01498 return(NULL); 01499 } 01500 01501 cuddRef(childBranch); 01502 01503 if (child == Nv) { 01504 ThenBranch = childBranch; 01505 } else { 01506 ElseBranch = childBranch; 01507 } 01508 processingDone++; 01509 01510 } /*end of while processing Nv, Nnv */ 01511 01512 info->findShortestPath = 0; 01513 topid = Cudd_NodeReadIndex(N); 01514 topv = Cudd_ReadVars(dd, topid); 01515 cuddRef(topv); 01516 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); 01517 if (neW != NULL) { 01518 cuddRef(neW); 01519 } 01520 Cudd_RecursiveDeref(dd, topv); 01521 Cudd_RecursiveDeref(dd, ThenBranch); 01522 Cudd_RecursiveDeref(dd, ElseBranch); 01523 01524 01525 /* Hard Limit of threshold has been imposed */ 01526 if (subsetNodeTable != NIL(st_table)) { 01527 /* check if a new node is created */ 01528 regNew = Cudd_Regular(neW); 01529 /* subset node table keeps all new nodes that have been created to keep 01530 * a running count of how many nodes have been built in the subset. 01531 */ 01532 if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) { 01533 if (!Cudd_IsConstant(regNew)) { 01534 if (st_insert(subsetNodeTable, (char *)regNew, 01535 (char *)NULL) == ST_OUT_OF_MEM) { 01536 (void) fprintf(dd->err, "Out of memory\n"); 01537 return (NULL); 01538 } 01539 if (st_count(subsetNodeTable) > info->threshold) { 01540 info->thresholdReached = 0; 01541 } 01542 } 01543 } 01544 } 01545 01546 01547 if (neW == NULL) { 01548 return(NULL); 01549 } else { 01550 /*store computed result in regular form*/ 01551 if (Cudd_IsComplement(node)) { 01552 nodeStat->compResult = neW; 01553 cuddRef(nodeStat->compResult); 01554 /* if the new node is the same as the corresponding node in the 01555 * original bdd then its complement need not be computed as it 01556 * cannot be larger than the node itself 01557 */ 01558 if (neW == node) { 01559 #ifdef DD_DEBUG 01560 thishit++; 01561 #endif 01562 /* if a result for the node has already been computed, then 01563 * it can only be smaller than teh node itself. hence store 01564 * the node result in order not to break recombination 01565 */ 01566 if (nodeStat->regResult != NULL) { 01567 Cudd_RecursiveDeref(dd, nodeStat->regResult); 01568 } 01569 nodeStat->regResult = Cudd_Not(neW); 01570 cuddRef(nodeStat->regResult); 01571 } 01572 01573 } else { 01574 nodeStat->regResult = neW; 01575 cuddRef(nodeStat->regResult); 01576 if (neW == node) { 01577 #ifdef DD_DEBUG 01578 thishit++; 01579 #endif 01580 if (nodeStat->compResult != NULL) { 01581 Cudd_RecursiveDeref(dd, nodeStat->compResult); 01582 } 01583 nodeStat->compResult = Cudd_Not(neW); 01584 cuddRef(nodeStat->compResult); 01585 } 01586 } 01587 01588 cuddDeref(neW); 01589 return(neW); 01590 } /* end of else i.e. Subset != NULL */ 01591 } /* end of BuildSubsetBdd */
static int CreateBotDist | ( | DdNode * | node, | |
st_table * | pathTable, | |||
unsigned int * | pathLengthArray, | |||
FILE * | fp | |||
) | [static] |
Function********************************************************************
Synopsis [ Labels each node with the shortest distance from the constant.]
Description [Labels each node with the shortest distance from the constant. This is done in a DFS search of the BDD. Each node has an odd and even parity distance from the sink (since there exists paths to both zero and one) which is less than MAXSHORTINT. At each node these distances are updated using the minimum distance of its children from the constant. SInce now both the length from the root and child is known, the minimum path length(length of the shortest path between the root and the constant that this node lies on) of this node can be calculated and used to update the pathLengthArray]
SideEffects [Updates Path Table and path length array]
SeeAlso [CreatePathTable CreateTopDist AssessPathLength]
Definition at line 798 of file cuddSubsetSP.c.
00803 { 00804 DdNode *N, *Nv, *Nnv; 00805 DdNode *realChild; 00806 DdNode *child, *regChild; 00807 NodeDist_t *nodeStat, *nodeStatChild; 00808 unsigned int oddLen, evenLen, pathLength; 00809 DdHalfWord botDist; 00810 int processingDone; 00811 00812 if (Cudd_IsConstant(node)) 00813 return(1); 00814 N = Cudd_Regular(node); 00815 /* each node has one table entry */ 00816 /* update as you go down the min dist of each node from 00817 the root in each (odd and even) parity */ 00818 if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { 00819 fprintf(fp, "Something wrong, the entry doesn't exist\n"); 00820 return(0); 00821 } 00822 00823 /* compute length of odd parity distances */ 00824 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00825 (nodeStat->oddBotDist != MAXSHORTINT)) 00826 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00827 else 00828 oddLen = MAXSHORTINT; 00829 00830 /* compute length of even parity distances */ 00831 if (!((nodeStat->evenTopDist == MAXSHORTINT) || 00832 (nodeStat->evenBotDist == MAXSHORTINT))) 00833 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00834 else 00835 evenLen = MAXSHORTINT; 00836 00837 /* assign pathlength to minimum of the two */ 00838 pathLength = (oddLen <= evenLen) ? oddLen : evenLen; 00839 00840 Nv = Cudd_T(N); 00841 Nnv = Cudd_E(N); 00842 00843 /* process each child */ 00844 processingDone = 0; 00845 while (processingDone != 2) { 00846 if (!processingDone) { 00847 child = Nv; 00848 } else { 00849 child = Nnv; 00850 } 00851 00852 realChild = Cudd_NotCond(child, Cudd_IsComplement(node)); 00853 regChild = Cudd_Regular(child); 00854 if (Cudd_IsConstant(realChild)) { 00855 /* Found a minterm; count parity and shortest distance 00856 ** from the constant. 00857 */ 00858 if (Cudd_IsComplement(child)) 00859 nodeStat->oddBotDist = 1; 00860 else 00861 nodeStat->evenBotDist = 1; 00862 } else { 00863 /* If node not in table, recur. */ 00864 if (!st_lookup(pathTable, (char *) regChild, 00865 (char **)&nodeStatChild)) { 00866 fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n"); 00867 return(0); 00868 } 00869 00870 if (nodeStatChild->oddBotDist == MAXSHORTINT) { 00871 if (nodeStatChild->evenBotDist == MAXSHORTINT) { 00872 if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp)) 00873 return(0); 00874 } else { 00875 fprintf(fp, "Something wrong, both bot nodeStats should be there\n"); 00876 return(0); 00877 } 00878 } 00879 00880 /* Update shortest distance from the constant depending on 00881 ** parity. */ 00882 00883 if (Cudd_IsComplement(child)) { 00884 /* If parity on the edge then add 1 to even distance 00885 ** of child to get odd parity distance and add 1 to 00886 ** odd distance of child to get even parity 00887 ** distance. Change distance of current node only if 00888 ** the calculated distance is less than existing 00889 ** distance. */ 00890 if (nodeStatChild->oddBotDist != MAXSHORTINT) 00891 botDist = nodeStatChild->oddBotDist + 1; 00892 else 00893 botDist = MAXSHORTINT; 00894 if (nodeStat->evenBotDist > botDist ) 00895 nodeStat->evenBotDist = botDist; 00896 00897 if (nodeStatChild->evenBotDist != MAXSHORTINT) 00898 botDist = nodeStatChild->evenBotDist + 1; 00899 else 00900 botDist = MAXSHORTINT; 00901 if (nodeStat->oddBotDist > botDist) 00902 nodeStat->oddBotDist = botDist; 00903 00904 } else { 00905 /* If parity on the edge then add 1 to even distance 00906 ** of child to get even parity distance and add 1 to 00907 ** odd distance of child to get odd parity distance. 00908 ** Change distance of current node only if the 00909 ** calculated distance is lesser than existing 00910 ** distance. */ 00911 if (nodeStatChild->evenBotDist != MAXSHORTINT) 00912 botDist = nodeStatChild->evenBotDist + 1; 00913 else 00914 botDist = MAXSHORTINT; 00915 if (nodeStat->evenBotDist > botDist) 00916 nodeStat->evenBotDist = botDist; 00917 00918 if (nodeStatChild->oddBotDist != MAXSHORTINT) 00919 botDist = nodeStatChild->oddBotDist + 1; 00920 else 00921 botDist = MAXSHORTINT; 00922 if (nodeStat->oddBotDist > botDist) 00923 nodeStat->oddBotDist = botDist; 00924 } 00925 } /* end of else (if not constant child ) */ 00926 processingDone++; 00927 } /* end of while processing Nv, Nnv */ 00928 00929 /* Compute shortest path length on the fly. */ 00930 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00931 (nodeStat->oddBotDist != MAXSHORTINT)) 00932 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00933 else 00934 oddLen = MAXSHORTINT; 00935 00936 if ((nodeStat->evenTopDist != MAXSHORTINT) && 00937 (nodeStat->evenBotDist != MAXSHORTINT)) 00938 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00939 else 00940 evenLen = MAXSHORTINT; 00941 00942 /* Update path length array that has number of nodes of a particular 00943 ** path length. */ 00944 if (oddLen < pathLength ) { 00945 if (pathLength != MAXSHORTINT) 00946 pathLengthArray[pathLength]--; 00947 if (oddLen != MAXSHORTINT) 00948 pathLengthArray[oddLen]++; 00949 pathLength = oddLen; 00950 } 00951 if (evenLen < pathLength ) { 00952 if (pathLength != MAXSHORTINT) 00953 pathLengthArray[pathLength]--; 00954 if (evenLen != MAXSHORTINT) 00955 pathLengthArray[evenLen]++; 00956 } 00957 00958 return(1); 00959 00960 } /*end of CreateBotDist */
static st_table* CreatePathTable | ( | DdNode * | node, | |
unsigned int * | pathLengthArray, | |||
FILE * | fp | |||
) | [static] |
Function********************************************************************
Synopsis [ The outer procedure to label each node with its shortest distance from the root and constant]
Description [ The outer procedure to label each node with its shortest distance from the root and constant. Calls CreateTopDist and CreateBotDist. The basis for computing the distance between root and constant is that the distance may be the sum of even distances from the node to the root and constant or the sum of odd distances from the node to the root and constant. Both CreateTopDist and CreateBotDist create the odd and even parity distances from the root and constant respectively.]
SideEffects [None]
SeeAlso [CreateTopDist CreateBotDist]
Definition at line 982 of file cuddSubsetSP.c.
00986 { 00987 00988 st_table *pathTable; 00989 NodeDist_t *nodeStat; 00990 DdHalfWord topLen; 00991 DdNode *N; 00992 int i, numParents; 00993 int insertValue; 00994 DdNode **childPage; 00995 int parentPage; 00996 int childQueueIndex, parentQueueIndex; 00997 00998 /* Creating path Table for storing data about nodes */ 00999 pathTable = st_init_table(st_ptrcmp,st_ptrhash); 01000 01001 /* initializing pages for info about each node */ 01002 maxNodeDistPages = INITIAL_PAGES; 01003 nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages); 01004 if (nodeDistPages == NULL) { 01005 goto OUT_OF_MEM; 01006 } 01007 nodeDistPage = 0; 01008 currentNodeDistPage = nodeDistPages[nodeDistPage] = 01009 ALLOC(NodeDist_t, nodeDistPageSize); 01010 if (currentNodeDistPage == NULL) { 01011 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 01012 FREE(nodeDistPages); 01013 goto OUT_OF_MEM; 01014 } 01015 nodeDistPageIndex = 0; 01016 01017 /* Initializing pages for the BFS search queue, implemented as an array. */ 01018 maxQueuePages = INITIAL_PAGES; 01019 queuePages = ALLOC(DdNode **, maxQueuePages); 01020 if (queuePages == NULL) { 01021 goto OUT_OF_MEM; 01022 } 01023 queuePage = 0; 01024 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize); 01025 if (currentQueuePage == NULL) { 01026 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01027 FREE(queuePages); 01028 goto OUT_OF_MEM; 01029 } 01030 queuePageIndex = 0; 01031 01032 /* Enter the root node into the queue to start with. */ 01033 parentPage = queuePage; 01034 parentQueueIndex = queuePageIndex; 01035 topLen = 0; 01036 *(currentQueuePage + queuePageIndex) = node; 01037 queuePageIndex++; 01038 childPage = currentQueuePage; 01039 childQueueIndex = queuePageIndex; 01040 01041 N = Cudd_Regular(node); 01042 01043 if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); 01044 if (memOut) { 01045 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 01046 FREE(nodeDistPages); 01047 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01048 FREE(queuePages); 01049 st_free_table(pathTable); 01050 goto OUT_OF_MEM; 01051 } 01052 01053 nodeStat = currentNodeDistPage + nodeDistPageIndex; 01054 nodeDistPageIndex++; 01055 01056 nodeStat->oddTopDist = MAXSHORTINT; 01057 nodeStat->evenTopDist = MAXSHORTINT; 01058 nodeStat->evenBotDist = MAXSHORTINT; 01059 nodeStat->oddBotDist = MAXSHORTINT; 01060 nodeStat->regResult = NULL; 01061 nodeStat->compResult = NULL; 01062 01063 insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat); 01064 if (insertValue == ST_OUT_OF_MEM) { 01065 memOut = 1; 01066 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 01067 FREE(nodeDistPages); 01068 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01069 FREE(queuePages); 01070 st_free_table(pathTable); 01071 goto OUT_OF_MEM; 01072 } else if (insertValue == 1) { 01073 fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n"); 01074 return(NULL); 01075 } 01076 01077 if (Cudd_IsComplement(node)) { 01078 nodeStat->oddTopDist = 0; 01079 } else { 01080 nodeStat->evenTopDist = 0; 01081 } 01082 numParents = 1; 01083 /* call the function that counts the distance of each node from the 01084 * root 01085 */ 01086 #ifdef DD_DEBUG 01087 numCalls = 0; 01088 #endif 01089 CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen, 01090 childPage, childQueueIndex, numParents, fp); 01091 if (memOut) { 01092 fprintf(fp, "Out of Memory and cant count path lengths\n"); 01093 goto OUT_OF_MEM; 01094 } 01095 01096 #ifdef DD_DEBUG 01097 numCalls = 0; 01098 #endif 01099 /* call the function that counts the distance of each node from the 01100 * constant 01101 */ 01102 if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL); 01103 01104 /* free BFS queue pages as no longer required */ 01105 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01106 FREE(queuePages); 01107 return(pathTable); 01108 01109 OUT_OF_MEM: 01110 (void) fprintf(fp, "Out of Memory, cannot allocate pages\n"); 01111 memOut = 1; 01112 return(NULL); 01113 01114 } /*end of CreatePathTable */
static void CreateTopDist | ( | st_table * | pathTable, | |
int | parentPage, | |||
int | parentQueueIndex, | |||
int | topLen, | |||
DdNode ** | childPage, | |||
int | childQueueIndex, | |||
int | numParents, | |||
FILE * | fp | |||
) | [static] |
Function********************************************************************
Synopsis [ Labels each node with its shortest distance from the root]
Description [ Labels each node with its shortest distance from the root. This is done in a BFS search of the BDD. The nodes are processed in a queue implemented as pages(array) to reduce memory fragmentation. An entry is created for each node visited. The distance from the root to the node with the corresponding parity is updated. The procedure is called recursively each recusion level handling nodes at a given level from the root.]
SideEffects [Creates entries in the pathTable]
SeeAlso [CreatePathTable CreateBotDist]
Definition at line 597 of file cuddSubsetSP.c.
00606 { 00607 NodeDist_t *nodeStat; 00608 DdNode *N, *Nv, *Nnv, *node, *child, *regChild; 00609 int i; 00610 int processingDone, childrenCount; 00611 00612 #ifdef DD_DEBUG 00613 numCalls++; 00614 00615 /* assume this procedure comes in with only the root node*/ 00616 /* set queue index to the next available entry for addition */ 00617 /* set queue page to page of addition */ 00618 if ((queuePages[parentPage] == childPage) && (parentQueueIndex == 00619 childQueueIndex)) { 00620 fprintf(fp, "Should not happen that they are equal\n"); 00621 } 00622 assert(queuePageIndex == childQueueIndex); 00623 assert(currentQueuePage == childPage); 00624 #endif 00625 /* number children added to queue is initialized , needed for 00626 * numParents in the next call 00627 */ 00628 childrenCount = 0; 00629 /* process all the nodes in this level */ 00630 while (numParents) { 00631 numParents--; 00632 if (parentQueueIndex == queuePageSize) { 00633 parentPage++; 00634 parentQueueIndex = 0; 00635 } 00636 /* a parent to process */ 00637 node = *(queuePages[parentPage] + parentQueueIndex); 00638 parentQueueIndex++; 00639 /* get its children */ 00640 N = Cudd_Regular(node); 00641 Nv = Cudd_T(N); 00642 Nnv = Cudd_E(N); 00643 00644 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 00645 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 00646 00647 processingDone = 2; 00648 while (processingDone) { 00649 /* processing the THEN and the ELSE children, the THEN 00650 * child first 00651 */ 00652 if (processingDone == 2) { 00653 child = Nv; 00654 } else { 00655 child = Nnv; 00656 } 00657 00658 regChild = Cudd_Regular(child); 00659 /* dont process if the child is a constant */ 00660 if (!Cudd_IsConstant(child)) { 00661 /* check is already visited, if not add a new entry in 00662 * the path Table 00663 */ 00664 if (!st_lookup(pathTable, (char *)regChild, (char **)&nodeStat)) { 00665 /* if not in table, has never been visited */ 00666 /* create entry for table */ 00667 if (nodeDistPageIndex == nodeDistPageSize) 00668 ResizeNodeDistPages(); 00669 if (memOut) { 00670 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 00671 FREE(queuePages); 00672 st_free_table(pathTable); 00673 return; 00674 } 00675 /* New entry for child in path Table is created here */ 00676 nodeStat = currentNodeDistPage + nodeDistPageIndex; 00677 nodeDistPageIndex++; 00678 00679 /* Initialize fields of the node data */ 00680 nodeStat->oddTopDist = MAXSHORTINT; 00681 nodeStat->evenTopDist = MAXSHORTINT; 00682 nodeStat->evenBotDist = MAXSHORTINT; 00683 nodeStat->oddBotDist = MAXSHORTINT; 00684 nodeStat->regResult = NULL; 00685 nodeStat->compResult = NULL; 00686 /* update the table entry element, the distance keeps 00687 * track of the parity of the path from the root 00688 */ 00689 if (Cudd_IsComplement(child)) { 00690 nodeStat->oddTopDist = (DdHalfWord) topLen + 1; 00691 } else { 00692 nodeStat->evenTopDist = (DdHalfWord) topLen + 1; 00693 } 00694 00695 /* insert entry element for child in the table */ 00696 if (st_insert(pathTable, (char *)regChild, 00697 (char *)nodeStat) == ST_OUT_OF_MEM) { 00698 memOut = 1; 00699 for (i = 0; i <= nodeDistPage; i++) 00700 FREE(nodeDistPages[i]); 00701 FREE(nodeDistPages); 00702 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 00703 FREE(queuePages); 00704 st_free_table(pathTable); 00705 return; 00706 } 00707 00708 /* Create list element for this child to process its children. 00709 * If this node has been processed already, then it appears 00710 * in the path table and hence is never added to the list 00711 * again. 00712 */ 00713 00714 if (queuePageIndex == queuePageSize) ResizeQueuePages(); 00715 if (memOut) { 00716 for (i = 0; i <= nodeDistPage; i++) 00717 FREE(nodeDistPages[i]); 00718 FREE(nodeDistPages); 00719 st_free_table(pathTable); 00720 return; 00721 } 00722 *(currentQueuePage + queuePageIndex) = child; 00723 queuePageIndex++; 00724 00725 childrenCount++; 00726 } else { 00727 /* if not been met in a path with this parity before */ 00728 /* put in list */ 00729 if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist == 00730 MAXSHORTINT)) || ((!Cudd_IsComplement(child)) && 00731 (nodeStat->evenTopDist == MAXSHORTINT))) { 00732 00733 if (queuePageIndex == queuePageSize) ResizeQueuePages(); 00734 if (memOut) { 00735 for (i = 0; i <= nodeDistPage; i++) 00736 FREE(nodeDistPages[i]); 00737 FREE(nodeDistPages); 00738 st_free_table(pathTable); 00739 return; 00740 00741 } 00742 *(currentQueuePage + queuePageIndex) = child; 00743 queuePageIndex++; 00744 00745 /* update the distance with the appropriate parity */ 00746 if (Cudd_IsComplement(child)) { 00747 nodeStat->oddTopDist = (DdHalfWord) topLen + 1; 00748 } else { 00749 nodeStat->evenTopDist = (DdHalfWord) topLen + 1; 00750 } 00751 childrenCount++; 00752 } 00753 00754 } /* end of else (not found in st_table) */ 00755 } /*end of if Not constant child */ 00756 processingDone--; 00757 } /*end of while processing Nv, Nnv */ 00758 } /*end of while numParents */ 00759 00760 #ifdef DD_DEBUG 00761 assert(queuePages[parentPage] == childPage); 00762 assert(parentQueueIndex == childQueueIndex); 00763 #endif 00764 00765 if (childrenCount != 0) { 00766 topLen++; 00767 childPage = currentQueuePage; 00768 childQueueIndex = queuePageIndex; 00769 CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen, 00770 childPage, childQueueIndex, childrenCount, fp); 00771 } 00772 00773 return; 00774 00775 } /* end of CreateTopDist */
DdNode* Cudd_SubsetShortPaths | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | numVars, | |||
int | threshold, | |||
int | hardlimit | |||
) |
AutomaticEnd Function********************************************************************
Synopsis [Extracts a dense subset from a BDD with the shortest paths heuristic.]
Description [Extracts a dense subset from a BDD. This procedure tries to preserve the shortest paths of the input BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the subset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the subset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVars. If 0 is passed, then the value returned by Cudd_ReadSize is used.]
SideEffects [None]
SeeAlso [Cudd_SupersetShortPaths Cudd_SubsetHeavyBranch Cudd_ReadSize]
Definition at line 182 of file cuddSubsetSP.c.
00187 : 1 if threshold is a hard limit */) 00188 { 00189 DdNode *subset; 00190 00191 memOut = 0; 00192 do { 00193 dd->reordered = 0; 00194 subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit); 00195 } while((dd->reordered ==1) && (!memOut)); 00196 00197 return(subset); 00198 00199 } /* end of Cudd_SubsetShortPaths */
DdNode* Cudd_SupersetShortPaths | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | numVars, | |||
int | threshold, | |||
int | hardlimit | |||
) |
Function********************************************************************
Synopsis [Extracts a dense superset from a BDD with the shortest paths 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 tries to preserve the shortest paths of the complement BDD, because they give many minterms and contribute few nodes. This procedure may increase the number of nodes in trying to create the superset or reduce the number of nodes due to recombination as compared to the original BDD. Hence the threshold may not be strictly adhered to. In practice, recombination overshadows the increase in the number of nodes and results in small BDDs as compared to the threshold. The hardlimit specifies whether threshold needs to be strictly adhered to. If it is set to 1, the procedure ensures that result is never larger than the specified limit but may be considerably less than the threshold. Returns a pointer to the BDD for the superset if successful; NULL otherwise. The value for numVars should be as close as possible to the size of the support of f for better efficiency. However, it is safe to pass the value returned by Cudd_ReadSize for numVar. If 0 is passed, then the value returned by Cudd_ReadSize is used.]
SideEffects [None]
SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]
Definition at line 234 of file cuddSubsetSP.c.
00239 : 1 if threshold is a hard limit */) 00240 { 00241 DdNode *subset, *g; 00242 00243 g = Cudd_Not(f); 00244 memOut = 0; 00245 do { 00246 dd->reordered = 0; 00247 subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit); 00248 } while((dd->reordered ==1) && (!memOut)); 00249 00250 return(Cudd_NotCond(subset, (subset != NULL))); 00251 00252 } /* end of Cudd_SupersetShortPaths */
DdNode* cuddSubsetShortPaths | ( | DdManager * | dd, | |
DdNode * | f, | |||
int | numVars, | |||
int | threshold, | |||
int | hardlimit | |||
) |
Function********************************************************************
Synopsis [The outermost procedure to return a subset of the given BDD with the shortest path lengths.]
Description [The outermost procedure to return a subset of the given BDD with the largest cubes. The path lengths are calculated, the maximum allowable path length is determined and the number of nodes of this path length that can be used to build a subset. If the threshold is larger than the size of the original BDD, the original BDD is returned. ]
SideEffects [None]
SeeAlso [Cudd_SubsetShortPaths]
Definition at line 278 of file cuddSubsetSP.c.
00284 { 00285 st_table *pathTable; 00286 DdNode *N, *subset; 00287 00288 unsigned int *pathLengthArray; 00289 unsigned int maxpath, oddLen, evenLen, pathLength, *excess; 00290 int i; 00291 NodeDist_t *nodeStat; 00292 struct AssortedInfo *info; 00293 st_table *subsetNodeTable; 00294 00295 one = DD_ONE(dd); 00296 zero = Cudd_Not(one); 00297 00298 if (numVars == 0) { 00299 /* set default value */ 00300 numVars = Cudd_ReadSize(dd); 00301 } 00302 00303 if (threshold > numVars) { 00304 threshold = threshold - numVars; 00305 } 00306 if (f == NULL) { 00307 fprintf(dd->err, "Cannot partition, nil object\n"); 00308 dd->errorCode = CUDD_INVALID_ARG; 00309 return(NULL); 00310 } 00311 if (Cudd_IsConstant(f)) 00312 return (f); 00313 00314 pathLengthArray = ALLOC(unsigned int, numVars+1); 00315 for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; 00316 00317 00318 #ifdef DD_DEBUG 00319 numCalls = 0; 00320 #endif 00321 00322 pathTable = CreatePathTable(f, pathLengthArray, dd->err); 00323 00324 if ((pathTable == NULL) || (memOut)) { 00325 if (pathTable != NULL) 00326 st_free_table(pathTable); 00327 FREE(pathLengthArray); 00328 return (NIL(DdNode)); 00329 } 00330 00331 excess = ALLOC(unsigned int, 1); 00332 *excess = 0; 00333 maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, 00334 dd->err); 00335 00336 if (maxpath != (unsigned) (numVars + 1)) { 00337 00338 info = ALLOC(struct AssortedInfo, 1); 00339 info->maxpath = maxpath; 00340 info->findShortestPath = 0; 00341 info->thresholdReached = *excess; 00342 info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash); 00343 info->threshold = threshold; 00344 00345 #ifdef DD_DEBUG 00346 (void) fprintf(dd->out, "Path length array\n"); 00347 for (i = 0; i < (numVars+1); i++) { 00348 if (pathLengthArray[i]) 00349 (void) fprintf(dd->out, "%d ",i); 00350 } 00351 (void) fprintf(dd->out, "\n"); 00352 for (i = 0; i < (numVars+1); i++) { 00353 if (pathLengthArray[i]) 00354 (void) fprintf(dd->out, "%d ",pathLengthArray[i]); 00355 } 00356 (void) fprintf(dd->out, "\n"); 00357 (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", 00358 maxpath, info->thresholdReached); 00359 #endif 00360 00361 N = Cudd_Regular(f); 00362 if (!st_lookup(pathTable, (char *)N, (char **)&nodeStat)) { 00363 fprintf(dd->err, "Something wrong, root node must be in table\n"); 00364 dd->errorCode = CUDD_INTERNAL_ERROR; 00365 return(NULL); 00366 } else { 00367 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00368 (nodeStat->oddBotDist != MAXSHORTINT)) 00369 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00370 else 00371 oddLen = MAXSHORTINT; 00372 00373 if ((nodeStat->evenTopDist != MAXSHORTINT) && 00374 (nodeStat->evenBotDist != MAXSHORTINT)) 00375 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00376 else 00377 evenLen = MAXSHORTINT; 00378 00379 pathLength = (oddLen <= evenLen) ? oddLen : evenLen; 00380 if (pathLength > maxpath) { 00381 (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %d, %d\n", maxpath, pathLength); 00382 dd->errorCode = CUDD_INTERNAL_ERROR; 00383 return(NULL); 00384 } 00385 } 00386 00387 #ifdef DD_DEBUG 00388 numCalls = 0; 00389 hits = 0; 00390 thishit = 0; 00391 #endif 00392 /* initialize a table to store computed nodes */ 00393 if (hardlimit) { 00394 subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash); 00395 } else { 00396 subsetNodeTable = NIL(st_table); 00397 } 00398 subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); 00399 if (subset != NULL) { 00400 cuddRef(subset); 00401 } 00402 /* record the number of times a computed result for a node is hit */ 00403 00404 #ifdef DD_DEBUG 00405 (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", 00406 hits, thishit, numCalls); 00407 #endif 00408 00409 if (subsetNodeTable != NIL(st_table)) { 00410 st_free_table(subsetNodeTable); 00411 } 00412 st_free_table(info->maxpathTable); 00413 st_foreach(pathTable, stPathTableDdFree, (char *)dd); 00414 00415 FREE(info); 00416 00417 } else {/* if threshold larger than size of dd */ 00418 subset = f; 00419 cuddRef(subset); 00420 } 00421 FREE(excess); 00422 st_free_table(pathTable); 00423 FREE(pathLengthArray); 00424 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 00425 FREE(nodeDistPages); 00426 00427 #ifdef DD_DEBUG 00428 /* check containment of subset in f */ 00429 if (subset != NULL) { 00430 DdNode *check; 00431 check = Cudd_bddIteConstant(dd, subset, f, one); 00432 if (check != one) { 00433 (void) fprintf(dd->err, "Wrong partition\n"); 00434 dd->errorCode = CUDD_INTERNAL_ERROR; 00435 return(NULL); 00436 } 00437 } 00438 #endif 00439 00440 if (subset != NULL) { 00441 cuddDeref(subset); 00442 return(subset); 00443 } else { 00444 return(NULL); 00445 } 00446 00447 } /* end of cuddSubsetShortPaths */
static void ResizeNodeDistPages | ( | ) | [static] |
Function********************************************************************
Synopsis [Resize the number of pages allocated to store the distances related to each node.]
Description [Resize the number of pages allocated to store the distances related to each node. 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 472 of file cuddSubsetSP.c.
00474 { 00475 int i; 00476 NodeDist_t **newNodeDistPages; 00477 00478 /* move to next page */ 00479 nodeDistPage++; 00480 00481 /* If the current page index is larger than the number of pages 00482 * allocated, allocate a new page array. Page numbers are incremented by 00483 * INITIAL_PAGES 00484 */ 00485 if (nodeDistPage == maxNodeDistPages) { 00486 newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); 00487 if (newNodeDistPages == NULL) { 00488 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); 00489 FREE(nodeDistPages); 00490 memOut = 1; 00491 return; 00492 } else { 00493 for (i = 0; i < maxNodeDistPages; i++) { 00494 newNodeDistPages[i] = nodeDistPages[i]; 00495 } 00496 /* Increase total page count */ 00497 maxNodeDistPages += INITIAL_PAGES; 00498 FREE(nodeDistPages); 00499 nodeDistPages = newNodeDistPages; 00500 } 00501 } 00502 /* Allocate a new page */ 00503 currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t, 00504 nodeDistPageSize); 00505 if (currentNodeDistPage == NULL) { 00506 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); 00507 FREE(nodeDistPages); 00508 memOut = 1; 00509 return; 00510 } 00511 /* reset page index */ 00512 nodeDistPageIndex = 0; 00513 return; 00514 00515 } /* end of ResizeNodeDistPages */
static void ResizeQueuePages | ( | ) | [static] |
Function********************************************************************
Synopsis [Resize the number of pages allocated to store nodes in the BFS traversal of the Bdd .]
Description [Resize the number of pages allocated to store nodes in the BFS traversal of the Bdd. 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 535 of file cuddSubsetSP.c.
00537 { 00538 int i; 00539 DdNode ***newQueuePages; 00540 00541 queuePage++; 00542 /* If the current page index is larger than the number of pages 00543 * allocated, allocate a new page array. Page numbers are incremented by 00544 * INITIAL_PAGES 00545 */ 00546 if (queuePage == maxQueuePages) { 00547 newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); 00548 if (newQueuePages == NULL) { 00549 for (i = 0; i < queuePage; i++) FREE(queuePages[i]); 00550 FREE(queuePages); 00551 memOut = 1; 00552 return; 00553 } else { 00554 for (i = 0; i < maxQueuePages; i++) { 00555 newQueuePages[i] = queuePages[i]; 00556 } 00557 /* Increase total page count */ 00558 maxQueuePages += INITIAL_PAGES; 00559 FREE(queuePages); 00560 queuePages = newQueuePages; 00561 } 00562 } 00563 /* Allocate a new page */ 00564 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize); 00565 if (currentQueuePage == NULL) { 00566 for (i = 0; i < queuePage; i++) FREE(queuePages[i]); 00567 FREE(queuePages); 00568 memOut = 1; 00569 return; 00570 } 00571 /* reset page index */ 00572 queuePageIndex = 0; 00573 return; 00574 00575 } /* end of ResizeQueuePages */
static enum st_retval stPathTableDdFree | ( | char * | key, | |
char * | value, | |||
char * | arg | |||
) | [static] |
Function********************************************************************
Synopsis [Procedure to free te result dds stored in the NodeDist pages.]
Description [None]
SideEffects [None]
SeeAlso []
Definition at line 1606 of file cuddSubsetSP.c.
01610 { 01611 NodeDist_t *nodeStat; 01612 DdManager *dd; 01613 01614 nodeStat = (NodeDist_t *)value; 01615 dd = (DdManager *)arg; 01616 if (nodeStat->regResult != NULL) { 01617 Cudd_RecursiveDeref(dd, nodeStat->regResult); 01618 } 01619 if (nodeStat->compResult != NULL) { 01620 Cudd_RecursiveDeref(dd, nodeStat->compResult); 01621 } 01622 return(ST_CONTINUE); 01623 01624 } /* end of stPathTableFree */
NodeDist_t* currentNodeDistPage [static] |
Definition at line 116 of file cuddSubsetSP.c.
DdNode** currentQueuePage [static] |
Definition at line 123 of file cuddSubsetSP.c.
char rcsid [] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static] |
Definition at line 98 of file cuddSubsetSP.c.
int maxNodeDistPages [static] |
Definition at line 115 of file cuddSubsetSP.c.
int maxQueuePages [static] |
Definition at line 122 of file cuddSubsetSP.c.
int memOut [static] |
Definition at line 108 of file cuddSubsetSP.c.
int nodeDistPage [static] |
Definition at line 113 of file cuddSubsetSP.c.
int nodeDistPageIndex [static] |
Definition at line 112 of file cuddSubsetSP.c.
NodeDist_t** nodeDistPages [static] |
Definition at line 111 of file cuddSubsetSP.c.
int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE [static] |
Definition at line 114 of file cuddSubsetSP.c.
Definition at line 109 of file cuddSubsetSP.c.
int queuePage [static] |
Definition at line 120 of file cuddSubsetSP.c.
int queuePageIndex [static] |
Definition at line 119 of file cuddSubsetSP.c.
DdNode*** queuePages [static] |
Definition at line 118 of file cuddSubsetSP.c.
int queuePageSize = DEFAULT_PAGE_SIZE [static] |
Definition at line 121 of file cuddSubsetSP.c.
Definition at line 109 of file cuddSubsetSP.c.