src/misc/extra/extraBddSymm.c File Reference

#include "extra.h"
Include dependency graph for extraBddSymm.c:

Go to the source code of this file.

Defines

#define DD_GET_SYMM_VARS_TAG   0x0a

Functions

Extra_SymmInfo_tExtra_SymmPairsCompute (DdManager *dd, DdNode *bFunc)
DdNodeExtra_zddSymmPairsCompute (DdManager *dd, DdNode *bF, DdNode *bVars)
DdNodeExtra_zddGetSymmetricVars (DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
DdNodeExtra_zddGetSingletons (DdManager *dd, DdNode *bVars)
DdNodeExtra_bddReduceVarSet (DdManager *dd, DdNode *bVars, DdNode *bF)
Extra_SymmInfo_tExtra_SymmPairsAllocate (int nVars)
void Extra_SymmPairsDissolve (Extra_SymmInfo_t *p)
void Extra_SymmPairsPrint (Extra_SymmInfo_t *p)
Extra_SymmInfo_tExtra_SymmPairsCreateFromZdd (DdManager *dd, DdNode *zPairs, DdNode *bSupp)
int Extra_bddCheckVarsSymmetric (DdManager *dd, DdNode *bF, int iVar1, int iVar2)
Extra_SymmInfo_tExtra_SymmPairsComputeNaive (DdManager *dd, DdNode *bFunc)
int Extra_bddCheckVarsSymmetricNaive (DdManager *dd, DdNode *bF, int iVar1, int iVar2)
DdNodeExtra_zddTuplesFromBdd (DdManager *dd, int K, DdNode *bVarsN)
DdNodeExtra_zddSelectOneSubset (DdManager *dd, DdNode *zS)
DdNodeextraZddSymmPairsCompute (DdManager *dd, DdNode *bFunc, DdNode *bVars)
DdNodeextraZddGetSymmetricVars (DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
DdNodeextraZddGetSingletons (DdManager *dd, DdNode *bVars)
DdNodeextraBddReduceVarSet (DdManager *dd, DdNode *bVars, DdNode *bF)
DdNodeextraBddCheckVarsSymmetric (DdManager *dd, DdNode *bF, DdNode *bVars)
DdNodeextraZddTuplesFromBdd (DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
DdNodeextraZddSelectOneSubset (DdManager *dd, DdNode *zS)

Define Documentation

#define DD_GET_SYMM_VARS_TAG   0x0a

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

FileName [extraBddSymm.c]

PackageName [extra]

Synopsis [Efficient methods to compute the information about symmetric variables using the algorithm presented in the paper: A. Mishchenko. Fast Computation of Symmetries in Boolean Functions. Transactions on CAD, Nov. 2003.]

Author [Alan Mishchenko]

Affiliation [UC Berkeley]

Date [Ver. 2.0. Started - September 1, 2003.]

Revision [

Id
extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp

]

Definition at line 44 of file extraBddSymm.c.


Function Documentation

int Extra_bddCheckVarsSymmetric ( DdManager dd,
DdNode bF,
int  iVar1,
int  iVar2 
)

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

Synopsis [Checks the possibility of two variables being symmetric.]

Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.]

SideEffects []

SeeAlso []

Definition at line 357 of file extraBddSymm.c.

00362 {
00363     DdNode * bVars;
00364     int Res;
00365 
00366 //  return 1;
00367 
00368     assert( iVar1 != iVar2 );
00369     assert( iVar1 < dd->size );
00370     assert( iVar2 < dd->size );
00371 
00372     bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] );   Cudd_Ref( bVars );
00373 
00374     Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 );
00375 
00376     Cudd_RecursiveDeref( dd, bVars );
00377 
00378     return Res;
00379 } /* end of Extra_bddCheckVarsSymmetric */

int Extra_bddCheckVarsSymmetricNaive ( DdManager dd,
DdNode bF,
int  iVar1,
int  iVar2 
)

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

Synopsis [Checks if the two variables are symmetric.]

Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.]

SideEffects []

SeeAlso []

Definition at line 440 of file extraBddSymm.c.

00445 {
00446     DdNode * bCube1, * bCube2;
00447     DdNode * bCof01, * bCof10;
00448     int Res;
00449 
00450     assert( iVar1 != iVar2 );
00451     assert( iVar1 < dd->size );
00452     assert( iVar2 < dd->size );
00453 
00454     bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] );   Cudd_Ref( bCube1 );
00455     bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] );   Cudd_Ref( bCube2 );
00456 
00457     bCof01 = Cudd_Cofactor( dd, bF, bCube1 );  Cudd_Ref( bCof01 );
00458     bCof10 = Cudd_Cofactor( dd, bF, bCube2 );  Cudd_Ref( bCof10 );
00459 
00460     Res = (int)( bCof10 == bCof01 );
00461 
00462     Cudd_RecursiveDeref( dd, bCof01 );
00463     Cudd_RecursiveDeref( dd, bCof10 );
00464     Cudd_RecursiveDeref( dd, bCube1 );
00465     Cudd_RecursiveDeref( dd, bCube2 );
00466 
00467     return Res;
00468 } /* end of Extra_bddCheckVarsSymmetricNaive */

DdNode* Extra_bddReduceVarSet ( DdManager dd,
DdNode bVars,
DdNode bF 
)

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

Synopsis [Filters the set of variables using the support of the function.]

Description []

SideEffects []

SeeAlso []

Definition at line 178 of file extraBddSymm.c.

00182 {
00183     DdNode * res;
00184     do {
00185         dd->reordered = 0;
00186         res = extraBddReduceVarSet( dd, bVars, bF );
00187     } while (dd->reordered == 1);
00188     return(res);
00189 
00190 } /* end of Extra_bddReduceVarSet */

Extra_SymmInfo_t* Extra_SymmPairsAllocate ( int  nVars  ) 

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

