ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
extraBddSymm.c
Go to the documentation of this file.
1
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
50
51/*---------------------------------------------------------------------------*/
52/* Static function prototypes */
53/*---------------------------------------------------------------------------*/
54
56
57/*---------------------------------------------------------------------------*/
58/* Definition of exported functions */
59/*---------------------------------------------------------------------------*/
60
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
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
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
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
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
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 */
226
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
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
288Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd( DdManager * dd, DdNode * zPairs, DdNode * bSupp )
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
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
396Extra_SymmInfo_t * Extra_SymmPairsComputeNaive( DdManager * dd, DdNode * bFunc )
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
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
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
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
579DdNode *
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
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
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
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
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
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
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
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define b0
Definition bbrImage.c:96
#define b1
Definition bbrImage.c:97
Cube * p
Definition exorList.c:222
DdNode * extraZddSelectOneSubset(DdManager *dd, DdNode *zS)
DdNode * extraBddCheckVarsSymmetric(DdManager *dd, DdNode *bF, DdNode *bVars)
Extra_SymmInfo_t * Extra_SymmPairsComputeNaive(DdManager *dd, DdNode *bFunc)
DdNode * Extra_zddSymmPairsCompute(DdManager *dd, DdNode *bF, DdNode *bVars)
DdNode * Extra_bddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
DdNode * extraZddGetSingletons(DdManager *dd, DdNode *bVars)
#define DD_GET_SYMM_VARS_TAG
DdNode * extraZddSymmPairsCompute(DdManager *dd, DdNode *bFunc, DdNode *bVars)
int Extra_bddCheckVarsSymmetric(DdManager *dd, DdNode *bF, int iVar1, int iVar2)
Extra_SymmInfo_t * Extra_SymmPairsCreateFromZdd(DdManager *dd, DdNode *zPairs, DdNode *bSupp)
DdNode * extraBddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
DdNode * extraZddGetSymmetricVars(DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
DdNode * Extra_zddTuplesFromBdd(DdManager *dd, int K, DdNode *bVarsN)
void Extra_SymmPairsPrint(Extra_SymmInfo_t *p)
Extra_SymmInfo_t * Extra_SymmPairsCompute(DdManager *dd, DdNode *bFunc)
DdNode * Extra_zddGetSymmetricVars(DdManager *dd, DdNode *bF, DdNode *bG, DdNode *bVars)
DdNode * Extra_zddGetSingletons(DdManager *dd, DdNode *bVars)
DdNode * Extra_zddSelectOneSubset(DdManager *dd, DdNode *zS)
DdNode * extraZddTuplesFromBdd(DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
void Extra_SymmPairsDissolve(Extra_SymmInfo_t *p)
int Extra_bddCheckVarsSymmetricNaive(DdManager *dd, DdNode *bF, int iVar1, int iVar2)
Extra_SymmInfo_t * Extra_SymmPairsAllocate(int nVars)
struct Extra_SymmInfo_t_ Extra_SymmInfo_t
Definition extraBdd.h:256
DdNode * extraZddSelectOneSubset(DdManager *dd, DdNode *zS)
DdNode * extraBddCheckVarsSymmetric(DdManager *dd, DdNode *bF, DdNode *bVars)
DdNode * extraZddGetSingletons(DdManager *dd, DdNode *bVars)
int Extra_bddSuppSize(DdManager *dd, DdNode *bSupp)
#define z0
Definition extraBdd.h:77
DdNode * extraBddReduceVarSet(DdManager *dd, DdNode *bVars, DdNode *bF)
DdNode * extraZddSymmPairsCompute(DdManager *dd, DdNode *bF, DdNode *bVars)
#define z1
Definition extraBdd.h:78
DdNode * extraZddTuplesFromBdd(DdManager *dd, DdNode *bVarsK, DdNode *bVarsN)
#define assert(ex)
Definition util_old.h:213
char * memset()