00001
00068 #include "util.h"
00069 #include "cuddInt.h"
00070
00071
00072
00073
00074
00075 #define MV_OOM (Move *)1
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #ifndef lint
00090 static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.26 2009/02/19 16:23:54 fabio Exp $";
00091 #endif
00092
00093 static int *entry;
00094
00095 extern int ddTotalNumberSwapping;
00096 #ifdef DD_STATS
00097 extern int ddTotalNISwaps;
00098 #endif
00099
00100
00101
00102
00103
00106
00107
00108
00109
00110 static int ddSymmUniqueCompare (int *ptrX, int *ptrY);
00111 static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh);
00112 static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh);
00113 static Move * ddSymmSiftingUp (DdManager *table, int y, int xLow);
00114 static Move * ddSymmSiftingDown (DdManager *table, int x, int xHigh);
00115 static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves);
00116 static int ddSymmGroupMoveBackward (DdManager *table, int x, int y);
00117 static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size);
00118 static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
00119
00123
00124
00125
00126
00127
00137 void
00138 Cudd_SymmProfile(
00139 DdManager * table,
00140 int lower,
00141 int upper)
00142 {
00143 int i,x,gbot;
00144 int TotalSymm = 0;
00145 int TotalSymmGroups = 0;
00146
00147 for (i = lower; i <= upper; i++) {
00148 if (table->subtables[i].next != (unsigned) i) {
00149 x = i;
00150 (void) fprintf(table->out,"Group:");
00151 do {
00152 (void) fprintf(table->out," %d",table->invperm[x]);
00153 TotalSymm++;
00154 gbot = x;
00155 x = table->subtables[x].next;
00156 } while (x != i);
00157 TotalSymmGroups++;
00158 #ifdef DD_DEBUG
00159 assert(table->subtables[gbot].next == (unsigned) i);
00160 #endif
00161 i = gbot;
00162 (void) fprintf(table->out,"\n");
00163 }
00164 }
00165 (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
00166 (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
00167
00168 }
00169
00170
00171
00172
00173
00174
00175
00187 int
00188 cuddSymmCheck(
00189 DdManager * table,
00190 int x,
00191 int y)
00192 {
00193 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
00194 int comple;
00195 int xsymmy;
00196 int xsymmyp;
00197 int arccount;
00198 int TotalRefCount;
00199 int yindex;
00200 int i;
00201 DdNodePtr *list;
00202 int slots;
00203 DdNode *sentinel = &(table->sentinel);
00204 #ifdef DD_DEBUG
00205 int xindex;
00206 #endif
00207
00208
00209
00210
00211
00212
00213
00214 if (table->subtables[x].keys == 1) {
00215 return(0);
00216 }
00217 yindex = table->invperm[y];
00218 if (table->subtables[y].keys == 1) {
00219 if (table->vars[yindex]->ref == 1)
00220 return(0);
00221 }
00222
00223 xsymmy = xsymmyp = 1;
00224 arccount = 0;
00225 slots = table->subtables[x].slots;
00226 list = table->subtables[x].nodelist;
00227 for (i = 0; i < slots; i++) {
00228 f = list[i];
00229 while (f != sentinel) {
00230
00231 f1 = cuddT(f);
00232 f0 = Cudd_Regular(cuddE(f));
00233 comple = Cudd_IsComplement(cuddE(f));
00234 if ((int) f1->index == yindex) {
00235 arccount++;
00236 f11 = cuddT(f1); f10 = cuddE(f1);
00237 } else {
00238 if ((int) f0->index != yindex) {
00239
00240
00241
00242 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
00243 return(0);
00244 }
00245 f11 = f10 = f1;
00246 }
00247 if ((int) f0->index == yindex) {
00248 arccount++;
00249 f01 = cuddT(f0); f00 = cuddE(f0);
00250 } else {
00251 f01 = f00 = f0;
00252 }
00253 if (comple) {
00254 f01 = Cudd_Not(f01);
00255 f00 = Cudd_Not(f00);
00256 }
00257
00258 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
00259 xsymmy &= f01 == f10;
00260 xsymmyp &= f11 == f00;
00261 if ((xsymmy == 0) && (xsymmyp == 0))
00262 return(0);
00263 }
00264
00265 f = f->next;
00266 }
00267 }
00268
00269
00270 TotalRefCount = -1;
00271 slots = table->subtables[y].slots;
00272 list = table->subtables[y].nodelist;
00273 for (i = 0; i < slots; i++) {
00274 f = list[i];
00275 while (f != sentinel) {
00276 TotalRefCount += f->ref;
00277 f = f->next;
00278 }
00279 }
00280
00281 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00282 if (arccount == TotalRefCount) {
00283 xindex = table->invperm[x];
00284 (void) fprintf(table->out,
00285 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00286 xindex,yindex,x,y);
00287 }
00288 #endif
00289
00290 return(arccount == TotalRefCount);
00291
00292 }
00293
00294
00317 int
00318 cuddSymmSifting(
00319 DdManager * table,
00320 int lower,
00321 int upper)
00322 {
00323 int i;
00324 int *var;
00325 int size;
00326 int x;
00327 int result;
00328 int symvars;
00329 int symgroups;
00330 #ifdef DD_STATS
00331 int previousSize;
00332 #endif
00333
00334 size = table->size;
00335
00336
00337 var = NULL;
00338 entry = ALLOC(int,size);
00339 if (entry == NULL) {
00340 table->errorCode = CUDD_MEMORY_OUT;
00341 goto ddSymmSiftingOutOfMem;
00342 }
00343 var = ALLOC(int,size);
00344 if (var == NULL) {
00345 table->errorCode = CUDD_MEMORY_OUT;
00346 goto ddSymmSiftingOutOfMem;
00347 }
00348
00349 for (i = 0; i < size; i++) {
00350 x = table->perm[i];
00351 entry[i] = table->subtables[x].keys;
00352 var[i] = i;
00353 }
00354
00355 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00356
00357
00358 for (i = lower; i <= upper; i++) {
00359 table->subtables[i].next = i;
00360 }
00361
00362 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00363 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00364 break;
00365 x = table->perm[var[i]];
00366 #ifdef DD_STATS
00367 previousSize = table->keys - table->isolated;
00368 #endif
00369 if (x < lower || x > upper) continue;
00370 if (table->subtables[x].next == (unsigned) x) {
00371 result = ddSymmSiftingAux(table,x,lower,upper);
00372 if (!result) goto ddSymmSiftingOutOfMem;
00373 #ifdef DD_STATS
00374 if (table->keys < (unsigned) previousSize + table->isolated) {
00375 (void) fprintf(table->out,"-");
00376 } else if (table->keys > (unsigned) previousSize +
00377 table->isolated) {
00378 (void) fprintf(table->out,"+");
00379 } else {
00380 (void) fprintf(table->out,"=");
00381 }
00382 fflush(table->out);
00383 #endif
00384 }
00385 }
00386
00387 FREE(var);
00388 FREE(entry);
00389
00390 ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00391
00392 #ifdef DD_STATS
00393 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00394 symvars);
00395 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00396 symgroups);
00397 #endif
00398
00399 return(1+symvars);
00400
00401 ddSymmSiftingOutOfMem:
00402
00403 if (entry != NULL) FREE(entry);
00404 if (var != NULL) FREE(var);
00405
00406 return(0);
00407
00408 }
00409
00410
00434 int
00435 cuddSymmSiftingConv(
00436 DdManager * table,
00437 int lower,
00438 int upper)
00439 {
00440 int i;
00441 int *var;
00442 int size;
00443 int x;
00444 int result;
00445 int symvars;
00446 int symgroups;
00447 int classes;
00448 int initialSize;
00449 #ifdef DD_STATS
00450 int previousSize;
00451 #endif
00452
00453 initialSize = table->keys - table->isolated;
00454
00455 size = table->size;
00456
00457
00458 var = NULL;
00459 entry = ALLOC(int,size);
00460 if (entry == NULL) {
00461 table->errorCode = CUDD_MEMORY_OUT;
00462 goto ddSymmSiftingConvOutOfMem;
00463 }
00464 var = ALLOC(int,size);
00465 if (var == NULL) {
00466 table->errorCode = CUDD_MEMORY_OUT;
00467 goto ddSymmSiftingConvOutOfMem;
00468 }
00469
00470 for (i = 0; i < size; i++) {
00471 x = table->perm[i];
00472 entry[i] = table->subtables[x].keys;
00473 var[i] = i;
00474 }
00475
00476 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00477
00478
00479
00480
00481 for (i = lower; i <= upper; i++) {
00482 table->subtables[i].next = i;
00483 }
00484
00485 for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
00486 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00487 break;
00488 x = table->perm[var[i]];
00489 if (x < lower || x > upper) continue;
00490
00491 if (table->subtables[x].next == (unsigned) x) {
00492 #ifdef DD_STATS
00493 previousSize = table->keys - table->isolated;
00494 #endif
00495 result = ddSymmSiftingAux(table,x,lower,upper);
00496 if (!result) goto ddSymmSiftingConvOutOfMem;
00497 #ifdef DD_STATS
00498 if (table->keys < (unsigned) previousSize + table->isolated) {
00499 (void) fprintf(table->out,"-");
00500 } else if (table->keys > (unsigned) previousSize +
00501 table->isolated) {
00502 (void) fprintf(table->out,"+");
00503 } else {
00504 (void) fprintf(table->out,"=");
00505 }
00506 fflush(table->out);
00507 #endif
00508 }
00509 }
00510
00511
00512 while ((unsigned) initialSize > table->keys - table->isolated) {
00513 initialSize = table->keys - table->isolated;
00514 #ifdef DD_STATS
00515 (void) fprintf(table->out,"\n");
00516 #endif
00517
00518 for (x = lower, classes = 0; x <= upper; x++, classes++) {
00519 while ((unsigned) x < table->subtables[x].next) {
00520 x = table->subtables[x].next;
00521 }
00522
00523
00524
00525
00526 i = table->invperm[x];
00527 entry[i] = table->subtables[x].keys;
00528 var[classes] = i;
00529 }
00530
00531 qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
00532
00533
00534 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00535 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00536 break;
00537 x = table->perm[var[i]];
00538 if ((unsigned) x >= table->subtables[x].next) {
00539 #ifdef DD_STATS
00540 previousSize = table->keys - table->isolated;
00541 #endif
00542 result = ddSymmSiftingConvAux(table,x,lower,upper);
00543 if (!result ) goto ddSymmSiftingConvOutOfMem;
00544 #ifdef DD_STATS
00545 if (table->keys < (unsigned) previousSize + table->isolated) {
00546 (void) fprintf(table->out,"-");
00547 } else if (table->keys > (unsigned) previousSize +
00548 table->isolated) {
00549 (void) fprintf(table->out,"+");
00550 } else {
00551 (void) fprintf(table->out,"=");
00552 }
00553 fflush(table->out);
00554 #endif
00555 }
00556 }
00557 }
00558
00559 ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00560
00561 #ifdef DD_STATS
00562 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00563 symvars);
00564 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00565 symgroups);
00566 #endif
00567
00568 FREE(var);
00569 FREE(entry);
00570
00571 return(1+symvars);
00572
00573 ddSymmSiftingConvOutOfMem:
00574
00575 if (entry != NULL) FREE(entry);
00576 if (var != NULL) FREE(var);
00577
00578 return(0);
00579
00580 }
00581
00582
00583
00584
00585
00586
00587
00600 static int
00601 ddSymmUniqueCompare(
00602 int * ptrX,
00603 int * ptrY)
00604 {
00605 #if 0
00606 if (entry[*ptrY] == entry[*ptrX]) {
00607 return((*ptrX) - (*ptrY));
00608 }
00609 #endif
00610 return(entry[*ptrY] - entry[*ptrX]);
00611
00612 }
00613
00614
00628 static int
00629 ddSymmSiftingAux(
00630 DdManager * table,
00631 int x,
00632 int xLow,
00633 int xHigh)
00634 {
00635 Move *move;
00636 Move *moveUp;
00637 Move *moveDown;
00638 int initialSize;
00639 int result;
00640 int i;
00641 int topbot;
00642 int initGroupSize, finalGroupSize;
00643
00644
00645 #ifdef DD_DEBUG
00646
00647 assert(table->subtables[x].next == (unsigned) x);
00648 #endif
00649
00650 initialSize = table->keys - table->isolated;
00651
00652 moveDown = NULL;
00653 moveUp = NULL;
00654
00655 if ((x - xLow) > (xHigh - x)) {
00656
00657
00658
00659 for (i = x; i > xLow; i--) {
00660 if (!cuddSymmCheck(table,i-1,i))
00661 break;
00662 topbot = table->subtables[i-1].next;
00663 table->subtables[i-1].next = i;
00664 table->subtables[x].next = topbot;
00665
00666 i = topbot + 1;
00667 }
00668 } else {
00669
00670
00671
00672 for (i = x; i < xHigh; i++) {
00673 if (!cuddSymmCheck(table,i,i+1))
00674 break;
00675
00676 topbot = i + 1;
00677 while ((unsigned) topbot < table->subtables[topbot].next) {
00678 topbot = table->subtables[topbot].next;
00679 }
00680 table->subtables[topbot].next = table->subtables[i].next;
00681 table->subtables[i].next = i + 1;
00682 i = topbot - 1;
00683 }
00684 }
00685
00686
00687
00688
00689 while ((unsigned) x < table->subtables[x].next)
00690 x = table->subtables[x].next;
00691
00692 if (x == xLow) {
00693
00694 #ifdef DD_DEBUG
00695
00696 assert((unsigned) x == table->subtables[x].next);
00697 #endif
00698 if (x == xHigh) return(1);
00699
00700 initGroupSize = 1;
00701
00702 moveDown = ddSymmSiftingDown(table,x,xHigh);
00703
00704 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00705 if (moveDown == NULL) return(1);
00706
00707 x = moveDown->y;
00708
00709 i = x;
00710 while ((unsigned) i < table->subtables[i].next) {
00711 i = table->subtables[i].next;
00712 }
00713 #ifdef DD_DEBUG
00714
00715 assert((unsigned) i >= table->subtables[i].next);
00716 assert((unsigned) x == table->subtables[i].next);
00717 #endif
00718 finalGroupSize = i - x + 1;
00719
00720 if (initGroupSize == finalGroupSize) {
00721
00722 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00723 } else {
00724 initialSize = table->keys - table->isolated;
00725 moveUp = ddSymmSiftingUp(table,x,xLow);
00726 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00727 }
00728 if (!result) goto ddSymmSiftingAuxOutOfMem;
00729
00730 } else if (cuddNextHigh(table,x) > xHigh) {
00731
00732 i = x;
00733 x = table->subtables[x].next;
00734
00735 if (x == xLow) return(1);
00736
00737 initGroupSize = i - x + 1;
00738
00739 moveUp = ddSymmSiftingUp(table,x,xLow);
00740
00741 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00742 if (moveUp == NULL) return(1);
00743
00744 x = moveUp->x;
00745
00746 i = table->subtables[x].next;
00747 #ifdef DD_DEBUG
00748
00749 assert((unsigned) x >= table->subtables[x].next);
00750 assert((unsigned) i == table->subtables[x].next);
00751 #endif
00752 finalGroupSize = x - i + 1;
00753
00754 if (initGroupSize == finalGroupSize) {
00755
00756 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00757 } else {
00758 initialSize = table->keys - table->isolated;
00759 moveDown = ddSymmSiftingDown(table,x,xHigh);
00760 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00761 }
00762 if (!result) goto ddSymmSiftingAuxOutOfMem;
00763
00764 } else if ((x - xLow) > (xHigh - x)) {
00765
00766 moveDown = ddSymmSiftingDown(table,x,xHigh);
00767
00768 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00769
00770 if (moveDown != NULL) {
00771 x = moveDown->y;
00772 i = x;
00773 while ((unsigned) i < table->subtables[i].next) {
00774 i = table->subtables[i].next;
00775 }
00776 } else {
00777 i = x;
00778 while ((unsigned) i < table->subtables[i].next) {
00779 i = table->subtables[i].next;
00780 }
00781 x = table->subtables[i].next;
00782 }
00783 #ifdef DD_DEBUG
00784
00785 assert((unsigned) i >= table->subtables[i].next);
00786 assert((unsigned) x == table->subtables[i].next);
00787 #endif
00788 initGroupSize = i - x + 1;
00789
00790 moveUp = ddSymmSiftingUp(table,x,xLow);
00791 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00792
00793 if (moveUp != NULL) {
00794 x = moveUp->x;
00795 i = table->subtables[x].next;
00796 } else {
00797 i = x;
00798 while ((unsigned) x < table->subtables[x].next)
00799 x = table->subtables[x].next;
00800 }
00801 #ifdef DD_DEBUG
00802
00803 assert((unsigned) x >= table->subtables[x].next);
00804 assert((unsigned) i == table->subtables[x].next);
00805 #endif
00806 finalGroupSize = x - i + 1;
00807
00808 if (initGroupSize == finalGroupSize) {
00809
00810 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00811 } else {
00812 while (moveDown != NULL) {
00813 move = moveDown->next;
00814 cuddDeallocMove(table, moveDown);
00815 moveDown = move;
00816 }
00817 initialSize = table->keys - table->isolated;
00818 moveDown = ddSymmSiftingDown(table,x,xHigh);
00819 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00820 }
00821 if (!result) goto ddSymmSiftingAuxOutOfMem;
00822
00823 } else {
00824
00825 x = table->subtables[x].next;
00826
00827 moveUp = ddSymmSiftingUp(table,x,xLow);
00828
00829 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00830
00831 if (moveUp != NULL) {
00832 x = moveUp->x;
00833 i = table->subtables[x].next;
00834 } else {
00835 while ((unsigned) x < table->subtables[x].next)
00836 x = table->subtables[x].next;
00837 i = table->subtables[x].next;
00838 }
00839 #ifdef DD_DEBUG
00840
00841 assert((unsigned) x >= table->subtables[x].next);
00842 assert((unsigned) i == table->subtables[x].next);
00843 #endif
00844 initGroupSize = x - i + 1;
00845
00846 moveDown = ddSymmSiftingDown(table,x,xHigh);
00847 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00848
00849 if (moveDown != NULL) {
00850 x = moveDown->y;
00851 i = x;
00852 while ((unsigned) i < table->subtables[i].next) {
00853 i = table->subtables[i].next;
00854 }
00855 } else {
00856 i = x;
00857 x = table->subtables[x].next;
00858 }
00859 #ifdef DD_DEBUG
00860
00861 assert((unsigned) i >= table->subtables[i].next);
00862 assert((unsigned) x == table->subtables[i].next);
00863 #endif
00864 finalGroupSize = i - x + 1;
00865
00866 if (initGroupSize == finalGroupSize) {
00867
00868 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00869 } else {
00870 while (moveUp != NULL) {
00871 move = moveUp->next;
00872 cuddDeallocMove(table, moveUp);
00873 moveUp = move;
00874 }
00875 initialSize = table->keys - table->isolated;
00876 moveUp = ddSymmSiftingUp(table,x,xLow);
00877 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00878 }
00879 if (!result) goto ddSymmSiftingAuxOutOfMem;
00880 }
00881
00882 while (moveDown != NULL) {
00883 move = moveDown->next;
00884 cuddDeallocMove(table, moveDown);
00885 moveDown = move;
00886 }
00887 while (moveUp != NULL) {
00888 move = moveUp->next;
00889 cuddDeallocMove(table, moveUp);
00890 moveUp = move;
00891 }
00892
00893 return(1);
00894
00895 ddSymmSiftingAuxOutOfMem:
00896 if (moveDown != MV_OOM) {
00897 while (moveDown != NULL) {
00898 move = moveDown->next;
00899 cuddDeallocMove(table, moveDown);
00900 moveDown = move;
00901 }
00902 }
00903 if (moveUp != MV_OOM) {
00904 while (moveUp != NULL) {
00905 move = moveUp->next;
00906 cuddDeallocMove(table, moveUp);
00907 moveUp = move;
00908 }
00909 }
00910
00911 return(0);
00912
00913 }
00914
00915
00930 static int
00931 ddSymmSiftingConvAux(
00932 DdManager * table,
00933 int x,
00934 int xLow,
00935 int xHigh)
00936 {
00937 Move *move;
00938 Move *moveUp;
00939 Move *moveDown;
00940 int initialSize;
00941 int result;
00942 int i;
00943 int initGroupSize, finalGroupSize;
00944
00945
00946 initialSize = table->keys - table->isolated;
00947
00948 moveDown = NULL;
00949 moveUp = NULL;
00950
00951 if (x == xLow) {
00952 #ifdef DD_DEBUG
00953
00954 assert((unsigned) x >= table->subtables[x].next);
00955 #endif
00956 i = table->subtables[x].next;
00957 initGroupSize = x - i + 1;
00958
00959 moveDown = ddSymmSiftingDown(table,x,xHigh);
00960
00961 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
00962 if (moveDown == NULL) return(1);
00963
00964 x = moveDown->y;
00965 i = x;
00966 while ((unsigned) i < table->subtables[i].next) {
00967 i = table->subtables[i].next;
00968 }
00969 #ifdef DD_DEBUG
00970
00971 assert((unsigned) i >= table->subtables[i].next);
00972 assert((unsigned) x == table->subtables[i].next);
00973 #endif
00974 finalGroupSize = i - x + 1;
00975
00976 if (initGroupSize == finalGroupSize) {
00977
00978 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00979 } else {
00980 initialSize = table->keys - table->isolated;
00981 moveUp = ddSymmSiftingUp(table,x,xLow);
00982 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00983 }
00984 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
00985
00986 } else if (cuddNextHigh(table,x) > xHigh) {
00987
00988 while ((unsigned) x < table->subtables[x].next)
00989 x = table->subtables[x].next;
00990 i = x;
00991 x = table->subtables[x].next;
00992
00993 if (x == xLow) return(1);
00994
00995 initGroupSize = i - x + 1;
00996
00997 moveUp = ddSymmSiftingUp(table,x,xLow);
00998
00999 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01000 if (moveUp == NULL) return(1);
01001
01002 x = moveUp->x;
01003 i = table->subtables[x].next;
01004 #ifdef DD_DEBUG
01005
01006 assert((unsigned) x >= table->subtables[x].next);
01007 assert((unsigned) i == table->subtables[x].next);
01008 #endif
01009 finalGroupSize = x - i + 1;
01010
01011 if (initGroupSize == finalGroupSize) {
01012
01013 result = ddSymmSiftingBackward(table,moveUp,initialSize);
01014 } else {
01015 initialSize = table->keys - table->isolated;
01016 moveDown = ddSymmSiftingDown(table,x,xHigh);
01017 result = ddSymmSiftingBackward(table,moveDown,initialSize);
01018 }
01019 if (!result)
01020 goto ddSymmSiftingConvAuxOutOfMem;
01021
01022 } else if ((x - xLow) > (xHigh - x)) {
01023 moveDown = ddSymmSiftingDown(table,x,xHigh);
01024
01025 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01026
01027 if (moveDown != NULL) {
01028 x = moveDown->y;
01029 i = x;
01030 while ((unsigned) i < table->subtables[i].next) {
01031 i = table->subtables[i].next;
01032 }
01033 } else {
01034 while ((unsigned) x < table->subtables[x].next)
01035 x = table->subtables[x].next;
01036 i = x;
01037 x = table->subtables[x].next;
01038 }
01039 #ifdef DD_DEBUG
01040
01041 assert((unsigned) i >= table->subtables[i].next);
01042 assert((unsigned) x == table->subtables[i].next);
01043 #endif
01044 initGroupSize = i - x + 1;
01045
01046 moveUp = ddSymmSiftingUp(table,x,xLow);
01047 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01048
01049 if (moveUp != NULL) {
01050 x = moveUp->x;
01051 i = table->subtables[x].next;
01052 } else {
01053 i = x;
01054 while ((unsigned) x < table->subtables[x].next)
01055 x = table->subtables[x].next;
01056 }
01057 #ifdef DD_DEBUG
01058
01059 assert((unsigned) x >= table->subtables[x].next);
01060 assert((unsigned) i == table->subtables[x].next);
01061 #endif
01062 finalGroupSize = x - i + 1;
01063
01064 if (initGroupSize == finalGroupSize) {
01065
01066 result = ddSymmSiftingBackward(table,moveUp,initialSize);
01067 } else {
01068 while (moveDown != NULL) {
01069 move = moveDown->next;
01070 cuddDeallocMove(table, moveDown);
01071 moveDown = move;
01072 }
01073 initialSize = table->keys - table->isolated;
01074 moveDown = ddSymmSiftingDown(table,x,xHigh);
01075 result = ddSymmSiftingBackward(table,moveDown,initialSize);
01076 }
01077 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
01078
01079 } else {
01080
01081 x = table->subtables[x].next;
01082
01083 moveUp = ddSymmSiftingUp(table,x,xLow);
01084
01085 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01086
01087 if (moveUp != NULL) {
01088 x = moveUp->x;
01089 i = table->subtables[x].next;
01090 } else {
01091 i = x;
01092 while ((unsigned) x < table->subtables[x].next)
01093 x = table->subtables[x].next;
01094 }
01095 #ifdef DD_DEBUG
01096
01097 assert((unsigned) x >= table->subtables[x].next);
01098 assert((unsigned) i == table->subtables[x].next);
01099 #endif
01100 initGroupSize = x - i + 1;
01101
01102 moveDown = ddSymmSiftingDown(table,x,xHigh);
01103 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01104
01105 if (moveDown != NULL) {
01106 x = moveDown->y;
01107 i = x;
01108 while ((unsigned) i < table->subtables[i].next) {
01109 i = table->subtables[i].next;
01110 }
01111 } else {
01112 i = x;
01113 x = table->subtables[x].next;
01114 }
01115 #ifdef DD_DEBUG
01116
01117 assert((unsigned) i >= table->subtables[i].next);
01118 assert((unsigned) x == table->subtables[i].next);
01119 #endif
01120 finalGroupSize = i - x + 1;
01121
01122 if (initGroupSize == finalGroupSize) {
01123
01124 result = ddSymmSiftingBackward(table,moveDown,initialSize);
01125 } else {
01126 while (moveUp != NULL) {
01127 move = moveUp->next;
01128 cuddDeallocMove(table, moveUp);
01129 moveUp = move;
01130 }
01131 initialSize = table->keys - table->isolated;
01132 moveUp = ddSymmSiftingUp(table,x,xLow);
01133 result = ddSymmSiftingBackward(table,moveUp,initialSize);
01134 }
01135 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
01136 }
01137
01138 while (moveDown != NULL) {
01139 move = moveDown->next;
01140 cuddDeallocMove(table, moveDown);
01141 moveDown = move;
01142 }
01143 while (moveUp != NULL) {
01144 move = moveUp->next;
01145 cuddDeallocMove(table, moveUp);
01146 moveUp = move;
01147 }
01148
01149 return(1);
01150
01151 ddSymmSiftingConvAuxOutOfMem:
01152 if (moveDown != MV_OOM) {
01153 while (moveDown != NULL) {
01154 move = moveDown->next;
01155 cuddDeallocMove(table, moveDown);
01156 moveDown = move;
01157 }
01158 }
01159 if (moveUp != MV_OOM) {
01160 while (moveUp != NULL) {
01161 move = moveUp->next;
01162 cuddDeallocMove(table, moveUp);
01163 moveUp = move;
01164 }
01165 }
01166
01167 return(0);
01168
01169 }
01170
01171
01187 static Move *
01188 ddSymmSiftingUp(
01189 DdManager * table,
01190 int y,
01191 int xLow)
01192 {
01193 Move *moves;
01194 Move *move;
01195 int x;
01196 int size;
01197 int i;
01198 int gxtop,gybot;
01199 int limitSize;
01200 int xindex, yindex;
01201 int zindex;
01202 int z;
01203 int isolated;
01204 int L;
01205 #ifdef DD_DEBUG
01206 int checkL;
01207 #endif
01208
01209
01210 moves = NULL;
01211 yindex = table->invperm[y];
01212
01213
01214
01215
01216
01217
01218
01219 limitSize = L = table->keys - table->isolated;
01220 gybot = y;
01221 while ((unsigned) gybot < table->subtables[gybot].next)
01222 gybot = table->subtables[gybot].next;
01223 for (z = xLow + 1; z <= gybot; z++) {
01224 zindex = table->invperm[z];
01225 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01226 isolated = table->vars[zindex]->ref == 1;
01227 L -= table->subtables[z].keys - isolated;
01228 }
01229 }
01230
01231 x = cuddNextLow(table,y);
01232 while (x >= xLow && L <= limitSize) {
01233 #ifdef DD_DEBUG
01234 gybot = y;
01235 while ((unsigned) gybot < table->subtables[gybot].next)
01236 gybot = table->subtables[gybot].next;
01237 checkL = table->keys - table->isolated;
01238 for (z = xLow + 1; z <= gybot; z++) {
01239 zindex = table->invperm[z];
01240 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01241 isolated = table->vars[zindex]->ref == 1;
01242 checkL -= table->subtables[z].keys - isolated;
01243 }
01244 }
01245 assert(L == checkL);
01246 #endif
01247 gxtop = table->subtables[x].next;
01248 if (cuddSymmCheck(table,x,y)) {
01249
01250 table->subtables[x].next = y;
01251 i = table->subtables[y].next;
01252 while (table->subtables[i].next != (unsigned) y)
01253 i = table->subtables[i].next;
01254 table->subtables[i].next = gxtop;
01255 } else if (table->subtables[x].next == (unsigned) x &&
01256 table->subtables[y].next == (unsigned) y) {
01257
01258 xindex = table->invperm[x];
01259 size = cuddSwapInPlace(table,x,y);
01260 #ifdef DD_DEBUG
01261 assert(table->subtables[x].next == (unsigned) x);
01262 assert(table->subtables[y].next == (unsigned) y);
01263 #endif
01264 if (size == 0) goto ddSymmSiftingUpOutOfMem;
01265
01266 if (cuddTestInteract(table,xindex,yindex)) {
01267 isolated = table->vars[xindex]->ref == 1;
01268 L += table->subtables[y].keys - isolated;
01269 }
01270 move = (Move *) cuddDynamicAllocNode(table);
01271 if (move == NULL) goto ddSymmSiftingUpOutOfMem;
01272 move->x = x;
01273 move->y = y;
01274 move->size = size;
01275 move->next = moves;
01276 moves = move;
01277 if ((double) size > (double) limitSize * table->maxGrowth)
01278 return(moves);
01279 if (size < limitSize) limitSize = size;
01280 } else {
01281 size = ddSymmGroupMove(table,x,y,&moves);
01282 if (size == 0) goto ddSymmSiftingUpOutOfMem;
01283
01284 z = moves->y;
01285 do {
01286 zindex = table->invperm[z];
01287 if (cuddTestInteract(table,zindex,yindex)) {
01288 isolated = table->vars[zindex]->ref == 1;
01289 L += table->subtables[z].keys - isolated;
01290 }
01291 z = table->subtables[z].next;
01292 } while (z != (int) moves->y);
01293 if ((double) size > (double) limitSize * table->maxGrowth)
01294 return(moves);
01295 if (size < limitSize) limitSize = size;
01296 }
01297 y = gxtop;
01298 x = cuddNextLow(table,y);
01299 }
01300
01301 return(moves);
01302
01303 ddSymmSiftingUpOutOfMem:
01304 while (moves != NULL) {
01305 move = moves->next;
01306 cuddDeallocMove(table, moves);
01307 moves = move;
01308 }
01309 return(MV_OOM);
01310
01311 }
01312
01313
01329 static Move *
01330 ddSymmSiftingDown(
01331 DdManager * table,
01332 int x,
01333 int xHigh)
01334 {
01335 Move *moves;
01336 Move *move;
01337 int y;
01338 int size;
01339 int limitSize;
01340 int gxtop,gybot;
01341 int R;
01342 int xindex, yindex;
01343 int isolated;
01344 int z;
01345 int zindex;
01346 #ifdef DD_DEBUG
01347 int checkR;
01348 #endif
01349
01350 moves = NULL;
01351
01352 xindex = table->invperm[x];
01353 gxtop = table->subtables[x].next;
01354 limitSize = size = table->keys - table->isolated;
01355 R = 0;
01356 for (z = xHigh; z > gxtop; z--) {
01357 zindex = table->invperm[z];
01358 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01359 isolated = table->vars[zindex]->ref == 1;
01360 R += table->subtables[z].keys - isolated;
01361 }
01362 }
01363
01364 y = cuddNextHigh(table,x);
01365 while (y <= xHigh && size - R < limitSize) {
01366 #ifdef DD_DEBUG
01367 gxtop = table->subtables[x].next;
01368 checkR = 0;
01369 for (z = xHigh; z > gxtop; z--) {
01370 zindex = table->invperm[z];
01371 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01372 isolated = table->vars[zindex]->ref == 1;
01373 checkR += table->subtables[z].keys - isolated;
01374 }
01375 }
01376 assert(R == checkR);
01377 #endif
01378 gybot = table->subtables[y].next;
01379 while (table->subtables[gybot].next != (unsigned) y)
01380 gybot = table->subtables[gybot].next;
01381 if (cuddSymmCheck(table,x,y)) {
01382
01383 gxtop = table->subtables[x].next;
01384 table->subtables[x].next = y;
01385 table->subtables[gybot].next = gxtop;
01386 } else if (table->subtables[x].next == (unsigned) x &&
01387 table->subtables[y].next == (unsigned) y) {
01388
01389
01390 yindex = table->invperm[y];
01391 if (cuddTestInteract(table,xindex,yindex)) {
01392 isolated = table->vars[yindex]->ref == 1;
01393 R -= table->subtables[y].keys - isolated;
01394 }
01395 size = cuddSwapInPlace(table,x,y);
01396 #ifdef DD_DEBUG
01397 assert(table->subtables[x].next == (unsigned) x);
01398 assert(table->subtables[y].next == (unsigned) y);
01399 #endif
01400 if (size == 0) goto ddSymmSiftingDownOutOfMem;
01401 move = (Move *) cuddDynamicAllocNode(table);
01402 if (move == NULL) goto ddSymmSiftingDownOutOfMem;
01403 move->x = x;
01404 move->y = y;
01405 move->size = size;
01406 move->next = moves;
01407 moves = move;
01408 if ((double) size > (double) limitSize * table->maxGrowth)
01409 return(moves);
01410 if (size < limitSize) limitSize = size;
01411 } else {
01412
01413 gxtop = table->subtables[x].next;
01414 z = gxtop + 1;
01415 do {
01416 zindex = table->invperm[z];
01417 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01418 isolated = table->vars[zindex]->ref == 1;
01419 R -= table->subtables[z].keys - isolated;
01420 }
01421 z++;
01422 } while (z <= gybot);
01423 size = ddSymmGroupMove(table,x,y,&moves);
01424 if (size == 0) goto ddSymmSiftingDownOutOfMem;
01425 if ((double) size > (double) limitSize * table->maxGrowth)
01426 return(moves);
01427 if (size < limitSize) limitSize = size;
01428
01429 gxtop = table->subtables[gybot].next;
01430 for (z = gxtop + 1; z <= gybot; z++) {
01431 zindex = table->invperm[z];
01432 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01433 isolated = table->vars[zindex]->ref == 1;
01434 R += table->subtables[z].keys - isolated;
01435 }
01436 }
01437 }
01438 x = gybot;
01439 y = cuddNextHigh(table,x);
01440 }
01441
01442 return(moves);
01443
01444 ddSymmSiftingDownOutOfMem:
01445 while (moves != NULL) {
01446 move = moves->next;
01447 cuddDeallocMove(table, moves);
01448 moves = move;
01449 }
01450 return(MV_OOM);
01451
01452 }
01453
01454
01467 static int
01468 ddSymmGroupMove(
01469 DdManager * table,
01470 int x,
01471 int y,
01472 Move ** moves)
01473 {
01474 Move *move;
01475 int size;
01476 int i,j;
01477 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01478 int swapx,swapy;
01479
01480 #ifdef DD_DEBUG
01481 assert(x < y);
01482 #endif
01483
01484 xbot = x;
01485 xtop = table->subtables[x].next;
01486 xsize = xbot - xtop + 1;
01487 ybot = y;
01488 while ((unsigned) ybot < table->subtables[ybot].next)
01489 ybot = table->subtables[ybot].next;
01490 ytop = y;
01491 ysize = ybot - ytop + 1;
01492
01493
01494 for (i = 1; i <= ysize; i++) {
01495 for (j = 1; j <= xsize; j++) {
01496 size = cuddSwapInPlace(table,x,y);
01497 if (size == 0) return(0);
01498 swapx = x; swapy = y;
01499 y = x;
01500 x = y - 1;
01501 }
01502 y = ytop + i;
01503 x = y - 1;
01504 }
01505
01506
01507 y = xtop;
01508 for (i = 0; i < ysize-1 ; i++) {
01509 table->subtables[y].next = y + 1;
01510 y = y + 1;
01511 }
01512 table->subtables[y].next = xtop;
01513
01514 x = y + 1;
01515 newxtop = x;
01516 for (i = 0; i < xsize - 1 ; i++) {
01517 table->subtables[x].next = x + 1;
01518 x = x + 1;
01519 }
01520 table->subtables[x].next = newxtop;
01521
01522
01523 move = (Move *) cuddDynamicAllocNode(table);
01524 if (move == NULL) return(0);
01525 move->x = swapx;
01526 move->y = swapy;
01527 move->size = size;
01528 move->next = *moves;
01529 *moves = move;
01530
01531 return(size);
01532
01533 }
01534
01535
01548 static int
01549 ddSymmGroupMoveBackward(
01550 DdManager * table,
01551 int x,
01552 int y)
01553 {
01554 int size;
01555 int i,j;
01556 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01557
01558 #ifdef DD_DEBUG
01559 assert(x < y);
01560 #endif
01561
01562
01563 xbot = x;
01564 xtop = table->subtables[x].next;
01565 xsize = xbot - xtop + 1;
01566 ybot = y;
01567 while ((unsigned) ybot < table->subtables[ybot].next)
01568 ybot = table->subtables[ybot].next;
01569 ytop = y;
01570 ysize = ybot - ytop + 1;
01571
01572
01573 for (i = 1; i <= ysize; i++) {
01574 for (j = 1; j <= xsize; j++) {
01575 size = cuddSwapInPlace(table,x,y);
01576 if (size == 0) return(0);
01577 y = x;
01578 x = cuddNextLow(table,y);
01579 }
01580 y = ytop + i;
01581 x = y - 1;
01582 }
01583
01584
01585 y = xtop;
01586 for (i = 0; i < ysize-1 ; i++) {
01587 table->subtables[y].next = y + 1;
01588 y = y + 1;
01589 }
01590 table->subtables[y].next = xtop;
01591
01592 x = y + 1;
01593 newxtop = x;
01594 for (i = 0; i < xsize-1 ; i++) {
01595 table->subtables[x].next = x + 1;
01596 x = x + 1;
01597 }
01598 table->subtables[x].next = newxtop;
01599
01600
01601 return(size);
01602
01603 }
01604
01605
01619 static int
01620 ddSymmSiftingBackward(
01621 DdManager * table,
01622 Move * moves,
01623 int size)
01624 {
01625 Move *move;
01626 int res;
01627
01628 for (move = moves; move != NULL; move = move->next) {
01629 if (move->size < size) {
01630 size = move->size;
01631 }
01632 }
01633
01634 for (move = moves; move != NULL; move = move->next) {
01635 if (move->size == size) return(1);
01636 if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
01637 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01638 #ifdef DD_DEBUG
01639 assert(table->subtables[move->x].next == move->x);
01640 assert(table->subtables[move->y].next == move->y);
01641 #endif
01642 } else {
01643 res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
01644 }
01645 if (!res) return(0);
01646 }
01647
01648 return(1);
01649
01650 }
01651
01652
01663 static void
01664 ddSymmSummary(
01665 DdManager * table,
01666 int lower,
01667 int upper,
01668 int * symvars,
01669 int * symgroups)
01670 {
01671 int i,x,gbot;
01672 int TotalSymm = 0;
01673 int TotalSymmGroups = 0;
01674
01675 for (i = lower; i <= upper; i++) {
01676 if (table->subtables[i].next != (unsigned) i) {
01677 TotalSymmGroups++;
01678 x = i;
01679 do {
01680 TotalSymm++;
01681 gbot = x;
01682 x = table->subtables[x].next;
01683 } while (x != i);
01684 #ifdef DD_DEBUG
01685 assert(table->subtables[gbot].next == (unsigned) i);
01686 #endif
01687 i = gbot;
01688 }
01689 }
01690 *symvars = TotalSymm;
01691 *symgroups = TotalSymmGroups;
01692
01693 return;
01694
01695 }