src/bdd/cudd/cuddSubsetSP.c File Reference

#include "util_hack.h"
#include "cuddInt.h"
Include dependency graph for cuddSubsetSP.c:

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))
DdNodeCudd_SubsetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
DdNodeCudd_SupersetShortPaths (DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
DdNodecuddSubsetShortPaths (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_tableCreatePathTable (DdNode *node, unsigned int *pathLengthArray, FILE *fp)
static unsigned int AssessPathLength (unsigned int *pathLengthArray, int threshold, int numVars, unsigned int *excess, FILE *fp)
static DdNodeBuildSubsetBdd (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 DdNodezero
static DdNodeone
static NodeDist_t ** nodeDistPages
static int nodeDistPageIndex
static int nodeDistPage
static int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE
static int maxNodeDistPages
static NodeDist_tcurrentNodeDistPage
static DdNode *** queuePages
static int queuePageIndex
static int queuePage
static int queuePageSize = DEFAULT_PAGE_SIZE
static int maxQueuePages
static DdNode ** currentQueuePage

Define Documentation

#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 Documentation

typedef struct NodeDist NodeDist_t

Definition at line 91 of file cuddSubsetSP.c.


Function Documentation

static enum st_retval stPathTableDdFree ARGS ( (char *key, char *value, char *arg)   )  [static]
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 */


Variable Documentation

Definition at line 116 of file cuddSubsetSP.c.

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.

Definition at line 111 of file cuddSubsetSP.c.

int nodeDistPageSize = DEFAULT_NODE_DIST_PAGE_SIZE [static]

Definition at line 114 of file cuddSubsetSP.c.

DdNode * one [static]

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.

DdNode* zero [static]

Definition at line 109 of file cuddSubsetSP.c.


Generated on Tue Jan 5 12:18:56 2010 for abc70930 by  doxygen 1.6.1