Synopsis [Allocates symmetry information structure.]

Description []

SideEffects []

SeeAlso []

Definition at line 204 of file extraBddSymm.c.

00205 {
00206     int i;
00207     Extra_SymmInfo_t * p;
00208 
00209     // allocate and clean the storage for symmetry info
00210     p = ALLOC( Extra_SymmInfo_t, 1 );
00211     memset( p, 0, sizeof(Extra_SymmInfo_t) );
00212     p->nVars     = nVars;
00213     p->pVars     = ALLOC( int, nVars );  
00214     p->pSymms    = ALLOC( char *, nVars );  
00215     p->pSymms[0] = ALLOC( char  , nVars * nVars );
00216     memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) );
00217 
00218     for ( i = 1; i < nVars; i++ )
00219         p->pSymms[i] = p->pSymms[i-1] + nVars;
00220 
00221     return p;
00222 } /* end of Extra_SymmPairsAllocate */

Extra_SymmInfo_t* Extra_SymmPairsCompute ( DdManager dd,
DdNode bFunc 
)

AutomaticStart AutomaticEnd Function********************************************************************

Synopsis [Computes the classical symmetry information for the function.]

Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.]

SideEffects [If the ZDD variables are not derived from BDD variables with multiplicity 2, this function may derive them in a wrong way.]

SeeAlso []

Definition at line 70 of file extraBddSymm.c.

00073 {
00074     DdNode * bSupp;
00075     DdNode * zRes;
00076     Extra_SymmInfo_t * p;
00077 
00078     bSupp = Cudd_Support( dd, bFunc );                      Cudd_Ref( bSupp );
00079     zRes  = Extra_zddSymmPairsCompute( dd, bFunc, bSupp );  Cudd_Ref( zRes );
00080 
00081     p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp );
00082 
00083     Cudd_RecursiveDeref( dd, bSupp );
00084     Cudd_RecursiveDerefZdd( dd, zRes );
00085 
00086     return p;
00087 
00088 } /* end of Extra_SymmPairsCompute */

Extra_SymmInfo_t* Extra_SymmPairsComputeNaive ( DdManager dd,
DdNode bFunc 
)

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

Synopsis [Computes the classical symmetry information for the function.]

Description [Uses the naive way of comparing cofactors.]

SideEffects []

SeeAlso []

Definition at line 393 of file extraBddSymm.c.

00394 {
00395     DdNode * bSupp, * bTemp;
00396     int nSuppSize;
00397     Extra_SymmInfo_t * p;
00398     int i, k;
00399 
00400     // compute the support
00401     bSupp = Cudd_Support( dd, bFunc );   Cudd_Ref( bSupp );
00402     nSuppSize = Extra_bddSuppSize( dd, bSupp );
00403 //printf( "Support = %d. ", nSuppSize );
00404 //Extra_bddPrint( dd, bSupp );
00405 //printf( "%d ", nSuppSize );
00406 
00407     // allocate the storage for symmetry info
00408     p = Extra_SymmPairsAllocate( nSuppSize );
00409 
00410     // assign the variables
00411     p->nVarsMax = dd->size;
00412     for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
00413         p->pVars[i] = bTemp->index;
00414 
00415     // go through the candidate pairs and check using Idea1
00416     for ( i = 0; i < nSuppSize; i++ )
00417     for ( k = i+1; k < nSuppSize; k++ )
00418     {
00419         p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] );
00420         if ( p->pSymms[i][k] )
00421              p->nSymms++;
00422     }
00423 
00424     Cudd_RecursiveDeref( dd, bSupp );
00425     return p;
00426 
00427 } /* end of Extra_SymmPairsComputeNaive */

Extra_SymmInfo_t* Extra_SymmPairsCreateFromZdd ( DdManager dd,
DdNode zPairs,
DdNode bSupp 
)

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

Synopsis [Creates the symmetry information structure from ZDD.]

Description [ZDD representation of symmetries is the set of cubes, each of which has two variables in the positive polarity. These variables correspond to the symmetric variable pair.]

SideEffects []

SeeAlso []

Definition at line 285 of file extraBddSymm.c.

00286 {
00287     int i;
00288     int nSuppSize;
00289     Extra_SymmInfo_t * p;
00290     int * pMapVars2Nums;
00291     DdNode * bTemp;
00292     DdNode * zSet, * zCube, * zTemp;
00293     int iVar1, iVar2;
00294 
00295     nSuppSize = Extra_bddSuppSize( dd, bSupp );
00296 
00297     // allocate and clean the storage for symmetry info
00298     p = Extra_SymmPairsAllocate( nSuppSize );
00299 
00300     // allocate the storage for the temporary map
00301     pMapVars2Nums = ALLOC( int, dd->size );
00302     memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
00303 
00304     // assign the variables
00305     p->nVarsMax = dd->size;
00306 //  p->nNodes   = Cudd_DagSize( zPairs );
00307     p->nNodes   = 0;
00308     for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
00309     {
00310         p->pVars[i] = bTemp->index;
00311         pMapVars2Nums[bTemp->index] = i;
00312     }
00313 
00314     // write the symmetry info into the structure
00315     zSet = zPairs;   Cudd_Ref( zSet );
00316     while ( zSet != z0 )
00317     {
00318         // get the next cube
00319         zCube  = Extra_zddSelectOneSubset( dd, zSet );    Cudd_Ref( zCube );
00320 
00321         // add these two variables to the data structure
00322         assert( cuddT( cuddT(zCube) ) == z1 );
00323         iVar1 = zCube->index/2;
00324         iVar2 = cuddT(zCube)->index/2;
00325         if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] )
00326             p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1;
00327         else
00328             p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1;
00329         // count the symmetric pairs
00330         p->nSymms ++;
00331 
00332         // update the cuver and deref the cube
00333         zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube );     Cudd_Ref( zSet );
00334         Cudd_RecursiveDerefZdd( dd, zTemp );
00335         Cudd_RecursiveDerefZdd( dd, zCube );
00336 
00337     } // for each cube 
00338     Cudd_RecursiveDerefZdd( dd, zSet );
00339 
00340     FREE( pMapVars2Nums );
00341     return p;
00342 
00343 } /* end of Extra_SymmPairsCreateFromZdd */

