src/bdd/cudd/cuddSubsetHB.c File Reference

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

Go to the source code of this file.

Data Structures

struct  NodeData

Defines

#define DBL_MAX_EXP   1024
#define DEFAULT_PAGE_SIZE   2048
#define DEFAULT_NODE_DATA_PAGE_SIZE   1024
#define INITIAL_PAGES   128

Typedefs

typedef struct NodeData NodeData_t

Functions

static void ResizeNodeDataPages ARGS (())
static double SubsetCountMintermAux ARGS ((DdNode *node, double max, st_table *table))
static st_table *SubsetCountMinterm ARGS ((DdNode *node, int nvars))
static int SubsetCountNodesAux ARGS ((DdNode *node, st_table *table, double max))
static int SubsetCountNodes ARGS ((DdNode *node, st_table *table, int nvars))
static void StoreNodes ARGS ((st_table *storeTable, DdManager *dd, DdNode *node))
static DdNode *BuildSubsetBdd ARGS ((DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable))
DdNodeCudd_SubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold)
DdNodeCudd_SupersetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold)
DdNodecuddSubsetHeavyBranch (DdManager *dd, DdNode *f, int numVars, int threshold)
static void ResizeNodeDataPages ()
static void ResizeCountMintermPages ()
static void ResizeCountNodePages ()
static double SubsetCountMintermAux (DdNode *node, double max, st_table *table)
static st_tableSubsetCountMinterm (DdNode *node, int nvars)
static int SubsetCountNodesAux (DdNode *node, st_table *table, double max)
static int SubsetCountNodes (DdNode *node, st_table *table, int nvars)
static void StoreNodes (st_table *storeTable, DdManager *dd, DdNode *node)
static DdNodeBuildSubsetBdd (DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $"
static int memOut
static DdNodezero
static DdNodeone
static double ** mintermPages
static int ** nodePages
static int ** lightNodePages
static double * currentMintermPage
static double max
static int * currentNodePage
static int * currentLightNodePage
static int pageIndex
static int page
static int pageSize = DEFAULT_PAGE_SIZE
static int maxPages
static NodeData_tcurrentNodeDataPage
static int nodeDataPage
static int nodeDataPageIndex
static NodeData_t ** nodeDataPages
static int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE
static int maxNodeDataPages

Define Documentation

#define DBL_MAX_EXP   1024

CFile***********************************************************************

FileName [cuddSubsetHB.c]

PackageName [cudd]

Synopsis [Procedure to subset the given BDD by choosing the heavier branches]

Description [External procedures provided by this module:

Internal procedures included in this module:

Static procedures included in this module:

]

SeeAlso [cuddSubsetSP.c]

Author [Kavita Ravi]

Copyright [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 47 of file cuddSubsetHB.c.

#define DEFAULT_NODE_DATA_PAGE_SIZE   1024

Definition at line 57 of file cuddSubsetHB.c.

#define DEFAULT_PAGE_SIZE   2048

Definition at line 56 of file cuddSubsetHB.c.

#define INITIAL_PAGES   128

Definition at line 58 of file cuddSubsetHB.c.


Typedef Documentation

typedef struct NodeData NodeData_t

Definition at line 82 of file cuddSubsetHB.c.


Function Documentation

static DdNode* BuildSubsetBdd ARGS ( (DdManager *dd, DdNode *node, int *size, st_table *visitedTable, int threshold, st_table *storeTable, st_table *approxTable)   )  [static]
static void StoreNodes ARGS ( (st_table *storeTable, DdManager *dd, DdNode *node)   )  [static]
static int SubsetCountNodes ARGS ( (DdNode *node, st_table *table, int nvars)   )  [static]
static int SubsetCountNodesAux ARGS ( (DdNode *node, st_table *table, double max  )  [static]
static st_table* SubsetCountMinterm ARGS ( (DdNode *node, int nvars)   )  [static]
static double SubsetCountMintermAux ARGS ( (DdNode *node, double max, st_table *table)   )  [static]
static void ResizeNodeDataPages ARGS ( ()   )  [static]

AutomaticStart

static DdNode* BuildSubsetBdd ( DdManager dd,
DdNode node,
int *  size,
st_table visitedTable,
int  threshold,
st_table storeTable,
st_table approxTable 
) [static]

Function********************************************************************

Synopsis [Builds the subset BDD using the heavy branch method.]

Description [The procedure carries out the building of the subset BDD starting at the root. Using the three different counts labelling each node, the procedure chooses the heavier branch starting from the root and keeps track of the number of nodes it discards at each step, thus keeping count of the size of the subset BDD dynamically. Once the threshold is satisfied, the procedure then calls ITE to build the BDD.]

SideEffects [None]

SeeAlso []

Definition at line 1135 of file cuddSubsetHB.c.

01143 {
01144 
01145     DdNode *Nv, *Nnv, *N, *topv, *neW;
01146     double minNv, minNnv;
01147     NodeData_t *currNodeQual;
01148     NodeData_t *currNodeQualT;
01149     NodeData_t *currNodeQualE;
01150     DdNode *ThenBranch, *ElseBranch;
01151     unsigned int topid;
01152     char *dummy;
01153 
01154 #ifdef DEBUG
01155     num_calls++;
01156 #endif
01157     /*If the size of the subset is below the threshold, dont do
01158       anything. */
01159     if ((*size) <= threshold) {
01160       /* store nodes below this, so we can recombine if possible */
01161       StoreNodes(storeTable, dd, node);
01162       return(node);
01163     }
01164 
01165     if (Cudd_IsConstant(node))
01166         return(node);
01167 
01168     /* Look up minterm count for this node. */
01169     if (!st_lookup(visitedTable, (char *)node, (char **)&currNodeQual)) {
01170         fprintf(dd->err,
01171                 "Something is wrong, ought to be in node quality table\n");
01172     }
01173 
01174     /* Get children. */
01175     N = Cudd_Regular(node);
01176     Nv = Cudd_T(N);
01177     Nnv = Cudd_E(N);
01178 
01179     /* complement if necessary */
01180     Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
01181     Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
01182 
01183     if (!Cudd_IsConstant(Nv)) {
01184         /* find out minterms and nodes contributed by then child */
01185         if (!st_lookup(visitedTable, (char *)Nv,
01186                        (char **)&currNodeQualT)) {
01187                 fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
01188                 dd->errorCode = CUDD_INTERNAL_ERROR;
01189                 return(NULL);
01190             }
01191         else {
01192             minNv = *(((NodeData_t *)currNodeQualT)->mintermPointer);
01193         }
01194     } else {
01195         if (Nv == zero) {
01196             minNv = 0;
01197         } else  {
01198             minNv = max;
01199         }
01200     }
01201     if (!Cudd_IsConstant(Nnv)) {
01202         /* find out minterms and nodes contributed by else child */
01203         if (!st_lookup(visitedTable, (char *)Nnv, (char **)&currNodeQualE)) {
01204             fprintf(dd->out,"Something wrong, couldnt find nodes in node quality table\n");
01205             dd->errorCode = CUDD_INTERNAL_ERROR;
01206             return(NULL);
01207         } else {
01208             minNnv = *(((NodeData_t *)currNodeQualE)->mintermPointer);
01209         }
01210     } else {
01211         if (Nnv == zero) {
01212             minNnv = 0;
01213         } else {
01214             minNnv = max;
01215         }
01216     }
01217 
01218     /* keep track of size of subset by subtracting the number of
01219      * differential nodes contributed by lighter child
01220      */
01221     *size = (*(size)) - (int)*(currNodeQual->lightChildNodesPointer);
01222     if (minNv >= minNnv) { /*SubsetCountNodesAux procedure takes
01223                              the Then branch in case of a tie */
01224 
01225         /* recur with the Then branch */
01226         ThenBranch = (DdNode *)BuildSubsetBdd(dd, Nv, size,
01227               visitedTable, threshold, storeTable, approxTable);
01228         if (ThenBranch == NULL) {
01229             return(NULL);
01230         }
01231         cuddRef(ThenBranch);
01232         /* The Else branch is either a node that already exists in the
01233          * subset, or one whose approximation has been computed, or
01234          * Zero.
01235          */
01236         if (st_lookup(storeTable, (char *)Cudd_Regular(Nnv), (char **)&dummy)) {
01237           ElseBranch = Nnv;
01238           cuddRef(ElseBranch);
01239         } else {
01240           if (st_lookup(approxTable, (char *)Nnv, (char **)&dummy)) {
01241             ElseBranch = (DdNode *)dummy;
01242             cuddRef(ElseBranch);
01243           } else {
01244             ElseBranch = zero;
01245             cuddRef(ElseBranch);
01246           }
01247         }
01248         
01249     }
01250     else {
01251         /* recur with the Else branch */
01252         ElseBranch = (DdNode *)BuildSubsetBdd(dd, Nnv, size,
01253                       visitedTable, threshold, storeTable, approxTable);
01254         if (ElseBranch == NULL) {
01255             return(NULL);
01256         }
01257         cuddRef(ElseBranch);
01258         /* The Then branch is either a node that already exists in the
01259          * subset, or one whose approximation has been computed, or
01260          * Zero.
01261          */
01262         if (st_lookup(storeTable, (char *)Cudd_Regular(Nv), (char **)&dummy)) {
01263           ThenBranch = Nv;
01264           cuddRef(ThenBranch);
01265         } else {
01266           if (st_lookup(approxTable, (char *)Nv, (char **)&dummy)) {
01267             ThenBranch = (DdNode *)dummy;
01268             cuddRef(ThenBranch);
01269           } else {
01270             ThenBranch = zero;
01271             cuddRef(ThenBranch);
01272           }
01273         }
01274     }
01275 
01276     /* construct the Bdd with the top variable and the two children */
01277     topid = Cudd_NodeReadIndex(N);
01278     topv = Cudd_ReadVars(dd, topid);
01279     cuddRef(topv);
01280     neW =  cuddBddIteRecur(dd, topv, ThenBranch, ElseBranch);
01281     if (neW != NULL) {
01282       cuddRef(neW);
01283     }
01284     Cudd_RecursiveDeref(dd, topv);
01285     Cudd_RecursiveDeref(dd, ThenBranch);
01286     Cudd_RecursiveDeref(dd, ElseBranch);
01287 
01288       
01289     if (neW == NULL)
01290         return(NULL);
01291     else {
01292         /* store this node in the store table */
01293         if (!st_lookup(storeTable, (char *)Cudd_Regular(neW), (char **)&dummy)) {
01294           cuddRef(neW);
01295           st_insert(storeTable, (char *)Cudd_Regular(neW), (char *)NIL(char));
01296           
01297         }
01298         /* store the approximation for this node */
01299         if (N !=  Cudd_Regular(neW)) {
01300             if (st_lookup(approxTable, (char *)node, (char **)&dummy)) {
01301                 fprintf(dd->err, "This node should not be in the approximated table\n");
01302             } else {
01303                 cuddRef(neW);
01304                 st_insert(approxTable, (char *)node, (char *)neW);
01305             }
01306         }
01307         cuddDeref(neW);
01308         return(neW);
01309     }
01310 } /* end of BuildSubsetBdd */

DdNode* Cudd_SubsetHeavyBranch ( DdManager dd,
DdNode f,
int  numVars,
int  threshold 
)

AutomaticEnd Function********************************************************************

Synopsis [Extracts a dense subset from a BDD with the heavy branch heuristic.]

Description [Extracts a dense subset from a BDD. This procedure builds a subset by throwing away one of the children of each node, starting from the root, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the subset if successful. NULL if the procedure runs out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.]

SideEffects [None]

SeeAlso [Cudd_SubsetShortPaths Cudd_SupersetHeavyBranch Cudd_ReadSize]

Definition at line 178 of file cuddSubsetHB.c.

00183 {
00184     DdNode *subset;
00185 
00186     memOut = 0;
00187     do {
00188         dd->reordered = 0;
00189         subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold);
00190     } while ((dd->reordered == 1) && (!memOut));
00191 
00192     return(subset);
00193 
00194 } /* end of Cudd_SubsetHeavyBranch */

DdNode* Cudd_SupersetHeavyBranch ( DdManager dd,
DdNode f,
int  numVars,
int  threshold 
)

Function********************************************************************

Synopsis [Extracts a dense superset from a BDD with the heavy branch heuristic.]

Description [Extracts a dense superset from a BDD. The procedure is identical to the subset procedure except for the fact that it receives the complement of the given function. Extracting the subset of the complement function is equivalent to extracting the superset of the function. This procedure builds a superset by throwing away one of the children of each node starting from the root of the complement function, until the result is small enough. The child that is eliminated from the result is the one that contributes the fewer minterms. Returns a pointer to the BDD of the superset if successful. NULL if intermediate result causes the procedure to run out of memory. The parameter numVars is the maximum number of variables to be used in minterm calculation and node count calculation. The optimal number should be as close as possible to the size of the support of f. However, it is safe to pass the value returned by Cudd_ReadSize for numVars when the number of variables is under 1023. If numVars is larger than 1023, it will overflow. If a 0 parameter is passed then the procedure will compute a value which will avoid overflow but will cause underflow with 2046 variables or more.]

SideEffects [None]

SeeAlso [Cudd_SubsetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]

Definition at line 228 of file cuddSubsetHB.c.

00233 {
00234     DdNode *subset, *g;
00235 
00236     g = Cudd_Not(f);    
00237     memOut = 0;
00238     do {
00239         dd->reordered = 0;
00240         subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold);
00241     } while ((dd->reordered == 1) && (!memOut));
00242     
00243     return(Cudd_NotCond(subset, (subset != NULL)));
00244     
00245 } /* end of Cudd_SupersetHeavyBranch */

DdNode* cuddSubsetHeavyBranch ( DdManager dd,
DdNode f,
int  numVars,
int  threshold 
)

Function********************************************************************

Synopsis [The main procedure that returns a subset by choosing the heavier branch in the BDD.]

Description [Here a subset BDD is built by throwing away one of the children. Starting at root, annotate each node with the number of minterms (in terms of the total number of variables specified - numVars), number of nodes taken by the DAG rooted at this node and number of additional nodes taken by the child that has the lesser minterms. The child with the lower number of minterms is thrown away and a dyanmic count of the nodes of the subset is kept. Once the threshold is reached the subset is returned to the calling procedure.]

SideEffects [None]

SeeAlso [Cudd_SubsetHeavyBranch]

Definition at line 274 of file cuddSubsetHB.c.

00279 {
00280 
00281     int i, *size;
00282     st_table *visitedTable;
00283     int numNodes;
00284     NodeData_t *currNodeQual;
00285     DdNode *subset;
00286     double minN;
00287     st_table *storeTable, *approxTable;
00288     char *key, *value;
00289     st_generator *stGen;
00290     
00291     if (f == NULL) {
00292         fprintf(dd->err, "Cannot subset, nil object\n");
00293         dd->errorCode = CUDD_INVALID_ARG;
00294         return(NULL);
00295     }
00296 
00297     one  = Cudd_ReadOne(dd);
00298     zero = Cudd_Not(one);
00299 
00300     /* If user does not know numVars value, set it to the maximum
00301      * exponent that the pow function can take. The -1 is due to the
00302      * discrepancy in the value that pow takes and the value that
00303      * log gives.
00304      */
00305     if (numVars == 0) {
00306         /* set default value */
00307         numVars = DBL_MAX_EXP - 1;
00308     }
00309 
00310     if (Cudd_IsConstant(f)) {
00311         return(f);
00312     }
00313 
00314     max = pow(2.0, (double)numVars);
00315 
00316     /* Create visited table where structures for node data are allocated and
00317        stored in a st_table */
00318     visitedTable = SubsetCountMinterm(f, numVars);
00319     if ((visitedTable == NULL) || memOut) {
00320         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00321         dd->errorCode = CUDD_MEMORY_OUT;
00322         return(0);
00323     }
00324     numNodes = SubsetCountNodes(f, visitedTable, numVars);
00325     if (memOut) {
00326         (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
00327         dd->errorCode = CUDD_MEMORY_OUT;
00328         return(0);
00329     }
00330 
00331     if (st_lookup(visitedTable, (char *)f, (char **)&currNodeQual)) {
00332         minN = *(((NodeData_t *)currNodeQual)->mintermPointer);
00333     } else {
00334         fprintf(dd->err,
00335                 "Something is wrong, ought to be node quality table\n");
00336         dd->errorCode = CUDD_INTERNAL_ERROR;
00337     }
00338 
00339     size = ALLOC(int, 1);
00340     if (size == NULL) {
00341         dd->errorCode = CUDD_MEMORY_OUT;
00342         return(NULL);
00343     }
00344     *size = numNodes;
00345 
00346 #ifdef DEBUG
00347     num_calls = 0;
00348 #endif
00349     /* table to store nodes being created. */
00350     storeTable = st_init_table(st_ptrcmp, st_ptrhash);
00351     /* insert the constant */
00352     cuddRef(one);
00353     if (st_insert(storeTable, (char *)Cudd_ReadOne(dd), NIL(char)) ==
00354         ST_OUT_OF_MEM) {
00355         fprintf(dd->out, "Something wrong, st_table insert failed\n");
00356     }
00357     /* table to store approximations of nodes */
00358     approxTable = st_init_table(st_ptrcmp, st_ptrhash);
00359     subset = (DdNode *)BuildSubsetBdd(dd, f, size, visitedTable, threshold,
00360                                       storeTable, approxTable);
00361     if (subset != NULL) {
00362         cuddRef(subset);
00363     }
00364 
00365     stGen = st_init_gen(approxTable);
00366     if (stGen == NULL) {
00367         st_free_table(approxTable);
00368         return(NULL);
00369     }
00370     while(st_gen(stGen, (char **)&key, (char **)&value)) {
00371         Cudd_RecursiveDeref(dd, (DdNode *)value);
00372     }
00373     st_free_gen(stGen); stGen = NULL;
00374     st_free_table(approxTable);
00375 
00376     stGen = st_init_gen(storeTable);
00377     if (stGen == NULL) {
00378         st_free_table(storeTable);
00379         return(NULL);
00380     }
00381     while(st_gen(stGen, (char **)&key, (char **)&value)) {
00382         Cudd_RecursiveDeref(dd, (DdNode *)key);
00383     }
00384     st_free_gen(stGen); stGen = NULL;
00385     st_free_table(storeTable);
00386 
00387     for (i = 0; i <= page; i++) {
00388         FREE(mintermPages[i]);
00389     }
00390     FREE(mintermPages);
00391     for (i = 0; i <= page; i++) {
00392         FREE(nodePages[i]);
00393     }
00394     FREE(nodePages);
00395     for (i = 0; i <= page; i++) {
00396         FREE(lightNodePages[i]);
00397     }
00398     FREE(lightNodePages);
00399     for (i = 0; i <= nodeDataPage; i++) {
00400         FREE(nodeDataPages[i]);
00401     }
00402     FREE(nodeDataPages);
00403     st_free_table(visitedTable);
00404     FREE(size);
00405 #if 0
00406     (void) Cudd_DebugCheck(dd);
00407     (void) Cudd_CheckKeys(dd);
00408 #endif
00409 
00410     if (subset != NULL) {
00411 #ifdef DD_DEBUG
00412       if (!Cudd_bddLeq(dd, subset, f)) {
00413             fprintf(dd->err, "Wrong subset\n");
00414             dd->errorCode = CUDD_INTERNAL_ERROR;
00415             return(NULL);
00416       }
00417 #endif
00418         cuddDeref(subset);
00419         return(subset);
00420     } else {
00421         return(NULL);
00422     }
00423 } /* end of cuddSubsetHeavyBranch */

static void ResizeCountMintermPages (  )  [static]

Function********************************************************************

Synopsis [Resize the number of pages allocated to store the minterm counts. ]

Description [Resize the number of pages allocated to store the minterm counts. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.]

SideEffects [Changes the size of minterm pages, page, page index, maximum number of pages freeing stuff in case of memory out. ]

SeeAlso []

Definition at line 506 of file cuddSubsetHB.c.

00508 {
00509     int i;
00510     double **newMintermPages;
00511 
00512     page++;
00513     /* If the current page index is larger than the number of pages
00514      * allocated, allocate a new page array. Page numbers are incremented by
00515      * INITIAL_PAGES
00516      */
00517     if (page == maxPages) {
00518         newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES);
00519         if (newMintermPages == NULL) {
00520             for (i = 0; i < page; i++) FREE(mintermPages[i]);
00521             FREE(mintermPages);
00522             memOut = 1;
00523             return;
00524         } else {
00525             for (i = 0; i < maxPages; i++) {
00526                 newMintermPages[i] = mintermPages[i];
00527             }
00528             /* Increase total page count */
00529             maxPages += INITIAL_PAGES;
00530             FREE(mintermPages);
00531             mintermPages = newMintermPages;
00532         }
00533     }
00534     /* Allocate a new page */
00535     currentMintermPage = mintermPages[page] = ALLOC(double,pageSize);
00536     if (currentMintermPage == NULL) {
00537         for (i = 0; i < page; i++) FREE(mintermPages[i]);
00538         FREE(mintermPages);
00539         memOut = 1;
00540         return;
00541     }
00542     /* reset page index */
00543     pageIndex = 0;
00544     return;
00545 
00546 } /* end of ResizeCountMintermPages */

static void ResizeCountNodePages (  )  [static]

Function********************************************************************

Synopsis [Resize the number of pages allocated to store the node counts.]

Description [Resize the number of pages allocated to store the node counts. The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.]

SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out.]

