ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
extraBddSymm.c File Reference
#include "extraBdd.h"
Include dependency graph for extraBddSymm.c:

Go to the source code of this file.

Macros

#define DD_GET_SYMM_VARS_TAG   0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */
 

Functions

Extra_SymmInfo_tExtra_SymmPairsCompute (DdManager *dd, DdNode *bFunc)
 
DdNode * Extra_zddSymmPairsCompute (DdManager *dd, DdNode *bF, DdNode *bVars)
 
DdNode * Extra_zddGetSymmetricVars (DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
 
DdNode * Extra_zddGetSingletons (DdManager *dd, DdNode *bVars)
 
DdNode * Extra_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)
 
DdNode * Extra_zddTuplesFromBdd (DdManager *dd, int K, DdNode *bVarsN)
 
DdNode * Extra_zddSelectOneSubset (DdManager *dd, DdNode *zS)
 
DdNode * extraZddSymmPairsCompute (DdManager *dd, DdNode *bFunc, DdNode *bVars)
 
DdNode * extraZddGetSymmetricVars (DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
 
DdNode * extraZddGetSingletons (DdManager *dd, DdNode *bVars)
 
DdNode * extraBddReduceVarSet (DdManager *dd, DdNode *bVars, DdNode *bF)
 
DdNode * extraBddCheckVarsSymmetric (DdManager *dd, DdNode *bF, DdNode *bVars)
 
DdNode * extraZddTuplesFromBdd (DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
 
DdNode * extraZddSelectOneSubset (DdManager *dd, DdNode *zS)
 

Macro Definition Documentation

◆ DD_GET_SYMM_VARS_TAG

#define DD_GET_SYMM_VARS_TAG   0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */

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 47 of file extraBddSymm.c.

Function Documentation

◆ Extra_bddCheckVarsSymmetric()

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 360 of file extraBddSymm.c.

365{
366 DdNode * bVars;
367 int Res;
368
369// return 1;
370
371 assert( iVar1 != iVar2 );
372 assert( iVar1 < dd->size );
373 assert( iVar2 < dd->size );
374
375 bVars = Cudd_bddAnd( dd, dd->vars[iVar1], dd->vars[iVar2] ); Cudd_Ref( bVars );
376
377 Res = (int)( extraBddCheckVarsSymmetric( dd, bF, bVars ) == b1 );
378
379 Cudd_RecursiveDeref( dd, bVars );
380
381 return Res;
382} /* end of Extra_bddCheckVarsSymmetric */
#define b1
Definition bbrImage.c:97
DdNode * extraBddCheckVarsSymmetric(DdManager *dd, DdNode *bF, DdNode *bVars)
#define assert(ex)
Definition util_old.h:213
Here is the call graph for this function:

◆ Extra_bddCheckVarsSymmetricNaive()

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 443 of file extraBddSymm.c.

448{
449 DdNode * bCube1, * bCube2;
450 DdNode * bCof01, * bCof10;
451 int Res;
452
453 assert( iVar1 != iVar2 );
454 assert( iVar1 < dd->size );
455 assert( iVar2 < dd->size );
456
457 bCube1 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar1] ), dd->vars[iVar2] ); Cudd_Ref( bCube1 );
458 bCube2 = Cudd_bddAnd( dd, Cudd_Not( dd->vars[iVar2] ), dd->vars[iVar1] ); Cudd_Ref( bCube2 );
459
460 bCof01 = Cudd_Cofactor( dd, bF, bCube1 ); Cudd_Ref( bCof01 );
461 bCof10 = Cudd_Cofactor( dd, bF, bCube2 ); Cudd_Ref( bCof10 );
462
463 Res = (int)( bCof10 == bCof01 );
464
465 Cudd_RecursiveDeref( dd, bCof01 );
466 Cudd_RecursiveDeref( dd, bCof10 );
467 Cudd_RecursiveDeref( dd, bCube1 );
468 Cudd_RecursiveDeref( dd, bCube2 );
469
470 return Res;
471} /* end of Extra_bddCheckVarsSymmetricNaive */
Here is the caller graph for this function:

◆ Extra_bddReduceVarSet()

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 181 of file extraBddSymm.c.

185{
186 DdNode * res;
187 do {
188 dd->reordered = 0;
189 res = extraBddReduceVarSet( dd, bVars, bF );
190 } while (dd->reordered == 1);
191 return(res);
192
193} /* end of Extra_bddReduceVarSet */
DdNode * extraBddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
Here is the call graph for this function:

◆ Extra_SymmPairsAllocate()

Extra_SymmInfo_t * Extra_SymmPairsAllocate ( int nVars)

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

Synopsis [Allocates symmetry information structure.]

Description []

SideEffects []

SeeAlso []

Definition at line 207 of file extraBddSymm.c.

208{
209 int i;
211
212 // allocate and clean the storage for symmetry info
214 memset( p, 0, sizeof(Extra_SymmInfo_t) );
215 p->nVars = nVars;
216 p->pVars = ABC_ALLOC( int, nVars );
217 p->pSymms = ABC_ALLOC( char *, nVars );
218 p->pSymms[0] = ABC_ALLOC( char , nVars * nVars );
219 memset( p->pSymms[0], 0, nVars * nVars * sizeof(char) );
220
221 for ( i = 1; i < nVars; i++ )
222 p->pSymms[i] = p->pSymms[i-1] + nVars;
223
224 return p;
225} /* end of Extra_SymmPairsAllocate */
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
Cube * p
Definition exorList.c:222
struct Extra_SymmInfo_t_ Extra_SymmInfo_t
Definition extraBdd.h:256
char * memset()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Extra_SymmPairsCompute()

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 73 of file extraBddSymm.c.

