summaryrefslogtreecommitdiffstats
path: root/abc70930/src/bdd/cudd/cuddApprox.c
diff options
context:
space:
mode:
Diffstat (limited to 'abc70930/src/bdd/cudd/cuddApprox.c')
-rw-r--r--abc70930/src/bdd/cudd/cuddApprox.c2192
1 files changed, 0 insertions, 2192 deletions
diff --git a/abc70930/src/bdd/cudd/cuddApprox.c b/abc70930/src/bdd/cudd/cuddApprox.c
deleted file mode 100644
index debcf48b..00000000
--- a/abc70930/src/bdd/cudd/cuddApprox.c
+++ /dev/null
@@ -1,2192 +0,0 @@
-/**CFile***********************************************************************
-
- FileName [cuddApprox.c]
-
- PackageName [cudd]
-
- Synopsis [Procedures to approximate a given BDD.]
-
- Description [External procedures provided by this module:
- <ul>
- <li> Cudd_UnderApprox()
- <li> Cudd_OverApprox()
- <li> Cudd_RemapUnderApprox()
- <li> Cudd_RemapOverApprox()
- <li> Cudd_BiasedUnderApprox()
- <li> Cudd_BiasedOverApprox()
- </ul>
- Internal procedures included in this module:
- <ul>
- <li> cuddUnderApprox()
- <li> cuddRemapUnderApprox()
- <li> cuddBiasedUnderApprox()
- </ul>
- Static procedures included in this module:
- <ul>
- <li> gatherInfoAux()
- <li> gatherInfo()
- <li> computeSavings()
- <li> UAmarkNodes()
- <li> UAbuildSubset()
- <li> updateRefs()
- <li> RAmarkNodes()
- <li> BAmarkNodes()
- <li> RAbuildSubset()
- </ul>
- ]
-
- SeeAlso [cuddSubsetHB.c cuddSubsetSP.c cuddGenCof.c]
-
- Author [Fabio Somenzi]
-
- 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.]
-
-******************************************************************************/
-
-#ifdef __STDC__
-#include <float.h>
-#else
-#define DBL_MAX_EXP 1024
-#endif
-#include "util_hack.h"
-#include "cuddInt.h"
-
-/*---------------------------------------------------------------------------*/
-/* Constant declarations */
-/*---------------------------------------------------------------------------*/
-
-#define NOTHING 0
-#define REPLACE_T 1
-#define REPLACE_E 2
-#define REPLACE_N 3
-#define REPLACE_TT 4
-#define REPLACE_TE 5
-
-#define DONT_CARE 0
-#define CARE 1
-#define TOTAL_CARE 2
-#define CARE_ERROR 3
-
-/*---------------------------------------------------------------------------*/
-/* Stucture declarations */
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* Type declarations */
-/*---------------------------------------------------------------------------*/
-
-/* Data structure to store the information on each node. It keeps the
-** number of minterms of the function rooted at this node in terms of
-** the number of variables specified by the user; the number of
-** minterms of the complement; the impact of the number of minterms of
-** this function on the number of minterms of the root function; the
-** reference count of the node from within the root function; the
-** reference count of the node from an internal node; and the flag
-** that says whether the node should be replaced and how. */
-typedef struct NodeData {
- double mintermsP; /* minterms for the regular node */
- double mintermsN; /* minterms for the complemented node */
- int functionRef; /* references from within this function */
- char care; /* node intersects care set */
- char replace; /* replacement decision */
- short int parity; /* 1: even; 2: odd; 3: both */
- DdNode *resultP; /* result for even parity */
- DdNode *resultN; /* result for odd parity */
-} NodeData;
-
-typedef struct ApproxInfo {
- DdNode *one; /* one constant */
- DdNode *zero; /* BDD zero constant */
- NodeData *page; /* per-node information */
- st_table *table; /* hash table to access the per-node info */
- int index; /* index of the current node */
- double max; /* max number of minterms */
- int size; /* how many nodes are left */
- double minterms; /* how many minterms are left */
-} ApproxInfo;
-
-/* Item of the queue used in the levelized traversal of the BDD. */
-#ifdef __osf__
-#pragma pointer_size save
-#pragma pointer_size short
-#endif
-typedef struct GlobalQueueItem {
- struct GlobalQueueItem *next;
- struct GlobalQueueItem *cnext;
- DdNode *node;
- double impactP;
- double impactN;
-} GlobalQueueItem;
-
-typedef struct LocalQueueItem {
- struct LocalQueueItem *next;
- struct LocalQueueItem *cnext;
- DdNode *node;
- int localRef;
-} LocalQueueItem;
-#ifdef __osf__
-#pragma pointer_size restore
-#endif
-
-
-/*---------------------------------------------------------------------------*/
-/* Variable declarations */
-/*---------------------------------------------------------------------------*/
-
-#ifndef lint
-static char rcsid[] DD_UNUSED = "$Id: cuddApprox.c,v 1.1.1.1 2003/02/24 22:23:51 wjiang Exp $";
-#endif
-
-/*---------------------------------------------------------------------------*/
-/* Macro declarations */
-/*---------------------------------------------------------------------------*/
-
-/**AutomaticStart*************************************************************/
-
-/*---------------------------------------------------------------------------*/
-/* Static function prototypes */
-/*---------------------------------------------------------------------------*/
-
-static void updateParity ARGS((DdNode *node, ApproxInfo *info, int newparity));
-static NodeData * gatherInfoAux ARGS((DdNode *node, ApproxInfo *info, int parity));
-static ApproxInfo * gatherInfo ARGS((DdManager *dd, DdNode *node, int numVars, int parity));
-static int computeSavings ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue));
-static int updateRefs ARGS((DdManager *dd, DdNode *f, DdNode *skip, ApproxInfo *info, DdLevelQueue *queue));
-static int UAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, int safe, double quality));
-static DdNode * UAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info));
-static int RAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality));
-static int BAmarkNodes ARGS((DdManager *dd, DdNode *f, ApproxInfo *info, int threshold, double quality1, double quality0));
-static DdNode * RAbuildSubset ARGS((DdManager *dd, DdNode *node, ApproxInfo *info));
-static int BAapplyBias ARGS((DdManager *dd, DdNode *f, DdNode *b, ApproxInfo *info, DdHashTable *cache));
-
-/**AutomaticEnd***************************************************************/
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of exported functions */
-/*---------------------------------------------------------------------------*/
-
-/**Function********************************************************************
-
- Synopsis [Extracts a dense subset from a BDD with Shiple's
- underapproximation method.]
-
- Description [Extracts a dense subset from a BDD. This procedure uses
- a variant of Tom Shiple's underapproximation method. The main
- difference from the original method is that density is used as cost
- function. 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. 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 cause
- 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_SubsetHeavyBranch Cudd_ReadSize]
-
-******************************************************************************/
-DdNode *
-Cudd_UnderApprox(
- DdManager * dd /* manager */,
- DdNode * f /* function to be subset */,
- int numVars /* number of variables in the support of f */,
- int threshold /* when to stop approximation */,
- int safe /* enforce safe approximation */,
- double quality /* minimum improvement for accepted changes */)
-{
- DdNode *subset;
-
- do {
- dd->reordered = 0;
- subset = cuddUnderApprox(dd, f, numVars, threshold, safe, quality);
- } while (dd->reordered == 1);
-
- return(subset);
-
-} /* end of Cudd_UnderApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Extracts a dense superset from a BDD with Shiple's
- underapproximation method.]
-
- Description [Extracts a dense superset from a BDD. The procedure is
- identical to the underapproximation procedure except for the fact that it
- works on the complement of the given function. Extracting the subset
- of the complement function is equivalent to extracting the superset
- of the function.
- 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. 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_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
-
-******************************************************************************/
-DdNode *
-Cudd_OverApprox(
- DdManager * dd /* manager */,
- DdNode * f /* function to be superset */,
- int numVars /* number of variables in the support of f */,
- int threshold /* when to stop approximation */,
- int safe /* enforce safe approximation */,
- double quality /* minimum improvement for accepted changes */)
-{
- DdNode *subset, *g;
-
- g = Cudd_Not(f);
- do {
- dd->reordered = 0;
- subset = cuddUnderApprox(dd, g, numVars, threshold, safe, quality);
- } while (dd->reordered == 1);
-
- return(Cudd_NotCond(subset, (subset != NULL)));
-
-} /* end of Cudd_OverApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Extracts a dense subset from a BDD with the remapping
- underapproximation method.]
-
- Description [Extracts a dense subset from a BDD. This procedure uses
- a remapping technique and density as the cost function.
- 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. 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 cause
- 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_SubsetHeavyBranch Cudd_UnderApprox Cudd_ReadSize]
-
-******************************************************************************/
-DdNode *
-Cudd_RemapUnderApprox(
- DdManager * dd /* manager */,
- DdNode * f /* function to be subset */,
- int numVars /* number of variables in the support of f */,
- int threshold /* when to stop approximation */,
- double quality /* minimum improvement for accepted changes */)
-{
- DdNode *subset;
-
- do {
- dd->reordered = 0;
- subset = cuddRemapUnderApprox(dd, f, numVars, threshold, quality);
- } while (dd->reordered == 1);
-
- return(subset);
-
-} /* end of Cudd_RemapUnderApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Extracts a dense superset from a BDD with the remapping
- underapproximation method.]
-
- Description [Extracts a dense superset from a BDD. The procedure is
- identical to the underapproximation procedure except for the fact that it
- works on the complement of the given function. Extracting the subset
- of the complement function is equivalent to extracting the superset
- of the function.
- 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. 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_SupersetHeavyBranch Cudd_SupersetShortPaths Cudd_ReadSize]
-
-******************************************************************************/
-DdNode *
-Cudd_RemapOverApprox(
- DdManager * dd /* manager */,
- DdNode * f /* function to be superset */,
- int numVars /* number of variables in the support of f */,
- int threshold /* when to stop approximation */,
- double quality /* minimum improvement for accepted changes */)
-{
- DdNode *subset, *g;
-
- g = Cudd_Not(f);
- do {
- dd->reordered = 0;
- subset = cuddRemapUnderApprox(dd, g, numVars, threshold, quality);
- } while (dd->reordered == 1);
-
- return(Cudd_NotCond(subset, (subset != NULL)));
-
-} /* end of Cudd_RemapOverApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Extracts a dense subset from a BDD with the biased
- underapproximation method.]
-
- Description [Extracts a dense subset from a BDD. This procedure uses
- a biased remapping technique and density as the cost function. The bias
- is a function. This procedure tries to approximate where the bias is 0
- and preserve the given function where the bias is 1.
- 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. 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 cause
- 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_SubsetHeavyBranch Cudd_UnderApprox
- Cudd_RemapUnderApprox Cudd_ReadSize]
-
-******************************************************************************/
-DdNode *
-Cudd_BiasedUnderApprox(
- DdManager *dd /* manager */,
- DdNode *f /* function to be subset */,
- DdNode *b /* bias function */,
- int numVars /* number of variables in the support of f */,
- int threshold /* when to stop approximation */,
- double quality1 /* minimum improvement for accepted changes when b=1 */,
- double quality0 /* minimum improvement for accepted changes when b=0 */)
-{
- DdNode *subset;
-
- do {
- dd->reordered = 0;
- subset = cuddBiasedUnderApprox(dd, f, b, numVars, threshold, quality1,
- quality0);
- } while (dd->reordered == 1);
-
- return(subset);
-
-} /* end of Cudd_BiasedUnderApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Extracts a dense superset from a BDD with the biased
- underapproximation method.]
-
- Description [Extracts a dense superset from a BDD. The procedure is
- identical to the underapproximation procedure except for the fact that it
- works on the complement of the given function. Extracting the subset
- of the complement function is equivalent to extracting the superset
- of the function.
- 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. 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_SupersetHeavyBranch Cudd_SupersetShortPaths
- Cudd_RemapOverApprox Cudd_BiasedUnderApprox Cudd_ReadSize]
-
-******************************************************************************/
-DdNode *
-Cudd_BiasedOverApprox(
- DdManager *dd /* manager */,
- DdNode *f /* function to be superset */,
- DdNode *b /* bias function */,
- int numVars /* number of variables in the support of f */,
- int threshold /* when to stop approximation */,
- double quality1 /* minimum improvement for accepted changes when b=1*/,
- double quality0 /* minimum improvement for accepted changes when b=0 */)
-{
- DdNode *subset, *g;
-
- g = Cudd_Not(f);
- do {
- dd->reordered = 0;
- subset = cuddBiasedUnderApprox(dd, g, b, numVars, threshold, quality1,
- quality0);
- } while (dd->reordered == 1);
-
- return(Cudd_NotCond(subset, (subset != NULL)));
-
-} /* end of Cudd_BiasedOverApprox */
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of internal functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**Function********************************************************************
-
- Synopsis [Applies Tom Shiple's underappoximation algorithm.]
-
- Description [Applies Tom Shiple's underappoximation algorithm. Proceeds
- in three phases:
- <ul>
- <li> collect information on each node in the BDD; this is done via DFS.
- <li> traverse the BDD in top-down fashion and compute for each node
- whether its elimination increases density.
- <li> traverse the BDD via DFS and actually perform the elimination.
- </ul>
- Returns the approximated BDD if successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [Cudd_UnderApprox]
-
-******************************************************************************/
-DdNode *
-cuddUnderApprox(
- DdManager * dd /* DD manager */,
- DdNode * f /* current DD */,
- int numVars /* maximum number of variables */,
- int threshold /* threshold under which approximation stops */,
- int safe /* enforce safe approximation */,
- double quality /* minimum improvement for accepted changes */)
-{
- ApproxInfo *info;
- DdNode *subset;
- int result;
-
- if (f == NULL) {
- fprintf(dd->err, "Cannot subset, nil object\n");
- return(NULL);
- }
-
- if (Cudd_IsConstant(f)) {
- return(f);
- }
-
- /* Create table where node data are accessible via a hash table. */
- info = gatherInfo(dd, f, numVars, safe);
- if (info == NULL) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
-
- /* Mark nodes that should be replaced by zero. */
- result = UAmarkNodes(dd, f, info, threshold, safe, quality);
- if (result == 0) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
-
- /* Build the result. */
- subset = UAbuildSubset(dd, f, info);
-#if 1
- if (subset && info->size < Cudd_DagSize(subset))
- (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
- info->size, Cudd_DagSize(subset));
-#endif
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
-
-#ifdef DD_DEBUG
- if (subset != NULL) {
- cuddRef(subset);
-#if 0
- (void) Cudd_DebugCheck(dd);
- (void) Cudd_CheckKeys(dd);
-#endif
- if (!Cudd_bddLeq(dd, subset, f)) {
- (void) fprintf(dd->err, "Wrong subset\n");
- dd->errorCode = CUDD_INTERNAL_ERROR;
- }
- cuddDeref(subset);
- }
-#endif
- return(subset);
-
-} /* end of cuddUnderApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Applies the remapping underappoximation algorithm.]
-
- Description [Applies the remapping underappoximation algorithm.
- Proceeds in three phases:
- <ul>
- <li> collect information on each node in the BDD; this is done via DFS.
- <li> traverse the BDD in top-down fashion and compute for each node
- whether remapping increases density.
- <li> traverse the BDD via DFS and actually perform the elimination.
- </ul>
- Returns the approximated BDD if successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [Cudd_RemapUnderApprox]
-
-******************************************************************************/
-DdNode *
-cuddRemapUnderApprox(
- DdManager * dd /* DD manager */,
- DdNode * f /* current DD */,
- int numVars /* maximum number of variables */,
- int threshold /* threshold under which approximation stops */,
- double quality /* minimum improvement for accepted changes */)
-{
- ApproxInfo *info;
- DdNode *subset;
- int result;
-
- if (f == NULL) {
- fprintf(dd->err, "Cannot subset, nil object\n");
- dd->errorCode = CUDD_INVALID_ARG;
- return(NULL);
- }
-
- if (Cudd_IsConstant(f)) {
- return(f);
- }
-
- /* Create table where node data are accessible via a hash table. */
- info = gatherInfo(dd, f, numVars, TRUE);
- if (info == NULL) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
-
- /* Mark nodes that should be replaced by zero. */
- result = RAmarkNodes(dd, f, info, threshold, quality);
- if (result == 0) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
-
- /* Build the result. */
- subset = RAbuildSubset(dd, f, info);
-#if 1
- if (subset && info->size < Cudd_DagSize(subset))
- (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
- info->size, Cudd_DagSize(subset));
-#endif
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
-
-#ifdef DD_DEBUG
- if (subset != NULL) {
- cuddRef(subset);
-#if 0
- (void) Cudd_DebugCheck(dd);
- (void) Cudd_CheckKeys(dd);
-#endif
- if (!Cudd_bddLeq(dd, subset, f)) {
- (void) fprintf(dd->err, "Wrong subset\n");
- }
- cuddDeref(subset);
- dd->errorCode = CUDD_INTERNAL_ERROR;
- }
-#endif
- return(subset);
-
-} /* end of cuddRemapUnderApprox */
-
-
-/**Function********************************************************************
-
- Synopsis [Applies the biased remapping underappoximation algorithm.]
-
- Description [Applies the biased remapping underappoximation algorithm.
- Proceeds in three phases:
- <ul>
- <li> collect information on each node in the BDD; this is done via DFS.
- <li> traverse the BDD in top-down fashion and compute for each node
- whether remapping increases density.
- <li> traverse the BDD via DFS and actually perform the elimination.
- </ul>
- Returns the approximated BDD if successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [Cudd_BiasedUnderApprox]
-
-******************************************************************************/
-DdNode *
-cuddBiasedUnderApprox(
- DdManager *dd /* DD manager */,
- DdNode *f /* current DD */,
- DdNode *b /* bias function */,
- int numVars /* maximum number of variables */,
- int threshold /* threshold under which approximation stops */,
- double quality1 /* minimum improvement for accepted changes when b=1 */,
- double quality0 /* minimum improvement for accepted changes when b=1 */)
-{
- ApproxInfo *info;
- DdNode *subset;
- int result;
- DdHashTable *cache;
-
- if (f == NULL) {
- fprintf(dd->err, "Cannot subset, nil object\n");
- dd->errorCode = CUDD_INVALID_ARG;
- return(NULL);
- }
-
- if (Cudd_IsConstant(f)) {
- return(f);
- }
-
- /* Create table where node data are accessible via a hash table. */
- info = gatherInfo(dd, f, numVars, TRUE);
- if (info == NULL) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
-
- cache = cuddHashTableInit(dd,2,2);
- result = BAapplyBias(dd, Cudd_Regular(f), b, info, cache);
- if (result == CARE_ERROR) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- cuddHashTableQuit(cache);
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
- cuddHashTableQuit(cache);
-
- /* Mark nodes that should be replaced by zero. */
- result = BAmarkNodes(dd, f, info, threshold, quality1, quality0);
- if (result == 0) {
- (void) fprintf(dd->err, "Out-of-memory; Cannot subset\n");
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
-
- /* Build the result. */
- subset = RAbuildSubset(dd, f, info);
-#if 1
- if (subset && info->size < Cudd_DagSize(subset))
- (void) fprintf(dd->err, "Wrong prediction: %d versus actual %d\n",
- info->size, Cudd_DagSize(subset));
-#endif
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
-
-#ifdef DD_DEBUG
- if (subset != NULL) {
- cuddRef(subset);
-#if 0
- (void) Cudd_DebugCheck(dd);
- (void) Cudd_CheckKeys(dd);
-#endif
- if (!Cudd_bddLeq(dd, subset, f)) {
- (void) fprintf(dd->err, "Wrong subset\n");
- }
- cuddDeref(subset);
- dd->errorCode = CUDD_INTERNAL_ERROR;
- }
-#endif
- return(subset);
-
-} /* end of cuddBiasedUnderApprox */
-
-
-/*---------------------------------------------------------------------------*/
-/* Definition of static functions */
-/*---------------------------------------------------------------------------*/
-
-
-/**Function********************************************************************
-
- Synopsis [Recursively update the parity of the paths reaching a node.]
-
- Description [Recursively update the parity of the paths reaching a node.
- Assumes that node is regular and propagates the invariant.]
-
- SideEffects [None]
-
- SeeAlso [gatherInfoAux]
-
-******************************************************************************/
-static void
-updateParity(
- DdNode * node /* function to analyze */,
- ApproxInfo * info /* info on BDD */,
- int newparity /* new parity for node */)
-{
- NodeData *infoN;
- DdNode *E;
-
- if (!st_lookup(info->table, (char *)node, (char **)&infoN)) return;
- if ((infoN->parity & newparity) != 0) return;
- infoN->parity |= newparity;
- if (Cudd_IsConstant(node)) return;
- updateParity(cuddT(node),info,newparity);
- E = cuddE(node);
- if (Cudd_IsComplement(E)) {
- updateParity(Cudd_Not(E),info,3-newparity);
- } else {
- updateParity(E,info,newparity);
- }
- return;
-
-} /* end of updateParity */
-
-
-/**Function********************************************************************
-
- Synopsis [Recursively counts minterms and computes reference counts
- of each node in the BDD.]
-
- Description [Recursively counts minterms and computes reference
- counts of each node in the BDD. 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). It assumes
- that the node pointer passed to it is regular and it maintains the
- invariant.]
-
- SideEffects [None]
-
- SeeAlso [gatherInfo]
-
-******************************************************************************/
-static NodeData *
-gatherInfoAux(
- DdNode * node /* function to analyze */,
- ApproxInfo * info /* info on BDD */,
- int parity /* gather parity information */)
-{
- DdNode *N, *Nt, *Ne;
- NodeData *infoN, *infoT, *infoE;
-
- N = Cudd_Regular(node);
-
- /* Check whether entry for this node exists. */
- if (st_lookup(info->table, (char *)N, (char **)&infoN)) {
- if (parity) {
- /* Update parity and propagate. */
- updateParity(N, info, 1 + (int) Cudd_IsComplement(node));
- }
- return(infoN);
- }
-
- /* Compute the cofactors. */
- Nt = Cudd_NotCond(cuddT(N), N != node);
- Ne = Cudd_NotCond(cuddE(N), N != node);
-
- infoT = gatherInfoAux(Nt, info, parity);
- if (infoT == NULL) return(NULL);
- infoE = gatherInfoAux(Ne, info, parity);
- if (infoE == NULL) return(NULL);
-
- infoT->functionRef++;
- infoE->functionRef++;
-
- /* Point to the correct location in the page. */
- infoN = &(info->page[info->index++]);
- infoN->parity |= 1 + (short) Cudd_IsComplement(node);
-
- infoN->mintermsP = infoT->mintermsP/2;
- infoN->mintermsN = infoT->mintermsN/2;
- if (Cudd_IsComplement(Ne) ^ Cudd_IsComplement(node)) {
- infoN->mintermsP += infoE->mintermsN/2;
- infoN->mintermsN += infoE->mintermsP/2;
- } else {
- infoN->mintermsP += infoE->mintermsP/2;
- infoN->mintermsN += infoE->mintermsN/2;
- }
-
- /* Insert entry for the node in the table. */
- if (st_insert(info->table,(char *)N, (char *)infoN) == ST_OUT_OF_MEM) {
- return(NULL);
- }
- return(infoN);
-
-} /* end of gatherInfoAux */
-
-
-/**Function********************************************************************
-
- Synopsis [Gathers information about each node.]
-
- Description [Counts minterms and computes reference counts of each
- node in the BDD . The minterm count is separately computed for the
- node and its complement. This is to avoid cancellation
- errors. Returns a pointer to the data structure holding the
- information gathered if successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddUnderApprox gatherInfoAux]
-
-******************************************************************************/
-static ApproxInfo *
-gatherInfo(
- DdManager * dd /* manager */,
- DdNode * node /* function to be analyzed */,
- int numVars /* number of variables node depends on */,
- int parity /* gather parity information */)
-{
- ApproxInfo *info;
- NodeData *infoTop;
-
- /* If user did not give numVars value, set it to the maximum
- ** exponent that the pow function can take. The -1 is due to the
- ** discrepancy in the value that pow takes and the value that
- ** log gives.
- */
- if (numVars == 0) {
- numVars = DBL_MAX_EXP - 1;
- }
-
- info = ALLOC(ApproxInfo,1);
- if (info == NULL) {
- dd->errorCode = CUDD_MEMORY_OUT;
- return(NULL);
- }
- info->max = pow(2.0,(double) numVars);
- info->one = DD_ONE(dd);
- info->zero = Cudd_Not(info->one);
- info->size = Cudd_DagSize(node);
- /* All the information gathered will be stored in a contiguous
- ** piece of memory, which is allocated here. This can be done
- ** efficiently because we have counted the number of nodes of the
- ** BDD. info->index points to the next available entry in the array
- ** that stores the per-node information. */
- info->page = ALLOC(NodeData,info->size);
- if (info->page == NULL) {
- dd->errorCode = CUDD_MEMORY_OUT;
- FREE(info);
- return(NULL);
- }
- memset(info->page, 0, info->size * sizeof(NodeData)); /* clear all page */
- info->table = st_init_table(st_ptrcmp,st_ptrhash);
- if (info->table == NULL) {
- FREE(info->page);
- FREE(info);
- return(NULL);
- }
- /* We visit the DAG in post-order DFS. Hence, the constant node is
- ** in first position, and the root of the DAG is in last position. */
-
- /* Info for the constant node: Initialize only fields different from 0. */
- if (st_insert(info->table, (char *)info->one, (char *)info->page) == ST_OUT_OF_MEM) {
- FREE(info->page);
- FREE(info);
- st_free_table(info->table);
- return(NULL);
- }
- info->page[0].mintermsP = info->max;
- info->index = 1;
-
- infoTop = gatherInfoAux(node,info,parity);
- if (infoTop == NULL) {
- FREE(info->page);
- st_free_table(info->table);
- FREE(info);
- return(NULL);
- }
- if (Cudd_IsComplement(node)) {
- info->minterms = infoTop->mintermsN;
- } else {
- info->minterms = infoTop->mintermsP;
- }
-
- infoTop->functionRef = 1;
- return(info);
-
-} /* end of gatherInfo */
-
-
-/**Function********************************************************************
-
- Synopsis [Counts the nodes that would be eliminated if a given node
- were replaced by zero.]
-
- Description [Counts the nodes that would be eliminated if a given
- node were replaced by zero. This procedure uses a queue passed by
- the caller for efficiency: since the queue is left empty at the
- endof the search, it can be reused as is by the next search. Returns
- the count (always striclty positive) if successful; 0 otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddUnderApprox]
-
-******************************************************************************/
-static int
-computeSavings(
- DdManager * dd,
- DdNode * f,
- DdNode * skip,
- ApproxInfo * info,
- DdLevelQueue * queue)
-{
- NodeData *infoN;
- LocalQueueItem *item;
- DdNode *node;
- int savings = 0;
-
- node = Cudd_Regular(f);
- skip = Cudd_Regular(skip);
- /* Insert the given node in the level queue. Its local reference
- ** count is set equal to the function reference count so that the
- ** search will continue from it when it is retrieved. */
- item = (LocalQueueItem *)
- cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
- if (item == NULL)
- return(0);
- (void) st_lookup(info->table, (char *)node, (char **)&infoN);
- item->localRef = infoN->functionRef;
-
- /* Process the queue. */
- while (queue->first != NULL) {
- item = (LocalQueueItem *) queue->first;
- node = item->node;
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
- if (node == skip) continue;
- (void) st_lookup(info->table, (char *)node, (char **)&infoN);
- if (item->localRef != infoN->functionRef) {
- /* This node is shared. */
- continue;
- }
- savings++;
- if (!cuddIsConstant(cuddT(node))) {
- item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
- cuddI(dd,cuddT(node)->index));
- if (item == NULL) return(0);
- item->localRef++;
- }
- if (!Cudd_IsConstant(cuddE(node))) {
- item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
- cuddI(dd,Cudd_Regular(cuddE(node))->index));
- if (item == NULL) return(0);
- item->localRef++;
- }
- }
-
-#ifdef DD_DEBUG
- /* At the end of a local search the queue should be empty. */
- assert(queue->size == 0);
-#endif
- return(savings);
-
-} /* end of computeSavings */
-
-
-/**Function********************************************************************
-
- Synopsis [Update function reference counts.]
-
- Description [Update function reference counts to account for replacement.
- Returns the number of nodes saved if successful; 0 otherwise.]
-
- SideEffects [None]
-
- SeeAlso [UAmarkNodes RAmarkNodes]
-
-******************************************************************************/
-static int
-updateRefs(
- DdManager * dd,
- DdNode * f,
- DdNode * skip,
- ApproxInfo * info,
- DdLevelQueue * queue)
-{
- NodeData *infoN;
- LocalQueueItem *item;
- DdNode *node;
- int savings = 0;
-
- node = Cudd_Regular(f);
- /* Insert the given node in the level queue. Its function reference
- ** count is set equal to 0 so that the search will continue from it
- ** when it is retrieved. */
- item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
- if (item == NULL)
- return(0);
- (void) st_lookup(info->table, (char *)node, (char **)&infoN);
- infoN->functionRef = 0;
-
- if (skip != NULL) {
- /* Increase the function reference count of the node to be skipped
- ** by 1 to account for the node pointing to it that will be created. */
- skip = Cudd_Regular(skip);
- (void) st_lookup(info->table, (char *)skip, (char **)&infoN);
- infoN->functionRef++;
- }
-
- /* Process the queue. */
- while (queue->first != NULL) {
- item = (LocalQueueItem *) queue->first;
- node = item->node;
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
- (void) st_lookup(info->table, (char *)node, (char **)&infoN);
- if (infoN->functionRef != 0) {
- /* This node is shared or must be skipped. */
- continue;
- }
- savings++;
- if (!cuddIsConstant(cuddT(node))) {
- item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
- cuddI(dd,cuddT(node)->index));
- if (item == NULL) return(0);
- (void) st_lookup(info->table, (char *)cuddT(node),
- (char **)&infoN);
- infoN->functionRef--;
- }
- if (!Cudd_IsConstant(cuddE(node))) {
- item = (LocalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
- cuddI(dd,Cudd_Regular(cuddE(node))->index));
- if (item == NULL) return(0);
- (void) st_lookup(info->table, (char *)Cudd_Regular(cuddE(node)),
- (char **)&infoN);
- infoN->functionRef--;
- }
- }
-
-#ifdef DD_DEBUG
- /* At the end of a local search the queue should be empty. */
- assert(queue->size == 0);
-#endif
- return(savings);
-
-} /* end of updateRefs */
-
-
-/**Function********************************************************************
-
- Synopsis [Marks nodes for replacement by zero.]
-
- Description [Marks nodes for replacement by zero. Returns 1 if successful;
- 0 otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddUnderApprox]
-
-******************************************************************************/
-static int
-UAmarkNodes(
- DdManager * dd /* manager */,
- DdNode * f /* function to be analyzed */,
- ApproxInfo * info /* info on BDD */,
- int threshold /* when to stop approximating */,
- int safe /* enforce safe approximation */,
- double quality /* minimum improvement for accepted changes */)
-{
- DdLevelQueue *queue;
- DdLevelQueue *localQueue;
- NodeData *infoN;
- GlobalQueueItem *item;
- DdNode *node;
- double numOnset;
- double impactP, impactN;
- int savings;
-
-#if 0
- (void) printf("initial size = %d initial minterms = %g\n",
- info->size, info->minterms);
-#endif
- queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
- if (queue == NULL) {
- return(0);
- }
- localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
- dd->initSlots);
- if (localQueue == NULL) {
- cuddLevelQueueQuit(queue);
- return(0);
- }
- node = Cudd_Regular(f);
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
- if (item == NULL) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- if (Cudd_IsComplement(f)) {
- item->impactP = 0.0;
- item->impactN = 1.0;
- } else {
- item->impactP = 1.0;
- item->impactN = 0.0;
- }
- while (queue->first != NULL) {
- /* If the size of the subset is below the threshold, quit. */
- if (info->size <= threshold)
- break;
- item = (GlobalQueueItem *) queue->first;
- node = item->node;
- node = Cudd_Regular(node);
- (void) st_lookup(info->table, (char *)node, (char **)&infoN);
- if (safe && infoN->parity == 3) {
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
- continue;
- }
- impactP = item->impactP;
- impactN = item->impactN;
- numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
- savings = computeSavings(dd,node,NULL,info,localQueue);
- if (savings == 0) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
-#if 0
- (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
- node, impactP, impactN, numOnset, savings);
-#endif
- if ((1 - numOnset / info->minterms) >
- quality * (1 - (double) savings / info->size)) {
- infoN->replace = TRUE;
- info->size -= savings;
- info->minterms -=numOnset;
-#if 0
- (void) printf("replace: new size = %d new minterms = %g\n",
- info->size, info->minterms);
-#endif
- savings -= updateRefs(dd,node,NULL,info,localQueue);
- assert(savings == 0);
- continue;
- }
- if (!cuddIsConstant(cuddT(node))) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
- cuddI(dd,cuddT(node)->index));
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- if (!Cudd_IsConstant(cuddE(node))) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
- cuddI(dd,Cudd_Regular(cuddE(node))->index));
- if (Cudd_IsComplement(cuddE(node))) {
- item->impactP += impactN/2.0;
- item->impactN += impactP/2.0;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- }
-
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(1);
-
-} /* end of UAmarkNodes */
-
-
-/**Function********************************************************************
-
- Synopsis [Builds the subset BDD.]
-
- Description [Builds the subset BDD. Based on the info table,
- replaces selected nodes by zero. Returns a pointer to the result if
- successful; NULL otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddUnderApprox]
-
-******************************************************************************/
-static DdNode *
-UAbuildSubset(
- DdManager * dd /* DD manager */,
- DdNode * node /* current node */,
- ApproxInfo * info /* node info */)
-{
-
- DdNode *Nt, *Ne, *N, *t, *e, *r;
- NodeData *infoN;
-
- if (Cudd_IsConstant(node))
- return(node);
-
- N = Cudd_Regular(node);
-
- if (st_lookup(info->table, (char *)N, (char **)&infoN)) {
- if (infoN->replace == TRUE) {
- return(info->zero);
- }
- if (N == node ) {
- if (infoN->resultP != NULL) {
- return(infoN->resultP);
- }
- } else {
- if (infoN->resultN != NULL) {
- return(infoN->resultN);
- }
- }
- } else {
- (void) fprintf(dd->err,
- "Something is wrong, ought to be in info table\n");
- dd->errorCode = CUDD_INTERNAL_ERROR;
- return(NULL);
- }
-
- Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
- Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
-
- t = UAbuildSubset(dd, Nt, info);
- if (t == NULL) {
- return(NULL);
- }
- cuddRef(t);
-
- e = UAbuildSubset(dd, Ne, info);
- if (e == NULL) {
- Cudd_RecursiveDeref(dd,t);
- return(NULL);
- }
- cuddRef(e);
-
- if (Cudd_IsComplement(t)) {
- t = Cudd_Not(t);
- e = Cudd_Not(e);
- r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, e);
- Cudd_RecursiveDeref(dd, t);
- return(NULL);
- }
- r = Cudd_Not(r);
- } else {
- r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, e);
- Cudd_RecursiveDeref(dd, t);
- return(NULL);
- }
- }
- cuddDeref(t);
- cuddDeref(e);
-
- if (N == node) {
- infoN->resultP = r;
- } else {
- infoN->resultN = r;
- }
-
- return(r);
-
-} /* end of UAbuildSubset */
-
-
-/**Function********************************************************************
-
- Synopsis [Marks nodes for remapping.]
-
- Description [Marks nodes for remapping. Returns 1 if successful; 0
- otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddRemapUnderApprox]
-
-******************************************************************************/
-static int
-RAmarkNodes(
- DdManager * dd /* manager */,
- DdNode * f /* function to be analyzed */,
- ApproxInfo * info /* info on BDD */,
- int threshold /* when to stop approximating */,
- double quality /* minimum improvement for accepted changes */)
-{
- DdLevelQueue *queue;
- DdLevelQueue *localQueue;
- NodeData *infoN, *infoT, *infoE;
- GlobalQueueItem *item;
- DdNode *node, *T, *E;
- DdNode *shared; /* grandchild shared by the two children of node */
- double numOnset;
- double impact, impactP, impactN;
- double minterms;
- int savings;
- int replace;
-
-#if 0
- (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
- info->size, info->minterms);
-#endif
- queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
- if (queue == NULL) {
- return(0);
- }
- localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
- dd->initSlots);
- if (localQueue == NULL) {
- cuddLevelQueueQuit(queue);
- return(0);
- }
- /* Enqueue regular pointer to root and initialize impact. */
- node = Cudd_Regular(f);
- item = (GlobalQueueItem *)
- cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
- if (item == NULL) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- if (Cudd_IsComplement(f)) {
- item->impactP = 0.0;
- item->impactN = 1.0;
- } else {
- item->impactP = 1.0;
- item->impactN = 0.0;
- }
- /* The nodes retrieved here are guaranteed to be non-terminal.
- ** The initial node is not terminal because constant nodes are
- ** dealt with in the calling procedure. Subsequent nodes are inserted
- ** only if they are not terminal. */
- while (queue->first != NULL) {
- /* If the size of the subset is below the threshold, quit. */
- if (info->size <= threshold)
- break;
- item = (GlobalQueueItem *) queue->first;
- node = item->node;
-#ifdef DD_DEBUG
- assert(item->impactP >= 0 && item->impactP <= 1.0);
- assert(item->impactN >= 0 && item->impactN <= 1.0);
- assert(!Cudd_IsComplement(node));
- assert(!Cudd_IsConstant(node));
-#endif
- if (!st_lookup(info->table, (char *)node, (char **)&infoN)) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
-#ifdef DD_DEBUG
- assert(infoN->parity >= 1 && infoN->parity <= 3);
-#endif
- if (infoN->parity == 3) {
- /* This node can be reached through paths of different parity.
- ** It is not safe to replace it, because remapping will give
- ** an incorrect result, while replacement by 0 may cause node
- ** splitting. */
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
- continue;
- }
- T = cuddT(node);
- E = cuddE(node);
- shared = NULL;
- impactP = item->impactP;
- impactN = item->impactN;
- if (Cudd_bddLeq(dd,T,E)) {
- /* Here we know that E is regular. */
-#ifdef DD_DEBUG
- assert(!Cudd_IsComplement(E));
-#endif
- (void) st_lookup(info->table, (char *)T, (char **)&infoT);
- (void) st_lookup(info->table, (char *)E, (char **)&infoE);
- if (infoN->parity == 1) {
- impact = impactP;
- minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
- if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
- savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_E;
- } else {
-#ifdef DD_DEBUG
- assert(infoN->parity == 2);
-#endif
- impact = impactN;
- minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
- if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
- savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_T;
- }
- numOnset = impact * minterms;
- } else if (Cudd_bddLeq(dd,E,T)) {
- /* Here E may be complemented. */
- DdNode *Ereg = Cudd_Regular(E);
- (void) st_lookup(info->table, (char *)T, (char **)&infoT);
- (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE);
- if (infoN->parity == 1) {
- impact = impactP;
- minterms = infoT->mintermsP/2.0 -
- ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
- if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
- savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_T;
- } else {
-#ifdef DD_DEBUG
- assert(infoN->parity == 2);
-#endif
- impact = impactN;
- minterms = ((E == Ereg) ? infoE->mintermsN :
- infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
- if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
- savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_E;
- }
- numOnset = impact * minterms;
- } else {
- DdNode *Ereg = Cudd_Regular(E);
- DdNode *TT = cuddT(T);
- DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
- if (T->index == Ereg->index && TT == ET) {
- shared = TT;
- replace = REPLACE_TT;
- } else {
- DdNode *TE = cuddE(T);
- DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
- if (T->index == Ereg->index && TE == EE) {
- shared = TE;
- replace = REPLACE_TE;
- } else {
- replace = REPLACE_N;
- }
- }
- numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
- savings = computeSavings(dd,node,shared,info,localQueue);
- if (shared != NULL) {
- NodeData *infoS;
- (void) st_lookup(info->table, (char *)Cudd_Regular(shared),
- (char **)&infoS);
- if (Cudd_IsComplement(shared)) {
- numOnset -= (infoS->mintermsN * impactP +
- infoS->mintermsP * impactN)/2.0;
- } else {
- numOnset -= (infoS->mintermsP * impactP +
- infoS->mintermsN * impactN)/2.0;
- }
- savings--;
- }
- }
-
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
-#if 0
- if (replace == REPLACE_T || replace == REPLACE_E)
- (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
- node, impact, numOnset, savings);
- else
- (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
- node, impactP, impactN, numOnset, savings);
-#endif
- if ((1 - numOnset / info->minterms) >
- quality * (1 - (double) savings / info->size)) {
- infoN->replace = replace;
- info->size -= savings;
- info->minterms -=numOnset;
-#if 0
- (void) printf("remap(%d): new size = %d new minterms = %g\n",
- replace, info->size, info->minterms);
-#endif
- if (replace == REPLACE_N) {
- savings -= updateRefs(dd,node,NULL,info,localQueue);
- } else if (replace == REPLACE_T) {
- savings -= updateRefs(dd,node,E,info,localQueue);
- } else if (replace == REPLACE_E) {
- savings -= updateRefs(dd,node,T,info,localQueue);
- } else {
-#ifdef DD_DEBUG
- assert(replace == REPLACE_TT || replace == REPLACE_TE);
-#endif
- savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
- }
- assert(savings == 0);
- } else {
- replace = NOTHING;
- }
- if (replace == REPLACE_N) continue;
- if ((replace == REPLACE_E || replace == NOTHING) &&
- !cuddIsConstant(cuddT(node))) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
- cuddI(dd,cuddT(node)->index));
- if (replace == REPLACE_E) {
- item->impactP += impactP;
- item->impactN += impactN;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- if ((replace == REPLACE_T || replace == NOTHING) &&
- !Cudd_IsConstant(cuddE(node))) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
- cuddI(dd,Cudd_Regular(cuddE(node))->index));
- if (Cudd_IsComplement(cuddE(node))) {
- if (replace == REPLACE_T) {
- item->impactP += impactN;
- item->impactN += impactP;
- } else {
- item->impactP += impactN/2.0;
- item->impactN += impactP/2.0;
- }
- } else {
- if (replace == REPLACE_T) {
- item->impactP += impactP;
- item->impactN += impactN;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- }
- if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
- !Cudd_IsConstant(shared)) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
- cuddI(dd,Cudd_Regular(shared)->index));
- if (Cudd_IsComplement(shared)) {
- if (replace == REPLACE_T) {
- item->impactP += impactN;
- item->impactN += impactP;
- } else {
- item->impactP += impactN/2.0;
- item->impactN += impactP/2.0;
- }
- } else {
- if (replace == REPLACE_T) {
- item->impactP += impactP;
- item->impactN += impactN;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- }
- }
-
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(1);
-
-} /* end of RAmarkNodes */
-
-
-/**Function********************************************************************
-
- Synopsis [Marks nodes for remapping.]
-
- Description [Marks nodes for remapping. Returns 1 if successful; 0
- otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddRemapUnderApprox]
-
-******************************************************************************/
-static int
-BAmarkNodes(
- DdManager *dd /* manager */,
- DdNode *f /* function to be analyzed */,
- ApproxInfo *info /* info on BDD */,
- int threshold /* when to stop approximating */,
- double quality1 /* minimum improvement for accepted changes when b=1 */,
- double quality0 /* minimum improvement for accepted changes when b=0 */)
-{
- DdLevelQueue *queue;
- DdLevelQueue *localQueue;
- NodeData *infoN, *infoT, *infoE;
- GlobalQueueItem *item;
- DdNode *node, *T, *E;
- DdNode *shared; /* grandchild shared by the two children of node */
- double numOnset;
- double impact, impactP, impactN;
- double minterms;
- double quality;
- int savings;
- int replace;
-
-#if 0
- (void) fprintf(dd->out,"initial size = %d initial minterms = %g\n",
- info->size, info->minterms);
-#endif
- queue = cuddLevelQueueInit(dd->size,sizeof(GlobalQueueItem),info->size);
- if (queue == NULL) {
- return(0);
- }
- localQueue = cuddLevelQueueInit(dd->size,sizeof(LocalQueueItem),
- dd->initSlots);
- if (localQueue == NULL) {
- cuddLevelQueueQuit(queue);
- return(0);
- }
- /* Enqueue regular pointer to root and initialize impact. */
- node = Cudd_Regular(f);
- item = (GlobalQueueItem *)
- cuddLevelQueueEnqueue(queue,node,cuddI(dd,node->index));
- if (item == NULL) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- if (Cudd_IsComplement(f)) {
- item->impactP = 0.0;
- item->impactN = 1.0;
- } else {
- item->impactP = 1.0;
- item->impactN = 0.0;
- }
- /* The nodes retrieved here are guaranteed to be non-terminal.
- ** The initial node is not terminal because constant nodes are
- ** dealt with in the calling procedure. Subsequent nodes are inserted
- ** only if they are not terminal. */
- while (queue->first != NULL) {
- /* If the size of the subset is below the threshold, quit. */
- if (info->size <= threshold)
- break;
- item = (GlobalQueueItem *) queue->first;
- node = item->node;
-#ifdef DD_DEBUG
- assert(item->impactP >= 0 && item->impactP <= 1.0);
- assert(item->impactN >= 0 && item->impactN <= 1.0);
- assert(!Cudd_IsComplement(node));
- assert(!Cudd_IsConstant(node));
-#endif
- if (!st_lookup(info->table, (char *)node, (char **)&infoN)) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- quality = infoN->care ? quality1 : quality0;
-#ifdef DD_DEBUG
- assert(infoN->parity >= 1 && infoN->parity <= 3);
-#endif
- if (infoN->parity == 3) {
- /* This node can be reached through paths of different parity.
- ** It is not safe to replace it, because remapping will give
- ** an incorrect result, while replacement by 0 may cause node
- ** splitting. */
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
- continue;
- }
- T = cuddT(node);
- E = cuddE(node);
- shared = NULL;
- impactP = item->impactP;
- impactN = item->impactN;
- if (Cudd_bddLeq(dd,T,E)) {
- /* Here we know that E is regular. */
-#ifdef DD_DEBUG
- assert(!Cudd_IsComplement(E));
-#endif
- (void) st_lookup(info->table, (char *)T, (char **)&infoT);
- (void) st_lookup(info->table, (char *)E, (char **)&infoE);
- if (infoN->parity == 1) {
- impact = impactP;
- minterms = infoE->mintermsP/2.0 - infoT->mintermsP/2.0;
- if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
- savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_E;
- } else {
-#ifdef DD_DEBUG
- assert(infoN->parity == 2);
-#endif
- impact = impactN;
- minterms = infoT->mintermsN/2.0 - infoE->mintermsN/2.0;
- if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
- savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_T;
- }
- numOnset = impact * minterms;
- } else if (Cudd_bddLeq(dd,E,T)) {
- /* Here E may be complemented. */
- DdNode *Ereg = Cudd_Regular(E);
- (void) st_lookup(info->table, (char *)T, (char **)&infoT);
- (void) st_lookup(info->table, (char *)Ereg, (char **)&infoE);
- if (infoN->parity == 1) {
- impact = impactP;
- minterms = infoT->mintermsP/2.0 -
- ((E == Ereg) ? infoE->mintermsP : infoE->mintermsN)/2.0;
- if (infoT->functionRef == 1 && !Cudd_IsConstant(T)) {
- savings = 1 + computeSavings(dd,T,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_T;
- } else {
-#ifdef DD_DEBUG
- assert(infoN->parity == 2);
-#endif
- impact = impactN;
- minterms = ((E == Ereg) ? infoE->mintermsN :
- infoE->mintermsP)/2.0 - infoT->mintermsN/2.0;
- if (infoE->functionRef == 1 && !Cudd_IsConstant(E)) {
- savings = 1 + computeSavings(dd,E,NULL,info,localQueue);
- if (savings == 1) {
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(0);
- }
- } else {
- savings = 1;
- }
- replace = REPLACE_E;
- }
- numOnset = impact * minterms;
- } else {
- DdNode *Ereg = Cudd_Regular(E);
- DdNode *TT = cuddT(T);
- DdNode *ET = Cudd_NotCond(cuddT(Ereg), Cudd_IsComplement(E));
- if (T->index == Ereg->index && TT == ET) {
- shared = TT;
- replace = REPLACE_TT;
- } else {
- DdNode *TE = cuddE(T);
- DdNode *EE = Cudd_NotCond(cuddE(Ereg), Cudd_IsComplement(E));
- if (T->index == Ereg->index && TE == EE) {
- shared = TE;
- replace = REPLACE_TE;
- } else {
- replace = REPLACE_N;
- }
- }
- numOnset = infoN->mintermsP * impactP + infoN->mintermsN * impactN;
- savings = computeSavings(dd,node,shared,info,localQueue);
- if (shared != NULL) {
- NodeData *infoS;
- (void) st_lookup(info->table, (char *)Cudd_Regular(shared),
- (char **)&infoS);
- if (Cudd_IsComplement(shared)) {
- numOnset -= (infoS->mintermsN * impactP +
- infoS->mintermsP * impactN)/2.0;
- } else {
- numOnset -= (infoS->mintermsP * impactP +
- infoS->mintermsN * impactN)/2.0;
- }
- savings--;
- }
- }
-
- cuddLevelQueueDequeue(queue,cuddI(dd,node->index));
-#if 0
- if (replace == REPLACE_T || replace == REPLACE_E)
- (void) printf("node %p: impact = %g numOnset = %g savings %d\n",
- node, impact, numOnset, savings);
- else
- (void) printf("node %p: impact = %g/%g numOnset = %g savings %d\n",
- node, impactP, impactN, numOnset, savings);
-#endif
- if ((1 - numOnset / info->minterms) >
- quality * (1 - (double) savings / info->size)) {
- infoN->replace = replace;
- info->size -= savings;
- info->minterms -=numOnset;
-#if 0
- (void) printf("remap(%d): new size = %d new minterms = %g\n",
- replace, info->size, info->minterms);
-#endif
- if (replace == REPLACE_N) {
- savings -= updateRefs(dd,node,NULL,info,localQueue);
- } else if (replace == REPLACE_T) {
- savings -= updateRefs(dd,node,E,info,localQueue);
- } else if (replace == REPLACE_E) {
- savings -= updateRefs(dd,node,T,info,localQueue);
- } else {
-#ifdef DD_DEBUG
- assert(replace == REPLACE_TT || replace == REPLACE_TE);
-#endif
- savings -= updateRefs(dd,node,shared,info,localQueue) - 1;
- }
- assert(savings == 0);
- } else {
- replace = NOTHING;
- }
- if (replace == REPLACE_N) continue;
- if ((replace == REPLACE_E || replace == NOTHING) &&
- !cuddIsConstant(cuddT(node))) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,cuddT(node),
- cuddI(dd,cuddT(node)->index));
- if (replace == REPLACE_E) {
- item->impactP += impactP;
- item->impactN += impactN;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- if ((replace == REPLACE_T || replace == NOTHING) &&
- !Cudd_IsConstant(cuddE(node))) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(cuddE(node)),
- cuddI(dd,Cudd_Regular(cuddE(node))->index));
- if (Cudd_IsComplement(cuddE(node))) {
- if (replace == REPLACE_T) {
- item->impactP += impactN;
- item->impactN += impactP;
- } else {
- item->impactP += impactN/2.0;
- item->impactN += impactP/2.0;
- }
- } else {
- if (replace == REPLACE_T) {
- item->impactP += impactP;
- item->impactN += impactN;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- }
- if ((replace == REPLACE_TT || replace == REPLACE_TE) &&
- !Cudd_IsConstant(shared)) {
- item = (GlobalQueueItem *) cuddLevelQueueEnqueue(queue,Cudd_Regular(shared),
- cuddI(dd,Cudd_Regular(shared)->index));
- if (Cudd_IsComplement(shared)) {
- if (replace == REPLACE_T) {
- item->impactP += impactN;
- item->impactN += impactP;
- } else {
- item->impactP += impactN/2.0;
- item->impactN += impactP/2.0;
- }
- } else {
- if (replace == REPLACE_T) {
- item->impactP += impactP;
- item->impactN += impactN;
- } else {
- item->impactP += impactP/2.0;
- item->impactN += impactN/2.0;
- }
- }
- }
- }
-
- cuddLevelQueueQuit(queue);
- cuddLevelQueueQuit(localQueue);
- return(1);
-
-} /* end of BAmarkNodes */
-
-
-/**Function********************************************************************
-
- Synopsis [Builds the subset BDD for cuddRemapUnderApprox.]
-
- Description [Builds the subset BDDfor cuddRemapUnderApprox. Based
- on the info table, performs remapping or replacement at selected
- nodes. Returns a pointer to the result if successful; NULL
- otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddRemapUnderApprox]
-
-******************************************************************************/
-static DdNode *
-RAbuildSubset(
- DdManager * dd /* DD manager */,
- DdNode * node /* current node */,
- ApproxInfo * info /* node info */)
-{
- DdNode *Nt, *Ne, *N, *t, *e, *r;
- NodeData *infoN;
-
- if (Cudd_IsConstant(node))
- return(node);
-
- N = Cudd_Regular(node);
-
- Nt = Cudd_NotCond(cuddT(N), Cudd_IsComplement(node));
- Ne = Cudd_NotCond(cuddE(N), Cudd_IsComplement(node));
-
- if (st_lookup(info->table, (char *)N, (char **)&infoN)) {
- if (N == node ) {
- if (infoN->resultP != NULL) {
- return(infoN->resultP);
- }
- } else {
- if (infoN->resultN != NULL) {
- return(infoN->resultN);
- }
- }
- if (infoN->replace == REPLACE_T) {
- r = RAbuildSubset(dd, Ne, info);
- return(r);
- } else if (infoN->replace == REPLACE_E) {
- r = RAbuildSubset(dd, Nt, info);
- return(r);
- } else if (infoN->replace == REPLACE_N) {
- return(info->zero);
- } else if (infoN->replace == REPLACE_TT) {
- DdNode *Ntt = Cudd_NotCond(cuddT(cuddT(N)),
- Cudd_IsComplement(node));
- int index = cuddT(N)->index;
- DdNode *e = info->zero;
- DdNode *t = RAbuildSubset(dd, Ntt, info);
- if (t == NULL) {
- return(NULL);
- }
- cuddRef(t);
- if (Cudd_IsComplement(t)) {
- t = Cudd_Not(t);
- e = Cudd_Not(e);
- r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, t);
- return(NULL);
- }
- r = Cudd_Not(r);
- } else {
- r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, t);
- return(NULL);
- }
- }
- cuddDeref(t);
- return(r);
- } else if (infoN->replace == REPLACE_TE) {
- DdNode *Nte = Cudd_NotCond(cuddE(cuddT(N)),
- Cudd_IsComplement(node));
- int index = cuddT(N)->index;
- DdNode *t = info->one;
- DdNode *e = RAbuildSubset(dd, Nte, info);
- if (e == NULL) {
- return(NULL);
- }
- cuddRef(e);
- e = Cudd_Not(e);
- r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, e);
- return(NULL);
- }
- r =Cudd_Not(r);
- cuddDeref(e);
- return(r);
- }
- } else {
- (void) fprintf(dd->err,
- "Something is wrong, ought to be in info table\n");
- dd->errorCode = CUDD_INTERNAL_ERROR;
- return(NULL);
- }
-
- t = RAbuildSubset(dd, Nt, info);
- if (t == NULL) {
- return(NULL);
- }
- cuddRef(t);
-
- e = RAbuildSubset(dd, Ne, info);
- if (e == NULL) {
- Cudd_RecursiveDeref(dd,t);
- return(NULL);
- }
- cuddRef(e);
-
- if (Cudd_IsComplement(t)) {
- t = Cudd_Not(t);
- e = Cudd_Not(e);
- r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, e);
- Cudd_RecursiveDeref(dd, t);
- return(NULL);
- }
- r = Cudd_Not(r);
- } else {
- r = (t == e) ? t : cuddUniqueInter(dd, N->index, t, e);
- if (r == NULL) {
- Cudd_RecursiveDeref(dd, e);
- Cudd_RecursiveDeref(dd, t);
- return(NULL);
- }
- }
- cuddDeref(t);
- cuddDeref(e);
-
- if (N == node) {
- infoN->resultP = r;
- } else {
- infoN->resultN = r;
- }
-
- return(r);
-
-} /* end of RAbuildSubset */
-
-
-/**Function********************************************************************
-
- Synopsis [Finds don't care nodes.]
-
- Description [Finds don't care nodes by traversing f and b in parallel.
- Returns the care status of the visited f node if successful; CARE_ERROR
- otherwise.]
-
- SideEffects [None]
-
- SeeAlso [cuddBiasedUnderApprox]
-
-******************************************************************************/
-static int
-BAapplyBias(
- DdManager *dd,
- DdNode *f,
- DdNode *b,
- ApproxInfo *info,
- DdHashTable *cache)
-{
- DdNode *one, *zero, *res;
- DdNode *Ft, *Fe, *B, *Bt, *Be;
- unsigned int topf, topb;
- NodeData *infoF;
- int careT, careE;
-
- one = DD_ONE(dd);
- zero = Cudd_Not(one);
-
- if (!st_lookup(info->table, (char *) f, (char **)&infoF))
- return(CARE_ERROR);
- if (f == one) return(TOTAL_CARE);
- if (b == zero) return(infoF->care);
- if (infoF->care == TOTAL_CARE) return(TOTAL_CARE);
-
- if ((f->ref != 1 || Cudd_Regular(b)->ref != 1) &&
- (res = cuddHashTableLookup2(cache,f,b)) != NULL) {
- if (res->ref == 0) {
- cache->manager->dead++;
- cache->manager->constants.dead++;
- }
- return(infoF->care);
- }
-
- topf = dd->perm[f->index];
- B = Cudd_Regular(b);
- topb = cuddI(dd,B->index);
- if (topf <= topb) {
- Ft = cuddT(f); Fe = cuddE(f);
- } else {
- Ft = Fe = f;
- }
- if (topb <= topf) {
- /* We know that b is not constant because f is not. */
- Bt = cuddT(B); Be = cuddE(B);
- if (Cudd_IsComplement(b)) {
- Bt = Cudd_Not(Bt);
- Be = Cudd_Not(Be);
- }
- } else {
- Bt = Be = b;
- }
-
- careT = BAapplyBias(dd, Ft, Bt, info, cache);
- if (careT == CARE_ERROR)
- return(CARE_ERROR);
- careE = BAapplyBias(dd, Cudd_Regular(Fe), Be, info, cache);
- if (careE == CARE_ERROR)
- return(CARE_ERROR);
- if (careT == TOTAL_CARE && careE == TOTAL_CARE) {
- infoF->care = TOTAL_CARE;
- } else {
- infoF->care = CARE;
- }
-
- if (f->ref != 1 || Cudd_Regular(b)->ref != 1) {
- ptrint fanout = (ptrint) f->ref * Cudd_Regular(b)->ref;
- cuddSatDec(fanout);
- if (!cuddHashTableInsert2(cache,f,b,one,fanout)) {
- return(CARE_ERROR);
- }
- }
- return(infoF->care);
-
-} /* end of BAapplyBias */