src/cuBdd/cuddSubsetSP.c File Reference

#include "util.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 (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_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)
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)

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

typedef struct NodeDist NodeDist_t

Definition at line 118 of file cuddSubsetSP.c.


Function Documentation

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 */


Variable Documentation

Definition at line 143 of file cuddSubsetSP.c.

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.

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.

DdNode * one [static]

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.

DdNode* zero [static]

Definition at line 136 of file cuddSubsetSP.c.


Generated on Tue Jan 12 13:57:21 2010 for glu-2.2 by  doxygen 1.6.1