SeeAlso []

Definition at line 564 of file cuddSubsetHB.c.

00566 {
00567     int i;
00568     int **newNodePages;
00569 
00570     page++;
00571 
00572     /* If the current page index is larger than the number of pages
00573      * allocated, allocate a new page array. The number of pages is incremented
00574      * by INITIAL_PAGES.
00575      */
00576     if (page == maxPages) {
00577         newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00578         if (newNodePages == NULL) {
00579             for (i = 0; i < page; i++) FREE(nodePages[i]);
00580             FREE(nodePages);
00581             for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00582             FREE(lightNodePages);
00583             memOut = 1;
00584             return;
00585         } else {
00586             for (i = 0; i < maxPages; i++) {
00587                 newNodePages[i] = nodePages[i];
00588             }
00589             FREE(nodePages);
00590             nodePages = newNodePages;
00591         }
00592 
00593         newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00594         if (newNodePages == NULL) {
00595             for (i = 0; i < page; i++) FREE(nodePages[i]);
00596             FREE(nodePages);
00597             for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00598             FREE(lightNodePages);
00599             memOut = 1;
00600             return;
00601         } else {
00602             for (i = 0; i < maxPages; i++) {
00603                 newNodePages[i] = lightNodePages[i];
00604             }
00605             FREE(lightNodePages);
00606             lightNodePages = newNodePages;
00607         }
00608         /* Increase total page count */
00609         maxPages += INITIAL_PAGES;
00610     }
00611     /* Allocate a new page */
00612     currentNodePage = nodePages[page] = ALLOC(int,pageSize);
00613     if (currentNodePage == NULL) {
00614         for (i = 0; i < page; i++) FREE(nodePages[i]);
00615         FREE(nodePages);
00616         for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00617         FREE(lightNodePages);
00618         memOut = 1;
00619         return;
00620     }
00621     /* Allocate a new page */
00622     currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
00623     if (currentLightNodePage == NULL) {
00624         for (i = 0; i <= page; i++) FREE(nodePages[i]);
00625         FREE(nodePages);
00626         for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00627         FREE(lightNodePages);
00628         memOut = 1;
00629         return;
00630     }
00631     /* reset page index */
00632     pageIndex = 0;
00633     return;
00634 
00635 } /* end of ResizeCountNodePages */