76{
77 DdNode * bSupp;
78 DdNode * zRes;
80
81 bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
82 zRes = Extra_zddSymmPairsCompute( dd, bFunc, bSupp ); Cudd_Ref( zRes );
83
84 p = Extra_SymmPairsCreateFromZdd( dd, zRes, bSupp );
85
86 Cudd_RecursiveDeref( dd, bSupp );
87 Cudd_RecursiveDerefZdd( dd, zRes );
88
89 return p;
90
91} /* end of Extra_SymmPairsCompute */
DdNode * Extra_zddSymmPairsCompute(DdManager *dd, DdNode *bF, DdNode *bVars)
Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd(DdManager *dd, DdNode *zPairs, DdNode *bSupp)
Here is the call graph for this function:

◆ Extra_SymmPairsComputeNaive()

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 396 of file extraBddSymm.c.

397{
398 DdNode * bSupp, * bTemp;
399 int nSuppSize;
401 int i, k;
402
403 // compute the support
404 bSupp = Cudd_Support( dd, bFunc ); Cudd_Ref( bSupp );
405 nSuppSize = Extra_bddSuppSize( dd, bSupp );
406//printf( "Support = %d. ", nSuppSize );
407//Extra_bddPrint( dd, bSupp );
408//printf( "%d ", nSuppSize );
409
410 // allocate the storage for symmetry info
411 p = Extra_SymmPairsAllocate( nSuppSize );
412
413 // assign the variables
414 p->nVarsMax = dd->size;
415 for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
416 p->pVars[i] = bTemp->index;
417
418 // go through the candidate pairs and check using Idea1
419 for ( i = 0; i < nSuppSize; i++ )
420 for ( k = i+1; k < nSuppSize; k++ )
421 {
422 p->pSymms[k][i] = p->pSymms[i][k] = Extra_bddCheckVarsSymmetricNaive( dd, bFunc, p->pVars[i], p->pVars[k] );
423 if ( p->pSymms[i][k] )
424 p->nSymms++;
425 }
426
427 Cudd_RecursiveDeref( dd, bSupp );
428 return p;
429
430} /* end of Extra_SymmPairsComputeNaive */
int Extra_bddCheckVarsSymmetricNaive(DdManager *dd, DdNode *bF, int iVar1, int iVar2)
Extra_SymmInfo_t * Extra_SymmPairsAllocate(int nVars)
int Extra_bddSuppSize(DdManager *dd, DdNode *bSupp)
Here is the call graph for this function:

◆ Extra_SymmPairsCreateFromZdd()

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 288 of file extraBddSymm.c.

289{
290 int i;
291 int nSuppSize;
293 int * pMapVars2Nums;
294 DdNode * bTemp;
295 DdNode * zSet, * zCube, * zTemp;
296 int iVar1, iVar2;
297
298 nSuppSize = Extra_bddSuppSize( dd, bSupp );
299
300 // allocate and clean the storage for symmetry info
301 p = Extra_SymmPairsAllocate( nSuppSize );
302
303 // allocate the storage for the temporary map
304 pMapVars2Nums = ABC_ALLOC( int, dd->size );
305 memset( pMapVars2Nums, 0, dd->size * sizeof(int) );
306
307 // assign the variables
308 p->nVarsMax = dd->size;
309// p->nNodes = Cudd_DagSize( zPairs );
310 p->nNodes = 0;
311 for ( i = 0, bTemp = bSupp; bTemp != b1; bTemp = cuddT(bTemp), i++ )
312 {
313 p->pVars[i] = bTemp->index;
314 pMapVars2Nums[bTemp->index] = i;
315 }
316
317 // write the symmetry info into the structure
318 zSet = zPairs; Cudd_Ref( zSet );
319 while ( zSet != z0 )
320 {
321 // get the next cube
322 zCube = Extra_zddSelectOneSubset( dd, zSet ); Cudd_Ref( zCube );
323
324 // add these two variables to the data structure
325 assert( cuddT( cuddT(zCube) ) == z1 );
326 iVar1 = zCube->index/2;
327 iVar2 = cuddT(zCube)->index/2;
328 if ( pMapVars2Nums[iVar1] < pMapVars2Nums[iVar2] )
329 p->pSymms[ pMapVars2Nums[iVar1] ][ pMapVars2Nums[iVar2] ] = 1;
330 else
331 p->pSymms[ pMapVars2Nums[iVar2] ][ pMapVars2Nums[iVar1] ] = 1;
332 // count the symmetric pairs
333 p->nSymms ++;
334
335 // update the cuver and deref the cube
336 zSet = Cudd_zddDiff( dd, zTemp = zSet, zCube ); Cudd_Ref( zSet );
337 Cudd_RecursiveDerefZdd( dd, zTemp );
338 Cudd_RecursiveDerefZdd( dd, zCube );
339
340 } // for each cube
341 Cudd_RecursiveDerefZdd( dd, zSet );
342
343 ABC_FREE( pMapVars2Nums );
344 return p;
345
346} /* end of Extra_SymmPairsCreateFromZdd */
#define ABC_FREE(obj)
Definition abc_global.h:267
DdNode * Extra_zddSelectOneSubset(DdManager *dd, DdNode *zS)
#define z0
Definition extraBdd.h:77
#define z1
Definition extraBdd.h:78
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Extra_SymmPairsDissolve()

