#include "util.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 (void) |
static void | ResizeQueuePages (void) |
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) |
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) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.34 2009/02/19 16:23:19 fabio Exp $" |
static int | numCalls |
static int | hits |
static int | thishit |
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 79 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 [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 78 of file cuddSubsetSP.c.
#define INITIAL_PAGES 128 |
Definition at line 85 of file cuddSubsetSP.c.
#define MAXSHORTINT ((DdHalfWord) ~0) |
Definition at line 80 of file cuddSubsetSP.c.
typedef struct NodeDist NodeDist_t |
Definition at line 118 of file cuddSubsetSP.c.
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 1167 of file cuddSubsetSP.c.
01173 { 01174 unsigned int i, maxpath; 01175 int temp; 01176 01177 temp = threshold; 01178 i = 0; 01179 maxpath = 0; 01180 /* quit loop if i reaches max number of variables or if temp reaches 01181 * below zero 01182 */ 01183 while ((i < (unsigned) numVars+1) && (temp > 0)) { 01184 if (pathLengthArray[i] > 0) { 01185 maxpath = i; 01186 temp = temp - pathLengthArray[i]; 01187 } 01188 i++; 01189 } 01190 /* if all nodes of max path are needed */ 01191 if (temp >= 0) { 01192 maxpath++; /* now maxpath becomes the next maxppath or max number 01193 of variables */ 01194 *excess = 0; 01195 } else { /* normal case when subset required is less than size of 01196 original BDD */ 01197 *excess = temp + pathLengthArray[maxpath]; 01198 } 01199 01200 if (maxpath == 0) { 01201 fprintf(fp, "Path Length array seems to be all zeroes, check\n"); 01202 } 01203 return(maxpath); 01204 01205 } /* 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 1251 of file cuddSubsetSP.c.
01257 { 01258 DdNode *N, *Nv, *Nnv; 01259 DdNode *ThenBranch, *ElseBranch, *childBranch; 01260 DdNode *child, *regChild, *regNnv, *regNv; 01261 NodeDist_t *nodeStatNv, *nodeStat, *nodeStatNnv; 01262 DdNode *neW, *topv, *regNew; 01263 char *entry; 01264 unsigned int topid; 01265 unsigned int childPathLength, oddLen, evenLen, NnvPathLength, NvPathLength; 01266 unsigned int NvBotDist, NnvBotDist; 01267 int tiebreakChild; 01268 int processingDone, thenDone, elseDone; 01269 01270 01271 #ifdef DD_DEBUG 01272 numCalls++; 01273 #endif 01274 if (Cudd_IsConstant(node)) 01275 return(node); 01276 01277 N = Cudd_Regular(node); 01278 /* Find node in table. */ 01279 if (!st_lookup(pathTable, N, &nodeStat)) { 01280 (void) fprintf(dd->err, "Something wrong, node must be in table \n"); 01281 dd->errorCode = CUDD_INTERNAL_ERROR; 01282 return(NULL); 01283 } 01284 /* If the node in the table has been visited, then return the corresponding 01285 ** Dd. Since a node can become a subset of itself, its 01286 ** complement (that is te same node reached by a different parity) will 01287 ** become a superset of the original node and result in some minterms 01288 ** that were not in the original set. Hence two different results are 01289 ** maintained, corresponding to the odd and even parities. 01290 */ 01291 01292 /* If this node is reached with an odd parity, get odd parity results. */ 01293 if (Cudd_IsComplement(node)) { 01294 if (nodeStat->compResult != NULL) { 01295 #ifdef DD_DEBUG 01296 hits++; 01297 #endif 01298 return(nodeStat->compResult); 01299 } 01300 } else { 01301 /* if this node is reached with an even parity, get even parity 01302 * results 01303 */ 01304 if (nodeStat->regResult != NULL) { 01305 #ifdef DD_DEBUG 01306 hits++; 01307 #endif 01308 return(nodeStat->regResult); 01309 } 01310 } 01311 01312 01313 /* get children */ 01314 Nv = Cudd_T(N); 01315 Nnv = Cudd_E(N); 01316 01317 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 01318 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 01319 01320 /* no child processed */ 01321 processingDone = 0; 01322 /* then child not processed */ 01323 thenDone = 0; 01324 ThenBranch = NULL; 01325 /* else child not processed */ 01326 elseDone = 0; 01327 ElseBranch = NULL; 01328 /* if then child constant, branch is the child */ 01329 if (Cudd_IsConstant(Nv)) { 01330 /*shortest path found */ 01331 if ((Nv == DD_ONE(dd)) && (info->findShortestPath)) { 01332 info->findShortestPath = 0; 01333 } 01334 01335 ThenBranch = Nv; 01336 cuddRef(ThenBranch); 01337 if (ThenBranch == NULL) { 01338 return(NULL); 01339 } 01340 01341 thenDone++; 01342 processingDone++; 01343 NvBotDist = MAXSHORTINT; 01344 } else { 01345 /* Derive regular child for table lookup. */ 01346 regNv = Cudd_Regular(Nv); 01347 /* Get node data for shortest path length. */ 01348 if (!st_lookup(pathTable, regNv, &nodeStatNv) ) { 01349 (void) fprintf(dd->err, "Something wrong, node must be in table\n"); 01350 dd->errorCode = CUDD_INTERNAL_ERROR; 01351 return(NULL); 01352 } 01353 /* Derive shortest path length for child. */ 01354 if ((nodeStatNv->oddTopDist != MAXSHORTINT) && 01355 (nodeStatNv->oddBotDist != MAXSHORTINT)) { 01356 oddLen = (nodeStatNv->oddTopDist + nodeStatNv->oddBotDist); 01357 } else { 01358 oddLen = MAXSHORTINT; 01359 } 01360 01361 if ((nodeStatNv->evenTopDist != MAXSHORTINT) && 01362 (nodeStatNv->evenBotDist != MAXSHORTINT)) { 01363 evenLen = (nodeStatNv->evenTopDist +nodeStatNv->evenBotDist); 01364 } else { 01365 evenLen = MAXSHORTINT; 01366 } 01367 01368 NvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; 01369 NvBotDist = (oddLen <= evenLen) ? nodeStatNv->oddBotDist: 01370 nodeStatNv->evenBotDist; 01371 } 01372 /* if else child constant, branch is the child */ 01373 if (Cudd_IsConstant(Nnv)) { 01374 /*shortest path found */ 01375 if ((Nnv == DD_ONE(dd)) && (info->findShortestPath)) { 01376 info->findShortestPath = 0; 01377 } 01378 01379 ElseBranch = Nnv; 01380 cuddRef(ElseBranch); 01381 if (ElseBranch == NULL) { 01382 return(NULL); 01383 } 01384 01385 elseDone++; 01386 processingDone++; 01387 NnvBotDist = MAXSHORTINT; 01388 } else { 01389 /* Derive regular child for table lookup. */ 01390 regNnv = Cudd_Regular(Nnv); 01391 /* Get node data for shortest path length. */ 01392 if (!st_lookup(pathTable, regNnv, &nodeStatNnv) ) { 01393 (void) fprintf(dd->err, "Something wrong, node must be in table\n"); 01394 dd->errorCode = CUDD_INTERNAL_ERROR; 01395 return(NULL); 01396 } 01397 /* Derive shortest path length for child. */ 01398 if ((nodeStatNnv->oddTopDist != MAXSHORTINT) && 01399 (nodeStatNnv->oddBotDist != MAXSHORTINT)) { 01400 oddLen = (nodeStatNnv->oddTopDist + nodeStatNnv->oddBotDist); 01401 } else { 01402 oddLen = MAXSHORTINT; 01403 } 01404 01405 if ((nodeStatNnv->evenTopDist != MAXSHORTINT) && 01406 (nodeStatNnv->evenBotDist != MAXSHORTINT)) { 01407 evenLen = (nodeStatNnv->evenTopDist +nodeStatNnv->evenBotDist); 01408 } else { 01409 evenLen = MAXSHORTINT; 01410 } 01411 01412 NnvPathLength = (oddLen <= evenLen) ? oddLen : evenLen; 01413 NnvBotDist = (oddLen <= evenLen) ? nodeStatNnv->oddBotDist : 01414 nodeStatNnv->evenBotDist; 01415 } 01416 01417 tiebreakChild = (NvBotDist <= NnvBotDist) ? 1 : 0; 01418 /* while both children not processed */ 01419 while (processingDone != 2) { 01420 if (!processingDone) { 01421 /* if no child processed */ 01422 /* pick the child with shortest path length and record which one 01423 * picked 01424 */ 01425 if ((NvPathLength < NnvPathLength) || 01426 ((NvPathLength == NnvPathLength) && (tiebreakChild == 1))) { 01427 child = Nv; 01428 regChild = regNv; 01429 thenDone = 1; 01430 childPathLength = NvPathLength; 01431 } else { 01432 child = Nnv; 01433 regChild = regNnv; 01434 elseDone = 1; 01435 childPathLength = NnvPathLength; 01436 } /* then path length less than else path length */ 01437 } else { 01438 /* if one child processed, process the other */ 01439 if (thenDone) { 01440 child = Nnv; 01441 regChild = regNnv; 01442 elseDone = 1; 01443 childPathLength = NnvPathLength; 01444 } else { 01445 child = Nv; 01446 regChild = regNv; 01447 thenDone = 1; 01448 childPathLength = NvPathLength; 01449 } /* end of else pick the Then child if ELSE child processed */ 01450 } /* end of else one child has been processed */ 01451 01452 /* ignore (replace with constant 0) all nodes which lie on paths larger 01453 * than the maximum length of the path required 01454 */ 01455 if (childPathLength > info->maxpath) { 01456 /* record nodes visited */ 01457 childBranch = zero; 01458 } else { 01459 if (childPathLength < info->maxpath) { 01460 if (info->findShortestPath) { 01461 info->findShortestPath = 0; 01462 } 01463 childBranch = BuildSubsetBdd(dd, pathTable, child, info, 01464 subsetNodeTable); 01465 01466 } else { /* Case: path length of node = maxpath */ 01467 /* If the node labeled with maxpath is found in the 01468 ** maxpathTable, use it to build the subset BDD. */ 01469 if (st_lookup(info->maxpathTable, (char *)regChild, 01470 (char **)&entry)) { 01471 /* When a node that is already been chosen is hit, 01472 ** the quest for a complete path is over. */ 01473 if (info->findShortestPath) { 01474 info->findShortestPath = 0; 01475 } 01476 childBranch = BuildSubsetBdd(dd, pathTable, child, info, 01477 subsetNodeTable); 01478 } else { 01479 /* If node is not found in the maxpathTable and 01480 ** the threshold has been reached, then if the 01481 ** path needs to be completed, continue. Else 01482 ** replace the node with a zero. */ 01483 if (info->thresholdReached <= 0) { 01484 if (info->findShortestPath) { 01485 if (st_insert(info->maxpathTable, (char *)regChild, 01486 (char *)NIL(char)) == ST_OUT_OF_MEM) { 01487 memOut = 1; 01488 (void) fprintf(dd->err, "OUT of memory\n"); 01489 info->thresholdReached = 0; 01490 childBranch = zero; 01491 } else { 01492 info->thresholdReached--; 01493 childBranch = BuildSubsetBdd(dd, pathTable, 01494 child, info,subsetNodeTable); 01495 } 01496 } else { /* not find shortest path, we dont need this 01497 node */ 01498 childBranch = zero; 01499 } 01500 } else { /* Threshold hasn't been reached, 01501 ** need the node. */ 01502 if (st_insert(info->maxpathTable, (char *)regChild, 01503 (char *)NIL(char)) == ST_OUT_OF_MEM) { 01504 memOut = 1; 01505 (void) fprintf(dd->err, "OUT of memory\n"); 01506 info->thresholdReached = 0; 01507 childBranch = zero; 01508 } else { 01509 info->thresholdReached--; 01510 if (info->thresholdReached <= 0) { 01511 info->findShortestPath = 1; 01512 } 01513 childBranch = BuildSubsetBdd(dd, pathTable, 01514 child, info, subsetNodeTable); 01515 01516 } /* end of st_insert successful */ 01517 } /* end of threshold hasnt been reached yet */ 01518 } /* end of else node not found in maxpath table */ 01519 } /* end of if (path length of node = maxpath) */ 01520 } /* end if !(childPathLength > maxpath) */ 01521 if (childBranch == NULL) { 01522 /* deref other stuff incase reordering has taken place */ 01523 if (ThenBranch != NULL) { 01524 Cudd_RecursiveDeref(dd, ThenBranch); 01525 ThenBranch = NULL; 01526 } 01527 if (ElseBranch != NULL) { 01528 Cudd_RecursiveDeref(dd, ElseBranch); 01529 ElseBranch = NULL; 01530 } 01531 return(NULL); 01532 } 01533 01534 cuddRef(childBranch); 01535 01536 if (child == Nv) { 01537 ThenBranch = childBranch; 01538 } else { 01539 ElseBranch = childBranch; 01540 } 01541 processingDone++; 01542 01543 } /*end of while processing Nv, Nnv */ 01544 01545 info->findShortestPath = 0; 01546 topid = Cudd_NodeReadIndex(N); 01547 topv = Cudd_ReadVars(dd, topid); 01548 cuddRef(topv); 01549 neW = cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch); 01550 if (neW != NULL) { 01551 cuddRef(neW); 01552 } 01553 Cudd_RecursiveDeref(dd, topv); 01554 Cudd_RecursiveDeref(dd, ThenBranch); 01555 Cudd_RecursiveDeref(dd, ElseBranch); 01556 01557 01558 /* Hard Limit of threshold has been imposed */ 01559 if (subsetNodeTable != NIL(st_table)) { 01560 /* check if a new node is created */ 01561 regNew = Cudd_Regular(neW); 01562 /* subset node table keeps all new nodes that have been created to keep 01563 * a running count of how many nodes have been built in the subset. 01564 */ 01565 if (!st_lookup(subsetNodeTable, (char *)regNew, (char **)&entry)) { 01566 if (!Cudd_IsConstant(regNew)) { 01567 if (st_insert(subsetNodeTable, (char *)regNew, 01568 (char *)NULL) == ST_OUT_OF_MEM) { 01569 (void) fprintf(dd->err, "Out of memory\n"); 01570 return (NULL); 01571 } 01572 if (st_count(subsetNodeTable) > info->threshold) { 01573 info->thresholdReached = 0; 01574 } 01575 } 01576 } 01577 } 01578 01579 01580 if (neW == NULL) { 01581 return(NULL); 01582 } else { 01583 /*store computed result in regular form*/ 01584 if (Cudd_IsComplement(node)) { 01585 nodeStat->compResult = neW; 01586 cuddRef(nodeStat->compResult); 01587 /* if the new node is the same as the corresponding node in the 01588 * original bdd then its complement need not be computed as it 01589 * cannot be larger than the node itself 01590 */ 01591 if (neW == node) { 01592 #ifdef DD_DEBUG 01593 thishit++; 01594 #endif 01595 /* if a result for the node has already been computed, then 01596 * it can only be smaller than teh node itself. hence store 01597 * the node result in order not to break recombination 01598 */ 01599 if (nodeStat->regResult != NULL) { 01600 Cudd_RecursiveDeref(dd, nodeStat->regResult); 01601 } 01602 nodeStat->regResult = Cudd_Not(neW); 01603 cuddRef(nodeStat->regResult); 01604 } 01605 01606 } else { 01607 nodeStat->regResult = neW; 01608 cuddRef(nodeStat->regResult); 01609 if (neW == node) { 01610 #ifdef DD_DEBUG 01611 thishit++; 01612 #endif 01613 if (nodeStat->compResult != NULL) { 01614 Cudd_RecursiveDeref(dd, nodeStat->compResult); 01615 } 01616 nodeStat->compResult = Cudd_Not(neW); 01617 cuddRef(nodeStat->compResult); 01618 } 01619 } 01620 01621 cuddDeref(neW); 01622 return(neW); 01623 } /* end of else i.e. Subset != NULL */ 01624 } /* 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 832 of file cuddSubsetSP.c.
00837 { 00838 DdNode *N, *Nv, *Nnv; 00839 DdNode *realChild; 00840 DdNode *child, *regChild; 00841 NodeDist_t *nodeStat, *nodeStatChild; 00842 unsigned int oddLen, evenLen, pathLength; 00843 DdHalfWord botDist; 00844 int processingDone; 00845 00846 if (Cudd_IsConstant(node)) 00847 return(1); 00848 N = Cudd_Regular(node); 00849 /* each node has one table entry */ 00850 /* update as you go down the min dist of each node from 00851 the root in each (odd and even) parity */ 00852 if (!st_lookup(pathTable, N, &nodeStat)) { 00853 fprintf(fp, "Something wrong, the entry doesn't exist\n"); 00854 return(0); 00855 } 00856 00857 /* compute length of odd parity distances */ 00858 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00859 (nodeStat->oddBotDist != MAXSHORTINT)) 00860 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00861 else 00862 oddLen = MAXSHORTINT; 00863 00864 /* compute length of even parity distances */ 00865 if (!((nodeStat->evenTopDist == MAXSHORTINT) || 00866 (nodeStat->evenBotDist == MAXSHORTINT))) 00867 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00868 else 00869 evenLen = MAXSHORTINT; 00870 00871 /* assign pathlength to minimum of the two */ 00872 pathLength = (oddLen <= evenLen) ? oddLen : evenLen; 00873 00874 Nv = Cudd_T(N); 00875 Nnv = Cudd_E(N); 00876 00877 /* process each child */ 00878 processingDone = 0; 00879 while (processingDone != 2) { 00880 if (!processingDone) { 00881 child = Nv; 00882 } else { 00883 child = Nnv; 00884 } 00885 00886 realChild = Cudd_NotCond(child, Cudd_IsComplement(node)); 00887 regChild = Cudd_Regular(child); 00888 if (Cudd_IsConstant(realChild)) { 00889 /* Found a minterm; count parity and shortest distance 00890 ** from the constant. 00891 */ 00892 if (Cudd_IsComplement(child)) 00893 nodeStat->oddBotDist = 1; 00894 else 00895 nodeStat->evenBotDist = 1; 00896 } else { 00897 /* If node not in table, recur. */ 00898 if (!st_lookup(pathTable, regChild, &nodeStatChild)) { 00899 fprintf(fp, "Something wrong, node in table should have been created in top dist proc.\n"); 00900 return(0); 00901 } 00902 00903 if (nodeStatChild->oddBotDist == MAXSHORTINT) { 00904 if (nodeStatChild->evenBotDist == MAXSHORTINT) { 00905 if (!CreateBotDist(realChild, pathTable, pathLengthArray, fp)) 00906 return(0); 00907 } else { 00908 fprintf(fp, "Something wrong, both bot nodeStats should be there\n"); 00909 return(0); 00910 } 00911 } 00912 00913 /* Update shortest distance from the constant depending on 00914 ** parity. */ 00915 00916 if (Cudd_IsComplement(child)) { 00917 /* If parity on the edge then add 1 to even distance 00918 ** of child to get odd parity distance and add 1 to 00919 ** odd distance of child to get even parity 00920 ** distance. Change distance of current node only if 00921 ** the calculated distance is less than existing 00922 ** distance. */ 00923 if (nodeStatChild->oddBotDist != MAXSHORTINT) 00924 botDist = nodeStatChild->oddBotDist + 1; 00925 else 00926 botDist = MAXSHORTINT; 00927 if (nodeStat->evenBotDist > botDist ) 00928 nodeStat->evenBotDist = botDist; 00929 00930 if (nodeStatChild->evenBotDist != MAXSHORTINT) 00931 botDist = nodeStatChild->evenBotDist + 1; 00932 else 00933 botDist = MAXSHORTINT; 00934 if (nodeStat->oddBotDist > botDist) 00935 nodeStat->oddBotDist = botDist; 00936 00937 } else { 00938 /* If parity on the edge then add 1 to even distance 00939 ** of child to get even parity distance and add 1 to 00940 ** odd distance of child to get odd parity distance. 00941 ** Change distance of current node only if the 00942 ** calculated distance is lesser than existing 00943 ** distance. */ 00944 if (nodeStatChild->evenBotDist != MAXSHORTINT) 00945 botDist = nodeStatChild->evenBotDist + 1; 00946 else 00947 botDist = MAXSHORTINT; 00948 if (nodeStat->evenBotDist > botDist) 00949 nodeStat->evenBotDist = botDist; 00950 00951 if (nodeStatChild->oddBotDist != MAXSHORTINT) 00952 botDist = nodeStatChild->oddBotDist + 1; 00953 else 00954 botDist = MAXSHORTINT; 00955 if (nodeStat->oddBotDist > botDist) 00956 nodeStat->oddBotDist = botDist; 00957 } 00958 } /* end of else (if not constant child ) */ 00959 processingDone++; 00960 } /* end of while processing Nv, Nnv */ 00961 00962 /* Compute shortest path length on the fly. */ 00963 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00964 (nodeStat->oddBotDist != MAXSHORTINT)) 00965 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00966 else 00967 oddLen = MAXSHORTINT; 00968 00969 if ((nodeStat->evenTopDist != MAXSHORTINT) && 00970 (nodeStat->evenBotDist != MAXSHORTINT)) 00971 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00972 else 00973 evenLen = MAXSHORTINT; 00974 00975 /* Update path length array that has number of nodes of a particular 00976 ** path length. */ 00977 if (oddLen < pathLength ) { 00978 if (pathLength != MAXSHORTINT) 00979 pathLengthArray[pathLength]--; 00980 if (oddLen != MAXSHORTINT) 00981 pathLengthArray[oddLen]++; 00982 pathLength = oddLen; 00983 } 00984 if (evenLen < pathLength ) { 00985 if (pathLength != MAXSHORTINT) 00986 pathLengthArray[pathLength]--; 00987 if (evenLen != MAXSHORTINT) 00988 pathLengthArray[evenLen]++; 00989 } 00990 00991 return(1); 00992 00993 } /*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 1015 of file cuddSubsetSP.c.
01019 { 01020 01021 st_table *pathTable; 01022 NodeDist_t *nodeStat; 01023 DdHalfWord topLen; 01024 DdNode *N; 01025 int i, numParents; 01026 int insertValue; 01027 DdNode **childPage; 01028 int parentPage; 01029 int childQueueIndex, parentQueueIndex; 01030 01031 /* Creating path Table for storing data about nodes */ 01032 pathTable = st_init_table(st_ptrcmp,st_ptrhash); 01033 01034 /* initializing pages for info about each node */ 01035 maxNodeDistPages = INITIAL_PAGES; 01036 nodeDistPages = ALLOC(NodeDist_t *, maxNodeDistPages); 01037 if (nodeDistPages == NULL) { 01038 goto OUT_OF_MEM; 01039 } 01040 nodeDistPage = 0; 01041 currentNodeDistPage = nodeDistPages[nodeDistPage] = 01042 ALLOC(NodeDist_t, nodeDistPageSize); 01043 if (currentNodeDistPage == NULL) { 01044 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 01045 FREE(nodeDistPages); 01046 goto OUT_OF_MEM; 01047 } 01048 nodeDistPageIndex = 0; 01049 01050 /* Initializing pages for the BFS search queue, implemented as an array. */ 01051 maxQueuePages = INITIAL_PAGES; 01052 queuePages = ALLOC(DdNode **, maxQueuePages); 01053 if (queuePages == NULL) { 01054 goto OUT_OF_MEM; 01055 } 01056 queuePage = 0; 01057 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *, queuePageSize); 01058 if (currentQueuePage == NULL) { 01059 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01060 FREE(queuePages); 01061 goto OUT_OF_MEM; 01062 } 01063 queuePageIndex = 0; 01064 01065 /* Enter the root node into the queue to start with. */ 01066 parentPage = queuePage; 01067 parentQueueIndex = queuePageIndex; 01068 topLen = 0; 01069 *(currentQueuePage + queuePageIndex) = node; 01070 queuePageIndex++; 01071 childPage = currentQueuePage; 01072 childQueueIndex = queuePageIndex; 01073 01074 N = Cudd_Regular(node); 01075 01076 if (nodeDistPageIndex == nodeDistPageSize) ResizeNodeDistPages(); 01077 if (memOut) { 01078 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 01079 FREE(nodeDistPages); 01080 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01081 FREE(queuePages); 01082 st_free_table(pathTable); 01083 goto OUT_OF_MEM; 01084 } 01085 01086 nodeStat = currentNodeDistPage + nodeDistPageIndex; 01087 nodeDistPageIndex++; 01088 01089 nodeStat->oddTopDist = MAXSHORTINT; 01090 nodeStat->evenTopDist = MAXSHORTINT; 01091 nodeStat->evenBotDist = MAXSHORTINT; 01092 nodeStat->oddBotDist = MAXSHORTINT; 01093 nodeStat->regResult = NULL; 01094 nodeStat->compResult = NULL; 01095 01096 insertValue = st_insert(pathTable, (char *)N, (char *)nodeStat); 01097 if (insertValue == ST_OUT_OF_MEM) { 01098 memOut = 1; 01099 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 01100 FREE(nodeDistPages); 01101 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01102 FREE(queuePages); 01103 st_free_table(pathTable); 01104 goto OUT_OF_MEM; 01105 } else if (insertValue == 1) { 01106 fprintf(fp, "Something wrong, the entry exists but didnt show up in st_lookup\n"); 01107 return(NULL); 01108 } 01109 01110 if (Cudd_IsComplement(node)) { 01111 nodeStat->oddTopDist = 0; 01112 } else { 01113 nodeStat->evenTopDist = 0; 01114 } 01115 numParents = 1; 01116 /* call the function that counts the distance of each node from the 01117 * root 01118 */ 01119 #ifdef DD_DEBUG 01120 numCalls = 0; 01121 #endif 01122 CreateTopDist(pathTable, parentPage, parentQueueIndex, (int) topLen, 01123 childPage, childQueueIndex, numParents, fp); 01124 if (memOut) { 01125 fprintf(fp, "Out of Memory and cant count path lengths\n"); 01126 goto OUT_OF_MEM; 01127 } 01128 01129 #ifdef DD_DEBUG 01130 numCalls = 0; 01131 #endif 01132 /* call the function that counts the distance of each node from the 01133 * constant 01134 */ 01135 if (!CreateBotDist(node, pathTable, pathLengthArray, fp)) return(NULL); 01136 01137 /* free BFS queue pages as no longer required */ 01138 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 01139 FREE(queuePages); 01140 return(pathTable); 01141 01142 OUT_OF_MEM: 01143 (void) fprintf(fp, "Out of Memory, cannot allocate pages\n"); 01144 memOut = 1; 01145 return(NULL); 01146 01147 } /*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 631 of file cuddSubsetSP.c.
00640 { 00641 NodeDist_t *nodeStat; 00642 DdNode *N, *Nv, *Nnv, *node, *child, *regChild; 00643 int i; 00644 int processingDone, childrenCount; 00645 00646 #ifdef DD_DEBUG 00647 numCalls++; 00648 00649 /* assume this procedure comes in with only the root node*/ 00650 /* set queue index to the next available entry for addition */ 00651 /* set queue page to page of addition */ 00652 if ((queuePages[parentPage] == childPage) && (parentQueueIndex == 00653 childQueueIndex)) { 00654 fprintf(fp, "Should not happen that they are equal\n"); 00655 } 00656 assert(queuePageIndex == childQueueIndex); 00657 assert(currentQueuePage == childPage); 00658 #endif 00659 /* number children added to queue is initialized , needed for 00660 * numParents in the next call 00661 */ 00662 childrenCount = 0; 00663 /* process all the nodes in this level */ 00664 while (numParents) { 00665 numParents--; 00666 if (parentQueueIndex == queuePageSize) { 00667 parentPage++; 00668 parentQueueIndex = 0; 00669 } 00670 /* a parent to process */ 00671 node = *(queuePages[parentPage] + parentQueueIndex); 00672 parentQueueIndex++; 00673 /* get its children */ 00674 N = Cudd_Regular(node); 00675 Nv = Cudd_T(N); 00676 Nnv = Cudd_E(N); 00677 00678 Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node)); 00679 Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node)); 00680 00681 processingDone = 2; 00682 while (processingDone) { 00683 /* processing the THEN and the ELSE children, the THEN 00684 * child first 00685 */ 00686 if (processingDone == 2) { 00687 child = Nv; 00688 } else { 00689 child = Nnv; 00690 } 00691 00692 regChild = Cudd_Regular(child); 00693 /* dont process if the child is a constant */ 00694 if (!Cudd_IsConstant(child)) { 00695 /* check is already visited, if not add a new entry in 00696 * the path Table 00697 */ 00698 if (!st_lookup(pathTable, regChild, &nodeStat)) { 00699 /* if not in table, has never been visited */ 00700 /* create entry for table */ 00701 if (nodeDistPageIndex == nodeDistPageSize) 00702 ResizeNodeDistPages(); 00703 if (memOut) { 00704 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 00705 FREE(queuePages); 00706 st_free_table(pathTable); 00707 return; 00708 } 00709 /* New entry for child in path Table is created here */ 00710 nodeStat = currentNodeDistPage + nodeDistPageIndex; 00711 nodeDistPageIndex++; 00712 00713 /* Initialize fields of the node data */ 00714 nodeStat->oddTopDist = MAXSHORTINT; 00715 nodeStat->evenTopDist = MAXSHORTINT; 00716 nodeStat->evenBotDist = MAXSHORTINT; 00717 nodeStat->oddBotDist = MAXSHORTINT; 00718 nodeStat->regResult = NULL; 00719 nodeStat->compResult = NULL; 00720 /* update the table entry element, the distance keeps 00721 * track of the parity of the path from the root 00722 */ 00723 if (Cudd_IsComplement(child)) { 00724 nodeStat->oddTopDist = (DdHalfWord) topLen + 1; 00725 } else { 00726 nodeStat->evenTopDist = (DdHalfWord) topLen + 1; 00727 } 00728 00729 /* insert entry element for child in the table */ 00730 if (st_insert(pathTable, (char *)regChild, 00731 (char *)nodeStat) == ST_OUT_OF_MEM) { 00732 memOut = 1; 00733 for (i = 0; i <= nodeDistPage; i++) 00734 FREE(nodeDistPages[i]); 00735 FREE(nodeDistPages); 00736 for (i = 0; i <= queuePage; i++) FREE(queuePages[i]); 00737 FREE(queuePages); 00738 st_free_table(pathTable); 00739 return; 00740 } 00741 00742 /* Create list element for this child to process its children. 00743 * If this node has been processed already, then it appears 00744 * in the path table and hence is never added to the list 00745 * again. 00746 */ 00747 00748 if (queuePageIndex == queuePageSize) ResizeQueuePages(); 00749 if (memOut) { 00750 for (i = 0; i <= nodeDistPage; i++) 00751 FREE(nodeDistPages[i]); 00752 FREE(nodeDistPages); 00753 st_free_table(pathTable); 00754 return; 00755 } 00756 *(currentQueuePage + queuePageIndex) = child; 00757 queuePageIndex++; 00758 00759 childrenCount++; 00760 } else { 00761 /* if not been met in a path with this parity before */ 00762 /* put in list */ 00763 if (((Cudd_IsComplement(child)) && (nodeStat->oddTopDist == 00764 MAXSHORTINT)) || ((!Cudd_IsComplement(child)) && 00765 (nodeStat->evenTopDist == MAXSHORTINT))) { 00766 00767 if (queuePageIndex == queuePageSize) ResizeQueuePages(); 00768 if (memOut) { 00769 for (i = 0; i <= nodeDistPage; i++) 00770 FREE(nodeDistPages[i]); 00771 FREE(nodeDistPages); 00772 st_free_table(pathTable); 00773 return; 00774 00775 } 00776 *(currentQueuePage + queuePageIndex) = child; 00777 queuePageIndex++; 00778 00779 /* update the distance with the appropriate parity */ 00780 if (Cudd_IsComplement(child)) { 00781 nodeStat->oddTopDist = (DdHalfWord) topLen + 1; 00782 } else { 00783 nodeStat->evenTopDist = (DdHalfWord) topLen + 1; 00784 } 00785 childrenCount++; 00786 } 00787 00788 } /* end of else (not found in st_table) */ 00789 } /*end of if Not constant child */ 00790 processingDone--; 00791 } /*end of while processing Nv, Nnv */ 00792 } /*end of while numParents */ 00793 00794 #ifdef DD_DEBUG 00795 assert(queuePages[parentPage] == childPage); 00796 assert(parentQueueIndex == childQueueIndex); 00797 #endif 00798 00799 if (childrenCount != 0) { 00800 topLen++; 00801 childPage = currentQueuePage; 00802 childQueueIndex = queuePageIndex; 00803 CreateTopDist(pathTable, parentPage, parentQueueIndex, topLen, 00804 childPage, childQueueIndex, childrenCount, fp); 00805 } 00806 00807 return; 00808 00809 } /* 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 216 of file cuddSubsetSP.c.
00221 : 1 if threshold is a hard limit */) 00222 { 00223 DdNode *subset; 00224 00225 memOut = 0; 00226 do { 00227 dd->reordered = 0; 00228 subset = cuddSubsetShortPaths(dd, f, numVars, threshold, hardlimit); 00229 } while((dd->reordered ==1) && (!memOut)); 00230 00231 return(subset); 00232 00233 } /* 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 268 of file cuddSubsetSP.c.
00273 : 1 if threshold is a hard limit */) 00274 { 00275 DdNode *subset, *g; 00276 00277 g = Cudd_Not(f); 00278 memOut = 0; 00279 do { 00280 dd->reordered = 0; 00281 subset = cuddSubsetShortPaths(dd, g, numVars, threshold, hardlimit); 00282 } while((dd->reordered ==1) && (!memOut)); 00283 00284 return(Cudd_NotCond(subset, (subset != NULL))); 00285 00286 } /* 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 312 of file cuddSubsetSP.c.
00318 { 00319 st_table *pathTable; 00320 DdNode *N, *subset; 00321 00322 unsigned int *pathLengthArray; 00323 unsigned int maxpath, oddLen, evenLen, pathLength, *excess; 00324 int i; 00325 NodeDist_t *nodeStat; 00326 struct AssortedInfo *info; 00327 st_table *subsetNodeTable; 00328 00329 one = DD_ONE(dd); 00330 zero = Cudd_Not(one); 00331 00332 if (numVars == 0) { 00333 /* set default value */ 00334 numVars = Cudd_ReadSize(dd); 00335 } 00336 00337 if (threshold > numVars) { 00338 threshold = threshold - numVars; 00339 } 00340 if (f == NULL) { 00341 fprintf(dd->err, "Cannot partition, nil object\n"); 00342 dd->errorCode = CUDD_INVALID_ARG; 00343 return(NULL); 00344 } 00345 if (Cudd_IsConstant(f)) 00346 return (f); 00347 00348 pathLengthArray = ALLOC(unsigned int, numVars+1); 00349 for (i = 0; i < numVars+1; i++) pathLengthArray[i] = 0; 00350 00351 00352 #ifdef DD_DEBUG 00353 numCalls = 0; 00354 #endif 00355 00356 pathTable = CreatePathTable(f, pathLengthArray, dd->err); 00357 00358 if ((pathTable == NULL) || (memOut)) { 00359 if (pathTable != NULL) 00360 st_free_table(pathTable); 00361 FREE(pathLengthArray); 00362 return (NIL(DdNode)); 00363 } 00364 00365 excess = ALLOC(unsigned int, 1); 00366 *excess = 0; 00367 maxpath = AssessPathLength(pathLengthArray, threshold, numVars, excess, 00368 dd->err); 00369 00370 if (maxpath != (unsigned) (numVars + 1)) { 00371 00372 info = ALLOC(struct AssortedInfo, 1); 00373 info->maxpath = maxpath; 00374 info->findShortestPath = 0; 00375 info->thresholdReached = *excess; 00376 info->maxpathTable = st_init_table(st_ptrcmp, st_ptrhash); 00377 info->threshold = threshold; 00378 00379 #ifdef DD_DEBUG 00380 (void) fprintf(dd->out, "Path length array\n"); 00381 for (i = 0; i < (numVars+1); i++) { 00382 if (pathLengthArray[i]) 00383 (void) fprintf(dd->out, "%d ",i); 00384 } 00385 (void) fprintf(dd->out, "\n"); 00386 for (i = 0; i < (numVars+1); i++) { 00387 if (pathLengthArray[i]) 00388 (void) fprintf(dd->out, "%d ",pathLengthArray[i]); 00389 } 00390 (void) fprintf(dd->out, "\n"); 00391 (void) fprintf(dd->out, "Maxpath = %d, Thresholdreached = %d\n", 00392 maxpath, info->thresholdReached); 00393 #endif 00394 00395 N = Cudd_Regular(f); 00396 if (!st_lookup(pathTable, N, &nodeStat)) { 00397 fprintf(dd->err, "Something wrong, root node must be in table\n"); 00398 dd->errorCode = CUDD_INTERNAL_ERROR; 00399 FREE(excess); 00400 FREE(info); 00401 return(NULL); 00402 } else { 00403 if ((nodeStat->oddTopDist != MAXSHORTINT) && 00404 (nodeStat->oddBotDist != MAXSHORTINT)) 00405 oddLen = (nodeStat->oddTopDist + nodeStat->oddBotDist); 00406 else 00407 oddLen = MAXSHORTINT; 00408 00409 if ((nodeStat->evenTopDist != MAXSHORTINT) && 00410 (nodeStat->evenBotDist != MAXSHORTINT)) 00411 evenLen = (nodeStat->evenTopDist +nodeStat->evenBotDist); 00412 else 00413 evenLen = MAXSHORTINT; 00414 00415 pathLength = (oddLen <= evenLen) ? oddLen : evenLen; 00416 if (pathLength > maxpath) { 00417 (void) fprintf(dd->err, "All computations are bogus, since root has path length greater than max path length within threshold %u, %u\n", maxpath, pathLength); 00418 dd->errorCode = CUDD_INTERNAL_ERROR; 00419 return(NULL); 00420 } 00421 } 00422 00423 #ifdef DD_DEBUG 00424 numCalls = 0; 00425 hits = 0; 00426 thishit = 0; 00427 #endif 00428 /* initialize a table to store computed nodes */ 00429 if (hardlimit) { 00430 subsetNodeTable = st_init_table(st_ptrcmp, st_ptrhash); 00431 } else { 00432 subsetNodeTable = NIL(st_table); 00433 } 00434 subset = BuildSubsetBdd(dd, pathTable, f, info, subsetNodeTable); 00435 if (subset != NULL) { 00436 cuddRef(subset); 00437 } 00438 /* record the number of times a computed result for a node is hit */ 00439 00440 #ifdef DD_DEBUG 00441 (void) fprintf(dd->out, "Hits = %d, New==Node = %d, NumCalls = %d\n", 00442 hits, thishit, numCalls); 00443 #endif 00444 00445 if (subsetNodeTable != NIL(st_table)) { 00446 st_free_table(subsetNodeTable); 00447 } 00448 st_free_table(info->maxpathTable); 00449 st_foreach(pathTable, stPathTableDdFree, (char *)dd); 00450 00451 FREE(info); 00452 00453 } else {/* if threshold larger than size of dd */ 00454 subset = f; 00455 cuddRef(subset); 00456 } 00457 FREE(excess); 00458 st_free_table(pathTable); 00459 FREE(pathLengthArray); 00460 for (i = 0; i <= nodeDistPage; i++) FREE(nodeDistPages[i]); 00461 FREE(nodeDistPages); 00462 00463 #ifdef DD_DEBUG 00464 /* check containment of subset in f */ 00465 if (subset != NULL) { 00466 DdNode *check; 00467 check = Cudd_bddIteConstant(dd, subset, f, one); 00468 if (check != one) { 00469 (void) fprintf(dd->err, "Wrong partition\n"); 00470 dd->errorCode = CUDD_INTERNAL_ERROR; 00471 return(NULL); 00472 } 00473 } 00474 #endif 00475 00476 if (subset != NULL) { 00477 cuddDeref(subset); 00478 return(subset); 00479 } else { 00480 return(NULL); 00481 } 00482 00483 } /* end of cuddSubsetShortPaths */
static void ResizeNodeDistPages | ( | void | ) | [static] |
AutomaticStart
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 508 of file cuddSubsetSP.c.
00509 { 00510 int i; 00511 NodeDist_t **newNodeDistPages; 00512 00513 /* move to next page */ 00514 nodeDistPage++; 00515 00516 /* If the current page index is larger than the number of pages 00517 * allocated, allocate a new page array. Page numbers are incremented by 00518 * INITIAL_PAGES 00519 */ 00520 if (nodeDistPage == maxNodeDistPages) { 00521 newNodeDistPages = ALLOC(NodeDist_t *,maxNodeDistPages + INITIAL_PAGES); 00522 if (newNodeDistPages == NULL) { 00523 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); 00524 FREE(nodeDistPages); 00525 memOut = 1; 00526 return; 00527 } else { 00528 for (i = 0; i < maxNodeDistPages; i++) { 00529 newNodeDistPages[i] = nodeDistPages[i]; 00530 } 00531 /* Increase total page count */ 00532 maxNodeDistPages += INITIAL_PAGES; 00533 FREE(nodeDistPages); 00534 nodeDistPages = newNodeDistPages; 00535 } 00536 } 00537 /* Allocate a new page */ 00538 currentNodeDistPage = nodeDistPages[nodeDistPage] = ALLOC(NodeDist_t, 00539 nodeDistPageSize); 00540 if (currentNodeDistPage == NULL) { 00541 for (i = 0; i < nodeDistPage; i++) FREE(nodeDistPages[i]); 00542 FREE(nodeDistPages); 00543 memOut = 1; 00544 return; 00545 } 00546 /* reset page index */ 00547 nodeDistPageIndex = 0; 00548 return; 00549 00550 } /* end of ResizeNodeDistPages */
static void ResizeQueuePages | ( | void | ) | [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 570 of file cuddSubsetSP.c.
00571 { 00572 int i; 00573 DdNode ***newQueuePages; 00574 00575 queuePage++; 00576 /* If the current page index is larger than the number of pages 00577 * allocated, allocate a new page array. Page numbers are incremented by 00578 * INITIAL_PAGES 00579 */ 00580 if (queuePage == maxQueuePages) { 00581 newQueuePages = ALLOC(DdNode **,maxQueuePages + INITIAL_PAGES); 00582 if (newQueuePages == NULL) { 00583 for (i = 0; i < queuePage; i++) FREE(queuePages[i]); 00584 FREE(queuePages); 00585 memOut = 1; 00586 return; 00587 } else { 00588 for (i = 0; i < maxQueuePages; i++) { 00589 newQueuePages[i] = queuePages[i]; 00590 } 00591 /* Increase total page count */ 00592 maxQueuePages += INITIAL_PAGES; 00593 FREE(queuePages); 00594 queuePages = newQueuePages; 00595 } 00596 } 00597 /* Allocate a new page */ 00598 currentQueuePage = queuePages[queuePage] = ALLOC(DdNode *,queuePageSize); 00599 if (currentQueuePage == NULL) { 00600 for (i = 0; i < queuePage; i++) FREE(queuePages[i]); 00601 FREE(queuePages); 00602 memOut = 1; 00603 return; 00604 } 00605 /* reset page index */ 00606 queuePageIndex = 0; 00607 return; 00608 00609 } /* 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 1639 of file cuddSubsetSP.c.
01643 { 01644 NodeDist_t *nodeStat; 01645 DdManager *dd; 01646 01647 nodeStat = (NodeDist_t *)value; 01648 dd = (DdManager *)arg; 01649 if (nodeStat->regResult != NULL) { 01650 Cudd_RecursiveDeref(dd, nodeStat->regResult); 01651 } 01652 if (nodeStat->compResult != NULL) { 01653 Cudd_RecursiveDeref(dd, nodeStat->compResult); 01654 } 01655 return(ST_CONTINUE); 01656 01657 } /* end of stPathTableFree */
NodeDist_t* currentNodeDistPage [static] |
Definition at line 143 of file cuddSubsetSP.c.
DdNode** currentQueuePage [static] |
Definition at line 150 of file cuddSubsetSP.c.
char rcsid [] DD_UNUSED = "$Id: cuddSubsetSP.c,v 1.34 2009/02/19 16:23:19 fabio Exp $" [static] |
Definition at line 125 of file cuddSubsetSP.c.
int hits [static] |
Definition at line 130 of file cuddSubsetSP.c.
int maxNodeDistPages [static] |
Definition at line 142 of file cuddSubsetSP.c.
int maxQueuePages [static] |
Definition at line 149 of file cuddSubsetSP.c.
int memOut [static] |
Definition at line 135 of file cuddSubsetSP.c.
int nodeDistPage [static] |
Definition at line 140 of file cuddSubsetSP.c.
int nodeDistPageIndex [static] |
Definition at line 139 of file cuddSubsetSP.c.
NodeDist_t** nodeDistPages [static] |
Definition at line 138 of file cuddSubsetSP.c.
int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE [static] |
Definition at line 141 of file cuddSubsetSP.c.
int numCalls [static] |
Definition at line 129 of file cuddSubsetSP.c.
Definition at line 136 of file cuddSubsetSP.c.
int queuePage [static] |
Definition at line 147 of file cuddSubsetSP.c.
int queuePageIndex [static] |
Definition at line 146 of file cuddSubsetSP.c.
DdNode*** queuePages [static] |
Definition at line 145 of file cuddSubsetSP.c.
int queuePageSize = DEFAULT_PAGE_SIZE [static] |
Definition at line 148 of file cuddSubsetSP.c.
int thishit [static] |
Definition at line 131 of file cuddSubsetSP.c.
Definition at line 136 of file cuddSubsetSP.c.