void Extra_SymmPairsDissolve ( Extra_SymmInfo_t p  ) 

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

Synopsis [Deallocates symmetry information structure.]

Description []

SideEffects []

SeeAlso []

Definition at line 235 of file extraBddSymm.c.

00236 {
00237     free( p->pVars );
00238     free( p->pSymms[0] );
00239     free( p->pSymms    );
00240     free( p );
00241 } /* end of Extra_SymmPairsDissolve */

void Extra_SymmPairsPrint ( Extra_SymmInfo_t p  ) 

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

Synopsis [Allocates symmetry information structure.]

Description []

SideEffects []

SeeAlso []

Definition at line 254 of file extraBddSymm.c.

00255 {
00256     int i, k;
00257     printf( "\n" );
00258     for ( i = 0; i < p->nVars; i++ )
00259     {
00260         for ( k = 0; k <= i; k++ )
00261             printf( " " );
00262         for ( k = i+1; k < p->nVars; k++ )
00263             if ( p->pSymms[i][k] )
00264                 printf( "1" );
00265             else
00266                 printf( "." );
00267         printf( "\n" );
00268     }
00269 } /* end of Extra_SymmPairsPrint */

DdNode* Extra_zddGetSingletons ( DdManager dd,
DdNode bVars 
)

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

Synopsis [Converts a set of variables into a set of singleton subsets.]

Description []

SideEffects []

SeeAlso []

Definition at line 154 of file extraBddSymm.c.

00157 {
00158     DdNode * res;
00159     do {
00160         dd->reordered = 0;
00161         res = extraZddGetSingletons( dd, bVars );
00162     } while (dd->reordered == 1);
00163     return(res);
00164 
00165 } /* end of Extra_zddGetSingletons */

DdNode* Extra_zddGetSymmetricVars ( DdManager dd,
DdNode bF,
DdNode bG,
DdNode bVars 
)

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

Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.]

Description []

SideEffects []

SeeAlso []

Definition at line 127 of file extraBddSymm.c.

00132 {
00133     DdNode * res;
00134     do {
00135         dd->reordered = 0;
00136         res = extraZddGetSymmetricVars( dd, bF, bG, bVars );
00137     } while (dd->reordered == 1);
00138     return(res);
00139 
00140 } /* end of Extra_zddGetSymmetricVars */

DdNode* Extra_zddSelectOneSubset ( DdManager dd,
DdNode zS 
)

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

Synopsis [Selects one subset from the set of subsets represented by a ZDD.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 543 of file extraBddSymm.c.

00546 {
00547     DdNode  *res;
00548     do {
00549         dd->reordered = 0;
00550         res = extraZddSelectOneSubset(dd, zS);
00551     } while (dd->reordered == 1);
00552     return(res);
00553 
00554 } /* end of Extra_zddSelectOneSubset */

DdNode* Extra_zddSymmPairsCompute ( DdManager dd,
DdNode bF,
DdNode bVars 
)

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

Synopsis [Computes the classical symmetry information as a ZDD.]

Description []

SideEffects []

SeeAlso []

Definition at line 102 of file extraBddSymm.c.

00106 {
00107     DdNode * res;
00108     do {
00109         dd->reordered = 0;
00110         res = extraZddSymmPairsCompute( dd, bF, bVars );
00111     } while (dd->reordered == 1);
00112     return(res);
00113 
00114 } /* end of Extra_zddSymmPairsCompute */

DdNode* Extra_zddTuplesFromBdd ( DdManager dd,
int  K,
DdNode bVarsN 
)

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

Synopsis [Builds ZDD representing the set of fixed-size variable tuples.]

Description [Creates ZDD of all combinations of variables in Support that is represented by a BDD.]

SideEffects [New ZDD variables are created if indices of the variables present in the combination are larger than the currently allocated number of ZDD variables.]

SeeAlso []

Definition at line 485 of file extraBddSymm.c.

00489 {
00490     DdNode  *zRes;
00491     int     autoDynZ;
00492 
00493     autoDynZ = dd->autoDynZ;
00494     dd->autoDynZ = 0;
00495 
00496     do {
00497         /* transform the numeric arguments (K) into a DdNode* argument;
00498          * this allows us to use the standard internal CUDD cache */
00499         DdNode *bVarSet = bVarsN, *bVarsK = bVarsN;
00500         int     nVars = 0, i;
00501 
00502         /* determine the number of variables in VarSet */
00503         while ( bVarSet != b1 )
00504         {
00505             nVars++;
00506             /* make sure that the VarSet is a cube */
00507             if ( cuddE( bVarSet ) != b0 )
00508                 return NULL;
00509             bVarSet = cuddT( bVarSet );
00510         }
00511         /* make sure that the number of variables in VarSet is less or equal 
00512            that the number of variables that should be present in the tuples
00513         */
00514         if ( K > nVars )
00515             return NULL;
00516 
00517         /* the second argument in the recursive call stannds for <n>;
00518         /* reate the first argument, which stands for <k> 
00519          * as when we are talking about the tuple of <k> out of <n> */
00520         for ( i = 0; i < nVars-K; i++ )
00521             bVarsK = cuddT( bVarsK );
00522 
00523         dd->reordered = 0;
00524         zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN );
00525 
00526     } while (dd->reordered == 1);
00527     dd->autoDynZ = autoDynZ;
00528     return zRes;
00529 
00530 } /* end of Extra_zddTuplesFromBdd */

