abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
extraBddSymm.c
Go to the documentation of this file.
1 /**CFile****************************************************************
2 
3  FileName [extraBddSymm.c]
4 
5  PackageName [extra]
6 
7  Synopsis [Efficient methods to compute the information about
8  symmetric variables using the algorithm presented in the paper:
9  A. Mishchenko. Fast Computation of Symmetries in Boolean Functions.
10  Transactions on CAD, Nov. 2003.]
11 
12  Author [Alan Mishchenko]
13 
14  Affiliation [UC Berkeley]
15 
16  Date [Ver. 2.0. Started - September 1, 2003.]
17 
18  Revision [$Id: extraBddSymm.c,v 1.0 2003/09/01 00:00:00 alanmi Exp $]
19 
20 ***********************************************************************/
21 
22 #include "extraBdd.h"
23 
25 
26 
27 /*---------------------------------------------------------------------------*/
28 /* Constant declarations */
29 /*---------------------------------------------------------------------------*/
30 
31 /*---------------------------------------------------------------------------*/
32 /* Stucture declarations */
33 /*---------------------------------------------------------------------------*/
34 
35 /*---------------------------------------------------------------------------*/
36 /* Type declarations */
37 /*---------------------------------------------------------------------------*/
38 
39 /*---------------------------------------------------------------------------*/
40 /* Variable declarations */
41 /*---------------------------------------------------------------------------*/
42 
43 /*---------------------------------------------------------------------------*/
44 /* Macro declarations */
45 /*---------------------------------------------------------------------------*/
46 
47 #define DD_GET_SYMM_VARS_TAG 0x0a /* former DD_BDD_XOR_EXIST_ABSTRACT_TAG */
48 
49 /**AutomaticStart*************************************************************/
50 
51 /*---------------------------------------------------------------------------*/
52 /* Static function prototypes */
53 /*---------------------------------------------------------------------------*/
54 
55 /**AutomaticEnd***************************************************************/
56 
57 /*---------------------------------------------------------------------------*/
58 /* Definition of exported functions */
59 /*---------------------------------------------------------------------------*/
60 
61 /**Function********************************************************************
62 
63  Synopsis [Computes the classical symmetry information for the function.]
64 
65  Description [Returns the symmetry information in the form of Extra_SymmInfo_t structure.]
66 
67  SideEffects [If the ZDD variables are not derived from BDD variables with
68  multiplicity 2, this function may derive them in a wrong way.]
69 
70  SeeAlso []
71 
72 ******************************************************************************/
74  DdManager * dd, /* the manager */
75  DdNode * bFunc) /* the function whose symmetries are computed */
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 */
92 
93 
94 /**Function********************************************************************
95 
96  Synopsis [Computes the classical symmetry information as a ZDD.]
97 
98  Description []
99 
100  SideEffects []
101 
102  SeeAlso []
103 
104 ******************************************************************************/
106  DdManager * dd, /* the DD manager */
107  DdNode * bF,
108  DdNode * bVars)
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 */
118 
119 /**Function********************************************************************
120 
121  Synopsis [Returns a singleton-set ZDD containing all variables that are symmetric with the given one.]
122 
123  Description []
124 
125  SideEffects []
126 
127  SeeAlso []
128 
129 ******************************************************************************/
131  DdManager * dd, /* the DD manager */
132  DdNode * bF, /* the first function - originally, the positive cofactor */
133  DdNode * bG, /* the second fucntion - originally, the negative cofactor */
134  DdNode * bVars) /* the set of variables, on which F and G depend */
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 */
144 
145 
146 /**Function********************************************************************
147 
148  Synopsis [Converts a set of variables into a set of singleton subsets.]
149 
150  Description []
151 
152  SideEffects []
153 
154  SeeAlso []
155 
156 ******************************************************************************/
158  DdManager * dd, /* the DD manager */
159  DdNode * bVars) /* the set of variables */
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 */
169 
170 /**Function********************************************************************
171 
172  Synopsis [Filters the set of variables using the support of the function.]
173 
174  Description []
175 
176  SideEffects []
177 
178  SeeAlso []
179 
180 ******************************************************************************/
182  DdManager * dd, /* the DD manager */
183  DdNode * bVars, /* the set of variables to be reduced */
184  DdNode * bF) /* the function whose support is used for reduction */
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 */
194 
195 
196 /**Function********************************************************************
197 
198  Synopsis [Allocates symmetry information structure.]
199 
200  Description []
201 
202  SideEffects []
203 
204  SeeAlso []
205 
206 ******************************************************************************/
208 {
209  int i;
211 
212  // allocate and clean the storage for symmetry info
213  p = ABC_ALLOC( Extra_SymmInfo_t, 1 );
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 */
226 
227 /**Function********************************************************************
228 
229  Synopsis [Deallocates symmetry information structure.]
230 
231  Description []
232 
233  SideEffects []
234 
235  SeeAlso []
236 
237 ******************************************************************************/
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 */
245 
246 /**Function********************************************************************
247 
248  Synopsis [Allocates symmetry information structure.]
249 
250  Description []
251 
252  SideEffects []
253 
254  SeeAlso []
255 
256 ******************************************************************************/
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 */
273 
274 
275 /**Function********************************************************************
276 
277  Synopsis [Creates the symmetry information structure from ZDD.]
278 
279  Description [ZDD representation of symmetries is the set of cubes, each
280  of which has two variables in the positive polarity. These variables correspond
281  to the symmetric variable pair.]
282 
283  SideEffects []
284 
285  SeeAlso []
286 
287 ******************************************************************************/
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 */
347 
348 
349 /**Function********************************************************************
350 
351  Synopsis [Checks the possibility of two variables being symmetric.]
352 
353  Description [Returns 0 if vars are not symmetric. Return 1 if vars can be symmetric.]
354 
355  SideEffects []
356 
357  SeeAlso []
358 
359 ******************************************************************************/
361  DdManager * dd, /* the DD manager */
362  DdNode * bF,
363  int iVar1,
364  int iVar2)
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 */
383 
384 
385 /**Function********************************************************************
386 
387  Synopsis [Computes the classical symmetry information for the function.]
388 
389  Description [Uses the naive way of comparing cofactors.]
390 
391  SideEffects []
392 
393  SeeAlso []
394 
395 ******************************************************************************/
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 */
431 
432 /**Function********************************************************************
433 
434  Synopsis [Checks if the two variables are symmetric.]
435 
436  Description [Returns 0 if vars are not symmetric. Return 1 if vars are symmetric.]
437 
438  SideEffects []
439 
440  SeeAlso []
441 
442 ******************************************************************************/
444  DdManager * dd, /* the DD manager */
445  DdNode * bF,
446  int iVar1,
447  int iVar2)
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 */
472 
473 
474 /**Function********************************************************************
475 
476  Synopsis [Builds ZDD representing the set of fixed-size variable tuples.]
477 
478  Description [Creates ZDD of all combinations of variables in Support that
479  is represented by a BDD.]
480 
481  SideEffects [New ZDD variables are created if indices of the variables
482  present in the combination are larger than the currently
483  allocated number of ZDD variables.]
484 
485  SeeAlso []
486 
487 ******************************************************************************/
489  DdManager * dd, /* the DD manager */
490  int K, /* the number of variables in tuples */
491  DdNode * bVarsN) /* the set of all variables represented as a BDD */
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 */
534 
535 /**Function********************************************************************
536 
537  Synopsis [Selects one subset from the set of subsets represented by a ZDD.]
538 
539  Description []
540 
541  SideEffects [None]
542 
543  SeeAlso []
544 
545 ******************************************************************************/
547  DdManager * dd, /* the DD manager */
548  DdNode * zS) /* the ZDD */
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 */
558 
559 
560 /*---------------------------------------------------------------------------*/
561 /* Definition of internal functions */
562 /*---------------------------------------------------------------------------*/
563 
564 /**Function********************************************************************
565 
566  Synopsis [Performs a recursive step of Extra_SymmPairsCompute.]
567 
568  Description [Returns the set of symmetric variable pairs represented as a set
569  of two-literal ZDD cubes. Both variables always appear in the positive polarity
570  in the cubes. This function works without building new BDD nodes. Some relatively
571  small number of ZDD nodes may be built to ensure proper bookkeeping of the
572  symmetry information.]
573 
574  SideEffects []
575 
576  SeeAlso []
577 
578 ******************************************************************************/
579 DdNode *
581  DdManager * dd, /* the manager */
582  DdNode * bFunc, /* the function whose symmetries are computed */
583  DdNode * bVars ) /* the set of variables on which this function depends */
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 */
790 
791 /**Function********************************************************************
792 
793  Synopsis [Performs a recursive step of Extra_zddGetSymmetricVars.]
794 
795  Description [Returns the set of ZDD singletons, containing those positive
796  ZDD variables that correspond to BDD variables x, for which it is true
797  that bF(x=0) == bG(x=1).]
798 
799  SideEffects []
800 
801  SeeAlso []
802 
803 ******************************************************************************/
805  DdManager * dd, /* the DD manager */
806  DdNode * bF, /* the first function - originally, the positive cofactor */
807  DdNode * bG, /* the second function - originally, the negative cofactor */
808  DdNode * bVars) /* the set of variables, on which F and G depend */
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 */
987 
988 
989 /**Function********************************************************************
990 
991  Synopsis [Performs a recursive step of Extra_zddGetSingletons.]
992 
993  Description [Returns the set of ZDD singletons, containing those positive
994  polarity ZDD variables that correspond to the BDD variables in bVars.]
995 
996  SideEffects []
997 
998  SeeAlso []
999 
1000 ******************************************************************************/
1002  DdManager * dd, /* the DD manager */
1003  DdNode * bVars) /* the set of variables */
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 */
1048 
1049 
1050 /**Function********************************************************************
1051 
1052  Synopsis [Performs a recursive step of Extra_bddReduceVarSet.]
1053 
1054  Description [Returns the set of all variables in the given set that are not in the
1055  support of the given function.]
1056 
1057  SideEffects []
1058 
1059  SeeAlso []
1060 
1061 ******************************************************************************/
1063  DdManager * dd, /* the DD manager */
1064  DdNode * bVars, /* the set of variables to be reduced */
1065  DdNode * bF) /* the function whose support is used for reduction */
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 */
1150 
1151 
1152 /**Function********************************************************************
1153 
1154  Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().]
1155 
1156  Description [Returns b0 if the variables are not symmetric. Returns b1 if the
1157  variables can be symmetric. The variables are represented in the form of a
1158  two-variable cube. In case the cube contains one variable (below Var1 level),
1159  the cube's pointer is complemented if the variable Var1 occurred on the
1160  current path; otherwise, the cube's pointer is regular. Uses additional
1161  complemented bit (Hash_Not) to mark the result if in the BDD rooted that this
1162  node there is a branch passing though the node labeled with Var2.]
1163 
1164  SideEffects []
1165 
1166  SeeAlso []
1167 
1168 ******************************************************************************/
1170  DdManager * dd, /* the DD manager */
1171  DdNode * bF,
1172  DdNode * bVars)
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 */
1328 
1329 /**Function********************************************************************
1330 
1331  Synopsis [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().]
1332 
1333  Description [Generates in a bottom-up fashion ZDD for all combinations
1334  composed of k variables out of variables belonging to Support.]
1335 
1336  SideEffects []
1337 
1338  SeeAlso []
1339 
1340 ******************************************************************************/
1342  DdManager * dd, /* the DD manager */
1343  DdNode * bVarsK, /* the number of variables in tuples */
1344  DdNode * bVarsN) /* the set of all variables */
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 */
1406 
1407 
1408 /**Function********************************************************************
1409 
1410  Synopsis [Performs the recursive step of Extra_zddSelectOneSubset.]
1411 
1412  Description []
1413 
1414  SideEffects [None]
1415 
1416  SeeAlso []
1417 
1418 ******************************************************************************/
1420  DdManager * dd,
1421  DdNode * zS )
1422 // selects one subset from the ZDD zS
1423 // returns z0 if and only if zS is an empty set of cubes
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 */
1468 
1469 
1470 /*---------------------------------------------------------------------------*/
1471 /* Definition of static Functions */
1472 /*---------------------------------------------------------------------------*/
1474 
char * memset()
DdNode * cuddBddExistAbstractRecur(DdManager *manager, DdNode *f, DdNode *cube)
Definition: cuddBddAbs.c:352
DdNode * cuddCacheLookupZdd(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddCache.c:435
DdNode * cuddCacheLookup2Zdd(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddCache.c:610
#define cuddRef(n)
Definition: cuddInt.h:584
void Cudd_RecursiveDerefZdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:385
char ** pSymms
Definition: extraBdd.h:219
#define cuddDeref(n)
Definition: cuddInt.h:604
DdNode * extraZddSymmPairsCompute(DdManager *dd, DdNode *bFunc, DdNode *bVars)
Definition: extraBddSymm.c:580
int Extra_bddSuppSize(DdManager *dd, DdNode *bSupp)
Definition: extraBddMisc.c:321
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
DdNode * cuddZddGetNode(DdManager *zdd, int id, DdNode *T, DdNode *E)
Definition: cuddTable.c:1041
#define z1
Definition: extraBdd.h:78
#define Cudd_Not(node)
Definition: cudd.h:367
void cuddCacheInsert2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g, DdNode *data)
Definition: cuddCache.c:277
static Llb_Mgr_t * p
Definition: llb3Image.c:950
DdNode * Cudd_Support(DdManager *dd, DdNode *f)
Definition: cuddUtil.c:740
DdNode * Extra_zddSymmPairsCompute(DdManager *dd, DdNode *bF, DdNode *bVars)
Definition: extraBddSymm.c:105
int size
Definition: cuddInt.h:361
#define b1
Definition: extraBdd.h:76
DdNode * Extra_zddTuplesFromBdd(DdManager *dd, int K, DdNode *bVarsN)
Definition: extraBddSymm.c:488
#define Cudd_Regular(node)
Definition: cudd.h:397
void cuddCacheInsert(DdManager *table, ptruint op, DdNode *f, DdNode *g, DdNode *h, DdNode *data)
Definition: cuddCache.c:222
DdNode * Extra_zddSelectOneSubset(DdManager *dd, DdNode *zS)
Definition: extraBddSymm.c:546
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
Extra_SymmInfo_t * Extra_SymmPairsComputeNaive(DdManager *dd, DdNode *bFunc)
Definition: extraBddSymm.c:396
DdNode * Cudd_zddDiff(DdManager *dd, DdNode *P, DdNode *Q)
Definition: cuddZddSetop.c:236
DdNode * extraBddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
DdNode * extraZddGetSingletons(DdManager *dd, DdNode *bVars)
for(p=first;p->value< newval;p=p->next)
DdNode * extraZddGetSymmetricVars(DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
Definition: extraBddSymm.c:804
#define statLine(dd)
Definition: cuddInt.h:1037
DdNode * cuddCacheLookup2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddCache.c:502
void Extra_SymmPairsPrint(Extra_SymmInfo_t *p)
Definition: extraBddSymm.c:257
int reordered
Definition: cuddInt.h:409
#define z0
Definition: extraBdd.h:77
Extra_SymmInfo_t * Extra_SymmPairsAllocate(int nVars)
Definition: extraBddSymm.c:207
DdNode * extraZddSelectOneSubset(DdManager *dd, DdNode *zS)
int Extra_bddCheckVarsSymmetric(DdManager *dd, DdNode *bF, int iVar1, int iVar2)
Definition: extraBddSymm.c:360
DdNode * Cudd_Cofactor(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddCof.c:123
DdNode * cuddZddIntersect(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddZddSetop.c:642
DdNode * Extra_zddGetSymmetricVars(DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
Definition: extraBddSymm.c:130
Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd(DdManager *dd, DdNode *zPairs, DdNode *bSupp)
Definition: extraBddSymm.c:288
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
#define cuddIsConstant(node)
Definition: cuddInt.h:620
static int size
Definition: cuddSign.c:86
#define cuddT(node)
Definition: cuddInt.h:636
Extra_SymmInfo_t * Extra_SymmPairsCompute(DdManager *dd, DdNode *bFunc)
Definition: extraBddSymm.c:73
DdNode * Extra_zddGetSingletons(DdManager *dd, DdNode *bVars)
Definition: extraBddSymm.c:157
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
#define cuddI(dd, index)
Definition: cuddInt.h:686
#define DD_GET_SYMM_VARS_TAG
Definition: extraBddSymm.c:47
int Extra_bddCheckVarsSymmetricNaive(DdManager *dd, DdNode *bF, int iVar1, int iVar2)
Definition: extraBddSymm.c:443
DdNode * cuddZddUnion(DdManager *zdd, DdNode *P, DdNode *Q)
Definition: cuddZddSetop.c:553
DdNode * extraZddTuplesFromBdd(DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
#define b0
Definition: extraBdd.h:75
DdHalfWord index
Definition: cudd.h:279
#define ABC_FREE(obj)
Definition: abc_global.h:232
DdNode ** vars
Definition: cuddInt.h:390
int autoDynZ
Definition: cuddInt.h:417
#define cuddE(node)
Definition: cuddInt.h:652
DdNode * Cudd_bddAnd(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddBddIte.c:314
DdNode * Extra_bddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
Definition: extraBddSymm.c:181
#define assert(ex)
Definition: util_old.h:213
void Extra_SymmPairsDissolve(Extra_SymmInfo_t *p)
Definition: extraBddSymm.c:238
void Cudd_Ref(DdNode *n)
Definition: cuddRef.c:129
DdNode * cuddBddAndRecur(DdManager *manager, DdNode *f, DdNode *g)
Definition: cuddBddIte.c:886
DdNode * extraBddCheckVarsSymmetric(DdManager *dd, DdNode *bF, DdNode *bVars)
int * perm
Definition: cuddInt.h:386
DdNode * cuddCacheLookup1Zdd(DdManager *table, DD_CTFP1 op, DdNode *f)
Definition: cuddCache.c:664
void cuddCacheInsert1(DdManager *table, DD_CTFP1 op, DdNode *f, DdNode *data)
Definition: cuddCache.c:323