src/cuBdd/cuddSubsetHB.c File Reference

#include "util.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 (void)
static void ResizeCountMintermPages (void)
static void ResizeCountNodePages (void)
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)
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)

Variables

static char rcsid[] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio 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 [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 74 of file cuddSubsetHB.c.

#define DEFAULT_NODE_DATA_PAGE_SIZE   1024

Definition at line 84 of file cuddSubsetHB.c.

#define DEFAULT_PAGE_SIZE   2048

Definition at line 83 of file cuddSubsetHB.c.

#define INITIAL_PAGES   128

Definition at line 85 of file cuddSubsetHB.c.


Typedef Documentation

typedef struct NodeData NodeData_t

Definition at line 109 of file cuddSubsetHB.c.


Function Documentation

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 1154 of file cuddSubsetHB.c.

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

00210 {
00211     DdNode *subset;
00212 
00213     memOut = 0;
00214     do {
00215         dd->reordered = 0;
00216         subset = cuddSubsetHeavyBranch(dd, f, numVars, threshold);
00217     } while ((dd->reordered == 1) && (!memOut));
00218 
00219     return(subset);
00220 
00221 } /* 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 255 of file cuddSubsetHB.c.

00260 {
00261     DdNode *subset, *g;
00262 
00263     g = Cudd_Not(f);
00264     memOut = 0;
00265     do {
00266         dd->reordered = 0;
00267         subset = cuddSubsetHeavyBranch(dd, g, numVars, threshold);
00268     } while ((dd->reordered == 1) && (!memOut));
00269 
00270     return(Cudd_NotCond(subset, (subset != NULL)));
00271 
00272 } /* 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 301 of file cuddSubsetHB.c.

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

static void ResizeCountMintermPages ( void   )  [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 529 of file cuddSubsetHB.c.

00530 {
00531     int i;
00532     double **newMintermPages;
00533 
00534     page++;
00535     /* If the current page index is larger than the number of pages
00536      * allocated, allocate a new page array. Page numbers are incremented by
00537      * INITIAL_PAGES
00538      */
00539     if (page == maxPages) {
00540         newMintermPages = ALLOC(double *,maxPages + INITIAL_PAGES);
00541         if (newMintermPages == NULL) {
00542             for (i = 0; i < page; i++) FREE(mintermPages[i]);
00543             FREE(mintermPages);
00544             memOut = 1;
00545             return;
00546         } else {
00547             for (i = 0; i < maxPages; i++) {
00548                 newMintermPages[i] = mintermPages[i];
00549             }
00550             /* Increase total page count */
00551             maxPages += INITIAL_PAGES;
00552             FREE(mintermPages);
00553             mintermPages = newMintermPages;
00554         }
00555     }
00556     /* Allocate a new page */
00557     currentMintermPage = mintermPages[page] = ALLOC(double,pageSize);
00558     if (currentMintermPage == NULL) {
00559         for (i = 0; i < page; i++) FREE(mintermPages[i]);
00560         FREE(mintermPages);
00561         memOut = 1;
00562         return;
00563     }
00564     /* reset page index */
00565     pageIndex = 0;
00566     return;
00567 
00568 } /* end of ResizeCountMintermPages */