DdNode* extraBddCheckVarsSymmetric ( DdManager dd,
DdNode bF,
DdNode bVars 
)

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

Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().]

Description [Returns b0 if the variables are not symmetric. Returns b1 if the variables can be symmetric. The variables are represented in the form of a two-variable cube. In case the cube contains one variable (below Var1 level), the cube's pointer is complemented if the variable Var1 occurred on the current path; otherwise, the cube's pointer is regular. Uses additional complemented bit (Hash_Not) to mark the result if in the BDD rooted that this node there is a branch passing though the node labeled with Var2.]

SideEffects []

SeeAlso []

Definition at line 1166 of file extraBddSymm.c.

01170 {
01171     DdNode * bRes;
01172 
01173     if ( bF == b0 )
01174         return b1;
01175 
01176     assert( bVars != b1 );
01177     
01178     if ( bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars) )
01179         return bRes;
01180     else
01181     {
01182         DdNode * bRes0, * bRes1;
01183         DdNode * bF0, * bF1;             
01184         DdNode * bFR = Cudd_Regular(bF);
01185         int LevelF = cuddI(dd,bFR->index);
01186 
01187         DdNode * bVarsR = Cudd_Regular(bVars);
01188         int fVar1Pres;
01189         int iLev1;
01190         int iLev2;
01191 
01192         if ( bVarsR != bVars ) // cube's pointer is complemented
01193         {
01194             assert( cuddT(bVarsR) == b1 );
01195             fVar1Pres = 1;                    // the first var is present on the path
01196             iLev1 = -1;                       // we are already below the first var level
01197             iLev2 = dd->perm[bVarsR->index];  // the level of the second var
01198         }
01199         else  // cube's pointer is NOT complemented
01200         {
01201             fVar1Pres = 0;                    // the first var is absent on the path
01202             if ( cuddT(bVars) == b1 )
01203             {
01204                 iLev1 = -1;                             // we are already below the first var level 
01205                 iLev2 = dd->perm[bVars->index];         // the level of the second var
01206             }
01207             else
01208             {
01209                 assert( cuddT(cuddT(bVars)) == b1 );
01210                 iLev1 = dd->perm[bVars->index];         // the level of the first var 
01211                 iLev2 = dd->perm[cuddT(bVars)->index];  // the level of the second var
01212             }
01213         }
01214 
01215         // cofactor the function
01216         // the cofactors are needed only if we are above the second level
01217         if ( LevelF < iLev2 )
01218         {
01219             if ( bFR != bF ) // bFunc is complemented 
01220             {
01221                 bF0 = Cudd_Not( cuddE(bFR) );
01222                 bF1 = Cudd_Not( cuddT(bFR) );
01223             }
01224             else
01225             {
01226                 bF0 = cuddE(bFR);
01227                 bF1 = cuddT(bFR);
01228             }
01229         }
01230         else
01231             bF0 = bF1 = NULL;
01232 
01233         // consider five cases:
01234         // (1) F is above iLev1
01235         // (2) F is on the level iLev1
01236         // (3) F is between iLev1 and iLev2
01237         // (4) F is on the level iLev2
01238         // (5) F is below iLev2
01239 
01240         // (1) F is above iLev1
01241         if ( LevelF < iLev1 )
01242         {
01243             // the returned result cannot have the hash attribute
01244             // because we still did not reach the level of Var1;
01245             // the attribute never travels above the level of Var1
01246             bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
01247 //          assert( !Hash_IsComplement( bRes0 ) );
01248             assert( bRes0 != z0 );
01249             if ( bRes0 == b0 )
01250                 bRes = b0;
01251             else
01252                 bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars );
01253 //          assert( !Hash_IsComplement( bRes ) );
01254             assert( bRes != z0 );
01255         }
01256         // (2) F is on the level iLev1
01257         else if ( LevelF == iLev1 )
01258         {
01259             bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) );
01260             if ( bRes0 == b0 )
01261                 bRes = b0;
01262             else
01263             {
01264                 bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) );
01265                 if ( bRes1 == b0 )
01266                     bRes = b0;
01267                 else
01268                 {
01269 //                  if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
01270                     if ( bRes0 == z0 || bRes1 == z0 )
01271                         bRes = b1;
01272                     else
01273                         bRes = b0;
01274                 }
01275             }
01276         }
01277         // (3) F is between iLev1 and iLev2
01278         else if ( LevelF < iLev2 )
01279         {
01280             bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
01281             if ( bRes0 == b0 )
01282                 bRes = b0;
01283             else
01284             {
01285                 bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars );
01286                 if ( bRes1 == b0 )
01287                     bRes = b0;
01288                 else
01289                 {
01290 //                  if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
01291 //                      bRes = Hash_Not( b1 );
01292                     if ( bRes0 == z0 || bRes1 == z0 )
01293                         bRes = z0;
01294                     else
01295                         bRes = b1;
01296                 }
01297             }
01298         }
01299         // (4) F is on the level iLev2
01300         else if ( LevelF == iLev2 )
01301         {
01302             // this is the only place where the hash attribute (Hash_Not) can be added 
01303             // to the result; it can be added only if the path came through the node
01304             // lebeled with Var1; therefore, the hash attribute cannot be returned
01305             // to the caller function
01306             if ( fVar1Pres )
01307 //              bRes = Hash_Not( b1 );
01308                 bRes = z0;
01309             else 
01310                 bRes = b0;
01311         }
01312         // (5) F is below iLev2
01313         else // if ( LevelF > iLev2 )
01314         {
01315             // it is possible that the path goes through the node labeled by Var1
01316             // and still everything is okay; we do not label with Hash_Not here
01317             // because the path does not go through node labeled by Var2
01318             bRes = b1;
01319         }
01320 
01321         cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes);
01322         return bRes;
01323     }
01324 } /* end of extraBddCheckVarsSymmetric */

