#include "extra.h"
Go to the source code of this file.
#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 [
]
Definition at line 44 of file extraBddSymm.c.
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 */
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 */
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.
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */