00001
00041 #include "util_hack.h"
00042 #include "cuddInt.h"
00043
00044
00045
00046
00047
00048 #define MV_OOM (Move *)1
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #ifndef lint
00063 static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $";
00064 #endif
00065
00066 static int *entry;
00067
00068 extern int ddTotalNumberSwapping;
00069 #ifdef DD_STATS
00070 extern int ddTotalNISwaps;
00071 #endif
00072
00073
00074
00075
00076
00079
00080
00081
00082
00083 static int ddSymmUniqueCompare ARGS((int *ptrX, int *ptrY));
00084 static int ddSymmSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh));
00085 static int ddSymmSiftingConvAux ARGS((DdManager *table, int x, int xLow, int xHigh));
00086 static Move * ddSymmSiftingUp ARGS((DdManager *table, int y, int xLow));
00087 static Move * ddSymmSiftingDown ARGS((DdManager *table, int x, int xHigh));
00088 static int ddSymmGroupMove ARGS((DdManager *table, int x, int y, Move **moves));
00089 static int ddSymmGroupMoveBackward ARGS((DdManager *table, int x, int y));
00090 static int ddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size));
00091 static void ddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups));
00092
00096
00097
00098
00099
00100
00110 void
00111 Cudd_SymmProfile(
00112 DdManager * table,
00113 int lower,
00114 int upper)
00115 {
00116 int i,x,gbot;
00117 int TotalSymm = 0;
00118 int TotalSymmGroups = 0;
00119
00120 for (i = lower; i <= upper; i++) {
00121 if (table->subtables[i].next != (unsigned) i) {
00122 x = i;
00123 (void) fprintf(table->out,"Group:");
00124 do {
00125 (void) fprintf(table->out," %d",table->invperm[x]);
00126 TotalSymm++;
00127 gbot = x;
00128 x = table->subtables[x].next;
00129 } while (x != i);
00130 TotalSymmGroups++;
00131 #ifdef DD_DEBUG
00132 assert(table->subtables[gbot].next == (unsigned) i);
00133 #endif
00134 i = gbot;
00135 (void) fprintf(table->out,"\n");
00136 }
00137 }
00138 (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
00139 (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
00140
00141 }
00142
00143
00144
00145
00146
00147
00148
00160 int
00161 cuddSymmCheck(
00162 DdManager * table,
00163 int x,
00164 int y)
00165 {
00166 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
00167 int comple;
00168 int xsymmy;
00169 int xsymmyp;
00170 int arccount;
00171 int TotalRefCount;
00172 int yindex;
00173 int i;
00174 DdNodePtr *list;
00175 int slots;
00176 DdNode *sentinel = &(table->sentinel);
00177 #ifdef DD_DEBUG
00178 int xindex;
00179 #endif
00180
00181
00182
00183
00184
00185
00186
00187 if (table->subtables[x].keys == 1) {
00188 return(0);
00189 }
00190 yindex = table->invperm[y];
00191 if (table->subtables[y].keys == 1) {
00192 if (table->vars[yindex]->ref == 1)
00193 return(0);
00194 }
00195
00196 xsymmy = xsymmyp = 1;
00197 arccount = 0;
00198 slots = table->subtables[x].slots;
00199 list = table->subtables[x].nodelist;
00200 for (i = 0; i < slots; i++) {
00201 f = list[i];
00202 while (f != sentinel) {
00203
00204 f1 = cuddT(f);
00205 f0 = Cudd_Regular(cuddE(f));
00206 comple = Cudd_IsComplement(cuddE(f));
00207 if ((int) f1->index == yindex) {
00208 arccount++;
00209 f11 = cuddT(f1); f10 = cuddE(f1);
00210 } else {
00211 if ((int) f0->index != yindex) {
00212
00213
00214
00215 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
00216 return(0);
00217 }
00218 f11 = f10 = f1;
00219 }
00220 if ((int) f0->index == yindex) {
00221 arccount++;
00222 f01 = cuddT(f0); f00 = cuddE(f0);
00223 } else {
00224 f01 = f00 = f0;
00225 }
00226 if (comple) {
00227 f01 = Cudd_Not(f01);
00228 f00 = Cudd_Not(f00);
00229 }
00230
00231 if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
00232 xsymmy &= f01 == f10;
00233 xsymmyp &= f11 == f00;
00234 if ((xsymmy == 0) && (xsymmyp == 0))
00235 return(0);
00236 }
00237
00238 f = f->next;
00239 }
00240 }
00241
00242
00243 TotalRefCount = -1;
00244 slots = table->subtables[y].slots;
00245 list = table->subtables[y].nodelist;
00246 for (i = 0; i < slots; i++) {
00247 f = list[i];
00248 while (f != sentinel) {
00249 TotalRefCount += f->ref;
00250 f = f->next;
00251 }
00252 }
00253
00254 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00255 if (arccount == TotalRefCount) {
00256 xindex = table->invperm[x];
00257 (void) fprintf(table->out,
00258 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00259 xindex,yindex,x,y);
00260 }
00261 #endif
00262
00263 return(arccount == TotalRefCount);
00264
00265 }
00266
00267
00290 int
00291 cuddSymmSifting(
00292 DdManager * table,
00293 int lower,
00294 int upper)
00295 {
00296 int i;
00297 int *var;
00298 int size;
00299 int x;
00300 int result;
00301 int symvars;
00302 int symgroups;
00303 #ifdef DD_STATS
00304 int previousSize;
00305 #endif
00306
00307 size = table->size;
00308
00309
00310 var = NULL;
00311 entry = ALLOC(int,size);
00312 if (entry == NULL) {
00313 table->errorCode = CUDD_MEMORY_OUT;
00314 goto ddSymmSiftingOutOfMem;
00315 }
00316 var = ALLOC(int,size);
00317 if (var == NULL) {
00318 table->errorCode = CUDD_MEMORY_OUT;
00319 goto ddSymmSiftingOutOfMem;
00320 }
00321
00322 for (i = 0; i < size; i++) {
00323 x = table->perm[i];
00324 entry[i] = table->subtables[x].keys;
00325 var[i] = i;
00326 }
00327
00328 qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare);
00329
00330
00331 for (i = lower; i <= upper; i++) {
00332 table->subtables[i].next = i;
00333 }
00334
00335 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00336 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00337 break;
00338 x = table->perm[var[i]];
00339 #ifdef DD_STATS
00340 previousSize = table->keys - table->isolated;
00341 #endif
00342 if (x < lower || x > upper) continue;
00343 if (table->subtables[x].next == (unsigned) x) {
00344 result = ddSymmSiftingAux(table,x,lower,upper);
00345 if (!result) goto ddSymmSiftingOutOfMem;
00346 #ifdef DD_STATS
00347 if (table->keys < (unsigned) previousSize + table->isolated) {
00348 (void) fprintf(table->out,"-");
00349 } else if (table->keys > (unsigned) previousSize +
00350 table->isolated) {
00351 (void) fprintf(table->out,"+");
00352 } else {
00353 (void) fprintf(table->out,"=");
00354 }
00355 fflush(table->out);
00356 #endif
00357 }
00358 }
00359
00360 FREE(var);
00361 FREE(entry);
00362
00363 ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00364
00365 #ifdef DD_STATS
00366 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00367 symvars);
00368 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00369 symgroups);
00370 #endif
00371
00372 return(1+symvars);
00373
00374 ddSymmSiftingOutOfMem:
00375
00376 if (entry != NULL) FREE(entry);
00377 if (var != NULL) FREE(var);
00378
00379 return(0);
00380
00381 }
00382
00383
00407 int
00408 cuddSymmSiftingConv(
00409 DdManager * table,
00410 int lower,
00411 int upper)
00412 {
00413 int i;
00414 int *var;
00415 int size;
00416 int x;
00417 int result;
00418 int symvars;
00419 int symgroups;
00420 int classes;
00421 int initialSize;
00422 #ifdef DD_STATS
00423 int previousSize;
00424 #endif
00425
00426 initialSize = table->keys - table->isolated;
00427
00428 size = table->size;
00429
00430
00431 var = NULL;
00432 entry = ALLOC(int,size);
00433 if (entry == NULL) {
00434 table->errorCode = CUDD_MEMORY_OUT;
00435 goto ddSymmSiftingConvOutOfMem;
00436 }
00437 var = ALLOC(int,size);
00438 if (var == NULL) {
00439 table->errorCode = CUDD_MEMORY_OUT;
00440 goto ddSymmSiftingConvOutOfMem;
00441 }
00442
00443 for (i = 0; i < size; i++) {
00444 x = table->perm[i];
00445 entry[i] = table->subtables[x].keys;
00446 var[i] = i;
00447 }
00448
00449 qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare);
00450
00451
00452
00453
00454 for (i = lower; i <= upper; i++) {
00455 table->subtables[i].next = i;
00456 }
00457
00458 for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
00459 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00460 break;
00461 x = table->perm[var[i]];
00462 if (x < lower || x > upper) continue;
00463
00464 if (table->subtables[x].next == (unsigned) x) {
00465 #ifdef DD_STATS
00466 previousSize = table->keys - table->isolated;
00467 #endif
00468 result = ddSymmSiftingAux(table,x,lower,upper);
00469 if (!result) goto ddSymmSiftingConvOutOfMem;
00470 #ifdef DD_STATS
00471 if (table->keys < (unsigned) previousSize + table->isolated) {
00472 (void) fprintf(table->out,"-");
00473 } else if (table->keys > (unsigned) previousSize +
00474 table->isolated) {
00475 (void) fprintf(table->out,"+");
00476 } else {
00477 (void) fprintf(table->out,"=");
00478 }
00479 fflush(table->out);
00480 #endif
00481 }
00482 }
00483
00484
00485 while ((unsigned) initialSize > table->keys - table->isolated) {
00486 initialSize = table->keys - table->isolated;
00487 #ifdef DD_STATS
00488 (void) fprintf(table->out,"\n");
00489 #endif
00490
00491 for (x = lower, classes = 0; x <= upper; x++, classes++) {
00492 while ((unsigned) x < table->subtables[x].next) {
00493 x = table->subtables[x].next;
00494 }
00495
00496
00497
00498
00499 i = table->invperm[x];
00500 entry[i] = table->subtables[x].keys;
00501 var[classes] = i;
00502 }
00503
00504 qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))ddSymmUniqueCompare);
00505
00506
00507 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00508 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00509 break;
00510 x = table->perm[var[i]];
00511 if ((unsigned) x >= table->subtables[x].next) {
00512 #ifdef DD_STATS
00513 previousSize = table->keys - table->isolated;
00514 #endif
00515 result = ddSymmSiftingConvAux(table,x,lower,upper);
00516 if (!result ) goto ddSymmSiftingConvOutOfMem;
00517 #ifdef DD_STATS
00518 if (table->keys < (unsigned) previousSize + table->isolated) {
00519 (void) fprintf(table->out,"-");
00520 } else if (table->keys > (unsigned) previousSize +
00521 table->isolated) {
00522 (void) fprintf(table->out,"+");
00523 } else {
00524 (void) fprintf(table->out,"=");
00525 }
00526 fflush(table->out);
00527 #endif
00528 }
00529 }
00530 }
00531
00532 ddSymmSummary(table, lower, upper, &symvars, &symgroups);
00533
00534 #ifdef DD_STATS
00535 (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
00536 symvars);
00537 (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
00538 symgroups);
00539 #endif
00540
00541 FREE(var);
00542 FREE(entry);
00543
00544 return(1+symvars);
00545
00546 ddSymmSiftingConvOutOfMem:
00547
00548 if (entry != NULL) FREE(entry);
00549 if (var != NULL) FREE(var);
00550
00551 return(0);
00552
00553 }
00554
00555
00556
00557
00558
00559
00560
00573 static int
00574 ddSymmUniqueCompare(
00575 int * ptrX,
00576 int * ptrY)
00577 {
00578 #if 0
00579 if (entry[*ptrY] == entry[*ptrX]) {
00580 return((*ptrX) - (*ptrY));
00581 }
00582 #endif
00583 return(entry[*ptrY] - entry[*ptrX]);
00584
00585 }
00586
00587
00601 static int
00602 ddSymmSiftingAux(
00603 DdManager * table,
00604 int x,
00605 int xLow,
00606 int xHigh)
00607 {
00608 Move *move;
00609 Move *moveUp;
00610 Move *moveDown;
00611 int initialSize;
00612 int result;
00613 int i;
00614 int topbot;
00615 int initGroupSize, finalGroupSize;
00616
00617
00618 #ifdef DD_DEBUG
00619
00620 assert(table->subtables[x].next == (unsigned) x);
00621 #endif
00622
00623 initialSize = table->keys - table->isolated;
00624
00625 moveDown = NULL;
00626 moveUp = NULL;
00627
00628 if ((x - xLow) > (xHigh - x)) {
00629
00630
00631
00632 for (i = x; i > xLow; i--) {
00633 if (!cuddSymmCheck(table,i-1,i))
00634 break;
00635 topbot = table->subtables[i-1].next;
00636 table->subtables[i-1].next = i;
00637 table->subtables[x].next = topbot;
00638
00639 i = topbot + 1;
00640 }
00641 } else {
00642
00643
00644
00645 for (i = x; i < xHigh; i++) {
00646 if (!cuddSymmCheck(table,i,i+1))
00647 break;
00648
00649 topbot = i + 1;
00650 while ((unsigned) topbot < table->subtables[topbot].next) {
00651 topbot = table->subtables[topbot].next;
00652 }
00653 table->subtables[topbot].next = table->subtables[i].next;
00654 table->subtables[i].next = i + 1;
00655 i = topbot - 1;
00656 }
00657 }
00658
00659
00660
00661
00662 while ((unsigned) x < table->subtables[x].next)
00663 x = table->subtables[x].next;
00664
00665 if (x == xLow) {
00666
00667 #ifdef DD_DEBUG
00668
00669 assert((unsigned) x == table->subtables[x].next);
00670 #endif
00671 if (x == xHigh) return(1);
00672
00673 initGroupSize = 1;
00674
00675 moveDown = ddSymmSiftingDown(table,x,xHigh);
00676
00677 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00678 if (moveDown == NULL) return(1);
00679
00680 x = moveDown->y;
00681
00682 i = x;
00683 while ((unsigned) i < table->subtables[i].next) {
00684 i = table->subtables[i].next;
00685 }
00686 #ifdef DD_DEBUG
00687
00688 assert((unsigned) i >= table->subtables[i].next);
00689 assert((unsigned) x == table->subtables[i].next);
00690 #endif
00691 finalGroupSize = i - x + 1;
00692
00693 if (initGroupSize == finalGroupSize) {
00694
00695 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00696 } else {
00697 initialSize = table->keys - table->isolated;
00698 moveUp = ddSymmSiftingUp(table,x,xLow);
00699 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00700 }
00701 if (!result) goto ddSymmSiftingAuxOutOfMem;
00702
00703 } else if (cuddNextHigh(table,x) > xHigh) {
00704
00705 i = x;
00706 x = table->subtables[x].next;
00707
00708 if (x == xLow) return(1);
00709
00710 initGroupSize = i - x + 1;
00711
00712 moveUp = ddSymmSiftingUp(table,x,xLow);
00713
00714 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00715 if (moveUp == NULL) return(1);
00716
00717 x = moveUp->x;
00718
00719 i = table->subtables[x].next;
00720 #ifdef DD_DEBUG
00721
00722 assert((unsigned) x >= table->subtables[x].next);
00723 assert((unsigned) i == table->subtables[x].next);
00724 #endif
00725 finalGroupSize = x - i + 1;
00726
00727 if (initGroupSize == finalGroupSize) {
00728
00729 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00730 } else {
00731 initialSize = table->keys - table->isolated;
00732 moveDown = ddSymmSiftingDown(table,x,xHigh);
00733 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00734 }
00735 if (!result) goto ddSymmSiftingAuxOutOfMem;
00736
00737 } else if ((x - xLow) > (xHigh - x)) {
00738
00739 moveDown = ddSymmSiftingDown(table,x,xHigh);
00740
00741 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00742
00743 if (moveDown != NULL) {
00744 x = moveDown->y;
00745 i = x;
00746 while ((unsigned) i < table->subtables[i].next) {
00747 i = table->subtables[i].next;
00748 }
00749 } else {
00750 i = x;
00751 while ((unsigned) i < table->subtables[i].next) {
00752 i = table->subtables[i].next;
00753 }
00754 x = table->subtables[i].next;
00755 }
00756 #ifdef DD_DEBUG
00757
00758 assert((unsigned) i >= table->subtables[i].next);
00759 assert((unsigned) x == table->subtables[i].next);
00760 #endif
00761 initGroupSize = i - x + 1;
00762
00763 moveUp = ddSymmSiftingUp(table,x,xLow);
00764 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00765
00766 if (moveUp != NULL) {
00767 x = moveUp->x;
00768 i = table->subtables[x].next;
00769 } else {
00770 i = x;
00771 while ((unsigned) x < table->subtables[x].next)
00772 x = table->subtables[x].next;
00773 }
00774 #ifdef DD_DEBUG
00775
00776 assert((unsigned) x >= table->subtables[x].next);
00777 assert((unsigned) i == table->subtables[x].next);
00778 #endif
00779 finalGroupSize = x - i + 1;
00780
00781 if (initGroupSize == finalGroupSize) {
00782
00783 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00784 } else {
00785 while (moveDown != NULL) {
00786 move = moveDown->next;
00787 cuddDeallocNode(table, (DdNode *) moveDown);
00788 moveDown = move;
00789 }
00790 initialSize = table->keys - table->isolated;
00791 moveDown = ddSymmSiftingDown(table,x,xHigh);
00792 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00793 }
00794 if (!result) goto ddSymmSiftingAuxOutOfMem;
00795
00796 } else {
00797
00798 x = table->subtables[x].next;
00799
00800 moveUp = ddSymmSiftingUp(table,x,xLow);
00801
00802 if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00803
00804 if (moveUp != NULL) {
00805 x = moveUp->x;
00806 i = table->subtables[x].next;
00807 } else {
00808 while ((unsigned) x < table->subtables[x].next)
00809 x = table->subtables[x].next;
00810 i = table->subtables[x].next;
00811 }
00812 #ifdef DD_DEBUG
00813
00814 assert((unsigned) x >= table->subtables[x].next);
00815 assert((unsigned) i == table->subtables[x].next);
00816 #endif
00817 initGroupSize = x - i + 1;
00818
00819 moveDown = ddSymmSiftingDown(table,x,xHigh);
00820 if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
00821
00822 if (moveDown != NULL) {
00823 x = moveDown->y;
00824 i = x;
00825 while ((unsigned) i < table->subtables[i].next) {
00826 i = table->subtables[i].next;
00827 }
00828 } else {
00829 i = x;
00830 x = table->subtables[x].next;
00831 }
00832 #ifdef DD_DEBUG
00833
00834 assert((unsigned) i >= table->subtables[i].next);
00835 assert((unsigned) x == table->subtables[i].next);
00836 #endif
00837 finalGroupSize = i - x + 1;
00838
00839 if (initGroupSize == finalGroupSize) {
00840
00841 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00842 } else {
00843 while (moveUp != NULL) {
00844 move = moveUp->next;
00845 cuddDeallocNode(table, (DdNode *) moveUp);
00846 moveUp = move;
00847 }
00848 initialSize = table->keys - table->isolated;
00849 moveUp = ddSymmSiftingUp(table,x,xLow);
00850 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00851 }
00852 if (!result) goto ddSymmSiftingAuxOutOfMem;
00853 }
00854
00855 while (moveDown != NULL) {
00856 move = moveDown->next;
00857 cuddDeallocNode(table, (DdNode *) moveDown);
00858 moveDown = move;
00859 }
00860 while (moveUp != NULL) {
00861 move = moveUp->next;
00862 cuddDeallocNode(table, (DdNode *) moveUp);
00863 moveUp = move;
00864 }
00865
00866 return(1);
00867
00868 ddSymmSiftingAuxOutOfMem:
00869 if (moveDown != MV_OOM) {
00870 while (moveDown != NULL) {
00871 move = moveDown->next;
00872 cuddDeallocNode(table, (DdNode *) moveDown);
00873 moveDown = move;
00874 }
00875 }
00876 if (moveUp != MV_OOM) {
00877 while (moveUp != NULL) {
00878 move = moveUp->next;
00879 cuddDeallocNode(table, (DdNode *) moveUp);
00880 moveUp = move;
00881 }
00882 }
00883
00884 return(0);
00885
00886 }
00887
00888
00903 static int
00904 ddSymmSiftingConvAux(
00905 DdManager * table,
00906 int x,
00907 int xLow,
00908 int xHigh)
00909 {
00910 Move *move;
00911 Move *moveUp;
00912 Move *moveDown;
00913 int initialSize;
00914 int result;
00915 int i;
00916 int initGroupSize, finalGroupSize;
00917
00918
00919 initialSize = table->keys - table->isolated;
00920
00921 moveDown = NULL;
00922 moveUp = NULL;
00923
00924 if (x == xLow) {
00925 #ifdef DD_DEBUG
00926
00927 assert((unsigned) x >= table->subtables[x].next);
00928 #endif
00929 i = table->subtables[x].next;
00930 initGroupSize = x - i + 1;
00931
00932 moveDown = ddSymmSiftingDown(table,x,xHigh);
00933
00934 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
00935 if (moveDown == NULL) return(1);
00936
00937 x = moveDown->y;
00938 i = x;
00939 while ((unsigned) i < table->subtables[i].next) {
00940 i = table->subtables[i].next;
00941 }
00942 #ifdef DD_DEBUG
00943
00944 assert((unsigned) i >= table->subtables[i].next);
00945 assert((unsigned) x == table->subtables[i].next);
00946 #endif
00947 finalGroupSize = i - x + 1;
00948
00949 if (initGroupSize == finalGroupSize) {
00950
00951 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00952 } else {
00953 initialSize = table->keys - table->isolated;
00954 moveUp = ddSymmSiftingUp(table,x,xLow);
00955 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00956 }
00957 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
00958
00959 } else if (cuddNextHigh(table,x) > xHigh) {
00960
00961 while ((unsigned) x < table->subtables[x].next)
00962 x = table->subtables[x].next;
00963 i = x;
00964 x = table->subtables[x].next;
00965
00966 if (x == xLow) return(1);
00967
00968 initGroupSize = i - x + 1;
00969
00970 moveUp = ddSymmSiftingUp(table,x,xLow);
00971
00972 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
00973 if (moveUp == NULL) return(1);
00974
00975 x = moveUp->x;
00976 i = table->subtables[x].next;
00977 #ifdef DD_DEBUG
00978
00979 assert((unsigned) x >= table->subtables[x].next);
00980 assert((unsigned) i == table->subtables[x].next);
00981 #endif
00982 finalGroupSize = x - i + 1;
00983
00984 if (initGroupSize == finalGroupSize) {
00985
00986 result = ddSymmSiftingBackward(table,moveUp,initialSize);
00987 } else {
00988 initialSize = table->keys - table->isolated;
00989 moveDown = ddSymmSiftingDown(table,x,xHigh);
00990 result = ddSymmSiftingBackward(table,moveDown,initialSize);
00991 }
00992 if (!result)
00993 goto ddSymmSiftingConvAuxOutOfMem;
00994
00995 } else if ((x - xLow) > (xHigh - x)) {
00996 moveDown = ddSymmSiftingDown(table,x,xHigh);
00997
00998 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
00999
01000 if (moveDown != NULL) {
01001 x = moveDown->y;
01002 i = x;
01003 while ((unsigned) i < table->subtables[i].next) {
01004 i = table->subtables[i].next;
01005 }
01006 } else {
01007 while ((unsigned) x < table->subtables[x].next)
01008 x = table->subtables[x].next;
01009 i = x;
01010 x = table->subtables[x].next;
01011 }
01012 #ifdef DD_DEBUG
01013
01014 assert((unsigned) i >= table->subtables[i].next);
01015 assert((unsigned) x == table->subtables[i].next);
01016 #endif
01017 initGroupSize = i - x + 1;
01018
01019 moveUp = ddSymmSiftingUp(table,x,xLow);
01020 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01021
01022 if (moveUp != NULL) {
01023 x = moveUp->x;
01024 i = table->subtables[x].next;
01025 } else {
01026 i = x;
01027 while ((unsigned) x < table->subtables[x].next)
01028 x = table->subtables[x].next;
01029 }
01030 #ifdef DD_DEBUG
01031
01032 assert((unsigned) x >= table->subtables[x].next);
01033 assert((unsigned) i == table->subtables[x].next);
01034 #endif
01035 finalGroupSize = x - i + 1;
01036
01037 if (initGroupSize == finalGroupSize) {
01038
01039 result = ddSymmSiftingBackward(table,moveUp,initialSize);
01040 } else {
01041 while (moveDown != NULL) {
01042 move = moveDown->next;
01043 cuddDeallocNode(table, (DdNode *) moveDown);
01044 moveDown = move;
01045 }
01046 initialSize = table->keys - table->isolated;
01047 moveDown = ddSymmSiftingDown(table,x,xHigh);
01048 result = ddSymmSiftingBackward(table,moveDown,initialSize);
01049 }
01050 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
01051
01052 } else {
01053
01054 x = table->subtables[x].next;
01055
01056 moveUp = ddSymmSiftingUp(table,x,xLow);
01057
01058 if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01059
01060 if (moveUp != NULL) {
01061 x = moveUp->x;
01062 i = table->subtables[x].next;
01063 } else {
01064 i = x;
01065 while ((unsigned) x < table->subtables[x].next)
01066 x = table->subtables[x].next;
01067 }
01068 #ifdef DD_DEBUG
01069
01070 assert((unsigned) x >= table->subtables[x].next);
01071 assert((unsigned) i == table->subtables[x].next);
01072 #endif
01073 initGroupSize = x - i + 1;
01074
01075 moveDown = ddSymmSiftingDown(table,x,xHigh);
01076 if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
01077
01078 if (moveDown != NULL) {
01079 x = moveDown->y;
01080 i = x;
01081 while ((unsigned) i < table->subtables[i].next) {
01082 i = table->subtables[i].next;
01083 }
01084 } else {
01085 i = x;
01086 x = table->subtables[x].next;
01087 }
01088 #ifdef DD_DEBUG
01089
01090 assert((unsigned) i >= table->subtables[i].next);
01091 assert((unsigned) x == table->subtables[i].next);
01092 #endif
01093 finalGroupSize = i - x + 1;
01094
01095 if (initGroupSize == finalGroupSize) {
01096
01097 result = ddSymmSiftingBackward(table,moveDown,initialSize);
01098 } else {
01099 while (moveUp != NULL) {
01100 move = moveUp->next;
01101 cuddDeallocNode(table, (DdNode *) moveUp);
01102 moveUp = move;
01103 }
01104 initialSize = table->keys - table->isolated;
01105 moveUp = ddSymmSiftingUp(table,x,xLow);
01106 result = ddSymmSiftingBackward(table,moveUp,initialSize);
01107 }
01108 if (!result) goto ddSymmSiftingConvAuxOutOfMem;
01109 }
01110
01111 while (moveDown != NULL) {
01112 move = moveDown->next;
01113 cuddDeallocNode(table, (DdNode *) moveDown);
01114 moveDown = move;
01115 }
01116 while (moveUp != NULL) {
01117 move = moveUp->next;
01118 cuddDeallocNode(table, (DdNode *) moveUp);
01119 moveUp = move;
01120 }
01121
01122 return(1);
01123
01124 ddSymmSiftingConvAuxOutOfMem:
01125 if (moveDown != MV_OOM) {
01126 while (moveDown != NULL) {
01127 move = moveDown->next;
01128 cuddDeallocNode(table, (DdNode *) moveDown);
01129 moveDown = move;
01130 }
01131 }
01132 if (moveUp != MV_OOM) {
01133 while (moveUp != NULL) {
01134 move = moveUp->next;
01135 cuddDeallocNode(table, (DdNode *) moveUp);
01136 moveUp = move;
01137 }
01138 }
01139
01140 return(0);
01141
01142 }
01143
01144
01160 static Move *
01161 ddSymmSiftingUp(
01162 DdManager * table,
01163 int y,
01164 int xLow)
01165 {
01166 Move *moves;
01167 Move *move;
01168 int x;
01169 int size;
01170 int i;
01171 int gxtop,gybot;
01172 int limitSize;
01173 int xindex, yindex;
01174 int zindex;
01175 int z;
01176 int isolated;
01177 int L;
01178 #ifdef DD_DEBUG
01179 int checkL;
01180 #endif
01181
01182
01183 moves = NULL;
01184 yindex = table->invperm[y];
01185
01186
01187
01188
01189
01190
01191
01192 limitSize = L = table->keys - table->isolated;
01193 gybot = y;
01194 while ((unsigned) gybot < table->subtables[gybot].next)
01195 gybot = table->subtables[gybot].next;
01196 for (z = xLow + 1; z <= gybot; z++) {
01197 zindex = table->invperm[z];
01198 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01199 isolated = table->vars[zindex]->ref == 1;
01200 L -= table->subtables[z].keys - isolated;
01201 }
01202 }
01203
01204 x = cuddNextLow(table,y);
01205 while (x >= xLow && L <= limitSize) {
01206 #ifdef DD_DEBUG
01207 gybot = y;
01208 while ((unsigned) gybot < table->subtables[gybot].next)
01209 gybot = table->subtables[gybot].next;
01210 checkL = table->keys - table->isolated;
01211 for (z = xLow + 1; z <= gybot; z++) {
01212 zindex = table->invperm[z];
01213 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01214 isolated = table->vars[zindex]->ref == 1;
01215 checkL -= table->subtables[z].keys - isolated;
01216 }
01217 }
01218 assert(L == checkL);
01219 #endif
01220 gxtop = table->subtables[x].next;
01221 if (cuddSymmCheck(table,x,y)) {
01222
01223 table->subtables[x].next = y;
01224 i = table->subtables[y].next;
01225 while (table->subtables[i].next != (unsigned) y)
01226 i = table->subtables[i].next;
01227 table->subtables[i].next = gxtop;
01228 } else if (table->subtables[x].next == (unsigned) x &&
01229 table->subtables[y].next == (unsigned) y) {
01230
01231 xindex = table->invperm[x];
01232 size = cuddSwapInPlace(table,x,y);
01233 #ifdef DD_DEBUG
01234 assert(table->subtables[x].next == (unsigned) x);
01235 assert(table->subtables[y].next == (unsigned) y);
01236 #endif
01237 if (size == 0) goto ddSymmSiftingUpOutOfMem;
01238
01239 if (cuddTestInteract(table,xindex,yindex)) {
01240 isolated = table->vars[xindex]->ref == 1;
01241 L += table->subtables[y].keys - isolated;
01242 }
01243 move = (Move *) cuddDynamicAllocNode(table);
01244 if (move == NULL) goto ddSymmSiftingUpOutOfMem;
01245 move->x = x;
01246 move->y = y;
01247 move->size = size;
01248 move->next = moves;
01249 moves = move;
01250 if ((double) size > (double) limitSize * table->maxGrowth)
01251 return(moves);
01252 if (size < limitSize) limitSize = size;
01253 } else {
01254 size = ddSymmGroupMove(table,x,y,&moves);
01255 if (size == 0) goto ddSymmSiftingUpOutOfMem;
01256
01257 z = moves->y;
01258 do {
01259 zindex = table->invperm[z];
01260 if (cuddTestInteract(table,zindex,yindex)) {
01261 isolated = table->vars[zindex]->ref == 1;
01262 L += table->subtables[z].keys - isolated;
01263 }
01264 z = table->subtables[z].next;
01265 } while (z != (int) moves->y);
01266 if ((double) size > (double) limitSize * table->maxGrowth)
01267 return(moves);
01268 if (size < limitSize) limitSize = size;
01269 }
01270 y = gxtop;
01271 x = cuddNextLow(table,y);
01272 }
01273
01274 return(moves);
01275
01276 ddSymmSiftingUpOutOfMem:
01277 while (moves != NULL) {
01278 move = moves->next;
01279 cuddDeallocNode(table, (DdNode *) moves);
01280 moves = move;
01281 }
01282 return(MV_OOM);
01283
01284 }
01285
01286
01302 static Move *
01303 ddSymmSiftingDown(
01304 DdManager * table,
01305 int x,
01306 int xHigh)
01307 {
01308 Move *moves;
01309 Move *move;
01310 int y;
01311 int size;
01312 int limitSize;
01313 int gxtop,gybot;
01314 int R;
01315 int xindex, yindex;
01316 int isolated;
01317 int z;
01318 int zindex;
01319 #ifdef DD_DEBUG
01320 int checkR;
01321 #endif
01322
01323 moves = NULL;
01324
01325 xindex = table->invperm[x];
01326 gxtop = table->subtables[x].next;
01327 limitSize = size = table->keys - table->isolated;
01328 R = 0;
01329 for (z = xHigh; z > gxtop; z--) {
01330 zindex = table->invperm[z];
01331 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01332 isolated = table->vars[zindex]->ref == 1;
01333 R += table->subtables[z].keys - isolated;
01334 }
01335 }
01336
01337 y = cuddNextHigh(table,x);
01338 while (y <= xHigh && size - R < limitSize) {
01339 #ifdef DD_DEBUG
01340 gxtop = table->subtables[x].next;
01341 checkR = 0;
01342 for (z = xHigh; z > gxtop; z--) {
01343 zindex = table->invperm[z];
01344 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01345 isolated = table->vars[zindex]->ref == 1;
01346 checkR += table->subtables[z].keys - isolated;
01347 }
01348 }
01349 assert(R == checkR);
01350 #endif
01351 gybot = table->subtables[y].next;
01352 while (table->subtables[gybot].next != (unsigned) y)
01353 gybot = table->subtables[gybot].next;
01354 if (cuddSymmCheck(table,x,y)) {
01355
01356 gxtop = table->subtables[x].next;
01357 table->subtables[x].next = y;
01358 table->subtables[gybot].next = gxtop;
01359 } else if (table->subtables[x].next == (unsigned) x &&
01360 table->subtables[y].next == (unsigned) y) {
01361
01362
01363 yindex = table->invperm[y];
01364 if (cuddTestInteract(table,xindex,yindex)) {
01365 isolated = table->vars[yindex]->ref == 1;
01366 R -= table->subtables[y].keys - isolated;
01367 }
01368 size = cuddSwapInPlace(table,x,y);
01369 #ifdef DD_DEBUG
01370 assert(table->subtables[x].next == (unsigned) x);
01371 assert(table->subtables[y].next == (unsigned) y);
01372 #endif
01373 if (size == 0) goto ddSymmSiftingDownOutOfMem;
01374 move = (Move *) cuddDynamicAllocNode(table);
01375 if (move == NULL) goto ddSymmSiftingDownOutOfMem;
01376 move->x = x;
01377 move->y = y;
01378 move->size = size;
01379 move->next = moves;
01380 moves = move;
01381 if ((double) size > (double) limitSize * table->maxGrowth)
01382 return(moves);
01383 if (size < limitSize) limitSize = size;
01384 } else {
01385
01386 gxtop = table->subtables[x].next;
01387 z = gxtop + 1;
01388 do {
01389 zindex = table->invperm[z];
01390 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01391 isolated = table->vars[zindex]->ref == 1;
01392 R -= table->subtables[z].keys - isolated;
01393 }
01394 z++;
01395 } while (z <= gybot);
01396 size = ddSymmGroupMove(table,x,y,&moves);
01397 if (size == 0) goto ddSymmSiftingDownOutOfMem;
01398 if ((double) size > (double) limitSize * table->maxGrowth)
01399 return(moves);
01400 if (size < limitSize) limitSize = size;
01401
01402 gxtop = table->subtables[gybot].next;
01403 for (z = gxtop + 1; z <= gybot; z++) {
01404 zindex = table->invperm[z];
01405 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01406 isolated = table->vars[zindex]->ref == 1;
01407 R += table->subtables[z].keys - isolated;
01408 }
01409 }
01410 }
01411 x = gybot;
01412 y = cuddNextHigh(table,x);
01413 }
01414
01415 return(moves);
01416
01417 ddSymmSiftingDownOutOfMem:
01418 while (moves != NULL) {
01419 move = moves->next;
01420 cuddDeallocNode(table, (DdNode *) moves);
01421 moves = move;
01422 }
01423 return(MV_OOM);
01424
01425 }
01426
01427
01440 static int
01441 ddSymmGroupMove(
01442 DdManager * table,
01443 int x,
01444 int y,
01445 Move ** moves)
01446 {
01447 Move *move;
01448 int size;
01449 int i,j;
01450 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01451 int swapx,swapy;
01452
01453 #if DD_DEBUG
01454 assert(x < y);
01455 #endif
01456
01457 xbot = x;
01458 xtop = table->subtables[x].next;
01459 xsize = xbot - xtop + 1;
01460 ybot = y;
01461 while ((unsigned) ybot < table->subtables[ybot].next)
01462 ybot = table->subtables[ybot].next;
01463 ytop = y;
01464 ysize = ybot - ytop + 1;
01465
01466
01467 for (i = 1; i <= ysize; i++) {
01468 for (j = 1; j <= xsize; j++) {
01469 size = cuddSwapInPlace(table,x,y);
01470 if (size == 0) return(0);
01471 swapx = x; swapy = y;
01472 y = x;
01473 x = y - 1;
01474 }
01475 y = ytop + i;
01476 x = y - 1;
01477 }
01478
01479
01480 y = xtop;
01481 for (i = 0; i < ysize-1 ; i++) {
01482 table->subtables[y].next = y + 1;
01483 y = y + 1;
01484 }
01485 table->subtables[y].next = xtop;
01486
01487 x = y + 1;
01488 newxtop = x;
01489 for (i = 0; i < xsize - 1 ; i++) {
01490 table->subtables[x].next = x + 1;
01491 x = x + 1;
01492 }
01493 table->subtables[x].next = newxtop;
01494
01495
01496 move = (Move *) cuddDynamicAllocNode(table);
01497 if (move == NULL) return(0);
01498 move->x = swapx;
01499 move->y = swapy;
01500 move->size = size;
01501 move->next = *moves;
01502 *moves = move;
01503
01504 return(size);
01505
01506 }
01507
01508
01521 static int
01522 ddSymmGroupMoveBackward(
01523 DdManager * table,
01524 int x,
01525 int y)
01526 {
01527 int size;
01528 int i,j;
01529 int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01530
01531 #if DD_DEBUG
01532 assert(x < y);
01533 #endif
01534
01535
01536 xbot = x;
01537 xtop = table->subtables[x].next;
01538 xsize = xbot - xtop + 1;
01539 ybot = y;
01540 while ((unsigned) ybot < table->subtables[ybot].next)
01541 ybot = table->subtables[ybot].next;
01542 ytop = y;
01543 ysize = ybot - ytop + 1;
01544
01545
01546 for (i = 1; i <= ysize; i++) {
01547 for (j = 1; j <= xsize; j++) {
01548 size = cuddSwapInPlace(table,x,y);
01549 if (size == 0) return(0);
01550 y = x;
01551 x = cuddNextLow(table,y);
01552 }
01553 y = ytop + i;
01554 x = y - 1;
01555 }
01556
01557
01558 y = xtop;
01559 for (i = 0; i < ysize-1 ; i++) {
01560 table->subtables[y].next = y + 1;
01561 y = y + 1;
01562 }
01563 table->subtables[y].next = xtop;
01564
01565 x = y + 1;
01566 newxtop = x;
01567 for (i = 0; i < xsize-1 ; i++) {
01568 table->subtables[x].next = x + 1;
01569 x = x + 1;
01570 }
01571 table->subtables[x].next = newxtop;
01572
01573
01574 return(size);
01575
01576 }
01577
01578
01592 static int
01593 ddSymmSiftingBackward(
01594 DdManager * table,
01595 Move * moves,
01596 int size)
01597 {
01598 Move *move;
01599 int res;
01600
01601 for (move = moves; move != NULL; move = move->next) {
01602 if (move->size < size) {
01603 size = move->size;
01604 }
01605 }
01606
01607 for (move = moves; move != NULL; move = move->next) {
01608 if (move->size == size) return(1);
01609 if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
01610 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01611 #ifdef DD_DEBUG
01612 assert(table->subtables[move->x].next == move->x);
01613 assert(table->subtables[move->y].next == move->y);
01614 #endif
01615 } else {
01616 res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
01617 }
01618 if (!res) return(0);
01619 }
01620
01621 return(1);
01622
01623 }
01624
01625
01636 static void
01637 ddSymmSummary(
01638 DdManager * table,
01639 int lower,
01640 int upper,
01641 int * symvars,
01642 int * symgroups)
01643 {
01644 int i,x,gbot;
01645 int TotalSymm = 0;
01646 int TotalSymmGroups = 0;
01647
01648 for (i = lower; i <= upper; i++) {
01649 if (table->subtables[i].next != (unsigned) i) {
01650 TotalSymmGroups++;
01651 x = i;
01652 do {
01653 TotalSymm++;
01654 gbot = x;
01655 x = table->subtables[x].next;
01656 } while (x != i);
01657 #ifdef DD_DEBUG
01658 assert(table->subtables[gbot].next == (unsigned) i);
01659 #endif
01660 i = gbot;
01661 }
01662 }
01663 *symvars = TotalSymm;
01664 *symgroups = TotalSymmGroups;
01665
01666 return;
01667
01668 }