void Extra_SymmPairsDissolve ( Extra_SymmInfo_t * p)

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

Synopsis [Deallocates symmetry information structure.]

Description []

SideEffects []

SeeAlso []

Definition at line 238 of file extraBddSymm.c.

239{
240 ABC_FREE( p->pVars );
241 ABC_FREE( p->pSymms[0] );
242 ABC_FREE( p->pSymms );
243 ABC_FREE( p );
244} /* end of Extra_SymmPairsDissolve */

◆ Extra_SymmPairsPrint()

void Extra_SymmPairsPrint ( Extra_SymmInfo_t * p)

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

Synopsis [Allocates symmetry information structure.]

Description []

SideEffects []

SeeAlso []

Definition at line 257 of file extraBddSymm.c.

258{
259 int i, k;
260 printf( "\n" );
261 for ( i = 0; i < p->nVars; i++ )
262 {
263 for ( k = 0; k <= i; k++ )
264 printf( " " );
265 for ( k = i+1; k < p->nVars; k++ )
266 if ( p->pSymms[i][k] )
267 printf( "1" );
268 else
269 printf( "." );
270 printf( "\n" );
271 }
272} /* end of Extra_SymmPairsPrint */

◆ Extra_zddGetSingletons()

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 157 of file extraBddSymm.c.

160{
161 DdNode * res;
162 do {
163 dd->reordered = 0;
164 res = extraZddGetSingletons( dd, bVars );
165 } while (dd->reordered == 1);
166 return(res);
167
168} /* end of Extra_zddGetSingletons */
DdNode * extraZddGetSingletons(DdManager *dd, DdNode *bVars)
Here is the call graph for this function:

◆ Extra_zddGetSymmetricVars()

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 130 of file extraBddSymm.c.