DdNode* extraBddReduceVarSet ( DdManager dd,
DdNode bVars,
DdNode bF 
)

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

Synopsis [Performs a recursive step of Extra_bddReduceVarSet.]

Description [Returns the set of all variables in the given set that are not in the support of the given function.]

SideEffects []

SeeAlso []

Definition at line 1059 of file extraBddSymm.c.

01063 {
01064     DdNode * bRes;
01065     DdNode * bFR = Cudd_Regular(bF);
01066 
01067     if ( cuddIsConstant(bFR) || bVars == b1 )
01068         return bVars;
01069 
01070     if ( bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF) )
01071         return bRes;
01072     else
01073     {
01074         DdNode * bF0, * bF1;             
01075         DdNode * bVarsThis, * bVarsLower, * bTemp;
01076         int LevelF;
01077 
01078         // if LevelF is below LevelV, scroll through the vars in bVars 
01079         LevelF = dd->perm[bFR->index];
01080         for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) );
01081         // scroll also through the current var, because it should be not be added
01082         if ( LevelF == cuddI(dd,bVarsThis->index) )
01083             bVarsLower = cuddT(bVarsThis);
01084         else
01085             bVarsLower = bVarsThis;
01086 
01087         // cofactor the function
01088         if ( bFR != bF ) // bFunc is complemented 
01089         {
01090             bF0 = Cudd_Not( cuddE(bFR) );
01091             bF1 = Cudd_Not( cuddT(bFR) );
01092         }
01093         else
01094         {
01095             bF0 = cuddE(bFR);
01096             bF1 = cuddT(bFR);
01097         }
01098 
01099         // solve subproblems
01100         bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 );
01101         if ( bRes == NULL ) 
01102             return NULL;
01103         cuddRef( bRes );
01104 
01105         bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 );
01106         if ( bRes == NULL ) 
01107         {
01108             Cudd_RecursiveDeref( dd, bTemp );
01109             return NULL;
01110         }
01111         cuddRef( bRes );
01112         Cudd_RecursiveDeref( dd, bTemp );
01113 
01114         // the current var should not be added
01115         // add the skipped vars
01116         if ( bVarsThis != bVars )
01117         {
01118             DdNode * bVarsExtra;
01119 
01120             // extract the skipped variables
01121             bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis );
01122             if ( bVarsExtra == NULL )
01123             {
01124                 Cudd_RecursiveDeref( dd, bRes );
01125                 return NULL;
01126             }
01127             cuddRef( bVarsExtra );
01128 
01129             // add these variables
01130             bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra );
01131             if ( bRes == NULL ) 
01132             {
01133                 Cudd_RecursiveDeref( dd, bTemp );
01134                 Cudd_RecursiveDeref( dd, bVarsExtra );
01135                 return NULL;
01136             }
01137             cuddRef( bRes );
01138             Cudd_RecursiveDeref( dd, bTemp );
01139             Cudd_RecursiveDeref( dd, bVarsExtra );
01140         }
01141         cuddDeref( bRes );
01142 
01143         cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes );
01144         return bRes;
01145     }
01146 }   /* end of extraBddReduceVarSet */

DdNode* extraZddGetSingletons ( DdManager dd,
DdNode bVars 
)

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

Synopsis [Performs a recursive step of Extra_zddGetSingletons.]

Description [Returns the set of ZDD singletons, containing those positive polarity ZDD variables that correspond to the BDD variables in bVars.]

SideEffects []

SeeAlso []

Definition at line 998 of file extraBddSymm.c.

01001 {
01002     DdNode * zRes;
01003 
01004     if ( bVars == b1 )
01005 //    if ( bVars == b0 )  // bug fixed by Jin Zhang, Jan 23, 2004
01006         return z1;
01007 
01008     if ( zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars) )
01009         return zRes;
01010     else
01011     {
01012         DdNode * zTemp, * zPlus;          
01013 
01014         // solve subproblem
01015         zRes = extraZddGetSingletons( dd, cuddT(bVars) );
01016         if ( zRes == NULL ) 
01017             return NULL;
01018         cuddRef( zRes );
01019         
01020         zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
01021         if ( zPlus == NULL ) 
01022         {
01023             Cudd_RecursiveDerefZdd( dd, zRes );
01024             return NULL;
01025         }
01026         cuddRef( zPlus );
01027 
01028         // add these to the result
01029         zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
01030         if ( zRes == NULL )
01031         {
01032             Cudd_RecursiveDerefZdd( dd, zTemp );
01033             Cudd_RecursiveDerefZdd( dd, zPlus );
01034             return NULL;
01035         }
01036         cuddRef( zRes );
01037         Cudd_RecursiveDerefZdd( dd, zTemp );
01038         Cudd_RecursiveDerefZdd( dd, zPlus );
01039         cuddDeref( zRes );
01040 
01041         cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes );
01042         return zRes;
01043     }
01044 }   /* end of extraZddGetSingletons */

DdNode* extraZddGetSymmetricVars ( DdManager dd,
DdNode bF,
DdNode bG,
DdNode bVars 
)

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

Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.]

Description [Returns the set of ZDD singletons, containing those positive ZDD variables that correspond to BDD variables x, for which it is true that bF(x=0) == bG(x=1).]

SideEffects []

SeeAlso []

Definition at line 801 of file extraBddSymm.c.