static void ResizeNodeDataPages (  )  [static]

Function********************************************************************

Synopsis [Resize the number of pages allocated to store the node data.]

Description [Resize the number of pages allocated to store the node data The procedure moves the counter to the next page when the end of the page is reached and allocates new pages when necessary.]

SideEffects [Changes the size of pages, page, page index, maximum number of pages freeing stuff in case of memory out. ]

SeeAlso []

Definition at line 446 of file cuddSubsetHB.c.

00448 {
00449     int i;
00450     NodeData_t **newNodeDataPages;
00451 
00452     nodeDataPage++;
00453     /* If the current page index is larger than the number of pages
00454      * allocated, allocate a new page array. Page numbers are incremented by
00455      * INITIAL_PAGES
00456      */
00457     if (nodeDataPage == maxNodeDataPages) {
00458         newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES);
00459         if (newNodeDataPages == NULL) {
00460             for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00461             FREE(nodeDataPages);
00462             memOut = 1;
00463             return;
00464         } else {
00465             for (i = 0; i < maxNodeDataPages; i++) {
00466                 newNodeDataPages[i] = nodeDataPages[i];
00467             }
00468             /* Increase total page count */
00469             maxNodeDataPages += INITIAL_PAGES;
00470             FREE(nodeDataPages);
00471             nodeDataPages = newNodeDataPages;
00472         }
00473     }
00474     /* Allocate a new page */
00475     currentNodeDataPage = nodeDataPages[nodeDataPage] =
00476         ALLOC(NodeData_t ,nodeDataPageSize);
00477     if (currentNodeDataPage == NULL) {
00478         for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00479         FREE(nodeDataPages);
00480         memOut = 1;
00481         return;
00482     }
00483     /* reset page index */
00484     nodeDataPageIndex = 0;
00485     return;
00486 
00487 } /* end of ResizeNodeDataPages */