135{
136 DdNode * res;
137 do {
138 dd->reordered = 0;
139 res = extraZddGetSymmetricVars( dd, bF, bG, bVars );
140 } while (dd->reordered == 1);
141 return(res);
142
143} /* end of Extra_zddGetSymmetricVars */
DdNode * extraZddGetSymmetricVars(DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
Here is the call graph for this function:

◆ Extra_zddSelectOneSubset()

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 546 of file extraBddSymm.c.

549{
550 DdNode *res;
551 do {
552 dd->reordered = 0;
553 res = extraZddSelectOneSubset(dd, zS);
554 } while (dd->reordered == 1);
555 return(res);
556
557} /* end of Extra_zddSelectOneSubset */
DdNode * extraZddSelectOneSubset(DdManager *dd, DdNode *zS)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Extra_zddSymmPairsCompute()

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 105 of file extraBddSymm.c.

109{
110 DdNode * res;
111 do {
112 dd->reordered = 0;
113 res = extraZddSymmPairsCompute( dd, bF, bVars );
114 } while (dd->reordered == 1);
115 return(res);
116
117} /* end of Extra_zddSymmPairsCompute */
DdNode * extraZddSymmPairsCompute(DdManager *dd, DdNode *bFunc, DdNode *bVars)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Extra_zddTuplesFromBdd()

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 488 of file extraBddSymm.c.

492{
493 DdNode *zRes;
494 int autoDynZ;
495
496 autoDynZ = dd->autoDynZ;
497 dd->autoDynZ = 0;
498
499 do {
500 /* transform the numeric arguments (K) into a DdNode* argument;
501 * this allows us to use the standard internal CUDD cache */
502 DdNode *bVarSet = bVarsN, *bVarsK = bVarsN;
503 int nVars = 0, i;
504
505 /* determine the number of variables in VarSet */
506 while ( bVarSet != b1 )
507 {
508 nVars++;
509 /* make sure that the VarSet is a cube */
510 if ( cuddE( bVarSet ) != b0 )
511 return NULL;
512 bVarSet = cuddT( bVarSet );
513 }
514 /* make sure that the number of variables in VarSet is less or equal
515 that the number of variables that should be present in the tuples
516 */
517 if ( K > nVars )
518 return NULL;
519
520 /* the second argument in the recursive call stannds for <n>;
521 * reate the first argument, which stands for <k>
522 * as when we are talking about the tuple of <k> out of <n> */
523 for ( i = 0; i < nVars-K; i++ )
524 bVarsK = cuddT( bVarsK );
525
526 dd->reordered = 0;
527 zRes = extraZddTuplesFromBdd(dd, bVarsK, bVarsN );
528
529 } while (dd->reordered == 1);
530 dd->autoDynZ = autoDynZ;
531 return zRes;
532
533} /* end of Extra_zddTuplesFromBdd */
#define b0
Definition bbrImage.c:96
DdNode * extraZddTuplesFromBdd(DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
Here is the call graph for this function:

◆ extraBddCheckVarsSymmetric()

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 1169 of file extraBddSymm.c.

1173{
1174 DdNode * bRes;
1175
1176 if ( bF == b0 )
1177 return b1;
1178
1179 assert( bVars != b1 );
1180
1181 if ( (bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars)) )
1182 return bRes;
1183 else
1184 {
1185 DdNode * bRes0, * bRes1;
1186 DdNode * bF0, * bF1;
1187 DdNode * bFR = Cudd_Regular(bF);
1188 int LevelF = cuddI(dd,bFR->index);
1189
1190 DdNode * bVarsR = Cudd_Regular(bVars);
1191 int fVar1Pres;
1192 int iLev1;
1193 int iLev2;
1194
1195 if ( bVarsR != bVars ) // cube's pointer is complemented
1196 {
1197 assert( cuddT(bVarsR) == b1 );
1198 fVar1Pres = 1; // the first var is present on the path
1199 iLev1 = -1; // we are already below the first var level
1200 iLev2 = dd->perm[bVarsR->index]; // the level of the second var
1201 }
1202 else // cube's pointer is NOT complemented
1203 {
1204 fVar1Pres = 0; // the first var is absent on the path
1205 if ( cuddT(bVars) == b1 )
1206 {
1207 iLev1 = -1; // we are already below the first var level
1208 iLev2 = dd->perm[bVars->index]; // the level of the second var
1209 }
1210 else
1211 {
1212 assert( cuddT(cuddT(bVars)) == b1 );
1213 iLev1 = dd->perm[bVars->index]; // the level of the first var
1214 iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var
1215 }
1216 }
1217
1218 // cofactor the function
1219 // the cofactors are needed only if we are above the second level
1220 if ( LevelF < iLev2 )
1221 {
1222 if ( bFR != bF ) // bFunc is complemented
1223 {
1224 bF0 = Cudd_Not( cuddE(bFR) );
1225 bF1 = Cudd_Not( cuddT(bFR) );
1226 }
1227 else
1228 {
1229 bF0 = cuddE(bFR);
1230 bF1 = cuddT(bFR);
1231 }
1232 }
1233 else
1234 bF0 = bF1 = NULL;
1235
1236 // consider five cases:
1237 // (1) F is above iLev1
1238 // (2) F is on the level iLev1
1239 // (3) F is between iLev1 and iLev2
1240 // (4) F is on the level iLev2
1241 // (5) F is below iLev2
1242
1243 // (1) F is above iLev1
1244 if ( LevelF < iLev1 )
1245 {
1246 // the returned result cannot have the hash attribute
1247 // because we still did not reach the level of Var1;
1248 // the attribute never travels above the level of Var1
1249 bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
1250// assert( !Hash_IsComplement( bRes0 ) );
1251 assert( bRes0 != z0 );
1252 if ( bRes0 == b0 )
1253 bRes = b0;
1254 else
1255 bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars );
1256// assert( !Hash_IsComplement( bRes ) );
1257 assert( bRes != z0 );
1258 }
1259 // (2) F is on the level iLev1
1260 else if ( LevelF == iLev1 )
1261 {
1262 bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) );
1263 if ( bRes0 == b0 )
1264 bRes = b0;
1265 else
1266 {
1267 bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) );
1268 if ( bRes1 == b0 )
1269 bRes = b0;
1270 else
1271 {
1272// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
1273 if ( bRes0 == z0 || bRes1 == z0 )
1274 bRes = b1;
1275 else
1276 bRes = b0;
1277 }
1278 }
1279 }
1280 // (3) F is between iLev1 and iLev2
1281 else if ( LevelF < iLev2 )
1282 {
1283 bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars );
1284 if ( bRes0 == b0 )
1285 bRes = b0;
1286 else
1287 {
1288 bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars );
1289 if ( bRes1 == b0 )
1290 bRes = b0;
1291 else
1292 {
1293// if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) )
1294// bRes = Hash_Not( b1 );
1295 if ( bRes0 == z0 || bRes1 == z0 )
1296 bRes = z0;
1297 else
1298 bRes = b1;
1299 }
1300 }
1301 }
1302 // (4) F is on the level iLev2
1303 else if ( LevelF == iLev2 )
1304 {
1305 // this is the only place where the hash attribute (Hash_Not) can be added
1306 // to the result; it can be added only if the path came through the node
1307 // lebeled with Var1; therefore, the hash attribute cannot be returned
1308 // to the caller function
1309 if ( fVar1Pres )
1310// bRes = Hash_Not( b1 );
1311 bRes = z0;
1312 else
1313 bRes = b0;
1314 }
1315 // (5) F is below iLev2
1316 else // if ( LevelF > iLev2 )
1317 {
1318 // it is possible that the path goes through the node labeled by Var1
1319 // and still everything is okay; we do not label with Hash_Not here
1320 // because the path does not go through node labeled by Var2
1321 bRes = b1;
1322 }
1323
1324 cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes);
1325 return bRes;
1326 }
1327} /* end of extraBddCheckVarsSymmetric */
DdNode * extraBddCheckVarsSymmetric(DdManager *dd, DdNode *bF, DdNode *bVars)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ extraBddReduceVarSet()

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 1062 of file extraBddSymm.c.