00806 {
00807     DdNode * zRes;
00808     DdNode * bFR = Cudd_Regular(bF); 
00809     DdNode * bGR = Cudd_Regular(bG); 
00810 
00811     if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) )
00812     {
00813         if ( bF == bG )
00814             return extraZddGetSingletons( dd, bVars );
00815         else 
00816             return z0;
00817     }
00818     assert( bVars != b1 );
00819 
00820     if ( zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars) )
00821         return zRes;
00822     else
00823     {
00824         DdNode * zRes0, * zRes1;             
00825         DdNode * zPlus, * zTemp;
00826         DdNode * bF0, * bF1;             
00827         DdNode * bG0, * bG1;             
00828         DdNode * bVarsNew;
00829     
00830         int LevelF = cuddI(dd,bFR->index);
00831         int LevelG = cuddI(dd,bGR->index);
00832         int LevelFG;
00833 
00834         if ( LevelF < LevelG )
00835             LevelFG = LevelF;
00836         else
00837             LevelFG = LevelG;
00838 
00839         // at least one of the arguments is not a constant
00840         assert( LevelFG < dd->size );
00841 
00842         // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV
00843         // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG
00844         for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) );
00845         assert( LevelFG == dd->perm[bVarsNew->index] );
00846 
00847         // cofactor the functions
00848         if ( LevelF == LevelFG )
00849         {
00850             if ( bFR != bF ) // bF is complemented 
00851             {
00852                 bF0 = Cudd_Not( cuddE(bFR) );
00853                 bF1 = Cudd_Not( cuddT(bFR) );
00854             }
00855             else
00856             {
00857                 bF0 = cuddE(bFR);
00858                 bF1 = cuddT(bFR);
00859             }
00860         }
00861         else 
00862             bF0 = bF1 = bF;
00863 
00864         if ( LevelG == LevelFG )
00865         {
00866             if ( bGR != bG ) // bG is complemented 
00867             {
00868                 bG0 = Cudd_Not( cuddE(bGR) );
00869                 bG1 = Cudd_Not( cuddT(bGR) );
00870             }
00871             else
00872             {
00873                 bG0 = cuddE(bGR);
00874                 bG1 = cuddT(bGR);
00875             }
00876         }
00877         else 
00878             bG0 = bG1 = bG;
00879 
00880         // solve subproblems
00881         zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) );
00882         if ( zRes0 == NULL ) 
00883             return NULL;
00884         cuddRef( zRes0 );
00885 
00886         // if there is not symmetries in the negative cofactor
00887         // there is no need to test the positive cofactor
00888         if ( zRes0 == z0 )
00889             zRes = zRes0;  // zRes takes reference
00890         else
00891         {
00892             zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) );
00893             if ( zRes1 == NULL ) 
00894             {
00895                 Cudd_RecursiveDerefZdd( dd, zRes0 );
00896                 return NULL;
00897             }
00898             cuddRef( zRes1 );
00899 
00900             // only those variables should belong to the resulting set 
00901             // for which the property is true for both cofactors
00902             zRes = cuddZddIntersect( dd, zRes0, zRes1 );
00903             if ( zRes == NULL )
00904             {
00905                 Cudd_RecursiveDerefZdd( dd, zRes0 );
00906                 Cudd_RecursiveDerefZdd( dd, zRes1 );
00907                 return NULL;
00908             }
00909             cuddRef( zRes );
00910             Cudd_RecursiveDerefZdd( dd, zRes0 );
00911             Cudd_RecursiveDerefZdd( dd, zRes1 );
00912         }
00913 
00914         // add one more singleton if the property is true for this variable
00915         if ( bF0 == bG1 )
00916         {
00917             zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
00918             if ( zPlus == NULL ) 
00919             {
00920                 Cudd_RecursiveDerefZdd( dd, zRes );
00921                 return NULL;
00922             }
00923             cuddRef( zPlus );
00924 
00925             // add these variable pairs to the result
00926             zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
00927             if ( zRes == NULL )
00928             {
00929                 Cudd_RecursiveDerefZdd( dd, zTemp );
00930                 Cudd_RecursiveDerefZdd( dd, zPlus );
00931                 return NULL;
00932             }
00933             cuddRef( zRes );
00934             Cudd_RecursiveDerefZdd( dd, zTemp );
00935             Cudd_RecursiveDerefZdd( dd, zPlus );
00936         }
00937 
00938         if ( bF == bG && bVars != bVarsNew )
00939         { 
00940             // if the functions are equal, so are their cofactors
00941             // add those variables from V that are above F and G 
00942 
00943             DdNode * bVarsExtra;
00944 
00945             assert( LevelFG > dd->perm[bVars->index] );
00946 
00947             // create the BDD of the extra variables
00948             bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew );
00949             if ( bVarsExtra == NULL )
00950             {
00951                 Cudd_RecursiveDerefZdd( dd, zRes );
00952                 return NULL;
00953             }
00954             cuddRef( bVarsExtra );
00955 
00956             zPlus = extraZddGetSingletons( dd, bVarsExtra );
00957             if ( zPlus == NULL )
00958             {
00959                 Cudd_RecursiveDeref( dd, bVarsExtra );
00960                 Cudd_RecursiveDerefZdd( dd, zRes );
00961                 return NULL;
00962             }
00963             cuddRef( zPlus );
00964             Cudd_RecursiveDeref( dd, bVarsExtra );
00965 
00966             // add these to the result
00967             zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
00968             if ( zRes == NULL )
00969             {
00970                 Cudd_RecursiveDerefZdd( dd, zTemp );
00971                 Cudd_RecursiveDerefZdd( dd, zPlus );
00972                 return NULL;
00973             }
00974             cuddRef( zRes );
00975             Cudd_RecursiveDerefZdd( dd, zTemp );
00976             Cudd_RecursiveDerefZdd( dd, zPlus );
00977         }
00978         cuddDeref( zRes );
00979 
00980         cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes );
00981         return zRes;
00982     }
00983 }   /* end of extraZddGetSymmetricVars */

DdNode* extraZddSelectOneSubset ( DdManager dd,
DdNode zS 
)

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

Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 1416 of file extraBddSymm.c.