static void StoreNodes ( st_table storeTable,
DdManager dd,
DdNode node 
) [static]

Function********************************************************************

Synopsis [Procedure to recursively store nodes that are retained in the subset.]

Description [rocedure to recursively store nodes that are retained in the subset.]

SideEffects [None]

SeeAlso [StoreNodes]

Definition at line 1089 of file cuddSubsetHB.c.

01093 {
01094     char *dummy;
01095     DdNode *N, *Nt, *Ne;
01096     if (Cudd_IsConstant(dd)) {
01097         return;
01098     }
01099     N = Cudd_Regular(node);
01100     if (st_lookup(storeTable, (char *)N, (char **)&dummy)) {
01101         return;
01102     }
01103     cuddRef(N);
01104     if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) {
01105         fprintf(dd->err,"Something wrong, st_table insert failed\n");
01106     }
01107 
01108     Nt = Cudd_T(N);
01109     Ne = Cudd_E(N);
01110 
01111     StoreNodes(storeTable, dd, Nt);
01112     StoreNodes(storeTable, dd, Ne);
01113     return;
01114 
01115 }

static st_table* SubsetCountMinterm ( DdNode node,
int  nvars 
) [static]

Function********************************************************************

Synopsis [Counts minterms of each node in the DAG]

Description [Counts minterms of each node in the DAG. Similar to the Cudd_CountMinterm procedure except this returns the minterm count for all the nodes in the bdd in an st_table.]

