1 /**CFile***********************************************************************
3 FileName [cuddWindow.c]
7 Synopsis [Functions for variable reordering by window permutation.]
9 Description [Internal procedures included in this module:
11 <li> cuddWindowReorder()
13 Static procedures included in this module:
17 <li> ddPermuteWindow3()
20 <li> ddPermuteWindow4()
25 Author [Fabio Somenzi]
27 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
31 Redistribution and use in source and binary forms, with or without
32 modification, are permitted provided that the following conditions
35 Redistributions of source code must retain the above copyright
36 notice, this list of conditions and the following disclaimer.
38 Redistributions in binary form must reproduce the above copyright
39 notice, this list of conditions and the following disclaimer in the
40 documentation and/or other materials provided with the distribution.
42 Neither the name of the University of Colorado nor the names of its
43 contributors may be used to endorse or promote products derived from
44 this software without specific prior written permission.
46 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
47 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
48 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
49 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
50 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
51 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
52 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
54 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
56 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
57 POSSIBILITY OF SUCH DAMAGE.]
59 ******************************************************************************/
64 /*---------------------------------------------------------------------------*/
65 /* Constant declarations */
66 /*---------------------------------------------------------------------------*/
69 /*---------------------------------------------------------------------------*/
70 /* Stucture declarations */
71 /*---------------------------------------------------------------------------*/
74 /*---------------------------------------------------------------------------*/
75 /* Type declarations */
76 /*---------------------------------------------------------------------------*/
79 /*---------------------------------------------------------------------------*/
80 /* Variable declarations */
81 /*---------------------------------------------------------------------------*/
84 static char rcsid
[] DD_UNUSED
= "$Id: cuddWindow.c,v 1.14 2009/02/20 02:14:58 fabio Exp $";
88 extern int ddTotalNumberSwapping
;
89 extern int ddTotalNISwaps
;
92 /*---------------------------------------------------------------------------*/
93 /* Macro declarations */
94 /*---------------------------------------------------------------------------*/
97 /**AutomaticStart*************************************************************/
99 /*---------------------------------------------------------------------------*/
100 /* Static function prototypes */
101 /*---------------------------------------------------------------------------*/
103 static int ddWindow2 (DdManager
*table
, int low
, int high
);
104 static int ddWindowConv2 (DdManager
*table
, int low
, int high
);
105 static int ddPermuteWindow3 (DdManager
*table
, int x
);
106 static int ddWindow3 (DdManager
*table
, int low
, int high
);
107 static int ddWindowConv3 (DdManager
*table
, int low
, int high
);
108 static int ddPermuteWindow4 (DdManager
*table
, int w
);
109 static int ddWindow4 (DdManager
*table
, int low
, int high
);
110 static int ddWindowConv4 (DdManager
*table
, int low
, int high
);
112 /**AutomaticEnd***************************************************************/
115 /*---------------------------------------------------------------------------*/
116 /* Definition of exported functions */
117 /*---------------------------------------------------------------------------*/
119 /*---------------------------------------------------------------------------*/
120 /* Definition of internal functions */
121 /*---------------------------------------------------------------------------*/
124 /**Function********************************************************************
126 Synopsis [Reorders by applying the method of the sliding window.]
128 Description [Reorders by applying the method of the sliding window.
129 Tries all possible permutations to the variables in a window that
130 slides from low to high. The size of the window is determined by
131 submethod. Assumes that no dead nodes are present. Returns 1 in
132 case of success; 0 otherwise.]
136 ******************************************************************************/
139 DdManager
* table
/* DD table */,
140 int low
/* lowest index to reorder */,
141 int high
/* highest index to reorder */,
142 Cudd_ReorderingType submethod
/* window reordering option */)
151 case CUDD_REORDER_WINDOW2
:
152 res
= ddWindow2(table
,low
,high
);
154 case CUDD_REORDER_WINDOW3
:
155 res
= ddWindow3(table
,low
,high
);
157 case CUDD_REORDER_WINDOW4
:
158 res
= ddWindow4(table
,low
,high
);
160 case CUDD_REORDER_WINDOW2_CONV
:
161 res
= ddWindowConv2(table
,low
,high
);
163 case CUDD_REORDER_WINDOW3_CONV
:
164 res
= ddWindowConv3(table
,low
,high
);
166 supposedOpt
= table
->keys
- table
->isolated
;
167 res
= ddWindow3(table
,low
,high
);
168 if (table
->keys
- table
->isolated
!= (unsigned) supposedOpt
) {
169 (void) fprintf(table
->err
, "Convergence failed! (%d != %d)\n",
170 table
->keys
- table
->isolated
, supposedOpt
);
174 case CUDD_REORDER_WINDOW4_CONV
:
175 res
= ddWindowConv4(table
,low
,high
);
177 supposedOpt
= table
->keys
- table
->isolated
;
178 res
= ddWindow4(table
,low
,high
);
179 if (table
->keys
- table
->isolated
!= (unsigned) supposedOpt
) {
180 (void) fprintf(table
->err
,"Convergence failed! (%d != %d)\n",
181 table
->keys
- table
->isolated
, supposedOpt
);
190 } /* end of cuddWindowReorder */
193 /*---------------------------------------------------------------------------*/
194 /* Definition of static functions */
195 /*---------------------------------------------------------------------------*/
197 /**Function********************************************************************
199 Synopsis [Reorders by applying a sliding window of width 2.]
201 Description [Reorders by applying a sliding window of width 2.
202 Tries both permutations of the variables in a window
203 that slides from low to high. Assumes that no dead nodes are
204 present. Returns 1 in case of success; 0 otherwise.]
208 ******************************************************************************/
221 assert(low
>= 0 && high
< table
->size
);
224 if (high
-low
< 1) return(0);
226 res
= table
->keys
- table
->isolated
;
227 for (x
= low
; x
< high
; x
++) {
229 res
= cuddSwapInPlace(table
,x
,x
+1);
230 if (res
== 0) return(0);
231 if (res
>= size
) { /* no improvement: undo permutation */
232 res
= cuddSwapInPlace(table
,x
,x
+1);
233 if (res
== 0) return(0);
237 (void) fprintf(table
->out
,"-");
239 (void) fprintf(table
->out
,"=");
247 } /* end of ddWindow2 */
250 /**Function********************************************************************
252 Synopsis [Reorders by repeatedly applying a sliding window of width 2.]
254 Description [Reorders by repeatedly applying a sliding window of width
255 2. Tries both permutations of the variables in a window
256 that slides from low to high. Assumes that no dead nodes are
257 present. Uses an event-driven approach to determine convergence.
258 Returns 1 in case of success; 0 otherwise.]
262 ******************************************************************************/
277 assert(low
>= 0 && high
< table
->size
);
280 if (high
-low
< 1) return(ddWindowConv2(table
,low
,high
));
283 events
= ALLOC(int,nwin
);
284 if (events
== NULL
) {
285 table
->errorCode
= CUDD_MEMORY_OUT
;
288 for (x
=0; x
<nwin
; x
++) {
292 res
= table
->keys
- table
->isolated
;
295 for (x
=0; x
<nwin
; x
++) {
298 res
= cuddSwapInPlace(table
,x
+low
,x
+low
+1);
303 if (res
>= size
) { /* no improvement: undo permutation */
304 res
= cuddSwapInPlace(table
,x
+low
,x
+low
+1);
311 if (x
< nwin
-1) events
[x
+1] = 1;
312 if (x
> 0) events
[x
-1] = 1;
318 (void) fprintf(table
->out
,"-");
320 (void) fprintf(table
->out
,"=");
328 (void) fprintf(table
->out
,"|");
338 } /* end of ddWindowConv3 */
341 /**Function********************************************************************
343 Synopsis [Tries all the permutations of the three variables between
344 x and x+2 and retains the best.]
346 Description [Tries all the permutations of the three variables between
347 x and x+2 and retains the best. Assumes that no dead nodes are
348 present. Returns the index of the best permutation (1-6) in case of
349 success; 0 otherwise.Assumes that no dead nodes are present. Returns
350 the index of the best permutation (1-6) in case of success; 0
355 ******************************************************************************/
366 assert(table
->dead
== 0);
367 assert(x
+2 < table
->size
);
370 size
= table
->keys
- table
->isolated
;
373 /* The permutation pattern is:
375 ** repeated three times to get all 3! = 6 permutations.
381 sizeNew
= cuddSwapInPlace(table
,x
,y
);
382 if (sizeNew
< size
) {
383 if (sizeNew
== 0) return(0);
388 sizeNew
= cuddSwapInPlace(table
,y
,z
);
389 if (sizeNew
< size
) {
390 if (sizeNew
== 0) return(0);
395 sizeNew
= cuddSwapInPlace(table
,x
,y
);
396 if (sizeNew
< size
) {
397 if (sizeNew
== 0) return(0);
402 sizeNew
= cuddSwapInPlace(table
,y
,z
);
403 if (sizeNew
< size
) {
404 if (sizeNew
== 0) return(0);
409 sizeNew
= cuddSwapInPlace(table
,x
,y
);
410 if (sizeNew
< size
) {
411 if (sizeNew
== 0) return(0);
416 /* Now take the shortest route to the best permuytation.
417 ** The initial permutation is ACB.
420 case BCA
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
421 case CBA
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
422 case ABC
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
424 case BAC
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
425 case CAB
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
431 assert(table
->keys
- table
->isolated
== (unsigned) size
);
436 } /* end of ddPermuteWindow3 */
439 /**Function********************************************************************
441 Synopsis [Reorders by applying a sliding window of width 3.]
443 Description [Reorders by applying a sliding window of width 3.
444 Tries all possible permutations to the variables in a
445 window that slides from low to high. Assumes that no dead nodes are
446 present. Returns 1 in case of success; 0 otherwise.]
450 ******************************************************************************/
462 assert(low
>= 0 && high
< table
->size
);
465 if (high
-low
< 2) return(ddWindow2(table
,low
,high
));
467 for (x
= low
; x
+1 < high
; x
++) {
468 res
= ddPermuteWindow3(table
,x
);
469 if (res
== 0) return(0);
472 (void) fprintf(table
->out
,"=");
474 (void) fprintf(table
->out
,"-");
482 } /* end of ddWindow3 */
485 /**Function********************************************************************
487 Synopsis [Reorders by repeatedly applying a sliding window of width 3.]
489 Description [Reorders by repeatedly applying a sliding window of width
490 3. Tries all possible permutations to the variables in a
491 window that slides from low to high. Assumes that no dead nodes are
492 present. Uses an event-driven approach to determine convergence.
493 Returns 1 in case of success; 0 otherwise.]
497 ******************************************************************************/
511 assert(low
>= 0 && high
< table
->size
);
514 if (high
-low
< 2) return(ddWindowConv2(table
,low
,high
));
517 events
= ALLOC(int,nwin
);
518 if (events
== NULL
) {
519 table
->errorCode
= CUDD_MEMORY_OUT
;
522 for (x
=0; x
<nwin
; x
++) {
528 for (x
=0; x
<nwin
; x
++) {
530 res
= ddPermuteWindow3(table
,x
+low
);
535 if (x
< nwin
-1) events
[x
+1] = 1;
536 if (x
> 1) events
[x
-2] = 1;
542 if (x
< nwin
-2) events
[x
+2] = 1;
543 if (x
< nwin
-1) events
[x
+1] = 1;
544 if (x
> 0) events
[x
-1] = 1;
545 if (x
> 1) events
[x
-2] = 1;
549 if (x
< nwin
-2) events
[x
+2] = 1;
550 if (x
> 0) events
[x
-1] = 1;
560 (void) fprintf(table
->out
,"=");
562 (void) fprintf(table
->out
,"-");
570 (void) fprintf(table
->out
,"|");
580 } /* end of ddWindowConv3 */
583 /**Function********************************************************************
585 Synopsis [Tries all the permutations of the four variables between w
586 and w+3 and retains the best.]
588 Description [Tries all the permutations of the four variables between
589 w and w+3 and retains the best. Assumes that no dead nodes are
590 present. Returns the index of the best permutation (1-24) in case of
591 success; 0 otherwise.]
595 ******************************************************************************/
606 assert(table
->dead
== 0);
607 assert(w
+3 < table
->size
);
610 size
= table
->keys
- table
->isolated
;
611 x
= w
+1; y
= x
+1; z
= y
+1;
613 /* The permutation pattern is:
614 * (w,x)(y,z)(w,x)(x,y)
615 * (y,z)(w,x)(y,z)(x,y)
616 * repeated three times to get all 4! = 24 permutations.
617 * This gives a hamiltonian circuit of Cayley's graph.
618 * The codes to the permutation are assigned in topological order.
619 * The permutations at lower distance from the final permutation are
620 * assigned lower codes. This way we can choose, between
621 * permutations that give the same size, one that requires the minimum
622 * number of swaps from the final permutation of the hamiltonian circuit.
623 * There is an exception to this rule: ABCD is given Code 1, to
624 * avoid oscillation when convergence is sought.
630 sizeNew
= cuddSwapInPlace(table
,w
,x
);
631 if (sizeNew
< size
) {
632 if (sizeNew
== 0) return(0);
637 sizeNew
= cuddSwapInPlace(table
,y
,z
);
638 if (sizeNew
< size
) {
639 if (sizeNew
== 0) return(0);
644 sizeNew
= cuddSwapInPlace(table
,w
,x
);
645 if (sizeNew
< size
|| (sizeNew
== size
&& ABDC
< best
)) {
646 if (sizeNew
== 0) return(0);
651 sizeNew
= cuddSwapInPlace(table
,x
,y
);
652 if (sizeNew
< size
) {
653 if (sizeNew
== 0) return(0);
658 sizeNew
= cuddSwapInPlace(table
,y
,z
);
659 if (sizeNew
< size
|| (sizeNew
== size
&& ADCB
< best
)) {
660 if (sizeNew
== 0) return(0);
665 sizeNew
= cuddSwapInPlace(table
,w
,x
);
666 if (sizeNew
< size
) {
667 if (sizeNew
== 0) return(0);
672 sizeNew
= cuddSwapInPlace(table
,y
,z
);
673 if (sizeNew
< size
) {
674 if (sizeNew
== 0) return(0);
679 sizeNew
= cuddSwapInPlace(table
,x
,y
);
680 if (sizeNew
< size
) {
681 if (sizeNew
== 0) return(0);
686 sizeNew
= cuddSwapInPlace(table
,w
,x
);
687 if (sizeNew
< size
|| (sizeNew
== size
&& BDAC
< best
)) {
688 if (sizeNew
== 0) return(0);
693 sizeNew
= cuddSwapInPlace(table
,y
,z
);
694 if (sizeNew
< size
|| (sizeNew
== size
&& BDCA
< best
)) {
695 if (sizeNew
== 0) return(0);
700 sizeNew
= cuddSwapInPlace(table
,w
,x
);
701 if (sizeNew
< size
) {
702 if (sizeNew
== 0) return(0);
707 sizeNew
= cuddSwapInPlace(table
,x
,y
);
708 if (sizeNew
< size
|| (sizeNew
== size
&& DCBA
< best
)) {
709 if (sizeNew
== 0) return(0);
714 sizeNew
= cuddSwapInPlace(table
,y
,z
);
715 if (sizeNew
< size
|| (sizeNew
== size
&& DCAB
< best
)) {
716 if (sizeNew
== 0) return(0);
721 sizeNew
= cuddSwapInPlace(table
,w
,x
);
722 if (sizeNew
< size
|| (sizeNew
== size
&& CDAB
< best
)) {
723 if (sizeNew
== 0) return(0);
728 sizeNew
= cuddSwapInPlace(table
,y
,z
);
729 if (sizeNew
< size
|| (sizeNew
== size
&& CDBA
< best
)) {
730 if (sizeNew
== 0) return(0);
735 sizeNew
= cuddSwapInPlace(table
,x
,y
);
736 if (sizeNew
< size
|| (sizeNew
== size
&& CBDA
< best
)) {
737 if (sizeNew
== 0) return(0);
742 sizeNew
= cuddSwapInPlace(table
,w
,x
);
743 if (sizeNew
< size
|| (sizeNew
== size
&& BCDA
< best
)) {
744 if (sizeNew
== 0) return(0);
749 sizeNew
= cuddSwapInPlace(table
,y
,z
);
750 if (sizeNew
< size
|| (sizeNew
== size
&& BCAD
< best
)) {
751 if (sizeNew
== 0) return(0);
756 sizeNew
= cuddSwapInPlace(table
,w
,x
);
757 if (sizeNew
< size
|| (sizeNew
== size
&& CBAD
< best
)) {
758 if (sizeNew
== 0) return(0);
763 sizeNew
= cuddSwapInPlace(table
,x
,y
);
764 if (sizeNew
< size
|| (sizeNew
== size
&& CABD
< best
)) {
765 if (sizeNew
== 0) return(0);
770 sizeNew
= cuddSwapInPlace(table
,y
,z
);
771 if (sizeNew
< size
|| (sizeNew
== size
&& CADB
< best
)) {
772 if (sizeNew
== 0) return(0);
777 sizeNew
= cuddSwapInPlace(table
,w
,x
);
778 if (sizeNew
< size
|| (sizeNew
== size
&& ACDB
< best
)) {
779 if (sizeNew
== 0) return(0);
784 sizeNew
= cuddSwapInPlace(table
,y
,z
);
785 if (sizeNew
< size
|| (sizeNew
== size
&& ACBD
< best
)) {
786 if (sizeNew
== 0) return(0);
791 /* Now take the shortest route to the best permutation.
792 ** The initial permutation is ACBD.
795 case DBCA
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
796 case BDCA
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
797 case CDBA
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
798 case ADBC
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
799 case ABDC
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
800 case ACDB
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
802 case DCBA
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
803 case BCDA
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
804 case CBDA
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
805 if (!cuddSwapInPlace(table
,x
,y
)) return(0);
806 if (!cuddSwapInPlace(table
,y
,z
)) return(0);
808 case DBAC
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
809 case DCAB
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
810 case DACB
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
811 case BACD
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
812 case CABD
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
814 case DABC
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
815 case BADC
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
816 case CADB
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
817 if (!cuddSwapInPlace(table
,y
,z
)) return(0);
819 case BDAC
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
820 case CDAB
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
821 case ADCB
: if (!cuddSwapInPlace(table
,y
,z
)) return(0);
822 case ABCD
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
824 case BCAD
: if (!cuddSwapInPlace(table
,x
,y
)) return(0);
825 case CBAD
: if (!cuddSwapInPlace(table
,w
,x
)) return(0);
826 if (!cuddSwapInPlace(table
,x
,y
)) return(0);
832 assert(table
->keys
- table
->isolated
== (unsigned) size
);
837 } /* end of ddPermuteWindow4 */
840 /**Function********************************************************************
842 Synopsis [Reorders by applying a sliding window of width 4.]
844 Description [Reorders by applying a sliding window of width 4.
845 Tries all possible permutations to the variables in a
846 window that slides from low to high. Assumes that no dead nodes are
847 present. Returns 1 in case of success; 0 otherwise.]
851 ******************************************************************************/
863 assert(low
>= 0 && high
< table
->size
);
866 if (high
-low
< 3) return(ddWindow3(table
,low
,high
));
868 for (w
= low
; w
+2 < high
; w
++) {
869 res
= ddPermuteWindow4(table
,w
);
870 if (res
== 0) return(0);
873 (void) fprintf(table
->out
,"=");
875 (void) fprintf(table
->out
,"-");
883 } /* end of ddWindow4 */
886 /**Function********************************************************************
888 Synopsis [Reorders by repeatedly applying a sliding window of width 4.]
890 Description [Reorders by repeatedly applying a sliding window of width
891 4. Tries all possible permutations to the variables in a
892 window that slides from low to high. Assumes that no dead nodes are
893 present. Uses an event-driven approach to determine convergence.
894 Returns 1 in case of success; 0 otherwise.]
898 ******************************************************************************/
912 assert(low
>= 0 && high
< table
->size
);
915 if (high
-low
< 3) return(ddWindowConv3(table
,low
,high
));
918 events
= ALLOC(int,nwin
);
919 if (events
== NULL
) {
920 table
->errorCode
= CUDD_MEMORY_OUT
;
923 for (x
=0; x
<nwin
; x
++) {
929 for (x
=0; x
<nwin
; x
++) {
931 res
= ddPermuteWindow4(table
,x
+low
);
936 if (x
< nwin
-1) events
[x
+1] = 1;
937 if (x
> 2) events
[x
-3] = 1;
941 if (x
< nwin
-3) events
[x
+3] = 1;
942 if (x
< nwin
-1) events
[x
+1] = 1;
943 if (x
> 0) events
[x
-1] = 1;
944 if (x
> 2) events
[x
-3] = 1;
948 if (x
< nwin
-3) events
[x
+3] = 1;
949 if (x
> 0) events
[x
-1] = 1;
955 if (x
< nwin
-3) events
[x
+3] = 1;
956 if (x
< nwin
-2) events
[x
+2] = 1;
957 if (x
> 0) events
[x
-1] = 1;
958 if (x
> 1) events
[x
-2] = 1;
974 if (x
< nwin
-3) events
[x
+3] = 1;
975 if (x
< nwin
-2) events
[x
+2] = 1;
976 if (x
< nwin
-1) events
[x
+1] = 1;
977 if (x
> 0) events
[x
-1] = 1;
978 if (x
> 1) events
[x
-2] = 1;
979 if (x
> 2) events
[x
-3] = 1;
985 if (x
< nwin
-2) events
[x
+2] = 1;
986 if (x
< nwin
-1) events
[x
+1] = 1;
987 if (x
> 1) events
[x
-2] = 1;
988 if (x
> 2) events
[x
-3] = 1;
992 if (x
< nwin
-2) events
[x
+2] = 1;
993 if (x
> 1) events
[x
-2] = 1;
1003 (void) fprintf(table
->out
,"=");
1005 (void) fprintf(table
->out
,"-");
1013 (void) fprintf(table
->out
,"|");
1023 } /* end of ddWindowConv4 */