static void ResizeCountNodePages ( void   )  [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 586 of file cuddSubsetHB.c.

00587 {
00588     int i;
00589     int **newNodePages;
00590 
00591     page++;
00592 
00593     /* If the current page index is larger than the number of pages
00594      * allocated, allocate a new page array. The number of pages is incremented
00595      * by INITIAL_PAGES.
00596      */
00597     if (page == maxPages) {
00598         newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00599         if (newNodePages == NULL) {
00600             for (i = 0; i < page; i++) FREE(nodePages[i]);
00601             FREE(nodePages);
00602             for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00603             FREE(lightNodePages);
00604             memOut = 1;
00605             return;
00606         } else {
00607             for (i = 0; i < maxPages; i++) {
00608                 newNodePages[i] = nodePages[i];
00609             }
00610             FREE(nodePages);
00611             nodePages = newNodePages;
00612         }
00613 
00614         newNodePages = ALLOC(int *,maxPages + INITIAL_PAGES);
00615         if (newNodePages == NULL) {
00616             for (i = 0; i < page; i++) FREE(nodePages[i]);
00617             FREE(nodePages);
00618             for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00619             FREE(lightNodePages);
00620             memOut = 1;
00621             return;
00622         } else {
00623             for (i = 0; i < maxPages; i++) {
00624                 newNodePages[i] = lightNodePages[i];
00625             }
00626             FREE(lightNodePages);
00627             lightNodePages = newNodePages;
00628         }
00629         /* Increase total page count */
00630         maxPages += INITIAL_PAGES;
00631     }
00632     /* Allocate a new page */
00633     currentNodePage = nodePages[page] = ALLOC(int,pageSize);
00634     if (currentNodePage == NULL) {
00635         for (i = 0; i < page; i++) FREE(nodePages[i]);
00636         FREE(nodePages);
00637         for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00638         FREE(lightNodePages);
00639         memOut = 1;
00640         return;
00641     }
00642     /* Allocate a new page */
00643     currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
00644     if (currentLightNodePage == NULL) {
00645         for (i = 0; i <= page; i++) FREE(nodePages[i]);
00646         FREE(nodePages);
00647         for (i = 0; i < page; i++) FREE(lightNodePages[i]);
00648         FREE(lightNodePages);
00649         memOut = 1;
00650         return;
00651     }
00652     /* reset page index */
00653     pageIndex = 0;
00654     return;
00655 
00656 } /* end of ResizeCountNodePages */

static void ResizeNodeDataPages ( void   )  [static]

AutomaticStart

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 470 of file cuddSubsetHB.c.

00471 {
00472     int i;
00473     NodeData_t **newNodeDataPages;
00474 
00475     nodeDataPage++;
00476     /* If the current page index is larger than the number of pages
00477      * allocated, allocate a new page array. Page numbers are incremented by
00478      * INITIAL_PAGES
00479      */
00480     if (nodeDataPage == maxNodeDataPages) {
00481         newNodeDataPages = ALLOC(NodeData_t *,maxNodeDataPages + INITIAL_PAGES);
00482         if (newNodeDataPages == NULL) {
00483             for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00484             FREE(nodeDataPages);
00485             memOut = 1;
00486             return;
00487         } else {
00488             for (i = 0; i < maxNodeDataPages; i++) {
00489                 newNodeDataPages[i] = nodeDataPages[i];
00490             }
00491             /* Increase total page count */
00492             maxNodeDataPages += INITIAL_PAGES;
00493             FREE(nodeDataPages);
00494             nodeDataPages = newNodeDataPages;
00495         }
00496     }
00497     /* Allocate a new page */
00498     currentNodeDataPage = nodeDataPages[nodeDataPage] =
00499         ALLOC(NodeData_t ,nodeDataPageSize);
00500     if (currentNodeDataPage == NULL) {
00501         for (i = 0; i < nodeDataPage; i++) FREE(nodeDataPages[i]);
00502         FREE(nodeDataPages);
00503         memOut = 1;
00504         return;
00505     }
00506     /* reset page index */
00507     nodeDataPageIndex = 0;
00508     return;
00509 
00510 } /* 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 1109 of file cuddSubsetHB.c.

01113 {
01114     DdNode *N, *Nt, *Ne;
01115     if (Cudd_IsConstant(dd)) {
01116         return;
01117     }
01118     N = Cudd_Regular(node);
01119     if (st_lookup(storeTable, (char *)N, NIL(char *))) {
01120         return;
01121     }
01122     cuddRef(N);
01123     if (st_insert(storeTable, (char *)N, NIL(char)) == ST_OUT_OF_MEM) {
01124         fprintf(dd->err,"Something wrong, st_table insert failed\n");
01125     }
01126 
01127     Nt = Cudd_T(N);
01128     Ne = Cudd_E(N);
01129 
01130     StoreNodes(storeTable, dd, Nt);
01131     StoreNodes(storeTable, dd, Ne);
01132     return;
01133 
01134 }

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 787 of file cuddSubsetHB.c.

00790 {
00791     st_table    *table;
00792     int i;
00793 
00794 
00795 #ifdef DEBUG
00796     num_calls = 0;
00797 #endif
00798 
00799     max = pow(2.0,(double) nvars);
00800     table = st_init_table(st_ptrcmp,st_ptrhash);
00801     if (table == NULL) goto OUT_OF_MEM;
00802     maxPages = INITIAL_PAGES;
00803     mintermPages = ALLOC(double *,maxPages);
00804     if (mintermPages == NULL) {
00805         st_free_table(table);
00806         goto OUT_OF_MEM;
00807     }
00808     page = 0;
00809     currentMintermPage = ALLOC(double,pageSize);
00810     mintermPages[page] = currentMintermPage;
00811     if (currentMintermPage == NULL) {
00812         FREE(mintermPages);
00813         st_free_table(table);
00814         goto OUT_OF_MEM;
00815     }
00816     pageIndex = 0;
00817     maxNodeDataPages = INITIAL_PAGES;
00818     nodeDataPages = ALLOC(NodeData_t *, maxNodeDataPages);
00819     if (nodeDataPages == NULL) {
00820         for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00821         FREE(mintermPages);
00822         st_free_table(table);
00823         goto OUT_OF_MEM;
00824     }
00825     nodeDataPage = 0;
00826     currentNodeDataPage = ALLOC(NodeData_t ,nodeDataPageSize);
00827     nodeDataPages[nodeDataPage] = currentNodeDataPage;
00828     if (currentNodeDataPage == NULL) {
00829         for (i = 0; i <= page ; i++) FREE(mintermPages[i]);
00830         FREE(mintermPages);
00831         FREE(nodeDataPages);
00832         st_free_table(table);
00833         goto OUT_OF_MEM;
00834     }
00835     nodeDataPageIndex = 0;
00836 
00837     (void) SubsetCountMintermAux(node,max,table);
00838     if (memOut) goto OUT_OF_MEM;
00839     return(table);
00840 
00841 OUT_OF_MEM:
00842     memOut = 1;
00843     return(NULL);
00844 
00845 } /* 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 676 of file cuddSubsetHB.c.

00680 {
00681 
00682     DdNode      *N,*Nv,*Nnv; /* nodes to store cofactors  */
00683     double      min,*pmin; /* minterm count */
00684     double      min1, min2; /* minterm count */
00685     NodeData_t *dummy;
00686     NodeData_t *newEntry;
00687     int i;
00688 
00689 #ifdef DEBUG
00690     num_calls++;
00691 #endif
00692 
00693     /* Constant case */
00694     if (Cudd_IsConstant(node)) {
00695         if (node == zero) {
00696             return(0.0);
00697         } else {
00698             return(max);
00699         }
00700     } else {
00701 
00702         /* check if entry for this node exists */
00703         if (st_lookup(table, node, &dummy)) {
00704             min = *(dummy->mintermPointer);
00705             return(min);
00706         }
00707 
00708         /* Make the node regular to extract cofactors */
00709         N = Cudd_Regular(node);
00710 
00711         /* store the cofactors */
00712         Nv = Cudd_T(N);
00713         Nnv = Cudd_E(N);
00714 
00715         Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
00716         Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
00717 
00718         min1 =  SubsetCountMintermAux(Nv, max,table)/2.0;
00719         if (memOut) return(0.0);
00720         min2 =  SubsetCountMintermAux(Nnv,max,table)/2.0;
00721         if (memOut) return(0.0);
00722         min = (min1+min2);
00723 
00724         /* if page index is at the bottom, then create a new page */
00725         if (pageIndex == pageSize) ResizeCountMintermPages();
00726         if (memOut) {
00727             for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00728             FREE(nodeDataPages);
00729             st_free_table(table);
00730             return(0.0);
00731         }
00732 
00733         /* point to the correct location in the page */
00734         pmin = currentMintermPage+pageIndex;
00735         pageIndex++;
00736 
00737         /* store the minterm count of this node in the page */
00738         *pmin = min;
00739 
00740         /* Note I allocate the struct here. Freeing taken care of later */
00741         if (nodeDataPageIndex == nodeDataPageSize) ResizeNodeDataPages();
00742         if (memOut) {
00743             for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00744             FREE(mintermPages);
00745             st_free_table(table);
00746             return(0.0);
00747         }
00748 
00749         newEntry = currentNodeDataPage + nodeDataPageIndex;
00750         nodeDataPageIndex++;
00751 
00752         /* points to the correct location in the page */
00753         newEntry->mintermPointer = pmin;
00754         /* initialize this field of the Node Quality structure */
00755         newEntry->nodesPointer = NULL;
00756 
00757         /* insert entry for the node in the table */
00758         if (st_insert(table,(char *)node, (char *)newEntry) == ST_OUT_OF_MEM) {
00759             memOut = 1;
00760             for (i = 0; i <= page; i++) FREE(mintermPages[i]);
00761             FREE(mintermPages);
00762             for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
00763             FREE(nodeDataPages);
00764             st_free_table(table);
00765             return(0.0);
00766         }
00767         return(min);
00768     }
00769 
00770 } /* 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 1032 of file cuddSubsetHB.c.

01036 {
01037     int num;
01038     int i;
01039 
01040 #ifdef DEBUG
01041     num_calls = 0;
01042 #endif
01043 
01044     max = pow(2.0,(double) nvars);
01045     maxPages = INITIAL_PAGES;
01046     nodePages = ALLOC(int *,maxPages);
01047     if (nodePages == NULL)  {
01048         goto OUT_OF_MEM;
01049     }
01050 
01051     lightNodePages = ALLOC(int *,maxPages);
01052     if (lightNodePages == NULL) {
01053         for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01054         FREE(mintermPages);
01055         for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01056         FREE(nodeDataPages);
01057         FREE(nodePages);
01058         goto OUT_OF_MEM;
01059     }
01060 
01061     page = 0;
01062     currentNodePage = nodePages[page] = ALLOC(int,pageSize);
01063     if (currentNodePage == NULL) {
01064         for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01065         FREE(mintermPages);
01066         for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01067         FREE(nodeDataPages);
01068         FREE(lightNodePages);
01069         FREE(nodePages);
01070         goto OUT_OF_MEM;
01071     }
01072 
01073     currentLightNodePage = lightNodePages[page] = ALLOC(int,pageSize);
01074     if (currentLightNodePage == NULL) {
01075         for (i = 0; i <= page; i++) FREE(mintermPages[i]);
01076         FREE(mintermPages);
01077         for (i = 0; i <= nodeDataPage; i++) FREE(nodeDataPages[i]);
01078         FREE(nodeDataPages);
01079         FREE(currentNodePage);
01080         FREE(lightNodePages);
01081         FREE(nodePages);
01082         goto OUT_OF_MEM;
01083     }
01084 
01085     pageIndex = 0;
01086     num = SubsetCountNodesAux(node,table,max);
01087     if (memOut) goto OUT_OF_MEM;
01088     return(num);
01089 
01090 OUT_OF_MEM:
01091     memOut = 1;
01092     return(0);
01093 
01094 } /* 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 868 of file cuddSubsetHB.c.

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


Variable Documentation

int* currentLightNodePage [static]

Definition at line 135 of file cuddSubsetHB.c.

double* currentMintermPage [static]

Definition at line 128 of file cuddSubsetHB.c.

Definition at line 142 of file cuddSubsetHB.c.

int* currentNodePage [static]

Definition at line 133 of file cuddSubsetHB.c.

char rcsid [] DD_UNUSED = "$Id: cuddSubsetHB.c,v 1.37 2009/02/20 02:14:58 fabio Exp $" [static]

Definition at line 116 of file cuddSubsetHB.c.

int** lightNodePages [static]

Definition at line 127 of file cuddSubsetHB.c.

double max [static]

Definition at line 130 of file cuddSubsetHB.c.

int maxNodeDataPages [static]

Definition at line 149 of file cuddSubsetHB.c.

int maxPages [static]

Definition at line 140 of file cuddSubsetHB.c.

int memOut [static]

Definition at line 119 of file cuddSubsetHB.c.

double** mintermPages [static]

Definition at line 125 of file cuddSubsetHB.c.

int nodeDataPage [static]

Definition at line 144 of file cuddSubsetHB.c.

int nodeDataPageIndex [static]

Definition at line 145 of file cuddSubsetHB.c.

Definition at line 146 of file cuddSubsetHB.c.

int nodeDataPageSize = DEFAULT_NODE_DATA_PAGE_SIZE [static]

Definition at line 147 of file cuddSubsetHB.c.

int** nodePages [static]

Definition at line 126 of file cuddSubsetHB.c.

DdNode * one [static]

Definition at line 124 of file cuddSubsetHB.c.

int page [static]

Definition at line 138 of file cuddSubsetHB.c.

int pageIndex [static]

Definition at line 137 of file cuddSubsetHB.c.

int pageSize = DEFAULT_PAGE_SIZE [static]

Definition at line 139 of file cuddSubsetHB.c.

DdNode* zero [static]

Definition at line 124 of file cuddSubsetHB.c.


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