01421 {
01422     DdNode * zRes;
01423 
01424     if ( zS == z0 )    return z0;
01425     if ( zS == z1 )    return z1;
01426     
01427     // check cache
01428     if ( zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS ) )
01429         return zRes;
01430     else
01431     {
01432         DdNode * zS0, * zS1, * zTemp; 
01433 
01434         zS0 = cuddE(zS);
01435         zS1 = cuddT(zS);
01436 
01437         if ( zS0 != z0 )
01438         {
01439             zRes = extraZddSelectOneSubset( dd, zS0 );
01440             if ( zRes == NULL )
01441                 return NULL;
01442         }
01443         else // if ( zS0 == z0 )
01444         {
01445             assert( zS1 != z0 );
01446             zRes = extraZddSelectOneSubset( dd, zS1 );
01447             if ( zRes == NULL )
01448                 return NULL;
01449             cuddRef( zRes );
01450 
01451             zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 );
01452             if ( zRes == NULL ) 
01453             {
01454                 Cudd_RecursiveDerefZdd( dd, zTemp );
01455                 return NULL;
01456             }
01457             cuddDeref( zTemp );
01458         }
01459 
01460         // insert the result into cache
01461         cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes );
01462         return zRes;
01463     }       
01464 } /* end of extraZddSelectOneSubset */

DdNode* extraZddSymmPairsCompute ( DdManager dd,
DdNode bFunc,
DdNode bVars 
)

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

Synopsis [Performs a recursive step of Extra_SymmPairsCompute.]

Description [Returns the set of symmetric variable pairs represented as a set of two-literal ZDD cubes. Both variables always appear in the positive polarity in the cubes. This function works without building new BDD nodes. Some relatively small number of ZDD nodes may be built to ensure proper bookkeeping of the symmetry information.]

SideEffects []

SeeAlso []

Definition at line 577 of file extraBddSymm.c.

00581 {
00582     DdNode * zRes;
00583     DdNode * bFR = Cudd_Regular(bFunc); 
00584 
00585     if ( cuddIsConstant(bFR) )
00586     {
00587         int nVars, i;
00588 
00589         // determine how many vars are in the bVars
00590         nVars = Extra_bddSuppSize( dd, bVars );
00591         if ( nVars < 2 )
00592             return z0;
00593         else
00594         {
00595             DdNode * bVarsK;
00596 
00597             // create the BDD bVarsK corresponding to K = 2;
00598             bVarsK = bVars;
00599             for ( i = 0; i < nVars-2; i++ )
00600                 bVarsK = cuddT( bVarsK );
00601             return extraZddTuplesFromBdd( dd, bVarsK, bVars );
00602         }
00603     }
00604     assert( bVars != b1 );
00605 
00606     if ( zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars) )
00607         return zRes;
00608     else
00609     {
00610         DdNode * zRes0, * zRes1;
00611         DdNode * zTemp, * zPlus, * zSymmVars;             
00612         DdNode * bF0, * bF1;             
00613         DdNode * bVarsNew;
00614         int nVarsExtra;
00615         int LevelF;
00616 
00617         // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
00618         // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
00619         // count how many extra vars are there in bVars
00620         nVarsExtra = 0;
00621         LevelF = dd->perm[bFR->index];
00622         for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
00623             nVarsExtra++; 
00624         // the indexes (level) of variables should be synchronized now
00625         assert( bFR->index == bVarsNew->index );
00626 
00627         // cofactor the function
00628         if ( bFR != bFunc ) // bFunc is complemented 
00629         {
00630             bF0 = Cudd_Not( cuddE(bFR) );
00631             bF1 = Cudd_Not( cuddT(bFR) );
00632         }
00633         else
00634         {
00635             bF0 = cuddE(bFR);
00636             bF1 = cuddT(bFR);
00637         }
00638 
00639         // solve subproblems
00640         zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) );
00641         if ( zRes0 == NULL )
00642             return NULL;
00643         cuddRef( zRes0 );
00644 
00645         // if there is no symmetries in the negative cofactor
00646         // there is no need to test the positive cofactor
00647         if ( zRes0 == z0 )
00648             zRes = zRes0;  // zRes takes reference
00649         else
00650         {
00651             zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) );
00652             if ( zRes1 == NULL )
00653             {
00654                 Cudd_RecursiveDerefZdd( dd, zRes0 );
00655                 return NULL;
00656             }
00657             cuddRef( zRes1 );
00658 
00659             // only those variables are pair-wise symmetric 
00660             // that are pair-wise symmetric in both cofactors
00661             // therefore, intersect the solutions
00662             zRes = cuddZddIntersect( dd, zRes0, zRes1 );
00663             if ( zRes == NULL )
00664             {
00665                 Cudd_RecursiveDerefZdd( dd, zRes0 );
00666                 Cudd_RecursiveDerefZdd( dd, zRes1 );
00667                 return NULL;
00668             }
00669             cuddRef( zRes );
00670             Cudd_RecursiveDerefZdd( dd, zRes0 );
00671             Cudd_RecursiveDerefZdd( dd, zRes1 );
00672         }
00673 
00674         // consider the current top-most variable and find all the vars
00675         // that are pairwise symmetric with it
00676         // these variables are returned as a set of ZDD singletons
00677         zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) );
00678         if ( zSymmVars == NULL )
00679         {
00680             Cudd_RecursiveDerefZdd( dd, zRes );
00681             return NULL;
00682         }
00683         cuddRef( zSymmVars );
00684 
00685         // attach the topmost variable to the set, to get the variable pairs
00686         // use the positive polarity ZDD variable for the purpose
00687 
00688         // there is no need to do so, if zSymmVars is empty
00689         if ( zSymmVars == z0 )
00690             Cudd_RecursiveDerefZdd( dd, zSymmVars );
00691         else
00692         {
00693             zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 );
00694             if ( zPlus == NULL ) 
00695             {
00696                 Cudd_RecursiveDerefZdd( dd, zRes );
00697                 Cudd_RecursiveDerefZdd( dd, zSymmVars );
00698                 return NULL;
00699             }
00700             cuddRef( zPlus );
00701             cuddDeref( zSymmVars );
00702 
00703             // add these variable pairs to the result
00704             zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
00705             if ( zRes == NULL )
00706             {
00707                 Cudd_RecursiveDerefZdd( dd, zTemp );
00708                 Cudd_RecursiveDerefZdd( dd, zPlus );
00709                 return NULL;
00710             }
00711             cuddRef( zRes );
00712             Cudd_RecursiveDerefZdd( dd, zTemp );
00713             Cudd_RecursiveDerefZdd( dd, zPlus );
00714         }
00715 
00716         // only zRes is referenced at this point
00717 
00718         // if we skipped some variables, these variables cannot be symmetric with
00719         // any variables that are currently in the support of bF, but they can be 
00720         // symmetric with the variables that are in bVars but not in the support of bF
00721         if ( nVarsExtra )
00722         {
00723             // it is possible to improve this step:
00724             // (1) there is no need to enter here, if nVarsExtra < 2
00725 
00726             // create the set of topmost nVarsExtra in bVars
00727             DdNode * bVarsExtra;
00728             int nVars;
00729 
00730             // remove from bVars all the variable that are in the support of bFunc
00731             bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc );  
00732             if ( bVarsExtra == NULL )
00733             {
00734                 Cudd_RecursiveDerefZdd( dd, zRes );
00735                 return NULL;
00736             }
00737             cuddRef( bVarsExtra );
00738 
00739             // determine how many vars are in the bVarsExtra
00740             nVars = Extra_bddSuppSize( dd, bVarsExtra );
00741             if ( nVars < 2 )
00742             {
00743                 Cudd_RecursiveDeref( dd, bVarsExtra );
00744             }
00745             else
00746             {
00747                 int i;
00748                 DdNode * bVarsK;
00749 
00750                 // create the BDD bVarsK corresponding to K = 2;
00751                 bVarsK = bVarsExtra;
00752                 for ( i = 0; i < nVars-2; i++ )
00753                     bVarsK = cuddT( bVarsK );
00754 
00755                 // create the 2 variable tuples
00756                 zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra );
00757                 if ( zPlus == NULL )
00758                 {
00759                     Cudd_RecursiveDeref( dd, bVarsExtra );
00760                     Cudd_RecursiveDerefZdd( dd, zRes );
00761                     return NULL;
00762                 }
00763                 cuddRef( zPlus );
00764                 Cudd_RecursiveDeref( dd, bVarsExtra );
00765 
00766                 // add these to the result
00767                 zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
00768                 if ( zRes == NULL )
00769                 {
00770                     Cudd_RecursiveDerefZdd( dd, zTemp );
00771                     Cudd_RecursiveDerefZdd( dd, zPlus );
00772                     return NULL;
00773                 }
00774                 cuddRef( zRes );
00775                 Cudd_RecursiveDerefZdd( dd, zTemp );
00776                 Cudd_RecursiveDerefZdd( dd, zPlus );
00777             }
00778         }
00779         cuddDeref( zRes );
00780 
00781 
00782         /* insert the result into cache */
00783         cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes);
00784         return zRes;
00785     }
00786 } /* end of extraZddSymmPairsCompute */