SideEffects [none]

SeeAlso [SubsetCountMintermAux]

Definition at line 766 of file cuddSubsetHB.c.

00769 {
00770     st_table    *table;
00771     double      num;
00772     int i;
00773 
00774 
00775 #ifdef DEBUG
00776     num_calls = 0;
00777 #endif
00778 
00779     max = pow(2.0,(double) nvars);
00780     table = st_init_table(st_ptrcmp,st_ptrhash);
00781     if (table == NULL) goto OUT_OF_MEM;
00782     maxPages = INITIAL_PAGES;
00783     mintermPages = ALLOC(double *,maxPages);
00784     if (mintermPages == NULL) {
00785         st_free_table(table);
00786         goto OUT_OF_MEM;
00787     }
00788     page = 0;
00789     currentMintermPage = ALLOC(double,pageSize);
00790     mintermPages[page] = currentMintermPage;
00791     if (currentMintermPage == NULL) {
00792         FREE(mintermPages);
00793         st_free_table(table);
00794         goto OUT_OF_MEM;
00795     }
00796     pageIndex = 0;
00797     maxNodeDataPages = INITIAL_PAGES;
00798     nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages);
00799     if (nodeDataPages == NULL) {
00800         for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00801         FREE(mintermPages);
00802         st_free_table(table);
00803         goto OUT_OF_MEM;
00804     }
00805     nodeDataPage = 0;
00806     currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize);
00807     nodeDataPages[nodeDataPage] = currentNodeDataPage;
00808     if (currentNodeDataPage == NULL) {
00809         for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00810         FREE(mintermPages);
00811         FREE(nodeDataPages);
00812         st_free_table(table);
00813         goto OUT_OF_MEM;
00814     }
00815     nodeDataPageIndex = 0;
00816 
00817     num = SubsetCountMintermAux(node,max,table);
00818     if (memOut) goto OUT_OF_MEM;
00819     return(table);
00820 
00821 OUT_OF_MEM:
00822     memOut = 1;
00823     return(NULL);
00824 
00825 } /* end of SubsetCountMinterm */