1066{
1067 DdNode * bRes;
1068 DdNode * bFR = Cudd_Regular(bF);
1069
1070 if ( cuddIsConstant(bFR) || bVars == b1 )
1071 return bVars;
1072
1073 if ( (bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF)) )
1074 return bRes;
1075 else
1076 {
1077 DdNode * bF0, * bF1;
1078 DdNode * bVarsThis, * bVarsLower, * bTemp;
1079 int LevelF;
1080
1081 // if LevelF is below LevelV, scroll through the vars in bVars
1082 LevelF = dd->perm[bFR->index];
1083 for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) );
1084 // scroll also through the current var, because it should be not be added
1085 if ( LevelF == cuddI(dd,bVarsThis->index) )
1086 bVarsLower = cuddT(bVarsThis);
1087 else
1088 bVarsLower = bVarsThis;
1089
1090 // cofactor the function
1091 if ( bFR != bF ) // bFunc is complemented
1092 {
1093 bF0 = Cudd_Not( cuddE(bFR) );
1094 bF1 = Cudd_Not( cuddT(bFR) );
1095 }
1096 else
1097 {
1098 bF0 = cuddE(bFR);
1099 bF1 = cuddT(bFR);
1100 }
1101
1102 // solve subproblems
1103 bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 );
1104 if ( bRes == NULL )
1105 return NULL;
1106 cuddRef( bRes );
1107
1108 bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 );
1109 if ( bRes == NULL )
1110 {
1111 Cudd_RecursiveDeref( dd, bTemp );
1112 return NULL;
1113 }
1114 cuddRef( bRes );
1115 Cudd_RecursiveDeref( dd, bTemp );
1116
1117 // the current var should not be added
1118 // add the skipped vars
1119 if ( bVarsThis != bVars )
1120 {
1121 DdNode * bVarsExtra;
1122
1123 // extract the skipped variables
1124 bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis );
1125 if ( bVarsExtra == NULL )
1126 {
1127 Cudd_RecursiveDeref( dd, bRes );
1128 return NULL;
1129 }
1130 cuddRef( bVarsExtra );
1131
1132 // add these variables
1133 bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra );
1134 if ( bRes == NULL )
1135 {
1136 Cudd_RecursiveDeref( dd, bTemp );
1137 Cudd_RecursiveDeref( dd, bVarsExtra );
1138 return NULL;
1139 }
1140 cuddRef( bRes );
1141 Cudd_RecursiveDeref( dd, bTemp );
1142 Cudd_RecursiveDeref( dd, bVarsExtra );
1143 }
1144 cuddDeref( bRes );
1145
1146 cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes );
1147 return bRes;
1148 }
1149} /* end of extraBddReduceVarSet */
DdNode * extraBddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ extraZddGetSingletons()

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 1001 of file extraBddSymm.c.

1004{
1005 DdNode * zRes;
1006
1007 if ( bVars == b1 )
1008// if ( bVars == b0 ) // bug fixed by Jin Zhang, Jan 23, 2004
1009 return z1;
1010
1011 if ( (zRes = cuddCacheLookup1Zdd(dd, extraZddGetSingletons, bVars)) )
1012 return zRes;
1013 else
1014 {
1015 DdNode * zTemp, * zPlus;
1016
1017 // solve subproblem
1018 zRes = extraZddGetSingletons( dd, cuddT(bVars) );
1019 if ( zRes == NULL )
1020 return NULL;
1021 cuddRef( zRes );
1022
1023 zPlus = cuddZddGetNode( dd, 2*bVars->index, z1, z0 );
1024 if ( zPlus == NULL )
1025 {
1026 Cudd_RecursiveDerefZdd( dd, zRes );
1027 return NULL;
1028 }
1029 cuddRef( zPlus );
1030
1031 // add these to the result
1032 zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
1033 if ( zRes == NULL )
1034 {
1035 Cudd_RecursiveDerefZdd( dd, zTemp );
1036 Cudd_RecursiveDerefZdd( dd, zPlus );
1037 return NULL;
1038 }
1039 cuddRef( zRes );
1040 Cudd_RecursiveDerefZdd( dd, zTemp );
1041 Cudd_RecursiveDerefZdd( dd, zPlus );
1042 cuddDeref( zRes );
1043
1044 cuddCacheInsert1( dd, extraZddGetSingletons, bVars, zRes );
1045 return zRes;
1046 }
1047} /* end of extraZddGetSingletons */
DdNode * extraZddGetSingletons(DdManager *dd, DdNode *bVars)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ extraZddGetSymmetricVars()

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 804 of file extraBddSymm.c.