DdNode* extraZddTuplesFromBdd ( DdManager dd,
DdNode bVarsK,
DdNode bVarsN 
)

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

Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().]

Description [Generates in a bottom-up fashion ZDD for all combinations composed of k variables out of variables belonging to Support.]

SideEffects []

SeeAlso []

Definition at line 1338 of file extraBddSymm.c.

01342 {
01343     DdNode *zRes, *zRes0, *zRes1;
01344     statLine(dd); 
01345 
01346     /* terminal cases */
01347 /*  if ( k < 0 || k > n )
01348  *      return dd->zero;
01349  *  if ( n == 0 )
01350  *      return dd->one; 
01351  */
01352     if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) )
01353         return z0;
01354     if ( bVarsN == b1 )
01355         return z1;
01356 
01357     /* check cache */
01358     zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN);
01359     if (zRes)
01360         return(zRes);
01361 
01362     /* ZDD in which this variable is 0 */
01363 /*  zRes0 = extraZddTuplesFromBdd( dd, k,     n-1 ); */
01364     zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) );
01365     if ( zRes0 == NULL ) 
01366         return NULL;
01367     cuddRef( zRes0 );
01368 
01369     /* ZDD in which this variable is 1 */
01370 /*  zRes1 = extraZddTuplesFromBdd( dd, k-1,          n-1 ); */
01371     if ( bVarsK == b1 )
01372     {
01373         zRes1 = z0;
01374         cuddRef( zRes1 );
01375     }
01376     else
01377     {
01378         zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) );
01379         if ( zRes1 == NULL ) 
01380         {
01381             Cudd_RecursiveDerefZdd( dd, zRes0 );
01382             return NULL;
01383         }
01384         cuddRef( zRes1 );
01385     }
01386 
01387     /* compose Res0 and Res1 with the given ZDD variable */
01388     zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 );
01389     if ( zRes == NULL ) 
01390     {
01391         Cudd_RecursiveDerefZdd( dd, zRes0 );
01392         Cudd_RecursiveDerefZdd( dd, zRes1 );
01393         return NULL;
01394     }
01395     cuddDeref( zRes0 );
01396     cuddDeref( zRes1 );
01397 
01398     /* insert the result into cache */
01399     cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes);
01400     return zRes;
01401 
01402 } /* end of extraZddTuplesFromBdd */


Generated on Tue Jan 5 12:19:14 2010 for abc70930 by  doxygen 1.6.1