static double SubsetCountMintermAux ( DdNode node,
double  max,
st_table table 
) [static]

Function********************************************************************

Synopsis [Recursively counts minterms of each node in the DAG.]

Description [Recursively counts minterms of each node in the DAG. Similar to the cuddCountMintermAux which recursively counts the number of minterms for the dag rooted at each node in terms of the total number of variables (max). This procedure creates the node data structure and stores the minterm count as part of the node data structure. ]

SideEffects [Creates structures of type node quality and fills the st_table]

SeeAlso [SubsetCountMinterm]

Definition at line 655 of file cuddSubsetHB.c.

00659 {
00660 
00661     DdNode      *N,*Nv,*Nnv; /* nodes to store cofactors  */
00662     double      min,*pmin; /* minterm count */
00663     double      min1, min2; /* minterm count */
00664     NodeData_t *dummy;
00665     NodeData_t *newEntry;
00666     int i;
00667 
00668 #ifdef DEBUG
00669     num_calls++;
00670 #endif
00671 
00672     /* Constant case */
00673     if (Cudd_IsConstant(node)) {
00674         if (node == zero) {
00675             return(0.0);
00676         } else {
00677             return(max);
00678         }
00679     } else {
00680 
00681         /* check if entry for this node exists */
00682         if (st_lookup(table,(char *)node, (char **)&dummy)) {
00683             min = *(dummy->mintermPointer);
00684             return(min);
00685         }
00686 
00687         /* Make the node regular to extract cofactors */
00688         N = Cudd_Regular(node);
00689 
00690         /* store the cofactors */
00691         Nv = Cudd_T(N);
00692         Nnv = Cudd_E(N);
00693         
00694         Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00695         Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00696 
00697         min1 =  SubsetCountMintermAux(Nv, max,table)/2.0;
00698         if (memOut) return(0.0);
00699         min2 =  SubsetCountMintermAux(Nnv,max,table)/2.0;
00700         if (memOut) return(0.0);
00701         min = (min1+min2);
00702 
00703         /* if page index is at the bottom, then create a new page */
00704         if (pageIndex == pageSize) ResizeCountMintermPages();
00705         if (memOut) {
00706             for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00707             FREE(nodeDataPages);
00708             st_free_table(table);
00709             return(0.0);
00710         }
00711 
00712         /* point to the correct location in the page */
00713         pmin = currentMintermPage+pageIndex;
00714         pageIndex++;
00715 
00716         /* store the minterm count of this node in the page */
00717         *pmin = min;
00718 
00719         /* Note I allocate the struct here. Freeing taken care of later */
00720         if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages();
00721         if (memOut) {
00722             for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00723             FREE(mintermPages);
00724             st_free_table(table);
00725             return(0.0);
00726         }
00727 
00728         newEntry = currentNodeDataPage + nodeDataPageIndex;
00729         nodeDataPageIndex++;
00730 
00731         /* points to the correct location in the page */
00732         newEntry->mintermPointer = pmin;
00733         /* initialize this field of the Node Quality structure */
00734         newEntry->nodesPointer = NULL;
00735 
00736         /* insert entry for the node in the table */
00737         if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) {
00738             memOut = 1;
00739             for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00740             FREE(mintermPages);
00741             for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00742             FREE(nodeDataPages);
00743             st_free_table(table);
00744             return(0.0);
00745         }
00746         return(min);
00747     }
00748 
00749 } /* end of SubsetCountMintermAux */