809{
810 DdNode * zRes;
811 DdNode * bFR = Cudd_Regular(bF);
812 DdNode * bGR = Cudd_Regular(bG);
813
814 if ( cuddIsConstant(bFR) && cuddIsConstant(bGR) )
815 {
816 if ( bF == bG )
817 return extraZddGetSingletons( dd, bVars );
818 else
819 return z0;
820 }
821 assert( bVars != b1 );
822
823 if ( (zRes = cuddCacheLookupZdd(dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars)) )
824 return zRes;
825 else
826 {
827 DdNode * zRes0, * zRes1;
828 DdNode * zPlus, * zTemp;
829 DdNode * bF0, * bF1;
830 DdNode * bG0, * bG1;
831 DdNode * bVarsNew;
832
833 int LevelF = cuddI(dd,bFR->index);
834 int LevelG = cuddI(dd,bGR->index);
835 int LevelFG;
836
837 if ( LevelF < LevelG )
838 LevelFG = LevelF;
839 else
840 LevelFG = LevelG;
841
842 // at least one of the arguments is not a constant
843 assert( LevelFG < dd->size );
844
845 // every variable in bF and bG should be also in bVars, therefore LevelFG cannot be above LevelV
846 // if LevelFG is below LevelV, scroll through the vars in bVars to the same level as LevelFG
847 for ( bVarsNew = bVars; LevelFG > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) );
848 assert( LevelFG == dd->perm[bVarsNew->index] );
849
850 // cofactor the functions
851 if ( LevelF == LevelFG )
852 {
853 if ( bFR != bF ) // bF is complemented
854 {
855 bF0 = Cudd_Not( cuddE(bFR) );
856 bF1 = Cudd_Not( cuddT(bFR) );
857 }
858 else
859 {
860 bF0 = cuddE(bFR);
861 bF1 = cuddT(bFR);
862 }
863 }
864 else
865 bF0 = bF1 = bF;
866
867 if ( LevelG == LevelFG )
868 {
869 if ( bGR != bG ) // bG is complemented
870 {
871 bG0 = Cudd_Not( cuddE(bGR) );
872 bG1 = Cudd_Not( cuddT(bGR) );
873 }
874 else
875 {
876 bG0 = cuddE(bGR);
877 bG1 = cuddT(bGR);
878 }
879 }
880 else
881 bG0 = bG1 = bG;
882
883 // solve subproblems
884 zRes0 = extraZddGetSymmetricVars( dd, bF0, bG0, cuddT(bVarsNew) );
885 if ( zRes0 == NULL )
886 return NULL;
887 cuddRef( zRes0 );
888
889 // if there is not symmetries in the negative cofactor
890 // there is no need to test the positive cofactor
891 if ( zRes0 == z0 )
892 zRes = zRes0; // zRes takes reference
893 else
894 {
895 zRes1 = extraZddGetSymmetricVars( dd, bF1, bG1, cuddT(bVarsNew) );
896 if ( zRes1 == NULL )
897 {
898 Cudd_RecursiveDerefZdd( dd, zRes0 );
899 return NULL;
900 }
901 cuddRef( zRes1 );
902
903 // only those variables should belong to the resulting set
904 // for which the property is true for both cofactors
905 zRes = cuddZddIntersect( dd, zRes0, zRes1 );
906 if ( zRes == NULL )
907 {
908 Cudd_RecursiveDerefZdd( dd, zRes0 );
909 Cudd_RecursiveDerefZdd( dd, zRes1 );
910 return NULL;
911 }
912 cuddRef( zRes );
913 Cudd_RecursiveDerefZdd( dd, zRes0 );
914 Cudd_RecursiveDerefZdd( dd, zRes1 );
915 }
916
917 // add one more singleton if the property is true for this variable
918 if ( bF0 == bG1 )
919 {
920 zPlus = cuddZddGetNode( dd, 2*bVarsNew->index, z1, z0 );
921 if ( zPlus == NULL )
922 {
923 Cudd_RecursiveDerefZdd( dd, zRes );
924 return NULL;
925 }
926 cuddRef( zPlus );
927
928 // add these variable pairs to the result
929 zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
930 if ( zRes == NULL )
931 {
932 Cudd_RecursiveDerefZdd( dd, zTemp );
933 Cudd_RecursiveDerefZdd( dd, zPlus );
934 return NULL;
935 }
936 cuddRef( zRes );
937 Cudd_RecursiveDerefZdd( dd, zTemp );
938 Cudd_RecursiveDerefZdd( dd, zPlus );
939 }
940
941 if ( bF == bG && bVars != bVarsNew )
942 {
943 // if the functions are equal, so are their cofactors
944 // add those variables from V that are above F and G
945
946 DdNode * bVarsExtra;
947
948 assert( LevelFG > dd->perm[bVars->index] );
949
950 // create the BDD of the extra variables
951 bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsNew );
952 if ( bVarsExtra == NULL )
953 {
954 Cudd_RecursiveDerefZdd( dd, zRes );
955 return NULL;
956 }
957 cuddRef( bVarsExtra );
958
959 zPlus = extraZddGetSingletons( dd, bVarsExtra );
960 if ( zPlus == NULL )
961 {
962 Cudd_RecursiveDeref( dd, bVarsExtra );
963 Cudd_RecursiveDerefZdd( dd, zRes );
964 return NULL;
965 }
966 cuddRef( zPlus );
967 Cudd_RecursiveDeref( dd, bVarsExtra );
968
969 // add these to the result
970 zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
971 if ( zRes == NULL )
972 {
973 Cudd_RecursiveDerefZdd( dd, zTemp );
974 Cudd_RecursiveDerefZdd( dd, zPlus );
975 return NULL;
976 }
977 cuddRef( zRes );
978 Cudd_RecursiveDerefZdd( dd, zTemp );
979 Cudd_RecursiveDerefZdd( dd, zPlus );
980 }
981 cuddDeref( zRes );
982
983 cuddCacheInsert( dd, DD_GET_SYMM_VARS_TAG, bF, bG, bVars, zRes );
984 return zRes;
985 }
986} /* end of extraZddGetSymmetricVars */
#define DD_GET_SYMM_VARS_TAG
Here is the call graph for this function:
Here is the caller graph for this function:

◆ extraZddSelectOneSubset()

DdNode * extraZddSelectOneSubset ( DdManager * dd,
DdNode * zS )

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

Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.]

Description []

