1 /**CFile***********************************************************************
3 FileName [cuddSymmetry.c]
7 Synopsis [Functions for symmetry-based variable reordering.]
9 Description [External procedures included in this file:
11 <li> Cudd_SymmProfile()
13 Internal procedures included in this module:
16 <li> cuddSymmSifting()
17 <li> cuddSymmSiftingConv()
19 Static procedures included in this module:
21 <li> ddSymmUniqueCompare()
22 <li> ddSymmSiftingAux()
23 <li> ddSymmSiftingConvAux()
24 <li> ddSymmSiftingUp()
25 <li> ddSymmSiftingDown()
26 <li> ddSymmGroupMove()
27 <li> ddSymmGroupMoveBackward()
28 <li> ddSymmSiftingBackward()
32 Author [Shipra Panda, Fabio Somenzi]
34 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
38 Redistribution and use in source and binary forms, with or without
39 modification, are permitted provided that the following conditions
42 Redistributions of source code must retain the above copyright
43 notice, this list of conditions and the following disclaimer.
45 Redistributions in binary form must reproduce the above copyright
46 notice, this list of conditions and the following disclaimer in the
47 documentation and/or other materials provided with the distribution.
49 Neither the name of the University of Colorado nor the names of its
50 contributors may be used to endorse or promote products derived from
51 this software without specific prior written permission.
53 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
54 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
55 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
56 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
57 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
58 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
59 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
61 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
63 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 POSSIBILITY OF SUCH DAMAGE.]
66 ******************************************************************************/
71 /*---------------------------------------------------------------------------*/
72 /* Constant declarations */
73 /*---------------------------------------------------------------------------*/
75 #define MV_OOM (Move *)1
77 /*---------------------------------------------------------------------------*/
78 /* Stucture declarations */
79 /*---------------------------------------------------------------------------*/
81 /*---------------------------------------------------------------------------*/
82 /* Type declarations */
83 /*---------------------------------------------------------------------------*/
85 /*---------------------------------------------------------------------------*/
86 /* Variable declarations */
87 /*---------------------------------------------------------------------------*/
90 static char rcsid
[] DD_UNUSED
= "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $";
95 extern int ddTotalNumberSwapping
;
97 extern int ddTotalNISwaps
;
100 /*---------------------------------------------------------------------------*/
101 /* Macro declarations */
102 /*---------------------------------------------------------------------------*/
104 /**AutomaticStart*************************************************************/
106 /*---------------------------------------------------------------------------*/
107 /* Static function prototypes */
108 /*---------------------------------------------------------------------------*/
110 static int ddSymmUniqueCompare (int *ptrX
, int *ptrY
);
111 static int ddSymmSiftingAux (DdManager
*table
, int x
, int xLow
, int xHigh
);
112 static int ddSymmSiftingConvAux (DdManager
*table
, int x
, int xLow
, int xHigh
);
113 static Move
* ddSymmSiftingUp (DdManager
*table
, int y
, int xLow
);
114 static Move
* ddSymmSiftingDown (DdManager
*table
, int x
, int xHigh
);
115 static int ddSymmGroupMove (DdManager
*table
, int x
, int y
, Move
**moves
);
116 static int ddSymmGroupMoveBackward (DdManager
*table
, int x
, int y
);
117 static int ddSymmSiftingBackward (DdManager
*table
, Move
*moves
, int size
);
118 static void ddSymmSummary (DdManager
*table
, int lower
, int upper
, int *symvars
, int *symgroups
);
120 /**AutomaticEnd***************************************************************/
123 /*---------------------------------------------------------------------------*/
124 /* Definition of exported functions */
125 /*---------------------------------------------------------------------------*/
128 /**Function********************************************************************
130 Synopsis [Prints statistics on symmetric variables.]
136 ******************************************************************************/
145 int TotalSymmGroups
= 0;
147 for (i
= lower
; i
<= upper
; i
++) {
148 if (table
->subtables
[i
].next
!= (unsigned) i
) {
150 (void) fprintf(table
->out
,"Group:");
152 (void) fprintf(table
->out
," %d",table
->invperm
[x
]);
155 x
= table
->subtables
[x
].next
;
159 assert(table
->subtables
[gbot
].next
== (unsigned) i
);
162 (void) fprintf(table
->out
,"\n");
165 (void) fprintf(table
->out
,"Total Symmetric = %d\n",TotalSymm
);
166 (void) fprintf(table
->out
,"Total Groups = %d\n",TotalSymmGroups
);
168 } /* end of Cudd_SymmProfile */
171 /*---------------------------------------------------------------------------*/
172 /* Definition of internal functions */
173 /*---------------------------------------------------------------------------*/
176 /**Function********************************************************************
178 Synopsis [Checks for symmetry of x and y.]
180 Description [Checks for symmetry of x and y. Ignores projection
181 functions, unless they are isolated. Returns 1 in case of symmetry; 0
186 ******************************************************************************/
193 DdNode
*f
,*f0
,*f1
,*f01
,*f00
,*f11
,*f10
;
194 int comple
; /* f0 is complemented */
195 int xsymmy
; /* x and y may be positively symmetric */
196 int xsymmyp
; /* x and y may be negatively symmetric */
197 int arccount
; /* number of arcs from layer x to layer y */
198 int TotalRefCount
; /* total reference count of layer y minus 1 */
203 DdNode
*sentinel
= &(table
->sentinel
);
208 /* Checks that x and y are not the projection functions.
209 ** For x it is sufficient to check whether there is only one
210 ** node; indeed, if there is one node, it is the projection function
211 ** and it cannot point to y. Hence, if y isn't just the projection
212 ** function, it has one arc coming from a layer different from x.
214 if (table
->subtables
[x
].keys
== 1) {
217 yindex
= table
->invperm
[y
];
218 if (table
->subtables
[y
].keys
== 1) {
219 if (table
->vars
[yindex
]->ref
== 1)
223 xsymmy
= xsymmyp
= 1;
225 slots
= table
->subtables
[x
].slots
;
226 list
= table
->subtables
[x
].nodelist
;
227 for (i
= 0; i
< slots
; i
++) {
229 while (f
!= sentinel
) {
230 /* Find f1, f0, f11, f10, f01, f00. */
232 f0
= Cudd_Regular(cuddE(f
));
233 comple
= Cudd_IsComplement(cuddE(f
));
234 if ((int) f1
->index
== yindex
) {
236 f11
= cuddT(f1
); f10
= cuddE(f1
);
238 if ((int) f0
->index
!= yindex
) {
239 /* If f is an isolated projection function it is
240 ** allowed to bypass layer y.
242 if (f1
!= DD_ONE(table
) || f0
!= DD_ONE(table
) || f
->ref
!= 1)
243 return(0); /* f bypasses layer y */
247 if ((int) f0
->index
== yindex
) {
249 f01
= cuddT(f0
); f00
= cuddE(f0
);
258 if (f1
!= DD_ONE(table
) || f0
!= DD_ONE(table
) || f
->ref
!= 1) {
259 xsymmy
&= f01
== f10
;
260 xsymmyp
&= f11
== f00
;
261 if ((xsymmy
== 0) && (xsymmyp
== 0))
269 /* Calculate the total reference counts of y */
270 TotalRefCount
= -1; /* -1 for projection function */
271 slots
= table
->subtables
[y
].slots
;
272 list
= table
->subtables
[y
].nodelist
;
273 for (i
= 0; i
< slots
; i
++) {
275 while (f
!= sentinel
) {
276 TotalRefCount
+= f
->ref
;
281 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
282 if (arccount
== TotalRefCount
) {
283 xindex
= table
->invperm
[x
];
284 (void) fprintf(table
->out
,
285 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
290 return(arccount
== TotalRefCount
);
292 } /* end of cuddSymmCheck */
295 /**Function********************************************************************
297 Synopsis [Symmetric sifting algorithm.]
299 Description [Symmetric sifting algorithm.
300 Assumes that no dead nodes are present.
302 <li> Order all the variables according to the number of entries in
303 each unique subtable.
304 <li> Sift the variable up and down, remembering each time the total
305 size of the DD heap and grouping variables that are symmetric.
306 <li> Select the best permutation.
307 <li> Repeat 3 and 4 for all variables.
309 Returns 1 plus the number of symmetric variables if successful; 0
314 SeeAlso [cuddSymmSiftingConv]
316 ******************************************************************************/
336 /* Find order in which to sift variables. */
338 entry
= ALLOC(int,size
);
340 table
->errorCode
= CUDD_MEMORY_OUT
;
341 goto ddSymmSiftingOutOfMem
;
343 var
= ALLOC(int,size
);
345 table
->errorCode
= CUDD_MEMORY_OUT
;
346 goto ddSymmSiftingOutOfMem
;
349 for (i
= 0; i
< size
; i
++) {
351 entry
[i
] = table
->subtables
[x
].keys
;
355 qsort((void *)var
,size
,sizeof(int),(DD_QSFP
)ddSymmUniqueCompare
);
357 /* Initialize the symmetry of each subtable to itself. */
358 for (i
= lower
; i
<= upper
; i
++) {
359 table
->subtables
[i
].next
= i
;
362 for (i
= 0; i
< ddMin(table
->siftMaxVar
,size
); i
++) {
363 if (ddTotalNumberSwapping
>= table
->siftMaxSwap
)
365 x
= table
->perm
[var
[i
]];
367 previousSize
= table
->keys
- table
->isolated
;
369 if (x
< lower
|| x
> upper
) continue;
370 if (table
->subtables
[x
].next
== (unsigned) x
) {
371 result
= ddSymmSiftingAux(table
,x
,lower
,upper
);
372 if (!result
) goto ddSymmSiftingOutOfMem
;
374 if (table
->keys
< (unsigned) previousSize
+ table
->isolated
) {
375 (void) fprintf(table
->out
,"-");
376 } else if (table
->keys
> (unsigned) previousSize
+
378 (void) fprintf(table
->out
,"+"); /* should never happen */
380 (void) fprintf(table
->out
,"=");
390 ddSymmSummary(table
, lower
, upper
, &symvars
, &symgroups
);
393 (void) fprintf(table
->out
, "\n#:S_SIFTING %8d: symmetric variables\n",
395 (void) fprintf(table
->out
, "#:G_SIFTING %8d: symmetric groups",
401 ddSymmSiftingOutOfMem
:
403 if (entry
!= NULL
) FREE(entry
);
404 if (var
!= NULL
) FREE(var
);
408 } /* end of cuddSymmSifting */
411 /**Function********************************************************************
413 Synopsis [Symmetric sifting to convergence algorithm.]
415 Description [Symmetric sifting to convergence algorithm.
416 Assumes that no dead nodes are present.
418 <li> Order all the variables according to the number of entries in
419 each unique subtable.
420 <li> Sift the variable up and down, remembering each time the total
421 size of the DD heap and grouping variables that are symmetric.
422 <li> Select the best permutation.
423 <li> Repeat 3 and 4 for all variables.
424 <li> Repeat 1-4 until no further improvement.
426 Returns 1 plus the number of symmetric variables if successful; 0
431 SeeAlso [cuddSymmSifting]
433 ******************************************************************************/
453 initialSize
= table
->keys
- table
->isolated
;
457 /* Find order in which to sift variables. */
459 entry
= ALLOC(int,size
);
461 table
->errorCode
= CUDD_MEMORY_OUT
;
462 goto ddSymmSiftingConvOutOfMem
;
464 var
= ALLOC(int,size
);
466 table
->errorCode
= CUDD_MEMORY_OUT
;
467 goto ddSymmSiftingConvOutOfMem
;
470 for (i
= 0; i
< size
; i
++) {
472 entry
[i
] = table
->subtables
[x
].keys
;
476 qsort((void *)var
,size
,sizeof(int),(DD_QSFP
)ddSymmUniqueCompare
);
478 /* Initialize the symmetry of each subtable to itself
479 ** for first pass of converging symmetric sifting.
481 for (i
= lower
; i
<= upper
; i
++) {
482 table
->subtables
[i
].next
= i
;
485 for (i
= 0; i
< ddMin(table
->siftMaxVar
, table
->size
); i
++) {
486 if (ddTotalNumberSwapping
>= table
->siftMaxSwap
)
488 x
= table
->perm
[var
[i
]];
489 if (x
< lower
|| x
> upper
) continue;
490 /* Only sift if not in symmetry group already. */
491 if (table
->subtables
[x
].next
== (unsigned) x
) {
493 previousSize
= table
->keys
- table
->isolated
;
495 result
= ddSymmSiftingAux(table
,x
,lower
,upper
);
496 if (!result
) goto ddSymmSiftingConvOutOfMem
;
498 if (table
->keys
< (unsigned) previousSize
+ table
->isolated
) {
499 (void) fprintf(table
->out
,"-");
500 } else if (table
->keys
> (unsigned) previousSize
+
502 (void) fprintf(table
->out
,"+");
504 (void) fprintf(table
->out
,"=");
511 /* Sifting now until convergence. */
512 while ((unsigned) initialSize
> table
->keys
- table
->isolated
) {
513 initialSize
= table
->keys
- table
->isolated
;
515 (void) fprintf(table
->out
,"\n");
517 /* Here we consider only one representative for each symmetry class. */
518 for (x
= lower
, classes
= 0; x
<= upper
; x
++, classes
++) {
519 while ((unsigned) x
< table
->subtables
[x
].next
) {
520 x
= table
->subtables
[x
].next
;
522 /* Here x is the largest index in a group.
523 ** Groups consist of adjacent variables.
524 ** Hence, the next increment of x will move it to a new group.
526 i
= table
->invperm
[x
];
527 entry
[i
] = table
->subtables
[x
].keys
;
531 qsort((void *)var
,classes
,sizeof(int),(DD_QSFP
)ddSymmUniqueCompare
);
534 for (i
= 0; i
< ddMin(table
->siftMaxVar
,classes
); i
++) {
535 if (ddTotalNumberSwapping
>= table
->siftMaxSwap
)
537 x
= table
->perm
[var
[i
]];
538 if ((unsigned) x
>= table
->subtables
[x
].next
) {
540 previousSize
= table
->keys
- table
->isolated
;
542 result
= ddSymmSiftingConvAux(table
,x
,lower
,upper
);
543 if (!result
) goto ddSymmSiftingConvOutOfMem
;
545 if (table
->keys
< (unsigned) previousSize
+ table
->isolated
) {
546 (void) fprintf(table
->out
,"-");
547 } else if (table
->keys
> (unsigned) previousSize
+
549 (void) fprintf(table
->out
,"+");
551 (void) fprintf(table
->out
,"=");
559 ddSymmSummary(table
, lower
, upper
, &symvars
, &symgroups
);
562 (void) fprintf(table
->out
, "\n#:S_SIFTING %8d: symmetric variables\n",
564 (void) fprintf(table
->out
, "#:G_SIFTING %8d: symmetric groups",
573 ddSymmSiftingConvOutOfMem
:
575 if (entry
!= NULL
) FREE(entry
);
576 if (var
!= NULL
) FREE(var
);
580 } /* end of cuddSymmSiftingConv */
583 /*---------------------------------------------------------------------------*/
584 /* Definition of static functions */
585 /*---------------------------------------------------------------------------*/
588 /**Function********************************************************************
590 Synopsis [Comparison function used by qsort.]
592 Description [Comparison function used by qsort to order the variables
593 according to the number of keys in the subtables.
594 Returns the difference in number of keys between the two
595 variables being compared.]
599 ******************************************************************************/
606 if (entry
[*ptrY
] == entry
[*ptrX
]) {
607 return((*ptrX
) - (*ptrY
));
610 return(entry
[*ptrY
] - entry
[*ptrX
]);
612 } /* end of ddSymmUniqueCompare */
615 /**Function********************************************************************
617 Synopsis [Given xLow <= x <= xHigh moves x up and down between the
620 Description [Given xLow <= x <= xHigh moves x up and down between the
621 boundaries. Finds the best position and does the required changes.
622 Assumes that x is not part of a symmetry group. Returns 1 if
623 successful; 0 otherwise.]
627 ******************************************************************************/
636 Move
*moveUp
; /* list of up moves */
637 Move
*moveDown
; /* list of down moves */
641 int topbot
; /* index to either top or bottom of symmetry group */
642 int initGroupSize
, finalGroupSize
;
646 /* check for previously detected symmetry */
647 assert(table
->subtables
[x
].next
== (unsigned) x
);
650 initialSize
= table
->keys
- table
->isolated
;
655 if ((x
- xLow
) > (xHigh
- x
)) {
656 /* Will go down first, unless x == xHigh:
657 ** Look for consecutive symmetries above x.
659 for (i
= x
; i
> xLow
; i
--) {
660 if (!cuddSymmCheck(table
,i
-1,i
))
662 topbot
= table
->subtables
[i
-1].next
; /* find top of i-1's group */
663 table
->subtables
[i
-1].next
= i
;
664 table
->subtables
[x
].next
= topbot
; /* x is bottom of group so its */
665 /* next is top of i-1's group */
666 i
= topbot
+ 1; /* add 1 for i--; new i is top of symm group */
669 /* Will go up first unless x == xlow:
670 ** Look for consecutive symmetries below x.
672 for (i
= x
; i
< xHigh
; i
++) {
673 if (!cuddSymmCheck(table
,i
,i
+1))
675 /* find bottom of i+1's symm group */
677 while ((unsigned) topbot
< table
->subtables
[topbot
].next
) {
678 topbot
= table
->subtables
[topbot
].next
;
680 table
->subtables
[topbot
].next
= table
->subtables
[i
].next
;
681 table
->subtables
[i
].next
= i
+ 1;
682 i
= topbot
- 1; /* subtract 1 for i++; new i is bottom of group */
686 /* Now x may be in the middle of a symmetry group.
687 ** Find bottom of x's symm group.
689 while ((unsigned) x
< table
->subtables
[x
].next
)
690 x
= table
->subtables
[x
].next
;
692 if (x
== xLow
) { /* Sift down */
695 /* x must be a singleton */
696 assert((unsigned) x
== table
->subtables
[x
].next
);
698 if (x
== xHigh
) return(1); /* just one variable */
702 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
703 /* after this point x --> xHigh, unless early term */
704 if (moveDown
== MV_OOM
) goto ddSymmSiftingAuxOutOfMem
;
705 if (moveDown
== NULL
) return(1);
708 /* Find bottom of x's group */
710 while ((unsigned) i
< table
->subtables
[i
].next
) {
711 i
= table
->subtables
[i
].next
;
714 /* x should be the top of the symmetry group and i the bottom */
715 assert((unsigned) i
>= table
->subtables
[i
].next
);
716 assert((unsigned) x
== table
->subtables
[i
].next
);
718 finalGroupSize
= i
- x
+ 1;
720 if (initGroupSize
== finalGroupSize
) {
721 /* No new symmetry groups detected, return to best position */
722 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
724 initialSize
= table
->keys
- table
->isolated
;
725 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
726 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
728 if (!result
) goto ddSymmSiftingAuxOutOfMem
;
730 } else if (cuddNextHigh(table
,x
) > xHigh
) { /* Sift up */
731 /* Find top of x's symm group */
733 x
= table
->subtables
[x
].next
; /* top */
735 if (x
== xLow
) return(1); /* just one big group */
737 initGroupSize
= i
- x
+ 1;
739 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
740 /* after this point x --> xLow, unless early term */
741 if (moveUp
== MV_OOM
) goto ddSymmSiftingAuxOutOfMem
;
742 if (moveUp
== NULL
) return(1);
745 /* Find top of x's group */
746 i
= table
->subtables
[x
].next
;
748 /* x should be the bottom of the symmetry group and i the top */
749 assert((unsigned) x
>= table
->subtables
[x
].next
);
750 assert((unsigned) i
== table
->subtables
[x
].next
);
752 finalGroupSize
= x
- i
+ 1;
754 if (initGroupSize
== finalGroupSize
) {
755 /* No new symmetry groups detected, return to best position */
756 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
758 initialSize
= table
->keys
- table
->isolated
;
759 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
760 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
762 if (!result
) goto ddSymmSiftingAuxOutOfMem
;
764 } else if ((x
- xLow
) > (xHigh
- x
)) { /* must go down first: shorter */
766 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
767 /* at this point x == xHigh, unless early term */
768 if (moveDown
== MV_OOM
) goto ddSymmSiftingAuxOutOfMem
;
770 if (moveDown
!= NULL
) {
771 x
= moveDown
->y
; /* x is top here */
773 while ((unsigned) i
< table
->subtables
[i
].next
) {
774 i
= table
->subtables
[i
].next
;
778 while ((unsigned) i
< table
->subtables
[i
].next
) {
779 i
= table
->subtables
[i
].next
;
781 x
= table
->subtables
[i
].next
;
784 /* x should be the top of the symmetry group and i the bottom */
785 assert((unsigned) i
>= table
->subtables
[i
].next
);
786 assert((unsigned) x
== table
->subtables
[i
].next
);
788 initGroupSize
= i
- x
+ 1;
790 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
791 if (moveUp
== MV_OOM
) goto ddSymmSiftingAuxOutOfMem
;
793 if (moveUp
!= NULL
) {
795 i
= table
->subtables
[x
].next
;
798 while ((unsigned) x
< table
->subtables
[x
].next
)
799 x
= table
->subtables
[x
].next
;
802 /* x should be the bottom of the symmetry group and i the top */
803 assert((unsigned) x
>= table
->subtables
[x
].next
);
804 assert((unsigned) i
== table
->subtables
[x
].next
);
806 finalGroupSize
= x
- i
+ 1;
808 if (initGroupSize
== finalGroupSize
) {
809 /* No new symmetry groups detected, return to best position */
810 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
812 while (moveDown
!= NULL
) {
813 move
= moveDown
->next
;
814 cuddDeallocMove(table
, moveDown
);
817 initialSize
= table
->keys
- table
->isolated
;
818 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
819 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
821 if (!result
) goto ddSymmSiftingAuxOutOfMem
;
823 } else { /* moving up first: shorter */
824 /* Find top of x's symmetry group */
825 x
= table
->subtables
[x
].next
;
827 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
828 /* at this point x == xHigh, unless early term */
829 if (moveUp
== MV_OOM
) goto ddSymmSiftingAuxOutOfMem
;
831 if (moveUp
!= NULL
) {
833 i
= table
->subtables
[x
].next
;
835 while ((unsigned) x
< table
->subtables
[x
].next
)
836 x
= table
->subtables
[x
].next
;
837 i
= table
->subtables
[x
].next
;
840 /* x is bottom of the symmetry group and i is top */
841 assert((unsigned) x
>= table
->subtables
[x
].next
);
842 assert((unsigned) i
== table
->subtables
[x
].next
);
844 initGroupSize
= x
- i
+ 1;
846 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
847 if (moveDown
== MV_OOM
) goto ddSymmSiftingAuxOutOfMem
;
849 if (moveDown
!= NULL
) {
852 while ((unsigned) i
< table
->subtables
[i
].next
) {
853 i
= table
->subtables
[i
].next
;
857 x
= table
->subtables
[x
].next
;
860 /* x should be the top of the symmetry group and i the bottom */
861 assert((unsigned) i
>= table
->subtables
[i
].next
);
862 assert((unsigned) x
== table
->subtables
[i
].next
);
864 finalGroupSize
= i
- x
+ 1;
866 if (initGroupSize
== finalGroupSize
) {
867 /* No new symmetries detected, go back to best position */
868 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
870 while (moveUp
!= NULL
) {
872 cuddDeallocMove(table
, moveUp
);
875 initialSize
= table
->keys
- table
->isolated
;
876 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
877 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
879 if (!result
) goto ddSymmSiftingAuxOutOfMem
;
882 while (moveDown
!= NULL
) {
883 move
= moveDown
->next
;
884 cuddDeallocMove(table
, moveDown
);
887 while (moveUp
!= NULL
) {
889 cuddDeallocMove(table
, moveUp
);
895 ddSymmSiftingAuxOutOfMem
:
896 if (moveDown
!= MV_OOM
) {
897 while (moveDown
!= NULL
) {
898 move
= moveDown
->next
;
899 cuddDeallocMove(table
, moveDown
);
903 if (moveUp
!= MV_OOM
) {
904 while (moveUp
!= NULL
) {
906 cuddDeallocMove(table
, moveUp
);
913 } /* end of ddSymmSiftingAux */
916 /**Function********************************************************************
918 Synopsis [Given xLow <= x <= xHigh moves x up and down between the
921 Description [Given xLow <= x <= xHigh moves x up and down between the
922 boundaries. Finds the best position and does the required changes.
923 Assumes that x is either an isolated variable, or it is the bottom of
924 a symmetry group. All symmetries may not have been found, because of
925 exceeded growth limit. Returns 1 if successful; 0 otherwise.]
929 ******************************************************************************/
931 ddSymmSiftingConvAux(
938 Move
*moveUp
; /* list of up moves */
939 Move
*moveDown
; /* list of down moves */
943 int initGroupSize
, finalGroupSize
;
946 initialSize
= table
->keys
- table
->isolated
;
951 if (x
== xLow
) { /* Sift down */
953 /* x is bottom of symmetry group */
954 assert((unsigned) x
>= table
->subtables
[x
].next
);
956 i
= table
->subtables
[x
].next
;
957 initGroupSize
= x
- i
+ 1;
959 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
960 /* at this point x == xHigh, unless early term */
961 if (moveDown
== MV_OOM
) goto ddSymmSiftingConvAuxOutOfMem
;
962 if (moveDown
== NULL
) return(1);
966 while ((unsigned) i
< table
->subtables
[i
].next
) {
967 i
= table
->subtables
[i
].next
;
970 /* x should be the top of the symmetric group and i the bottom */
971 assert((unsigned) i
>= table
->subtables
[i
].next
);
972 assert((unsigned) x
== table
->subtables
[i
].next
);
974 finalGroupSize
= i
- x
+ 1;
976 if (initGroupSize
== finalGroupSize
) {
977 /* No new symmetries detected, go back to best position */
978 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
980 initialSize
= table
->keys
- table
->isolated
;
981 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
982 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
984 if (!result
) goto ddSymmSiftingConvAuxOutOfMem
;
986 } else if (cuddNextHigh(table
,x
) > xHigh
) { /* Sift up */
987 /* Find top of x's symm group */
988 while ((unsigned) x
< table
->subtables
[x
].next
)
989 x
= table
->subtables
[x
].next
;
991 x
= table
->subtables
[x
].next
; /* top */
993 if (x
== xLow
) return(1);
995 initGroupSize
= i
- x
+ 1;
997 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
998 /* at this point x == xLow, unless early term */
999 if (moveUp
== MV_OOM
) goto ddSymmSiftingConvAuxOutOfMem
;
1000 if (moveUp
== NULL
) return(1);
1003 i
= table
->subtables
[x
].next
;
1005 /* x should be the bottom of the symmetry group and i the top */
1006 assert((unsigned) x
>= table
->subtables
[x
].next
);
1007 assert((unsigned) i
== table
->subtables
[x
].next
);
1009 finalGroupSize
= x
- i
+ 1;
1011 if (initGroupSize
== finalGroupSize
) {
1012 /* No new symmetry groups detected, return to best position */
1013 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
1015 initialSize
= table
->keys
- table
->isolated
;
1016 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
1017 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
1020 goto ddSymmSiftingConvAuxOutOfMem
;
1022 } else if ((x
- xLow
) > (xHigh
- x
)) { /* must go down first: shorter */
1023 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
1024 /* at this point x == xHigh, unless early term */
1025 if (moveDown
== MV_OOM
) goto ddSymmSiftingConvAuxOutOfMem
;
1027 if (moveDown
!= NULL
) {
1030 while ((unsigned) i
< table
->subtables
[i
].next
) {
1031 i
= table
->subtables
[i
].next
;
1034 while ((unsigned) x
< table
->subtables
[x
].next
)
1035 x
= table
->subtables
[x
].next
;
1037 x
= table
->subtables
[x
].next
;
1040 /* x should be the top of the symmetry group and i the bottom */
1041 assert((unsigned) i
>= table
->subtables
[i
].next
);
1042 assert((unsigned) x
== table
->subtables
[i
].next
);
1044 initGroupSize
= i
- x
+ 1;
1046 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
1047 if (moveUp
== MV_OOM
) goto ddSymmSiftingConvAuxOutOfMem
;
1049 if (moveUp
!= NULL
) {
1051 i
= table
->subtables
[x
].next
;
1054 while ((unsigned) x
< table
->subtables
[x
].next
)
1055 x
= table
->subtables
[x
].next
;
1058 /* x should be the bottom of the symmetry group and i the top */
1059 assert((unsigned) x
>= table
->subtables
[x
].next
);
1060 assert((unsigned) i
== table
->subtables
[x
].next
);
1062 finalGroupSize
= x
- i
+ 1;
1064 if (initGroupSize
== finalGroupSize
) {
1065 /* No new symmetry groups detected, return to best position */
1066 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
1068 while (moveDown
!= NULL
) {
1069 move
= moveDown
->next
;
1070 cuddDeallocMove(table
, moveDown
);
1073 initialSize
= table
->keys
- table
->isolated
;
1074 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
1075 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
1077 if (!result
) goto ddSymmSiftingConvAuxOutOfMem
;
1079 } else { /* moving up first: shorter */
1080 /* Find top of x's symmetry group */
1081 x
= table
->subtables
[x
].next
;
1083 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
1084 /* at this point x == xHigh, unless early term */
1085 if (moveUp
== MV_OOM
) goto ddSymmSiftingConvAuxOutOfMem
;
1087 if (moveUp
!= NULL
) {
1089 i
= table
->subtables
[x
].next
;
1092 while ((unsigned) x
< table
->subtables
[x
].next
)
1093 x
= table
->subtables
[x
].next
;
1096 /* x is bottom of the symmetry group and i is top */
1097 assert((unsigned) x
>= table
->subtables
[x
].next
);
1098 assert((unsigned) i
== table
->subtables
[x
].next
);
1100 initGroupSize
= x
- i
+ 1;
1102 moveDown
= ddSymmSiftingDown(table
,x
,xHigh
);
1103 if (moveDown
== MV_OOM
) goto ddSymmSiftingConvAuxOutOfMem
;
1105 if (moveDown
!= NULL
) {
1108 while ((unsigned) i
< table
->subtables
[i
].next
) {
1109 i
= table
->subtables
[i
].next
;
1113 x
= table
->subtables
[x
].next
;
1116 /* x should be the top of the symmetry group and i the bottom */
1117 assert((unsigned) i
>= table
->subtables
[i
].next
);
1118 assert((unsigned) x
== table
->subtables
[i
].next
);
1120 finalGroupSize
= i
- x
+ 1;
1122 if (initGroupSize
== finalGroupSize
) {
1123 /* No new symmetries detected, go back to best position */
1124 result
= ddSymmSiftingBackward(table
,moveDown
,initialSize
);
1126 while (moveUp
!= NULL
) {
1127 move
= moveUp
->next
;
1128 cuddDeallocMove(table
, moveUp
);
1131 initialSize
= table
->keys
- table
->isolated
;
1132 moveUp
= ddSymmSiftingUp(table
,x
,xLow
);
1133 result
= ddSymmSiftingBackward(table
,moveUp
,initialSize
);
1135 if (!result
) goto ddSymmSiftingConvAuxOutOfMem
;
1138 while (moveDown
!= NULL
) {
1139 move
= moveDown
->next
;
1140 cuddDeallocMove(table
, moveDown
);
1143 while (moveUp
!= NULL
) {
1144 move
= moveUp
->next
;
1145 cuddDeallocMove(table
, moveUp
);
1151 ddSymmSiftingConvAuxOutOfMem
:
1152 if (moveDown
!= MV_OOM
) {
1153 while (moveDown
!= NULL
) {
1154 move
= moveDown
->next
;
1155 cuddDeallocMove(table
, moveDown
);
1159 if (moveUp
!= MV_OOM
) {
1160 while (moveUp
!= NULL
) {
1161 move
= moveUp
->next
;
1162 cuddDeallocMove(table
, moveUp
);
1169 } /* end of ddSymmSiftingConvAux */
1172 /**Function********************************************************************
1174 Synopsis [Moves x up until either it reaches the bound (xLow) or
1175 the size of the DD heap increases too much.]
1177 Description [Moves x up until either it reaches the bound (xLow) or
1178 the size of the DD heap increases too much. Assumes that x is the top
1179 of a symmetry group. Checks x for symmetry to the adjacent
1180 variables. If symmetry is found, the symmetry group of x is merged
1181 with the symmetry group of the other variable. Returns the set of
1182 moves in case of success; MV_OOM if memory is full.]
1186 ******************************************************************************/
1204 int L
; /* lower bound on DD size */
1211 yindex
= table
->invperm
[y
];
1213 /* Initialize the lower bound.
1214 ** The part of the DD below the bottom of y' group will not change.
1215 ** The part of the DD above y that does not interact with y will not
1216 ** change. The rest may vanish in the best case, except for
1217 ** the nodes at level xLow, which will not vanish, regardless.
1219 limitSize
= L
= table
->keys
- table
->isolated
;
1221 while ((unsigned) gybot
< table
->subtables
[gybot
].next
)
1222 gybot
= table
->subtables
[gybot
].next
;
1223 for (z
= xLow
+ 1; z
<= gybot
; z
++) {
1224 zindex
= table
->invperm
[z
];
1225 if (zindex
== yindex
|| cuddTestInteract(table
,zindex
,yindex
)) {
1226 isolated
= table
->vars
[zindex
]->ref
== 1;
1227 L
-= table
->subtables
[z
].keys
- isolated
;
1231 x
= cuddNextLow(table
,y
);
1232 while (x
>= xLow
&& L
<= limitSize
) {
1235 while ((unsigned) gybot
< table
->subtables
[gybot
].next
)
1236 gybot
= table
->subtables
[gybot
].next
;
1237 checkL
= table
->keys
- table
->isolated
;
1238 for (z
= xLow
+ 1; z
<= gybot
; z
++) {
1239 zindex
= table
->invperm
[z
];
1240 if (zindex
== yindex
|| cuddTestInteract(table
,zindex
,yindex
)) {
1241 isolated
= table
->vars
[zindex
]->ref
== 1;
1242 checkL
-= table
->subtables
[z
].keys
- isolated
;
1245 assert(L
== checkL
);
1247 gxtop
= table
->subtables
[x
].next
;
1248 if (cuddSymmCheck(table
,x
,y
)) {
1249 /* Symmetry found, attach symm groups */
1250 table
->subtables
[x
].next
= y
;
1251 i
= table
->subtables
[y
].next
;
1252 while (table
->subtables
[i
].next
!= (unsigned) y
)
1253 i
= table
->subtables
[i
].next
;
1254 table
->subtables
[i
].next
= gxtop
;
1255 } else if (table
->subtables
[x
].next
== (unsigned) x
&&
1256 table
->subtables
[y
].next
== (unsigned) y
) {
1257 /* x and y have self symmetry */
1258 xindex
= table
->invperm
[x
];
1259 size
= cuddSwapInPlace(table
,x
,y
);
1261 assert(table
->subtables
[x
].next
== (unsigned) x
);
1262 assert(table
->subtables
[y
].next
== (unsigned) y
);
1264 if (size
== 0) goto ddSymmSiftingUpOutOfMem
;
1265 /* Update the lower bound. */
1266 if (cuddTestInteract(table
,xindex
,yindex
)) {
1267 isolated
= table
->vars
[xindex
]->ref
== 1;
1268 L
+= table
->subtables
[y
].keys
- isolated
;
1270 move
= (Move
*) cuddDynamicAllocNode(table
);
1271 if (move
== NULL
) goto ddSymmSiftingUpOutOfMem
;
1277 if ((double) size
> (double) limitSize
* table
->maxGrowth
)
1279 if (size
< limitSize
) limitSize
= size
;
1280 } else { /* Group move */
1281 size
= ddSymmGroupMove(table
,x
,y
,&moves
);
1282 if (size
== 0) goto ddSymmSiftingUpOutOfMem
;
1283 /* Update the lower bound. */
1286 zindex
= table
->invperm
[z
];
1287 if (cuddTestInteract(table
,zindex
,yindex
)) {
1288 isolated
= table
->vars
[zindex
]->ref
== 1;
1289 L
+= table
->subtables
[z
].keys
- isolated
;
1291 z
= table
->subtables
[z
].next
;
1292 } while (z
!= (int) moves
->y
);
1293 if ((double) size
> (double) limitSize
* table
->maxGrowth
)
1295 if (size
< limitSize
) limitSize
= size
;
1298 x
= cuddNextLow(table
,y
);
1303 ddSymmSiftingUpOutOfMem
:
1304 while (moves
!= NULL
) {
1306 cuddDeallocMove(table
, moves
);
1311 } /* end of ddSymmSiftingUp */
1314 /**Function********************************************************************
1316 Synopsis [Moves x down until either it reaches the bound (xHigh) or
1317 the size of the DD heap increases too much.]
1319 Description [Moves x down until either it reaches the bound (xHigh)
1320 or the size of the DD heap increases too much. Assumes that x is the
1321 bottom of a symmetry group. Checks x for symmetry to the adjacent
1322 variables. If symmetry is found, the symmetry group of x is merged
1323 with the symmetry group of the other variable. Returns the set of
1324 moves in case of success; MV_OOM if memory is full.]
1328 ******************************************************************************/
1341 int R
; /* upper bound on node decrease */
1352 xindex
= table
->invperm
[x
];
1353 gxtop
= table
->subtables
[x
].next
;
1354 limitSize
= size
= table
->keys
- table
->isolated
;
1356 for (z
= xHigh
; z
> gxtop
; z
--) {
1357 zindex
= table
->invperm
[z
];
1358 if (zindex
== xindex
|| cuddTestInteract(table
,xindex
,zindex
)) {
1359 isolated
= table
->vars
[zindex
]->ref
== 1;
1360 R
+= table
->subtables
[z
].keys
- isolated
;
1364 y
= cuddNextHigh(table
,x
);
1365 while (y
<= xHigh
&& size
- R
< limitSize
) {
1367 gxtop
= table
->subtables
[x
].next
;
1369 for (z
= xHigh
; z
> gxtop
; z
--) {
1370 zindex
= table
->invperm
[z
];
1371 if (zindex
== xindex
|| cuddTestInteract(table
,xindex
,zindex
)) {
1372 isolated
= table
->vars
[zindex
]->ref
== 1;
1373 checkR
+= table
->subtables
[z
].keys
- isolated
;
1376 assert(R
== checkR
);
1378 gybot
= table
->subtables
[y
].next
;
1379 while (table
->subtables
[gybot
].next
!= (unsigned) y
)
1380 gybot
= table
->subtables
[gybot
].next
;
1381 if (cuddSymmCheck(table
,x
,y
)) {
1382 /* Symmetry found, attach symm groups */
1383 gxtop
= table
->subtables
[x
].next
;
1384 table
->subtables
[x
].next
= y
;
1385 table
->subtables
[gybot
].next
= gxtop
;
1386 } else if (table
->subtables
[x
].next
== (unsigned) x
&&
1387 table
->subtables
[y
].next
== (unsigned) y
) {
1388 /* x and y have self symmetry */
1389 /* Update upper bound on node decrease. */
1390 yindex
= table
->invperm
[y
];
1391 if (cuddTestInteract(table
,xindex
,yindex
)) {
1392 isolated
= table
->vars
[yindex
]->ref
== 1;
1393 R
-= table
->subtables
[y
].keys
- isolated
;
1395 size
= cuddSwapInPlace(table
,x
,y
);
1397 assert(table
->subtables
[x
].next
== (unsigned) x
);
1398 assert(table
->subtables
[y
].next
== (unsigned) y
);
1400 if (size
== 0) goto ddSymmSiftingDownOutOfMem
;
1401 move
= (Move
*) cuddDynamicAllocNode(table
);
1402 if (move
== NULL
) goto ddSymmSiftingDownOutOfMem
;
1408 if ((double) size
> (double) limitSize
* table
->maxGrowth
)
1410 if (size
< limitSize
) limitSize
= size
;
1411 } else { /* Group move */
1412 /* Update upper bound on node decrease: first phase. */
1413 gxtop
= table
->subtables
[x
].next
;
1416 zindex
= table
->invperm
[z
];
1417 if (zindex
== xindex
|| cuddTestInteract(table
,xindex
,zindex
)) {
1418 isolated
= table
->vars
[zindex
]->ref
== 1;
1419 R
-= table
->subtables
[z
].keys
- isolated
;
1422 } while (z
<= gybot
);
1423 size
= ddSymmGroupMove(table
,x
,y
,&moves
);
1424 if (size
== 0) goto ddSymmSiftingDownOutOfMem
;
1425 if ((double) size
> (double) limitSize
* table
->maxGrowth
)
1427 if (size
< limitSize
) limitSize
= size
;
1428 /* Update upper bound on node decrease: second phase. */
1429 gxtop
= table
->subtables
[gybot
].next
;
1430 for (z
= gxtop
+ 1; z
<= gybot
; z
++) {
1431 zindex
= table
->invperm
[z
];
1432 if (zindex
== xindex
|| cuddTestInteract(table
,xindex
,zindex
)) {
1433 isolated
= table
->vars
[zindex
]->ref
== 1;
1434 R
+= table
->subtables
[z
].keys
- isolated
;
1439 y
= cuddNextHigh(table
,x
);
1444 ddSymmSiftingDownOutOfMem
:
1445 while (moves
!= NULL
) {
1447 cuddDeallocMove(table
, moves
);
1452 } /* end of ddSymmSiftingDown */
1455 /**Function********************************************************************
1457 Synopsis [Swaps two groups.]
1459 Description [Swaps two groups. x is assumed to be the bottom variable
1460 of the first group. y is assumed to be the top variable of the second
1461 group. Updates the list of moves. Returns the number of keys in the
1462 table if successful; 0 otherwise.]
1466 ******************************************************************************/
1477 int xtop
,xbot
,xsize
,ytop
,ybot
,ysize
,newxtop
;
1481 assert(x
< y
); /* we assume that x < y */
1483 /* Find top, bottom, and size for the two groups. */
1485 xtop
= table
->subtables
[x
].next
;
1486 xsize
= xbot
- xtop
+ 1;
1488 while ((unsigned) ybot
< table
->subtables
[ybot
].next
)
1489 ybot
= table
->subtables
[ybot
].next
;
1491 ysize
= ybot
- ytop
+ 1;
1493 /* Sift the variables of the second group up through the first group. */
1494 for (i
= 1; i
<= ysize
; i
++) {
1495 for (j
= 1; j
<= xsize
; j
++) {
1496 size
= cuddSwapInPlace(table
,x
,y
);
1497 if (size
== 0) return(0);
1498 swapx
= x
; swapy
= y
;
1506 /* fix symmetries */
1507 y
= xtop
; /* ytop is now where xtop used to be */
1508 for (i
= 0; i
< ysize
-1 ; i
++) {
1509 table
->subtables
[y
].next
= y
+ 1;
1512 table
->subtables
[y
].next
= xtop
; /* y is bottom of its group, join */
1513 /* its symmetry to top of its group */
1516 for (i
= 0; i
< xsize
- 1 ; i
++) {
1517 table
->subtables
[x
].next
= x
+ 1;
1520 table
->subtables
[x
].next
= newxtop
; /* x is bottom of its group, join */
1521 /* its symmetry to top of its group */
1522 /* Store group move */
1523 move
= (Move
*) cuddDynamicAllocNode(table
);
1524 if (move
== NULL
) return(0);
1528 move
->next
= *moves
;
1533 } /* end of ddSymmGroupMove */
1536 /**Function********************************************************************
1538 Synopsis [Undoes the swap of two groups.]
1540 Description [Undoes the swap of two groups. x is assumed to be the
1541 bottom variable of the first group. y is assumed to be the top
1542 variable of the second group. Returns the number of keys in the table
1543 if successful; 0 otherwise.]
1547 ******************************************************************************/
1549 ddSymmGroupMoveBackward(
1556 int xtop
,xbot
,xsize
,ytop
,ybot
,ysize
,newxtop
;
1559 assert(x
< y
); /* We assume that x < y */
1562 /* Find top, bottom, and size for the two groups. */
1564 xtop
= table
->subtables
[x
].next
;
1565 xsize
= xbot
- xtop
+ 1;
1567 while ((unsigned) ybot
< table
->subtables
[ybot
].next
)
1568 ybot
= table
->subtables
[ybot
].next
;
1570 ysize
= ybot
- ytop
+ 1;
1572 /* Sift the variables of the second group up through the first group. */
1573 for (i
= 1; i
<= ysize
; i
++) {
1574 for (j
= 1; j
<= xsize
; j
++) {
1575 size
= cuddSwapInPlace(table
,x
,y
);
1576 if (size
== 0) return(0);
1578 x
= cuddNextLow(table
,y
);
1584 /* Fix symmetries. */
1586 for (i
= 0; i
< ysize
-1 ; i
++) {
1587 table
->subtables
[y
].next
= y
+ 1;
1590 table
->subtables
[y
].next
= xtop
; /* y is bottom of its group, join */
1591 /* its symmetry to top of its group */
1594 for (i
= 0; i
< xsize
-1 ; i
++) {
1595 table
->subtables
[x
].next
= x
+ 1;
1598 table
->subtables
[x
].next
= newxtop
; /* x is bottom of its group, join */
1599 /* its symmetry to top of its group */
1603 } /* end of ddSymmGroupMoveBackward */
1606 /**Function********************************************************************
1608 Synopsis [Given a set of moves, returns the DD heap to the position
1609 giving the minimum size.]
1611 Description [Given a set of moves, returns the DD heap to the
1612 position giving the minimum size. In case of ties, returns to the
1613 closest position giving the minimum size. Returns 1 in case of
1614 success; 0 otherwise.]
1618 ******************************************************************************/
1620 ddSymmSiftingBackward(
1628 for (move
= moves
; move
!= NULL
; move
= move
->next
) {
1629 if (move
->size
< size
) {
1634 for (move
= moves
; move
!= NULL
; move
= move
->next
) {
1635 if (move
->size
== size
) return(1);
1636 if (table
->subtables
[move
->x
].next
== move
->x
&& table
->subtables
[move
->y
].next
== move
->y
) {
1637 res
= cuddSwapInPlace(table
,(int)move
->x
,(int)move
->y
);
1639 assert(table
->subtables
[move
->x
].next
== move
->x
);
1640 assert(table
->subtables
[move
->y
].next
== move
->y
);
1642 } else { /* Group move necessary */
1643 res
= ddSymmGroupMoveBackward(table
,(int)move
->x
,(int)move
->y
);
1645 if (!res
) return(0);
1650 } /* end of ddSymmSiftingBackward */
1653 /**Function********************************************************************
1655 Synopsis [Counts numbers of symmetric variables and symmetry
1662 ******************************************************************************/
1673 int TotalSymmGroups
= 0;
1675 for (i
= lower
; i
<= upper
; i
++) {
1676 if (table
->subtables
[i
].next
!= (unsigned) i
) {
1682 x
= table
->subtables
[x
].next
;
1685 assert(table
->subtables
[gbot
].next
== (unsigned) i
);
1690 *symvars
= TotalSymm
;
1691 *symgroups
= TotalSymmGroups
;
1695 } /* end of ddSymmSummary */