static int SubsetCountNodes ( DdNode node,
st_table table,
int  nvars 
) [static]

Function********************************************************************

Synopsis [Counts the nodes under the current node and its lighter child]

Description [Counts the nodes under the current node and its lighter child. Calls a recursive procedure to count the number of nodes of a DAG rooted at a particular node and the number of nodes taken by its lighter child.]

SideEffects [None]

SeeAlso [SubsetCountNodesAux]

Definition at line 1012 of file cuddSubsetHB.c.

01016 {
01017     int num;
01018     int i;
01019 
01020 #ifdef DEBUG
01021     num_calls = 0;
01022 #endif
01023 
01024     max = pow(2.0,(double) nvars);
01025     maxPages = INITIAL_PAGES;
01026     nodePages = ALLOC(int *,maxPages);
01027     if (nodePages == NULL)  {
01028         goto OUT_OF_MEM;
01029     }
01030 
01031     lightNodePages = ALLOC(int *,maxPages);
01032     if (lightNodePages == NULL) {
01033         for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01034         FREE(mintermPages);
01035         for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01036         FREE(nodeDataPages);
01037         FREE(nodePages);
01038         goto OUT_OF_MEM;
01039     }
01040 
01041     page = 0;
01042     currentNodePage = nodePages[page] = ALLOC(int,pageSize);
01043     if (currentNodePage == NULL) {
01044         for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01045         FREE(mintermPages);
01046         for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01047         FREE(nodeDataPages);
01048         FREE(lightNodePages);
01049         FREE(nodePages);
01050         goto OUT_OF_MEM;
01051     }
01052 
01053     currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
01054     if (currentLightNodePage == NULL) {
01055         for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01056         FREE(mintermPages);
01057         for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01058         FREE(nodeDataPages);
01059         FREE(currentNodePage);
01060         FREE(lightNodePages);
01061         FREE(nodePages);
01062         goto OUT_OF_MEM;
01063     }
01064 
01065     pageIndex = 0;
01066     num = SubsetCountNodesAux(node,table,max);
01067     if (memOut) goto OUT_OF_MEM;
01068     return(num);
01069 
01070 OUT_OF_MEM:
01071     memOut = 1;
01072     return(0);
01073 
01074 } /* end of SubsetCountNodes */

static int SubsetCountNodesAux ( DdNode node,
st_table table,
double  max 
) [static]

Function********************************************************************

Synopsis [Recursively counts the number of nodes under the dag. Also counts the number of nodes under the lighter child of this node.]

Description [Recursively counts the number of nodes under the dag. Also counts the number of nodes under the lighter child of this node. . Note that the same dag may be the lighter child of two different nodes and have different counts. As with the minterm counts, the node counts are stored in pages to be space efficient and the address for these node counts are stored in an st_table associated to each node. ]

SideEffects [Updates the node data table with node counts]

SeeAlso [SubsetCountNodes]

Definition at line 848 of file cuddSubsetHB.c.

00852 {
00853     int tval, eval, i;
00854     DdNode *N, *Nv, *Nnv;
00855     double minNv, minNnv;
00856     NodeData_t *dummyN, *dummyNv, *dummyNnv, *dummyNBar;
00857     int *pmin, *pminBar, *val;
00858 
00859     if ((node == NULL) || Cudd_IsConstant(node))
00860         return(0);
00861 
00862     /* if this node has been processed do nothing */
00863     if (st_lookup(table, (char *)node, (char **)&dummyN) == 1) {
00864         val = dummyN->nodesPointer;
00865         if (val != NULL)
00866             return(0);
00867     } else {
00868         return(0);
00869     }
00870 
00871     N  = Cudd_Regular(node);
00872     Nv = Cudd_T(N);
00873     Nnv = Cudd_E(N);
00874     
00875     Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00876     Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00877 
00878     /* find the minterm counts for the THEN and ELSE branches */
00879     if (Cudd_IsConstant(Nv)) {
00880         if (Nv == zero) {
00881             minNv = 0.0;
00882         } else {
00883             minNv = max;
00884         }
00885     } else {
00886         if (st_lookup(table, (char *)Nv, (char **)&dummyNv) == 1)
00887             minNv = *(dummyNv->mintermPointer);
00888         else {
00889             return(0);
00890         }
00891     }
00892     if (Cudd_IsConstant(Nnv)) {
00893         if (Nnv == zero) {
00894             minNnv = 0.0;
00895         } else {
00896             minNnv = max;
00897         }
00898     } else {
00899         if (st_lookup(table, (char *)Nnv, (char **)&dummyNnv) == 1) {
00900             minNnv = *(dummyNnv->mintermPointer);
00901         }
00902         else {
00903             return(0);
00904         }
00905     }
00906 
00907 
00908     /* recur based on which has larger minterm, */
00909     if (minNv >= minNnv) {
00910         tval = SubsetCountNodesAux(Nv, table, max);
00911         if (memOut) return(0);
00912         eval = SubsetCountNodesAux(Nnv, table, max);
00913         if (memOut) return(0);
00914 
00915         /* store the node count of the lighter child. */
00916         if (pageIndex == pageSize) ResizeCountNodePages();
00917         if (memOut) {
00918             for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00919             FREE(mintermPages);
00920             for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00921             FREE(nodeDataPages);
00922             st_free_table(table);
00923             return(0);
00924         }
00925         pmin = currentLightNodePage + pageIndex;
00926         *pmin = eval; /* Here the ELSE child is lighter */
00927         dummyN->lightChildNodesPointer = pmin;
00928 
00929     } else {
00930         eval = SubsetCountNodesAux(Nnv, table, max);
00931         if (memOut) return(0);
00932         tval = SubsetCountNodesAux(Nv, table, max);
00933         if (memOut) return(0);
00934 
00935         /* store the node count of the lighter child. */
00936         if (pageIndex == pageSize) ResizeCountNodePages();
00937         if (memOut) {
00938             for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00939             FREE(mintermPages);
00940             for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00941             FREE(nodeDataPages);
00942             st_free_table(table);
00943             return(0);
00944         }
00945         pmin = currentLightNodePage + pageIndex;
00946         *pmin = tval; /* Here the THEN child is lighter */
00947         dummyN->lightChildNodesPointer = pmin;
00948 
00949     }
00950     /* updating the page index for node count storage. */
00951     pmin = currentNodePage + pageIndex;
00952     *pmin = tval + eval + 1;
00953     dummyN->nodesPointer = pmin;
00954 
00955     /* pageIndex is parallel page index for count_nodes and count_lightNodes */
00956     pageIndex++;
00957 
00958     /* if this node has been reached first, it belongs to a heavier
00959        branch. Its complement will be reached later on a lighter branch.
00960        Hence the complement has zero node count. */
00961 
00962     if (st_lookup(table, (char *)Cudd_Not(node), (char **)&dummyNBar) == 1)  {
00963         if (pageIndex == pageSize) ResizeCountNodePages();
00964         if (memOut) {
00965             for (i = 0; i < page; i++) FREE(mintermPages[i]);
00966             FREE(mintermPages);
00967             for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00968             FREE(nodeDataPages);
00969             st_free_table(table);
00970             return(0);
00971         }
00972         pminBar = currentLightNodePage + pageIndex;
00973         *pminBar = 0;
00974         dummyNBar->lightChildNodesPointer = pminBar;
00975         /* The lighter child has less nodes than the parent.
00976          * So if parent 0 then lighter child zero
00977          */
00978         if (pageIndex == pageSize) ResizeCountNodePages();
00979         if (memOut) {
00980             for (i = 0; i < page; i++) FREE(mintermPages[i]);
00981             FREE(mintermPages);
00982             for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00983             FREE(nodeDataPages);
00984             st_free_table(table);
00985             return(0);
00986         }
00987         pminBar = currentNodePage + pageIndex;
00988         *pminBar = 0;
00989         dummyNBar->nodesPointer = pminBar ; /* maybe should point to zero */
00990 
00991         pageIndex++;
00992     }
00993     return(*pmin);
00994 } /*end of SubsetCountNodesAux */


Variable Documentation

int* currentLightNodePage [static]

Definition at line 108 of file cuddSubsetHB.c.

double* currentMintermPage [static]

Definition at line 101 of file cuddSubsetHB.c.

Definition at line 115 of file cuddSubsetHB.c.

int* currentNodePage [static]

Definition at line 106 of file cuddSubsetHB.c.

char rcsid [] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $" [static]

Definition at line 89 of file cuddSubsetHB.c.

int** lightNodePages [static]

Definition at line 100 of file cuddSubsetHB.c.

double max [static]

Definition at line 103 of file cuddSubsetHB.c.

int maxNodeDataPages [static]

Definition at line 122 of file cuddSubsetHB.c.

int maxPages [static]

Definition at line 113 of file cuddSubsetHB.c.

int memOut [static]

Definition at line 92 of file cuddSubsetHB.c.

double** mintermPages [static]

Definition at line 98 of file cuddSubsetHB.c.

int nodeDataPage [static]

Definition at line 117 of file cuddSubsetHB.c.

int nodeDataPageIndex [static]

Definition at line 118 of file cuddSubsetHB.c.

Definition at line 119 of file cuddSubsetHB.c.

int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE [static]

Definition at line 120 of file cuddSubsetHB.c.

int** nodePages [static]

Definition at line 99 of file cuddSubsetHB.c.

DdNode * one [static]

Definition at line 97 of file cuddSubsetHB.c.

int page [static]

Definition at line 111 of file cuddSubsetHB.c.

int pageIndex [static]

Definition at line 110 of file cuddSubsetHB.c.

int pageSize = DEFAULT_PAGE_SIZE [static]

Definition at line 112 of file cuddSubsetHB.c.

DdNode* zero [static]

Definition at line 97 of file cuddSubsetHB.c.


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