SideEffects [None]

SeeAlso []

Definition at line 1419 of file extraBddSymm.c.

1424{
1425 DdNode * zRes;
1426
1427 if ( zS == z0 ) return z0;
1428 if ( zS == z1 ) return z1;
1429
1430 // check cache
1431 if ( (zRes = cuddCacheLookup1Zdd( dd, extraZddSelectOneSubset, zS )) )
1432 return zRes;
1433 else
1434 {
1435 DdNode * zS0, * zS1, * zTemp;
1436
1437 zS0 = cuddE(zS);
1438 zS1 = cuddT(zS);
1439
1440 if ( zS0 != z0 )
1441 {
1442 zRes = extraZddSelectOneSubset( dd, zS0 );
1443 if ( zRes == NULL )
1444 return NULL;
1445 }
1446 else // if ( zS0 == z0 )
1447 {
1448 assert( zS1 != z0 );
1449 zRes = extraZddSelectOneSubset( dd, zS1 );
1450 if ( zRes == NULL )
1451 return NULL;
1452 cuddRef( zRes );
1453
1454 zRes = cuddZddGetNode( dd, zS->index, zTemp = zRes, z0 );
1455 if ( zRes == NULL )
1456 {
1457 Cudd_RecursiveDerefZdd( dd, zTemp );
1458 return NULL;
1459 }
1460 cuddDeref( zTemp );
1461 }
1462
1463 // insert the result into cache
1464 cuddCacheInsert1( dd, extraZddSelectOneSubset, zS, zRes );
1465 return zRes;
1466 }
1467} /* end of extraZddSelectOneSubset */
DdNode * extraZddSelectOneSubset(DdManager *dd, DdNode *zS)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ extraZddSymmPairsCompute()

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 580 of file extraBddSymm.c.

584{
585 DdNode * zRes;
586 DdNode * bFR = Cudd_Regular(bFunc);
587
588 if ( cuddIsConstant(bFR) )
589 {
590 int nVars, i;
591
592 // determine how many vars are in the bVars
593 nVars = Extra_bddSuppSize( dd, bVars );
594 if ( nVars < 2 )
595 return z0;
596 else
597 {
598 DdNode * bVarsK;
599
600 // create the BDD bVarsK corresponding to K = 2;
601 bVarsK = bVars;
602 for ( i = 0; i < nVars-2; i++ )
603 bVarsK = cuddT( bVarsK );
604 return extraZddTuplesFromBdd( dd, bVarsK, bVars );
605 }
606 }
607 assert( bVars != b1 );
608
609 if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars)) )
610 return zRes;
611 else
612 {
613 DdNode * zRes0, * zRes1;
614 DdNode * zTemp, * zPlus, * zSymmVars;
615 DdNode * bF0, * bF1;
616 DdNode * bVarsNew;
617 int nVarsExtra;
618 int LevelF;
619
620 // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
621 // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
622 // count how many extra vars are there in bVars
623 nVarsExtra = 0;
624 LevelF = dd->perm[bFR->index];
625 for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
626 nVarsExtra++;
627 // the indexes (level) of variables should be synchronized now
628 assert( bFR->index == bVarsNew->index );
629
630 // cofactor the function
631 if ( bFR != bFunc ) // bFunc is complemented
632 {
633 bF0 = Cudd_Not( cuddE(bFR) );
634 bF1 = Cudd_Not( cuddT(bFR) );
635 }
636 else
637 {
638 bF0 = cuddE(bFR);
639 bF1 = cuddT(bFR);
640 }
641
642 // solve subproblems
643 zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) );
644 if ( zRes0 == NULL )
645 return NULL;
646 cuddRef( zRes0 );
647
648 // if there is no symmetries in the negative cofactor
649 // there is no need to test the positive cofactor
650 if ( zRes0 == z0 )
651 zRes = zRes0; // zRes takes reference
652 else
653 {
654 zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) );
655 if ( zRes1 == NULL )
656 {
657 Cudd_RecursiveDerefZdd( dd, zRes0 );
658 return NULL;
659 }
660 cuddRef( zRes1 );
661
662 // only those variables are pair-wise symmetric
663 // that are pair-wise symmetric in both cofactors
664 // therefore, intersect the solutions
665 zRes = cuddZddIntersect( dd, zRes0, zRes1 );
666 if ( zRes == NULL )
667 {
668 Cudd_RecursiveDerefZdd( dd, zRes0 );
669 Cudd_RecursiveDerefZdd( dd, zRes1 );
670 return NULL;
671 }
672 cuddRef( zRes );
673 Cudd_RecursiveDerefZdd( dd, zRes0 );
674 Cudd_RecursiveDerefZdd( dd, zRes1 );
675 }
676
677 // consider the current top-most variable and find all the vars
678 // that are pairwise symmetric with it
679 // these variables are returned as a set of ZDD singletons
680 zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) );
681 if ( zSymmVars == NULL )
682 {
683 Cudd_RecursiveDerefZdd( dd, zRes );
684 return NULL;
685 }
686 cuddRef( zSymmVars );
687
688 // attach the topmost variable to the set, to get the variable pairs
689 // use the positive polarity ZDD variable for the purpose
690
691 // there is no need to do so, if zSymmVars is empty
692 if ( zSymmVars == z0 )
693 Cudd_RecursiveDerefZdd( dd, zSymmVars );
694 else
695 {
696 zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 );
697 if ( zPlus == NULL )
698 {
699 Cudd_RecursiveDerefZdd( dd, zRes );
700 Cudd_RecursiveDerefZdd( dd, zSymmVars );
701 return NULL;
702 }
703 cuddRef( zPlus );
704 cuddDeref( zSymmVars );
705
706 // add these variable pairs to the result
707 zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
708 if ( zRes == NULL )
709 {
710 Cudd_RecursiveDerefZdd( dd, zTemp );
711 Cudd_RecursiveDerefZdd( dd, zPlus );
712 return NULL;
713 }
714 cuddRef( zRes );
715 Cudd_RecursiveDerefZdd( dd, zTemp );
716 Cudd_RecursiveDerefZdd( dd, zPlus );
717 }
718
719 // only zRes is referenced at this point
720
721 // if we skipped some variables, these variables cannot be symmetric with
722 // any variables that are currently in the support of bF, but they can be
723 // symmetric with the variables that are in bVars but not in the support of bF
724 if ( nVarsExtra )
725 {
726 // it is possible to improve this step:
727 // (1) there is no need to enter here, if nVarsExtra < 2
728
729 // create the set of topmost nVarsExtra in bVars
730 DdNode * bVarsExtra;
731 int nVars;
732
733 // remove from bVars all the variable that are in the support of bFunc
734 bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc );
735 if ( bVarsExtra == NULL )
736 {
737 Cudd_RecursiveDerefZdd( dd, zRes );
738 return NULL;
739 }
740 cuddRef( bVarsExtra );
741
742 // determine how many vars are in the bVarsExtra
743 nVars = Extra_bddSuppSize( dd, bVarsExtra );
744 if ( nVars < 2 )
745 {
746 Cudd_RecursiveDeref( dd, bVarsExtra );
747 }
748 else
749 {
750 int i;
751 DdNode * bVarsK;
752
753 // create the BDD bVarsK corresponding to K = 2;
754 bVarsK = bVarsExtra;
755 for ( i = 0; i < nVars-2; i++ )
756 bVarsK = cuddT( bVarsK );
757
758 // create the 2 variable tuples
759 zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra );
760 if ( zPlus == NULL )
761 {
762 Cudd_RecursiveDeref( dd, bVarsExtra );
763 Cudd_RecursiveDerefZdd( dd, zRes );
764 return NULL;
765 }
766 cuddRef( zPlus );
767 Cudd_RecursiveDeref( dd, bVarsExtra );
768
769 // add these to the result
770 zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
771 if ( zRes == NULL )
772 {
773 Cudd_RecursiveDerefZdd( dd, zTemp );
774 Cudd_RecursiveDerefZdd( dd, zPlus );
775 return NULL;
776 }
777 cuddRef( zRes );
778 Cudd_RecursiveDerefZdd( dd, zTemp );
779 Cudd_RecursiveDerefZdd( dd, zPlus );
780 }
781 }
782 cuddDeref( zRes );
783
784
785 /* insert the result into cache */
786 cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes);
787 return zRes;
788 }
789} /* end of extraZddSymmPairsCompute */
DdNode * extraZddSymmPairsCompute(DdManager *dd, DdNode *bF, DdNode *bVars)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ extraZddTuplesFromBdd()

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 1341 of file extraBddSymm.c.

1345{
1346 DdNode *zRes, *zRes0, *zRes1;
1347 statLine(dd);
1348
1349 /* terminal cases */
1350/* if ( k < 0 || k > n )
1351 * return dd->zero;
1352 * if ( n == 0 )
1353 * return dd->one;
1354 */
1355 if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) )
1356 return z0;
1357 if ( bVarsN == b1 )
1358 return z1;
1359
1360 /* check cache */
1361 zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN);
1362 if (zRes)
1363 return(zRes);
1364
1365 /* ZDD in which this variable is 0 */
1366/* zRes0 = extraZddTuplesFromBdd( dd, k, n-1 ); */
1367 zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) );
1368 if ( zRes0 == NULL )
1369 return NULL;
1370 cuddRef( zRes0 );
1371
1372 /* ZDD in which this variable is 1 */
1373/* zRes1 = extraZddTuplesFromBdd( dd, k-1, n-1 ); */
1374 if ( bVarsK == b1 )
1375 {
1376 zRes1 = z0;
1377 cuddRef( zRes1 );
1378 }
1379 else
1380 {
1381 zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) );
1382 if ( zRes1 == NULL )
1383 {
1384 Cudd_RecursiveDerefZdd( dd, zRes0 );
1385 return NULL;
1386 }
1387 cuddRef( zRes1 );
1388 }
1389
1390 /* compose Res0 and Res1 with the given ZDD variable */
1391 zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 );
1392 if ( zRes == NULL )
1393 {
1394 Cudd_RecursiveDerefZdd( dd, zRes0 );
1395 Cudd_RecursiveDerefZdd( dd, zRes1 );
1396 return NULL;
1397 }
1398 cuddDeref( zRes0 );
1399 cuddDeref( zRes1 );
1400
1401 /* insert the result into cache */
1402 cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes);
1403 return zRes;
1404
1405} /* end of extraZddTuplesFromBdd */
DdNode * extraZddTuplesFromBdd(DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
Here is the call graph for this function:
Here is the caller graph for this function: