00001
00043 #include "util_hack.h"
00044 #include "cuddInt.h"
00045
00046
00047
00048
00049
00050 #define ZDD_MV_OOM (Move *)1
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #ifndef lint
00065 static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $";
00066 #endif
00067
00068 extern int *zdd_entry;
00069
00070 extern int zddTotalNumberSwapping;
00071
00072 static DdNode *empty;
00073
00074
00075
00076
00077
00078
00081
00082
00083
00084
00085 static int cuddZddSymmSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high));
00086 static int cuddZddSymmSiftingConvAux ARGS((DdManager *table, int x, int x_low, int x_high));
00087 static Move * cuddZddSymmSifting_up ARGS((DdManager *table, int x, int x_low, int initial_size));
00088 static Move * cuddZddSymmSifting_down ARGS((DdManager *table, int x, int x_high, int initial_size));
00089 static int cuddZddSymmSiftingBackward ARGS((DdManager *table, Move *moves, int size));
00090 static int zdd_group_move ARGS((DdManager *table, int x, int y, Move **moves));
00091 static int zdd_group_move_backward ARGS((DdManager *table, int x, int y));
00092 static void cuddZddSymmSummary ARGS((DdManager *table, int lower, int upper, int *symvars, int *symgroups));
00093
00097
00098
00099
00100
00101
00113 void
00114 Cudd_zddSymmProfile(
00115 DdManager * table,
00116 int lower,
00117 int upper)
00118 {
00119 int i, x, gbot;
00120 int TotalSymm = 0;
00121 int TotalSymmGroups = 0;
00122 int nvars;
00123
00124 nvars = table->sizeZ;
00125
00126 for (i = lower; i < upper; i++) {
00127 if (table->subtableZ[i].next != (unsigned) i) {
00128 x = i;
00129 (void) fprintf(table->out,"Group:");
00130 do {
00131 (void) fprintf(table->out," %d", table->invpermZ[x]);
00132 TotalSymm++;
00133 gbot = x;
00134 x = table->subtableZ[x].next;
00135 } while (x != i);
00136 TotalSymmGroups++;
00137 #ifdef DD_DEBUG
00138 assert(table->subtableZ[gbot].next == (unsigned) i);
00139 #endif
00140 i = gbot;
00141 (void) fprintf(table->out,"\n");
00142 }
00143 }
00144 (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
00145 (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
00146
00147 }
00148
00149
00150
00151
00152
00153
00154
00168 int
00169 cuddZddSymmCheck(
00170 DdManager * table,
00171 int x,
00172 int y)
00173 {
00174 int i;
00175 DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10;
00176 int yindex;
00177 int xsymmy = 1;
00178 int xsymmyp = 1;
00179 int arccount = 0;
00180 int TotalRefCount = 0;
00181 int symm_found;
00182
00183 empty = table->zero;
00184
00185 yindex = table->invpermZ[y];
00186 for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
00187 f = table->subtableZ[x].nodelist[i];
00188 while (f != NULL) {
00189
00190 f1 = cuddT(f);
00191 f0 = cuddE(f);
00192 if ((int) f1->index == yindex) {
00193 f11 = cuddT(f1);
00194 f10 = cuddE(f1);
00195 if (f10 != empty)
00196 arccount++;
00197 } else {
00198 if ((int) f0->index != yindex) {
00199 return(0);
00200 }
00201 f11 = empty;
00202 f10 = f1;
00203 }
00204 if ((int) f0->index == yindex) {
00205 f01 = cuddT(f0);
00206 f00 = cuddE(f0);
00207 if (f00 != empty)
00208 arccount++;
00209 } else {
00210 f01 = empty;
00211 f00 = f0;
00212 }
00213 if (f01 != f10)
00214 xsymmy = 0;
00215 if (f11 != f00)
00216 xsymmyp = 0;
00217 if ((xsymmy == 0) && (xsymmyp == 0))
00218 return(0);
00219
00220 f = f->next;
00221 }
00222 }
00223
00224
00225
00226
00227 for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
00228 f = table->subtableZ[y].nodelist[i];
00229 while (f != NIL(DdNode)) {
00230 if (cuddE(f) != empty)
00231 TotalRefCount += f->ref;
00232 f = f->next;
00233 }
00234 }
00235
00236 symm_found = (arccount == TotalRefCount);
00237 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00238 if (symm_found) {
00239 int xindex = table->invpermZ[x];
00240 (void) fprintf(table->out,
00241 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00242 xindex,yindex,x,y);
00243 }
00244 #endif
00245
00246 return(symm_found);
00247
00248 }
00249
00250
00273 int
00274 cuddZddSymmSifting(
00275 DdManager * table,
00276 int lower,
00277 int upper)
00278 {
00279 int i;
00280 int *var;
00281 int nvars;
00282 int x;
00283 int result;
00284 int symvars;
00285 int symgroups;
00286 int iteration;
00287 #ifdef DD_STATS
00288 int previousSize;
00289 #endif
00290
00291 nvars = table->sizeZ;
00292
00293
00294 var = NULL;
00295 zdd_entry = ALLOC(int, nvars);
00296 if (zdd_entry == NULL) {
00297 table->errorCode = CUDD_MEMORY_OUT;
00298 goto cuddZddSymmSiftingOutOfMem;
00299 }
00300 var = ALLOC(int, nvars);
00301 if (var == NULL) {
00302 table->errorCode = CUDD_MEMORY_OUT;
00303 goto cuddZddSymmSiftingOutOfMem;
00304 }
00305
00306 for (i = 0; i < nvars; i++) {
00307 x = table->permZ[i];
00308 zdd_entry[i] = table->subtableZ[x].keys;
00309 var[i] = i;
00310 }
00311
00312 qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare);
00313
00314
00315 for (i = lower; i <= upper; i++)
00316 table->subtableZ[i].next = i;
00317
00318 iteration = ddMin(table->siftMaxVar, nvars);
00319 for (i = 0; i < iteration; i++) {
00320 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00321 break;
00322 x = table->permZ[var[i]];
00323 #ifdef DD_STATS
00324 previousSize = table->keysZ;
00325 #endif
00326 if (x < lower || x > upper) continue;
00327 if (table->subtableZ[x].next == (unsigned) x) {
00328 result = cuddZddSymmSiftingAux(table, x, lower, upper);
00329 if (!result)
00330 goto cuddZddSymmSiftingOutOfMem;
00331 #ifdef DD_STATS
00332 if (table->keysZ < (unsigned) previousSize) {
00333 (void) fprintf(table->out,"-");
00334 } else if (table->keysZ > (unsigned) previousSize) {
00335 (void) fprintf(table->out,"+");
00336 #ifdef DD_VERBOSE
00337 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00338 #endif
00339 } else {
00340 (void) fprintf(table->out,"=");
00341 }
00342 fflush(table->out);
00343 #endif
00344 }
00345 }
00346
00347 FREE(var);
00348 FREE(zdd_entry);
00349
00350 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00351
00352 #ifdef DD_STATS
00353 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
00354 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
00355 #endif
00356
00357 return(1+symvars);
00358
00359 cuddZddSymmSiftingOutOfMem:
00360
00361 if (zdd_entry != NULL)
00362 FREE(zdd_entry);
00363 if (var != NULL)
00364 FREE(var);
00365
00366 return(0);
00367
00368 }
00369
00370
00394 int
00395 cuddZddSymmSiftingConv(
00396 DdManager * table,
00397 int lower,
00398 int upper)
00399 {
00400 int i;
00401 int *var;
00402 int nvars;
00403 int initialSize;
00404 int x;
00405 int result;
00406 int symvars;
00407 int symgroups;
00408 int classes;
00409 int iteration;
00410 #ifdef DD_STATS
00411 int previousSize;
00412 #endif
00413
00414 initialSize = table->keysZ;
00415
00416 nvars = table->sizeZ;
00417
00418
00419 var = NULL;
00420 zdd_entry = ALLOC(int, nvars);
00421 if (zdd_entry == NULL) {
00422 table->errorCode = CUDD_MEMORY_OUT;
00423 goto cuddZddSymmSiftingConvOutOfMem;
00424 }
00425 var = ALLOC(int, nvars);
00426 if (var == NULL) {
00427 table->errorCode = CUDD_MEMORY_OUT;
00428 goto cuddZddSymmSiftingConvOutOfMem;
00429 }
00430
00431 for (i = 0; i < nvars; i++) {
00432 x = table->permZ[i];
00433 zdd_entry[i] = table->subtableZ[x].keys;
00434 var[i] = i;
00435 }
00436
00437 qsort((void *)var, nvars, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare);
00438
00439
00440
00441
00442 for (i = lower; i <= upper; i++)
00443 table->subtableZ[i].next = i;
00444
00445 iteration = ddMin(table->siftMaxVar, table->sizeZ);
00446 for (i = 0; i < iteration; i++) {
00447 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00448 break;
00449 x = table->permZ[var[i]];
00450 if (x < lower || x > upper) continue;
00451
00452 if (table->subtableZ[x].next == (unsigned) x) {
00453 #ifdef DD_STATS
00454 previousSize = table->keysZ;
00455 #endif
00456 result = cuddZddSymmSiftingAux(table, x, lower, upper);
00457 if (!result)
00458 goto cuddZddSymmSiftingConvOutOfMem;
00459 #ifdef DD_STATS
00460 if (table->keysZ < (unsigned) previousSize) {
00461 (void) fprintf(table->out,"-");
00462 } else if (table->keysZ > (unsigned) previousSize) {
00463 (void) fprintf(table->out,"+");
00464 #ifdef DD_VERBOSE
00465 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00466 #endif
00467 } else {
00468 (void) fprintf(table->out,"=");
00469 }
00470 fflush(table->out);
00471 #endif
00472 }
00473 }
00474
00475
00476 while ((unsigned) initialSize > table->keysZ) {
00477 initialSize = table->keysZ;
00478 #ifdef DD_STATS
00479 (void) fprintf(table->out,"\n");
00480 #endif
00481
00482 for (x = lower, classes = 0; x <= upper; x++, classes++) {
00483 while ((unsigned) x < table->subtableZ[x].next)
00484 x = table->subtableZ[x].next;
00485
00486
00487
00488
00489 i = table->invpermZ[x];
00490 zdd_entry[i] = table->subtableZ[x].keys;
00491 var[classes] = i;
00492 }
00493
00494 qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))cuddZddUniqueCompare);
00495
00496
00497 iteration = ddMin(table->siftMaxVar, nvars);
00498 for (i = 0; i < iteration; i++) {
00499 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00500 break;
00501 x = table->permZ[var[i]];
00502 if ((unsigned) x >= table->subtableZ[x].next) {
00503 #ifdef DD_STATS
00504 previousSize = table->keysZ;
00505 #endif
00506 result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
00507 if (!result)
00508 goto cuddZddSymmSiftingConvOutOfMem;
00509 #ifdef DD_STATS
00510 if (table->keysZ < (unsigned) previousSize) {
00511 (void) fprintf(table->out,"-");
00512 } else if (table->keysZ > (unsigned) previousSize) {
00513 (void) fprintf(table->out,"+");
00514 #ifdef DD_VERBOSE
00515 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00516 #endif
00517 } else {
00518 (void) fprintf(table->out,"=");
00519 }
00520 fflush(table->out);
00521 #endif
00522 }
00523 }
00524 }
00525
00526 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00527
00528 #ifdef DD_STATS
00529 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
00530 symvars);
00531 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
00532 symgroups);
00533 #endif
00534
00535 FREE(var);
00536 FREE(zdd_entry);
00537
00538 return(1+symvars);
00539
00540 cuddZddSymmSiftingConvOutOfMem:
00541
00542 if (zdd_entry != NULL)
00543 FREE(zdd_entry);
00544 if (var != NULL)
00545 FREE(var);
00546
00547 return(0);
00548
00549 }
00550
00551
00552
00553
00554
00555
00556
00572 static int
00573 cuddZddSymmSiftingAux(
00574 DdManager * table,
00575 int x,
00576 int x_low,
00577 int x_high)
00578 {
00579 Move *move;
00580 Move *move_up;
00581 Move *move_down;
00582 int initial_size;
00583 int result;
00584 int i;
00585 int topbot;
00586 int init_group_size, final_group_size;
00587
00588 initial_size = table->keysZ;
00589
00590 move_down = NULL;
00591 move_up = NULL;
00592
00593
00594 for (i = x; i > x_low; i--) {
00595 if (!cuddZddSymmCheck(table, i - 1, i))
00596 break;
00597
00598 topbot = table->subtableZ[i - 1].next;
00599 table->subtableZ[i - 1].next = i;
00600 table->subtableZ[x].next = topbot;
00601
00602
00603 i = topbot + 1;
00604 }
00605
00606 for (i = x; i < x_high; i++) {
00607 if (!cuddZddSymmCheck(table, i, i + 1))
00608 break;
00609
00610 topbot = i + 1;
00611 while ((unsigned) topbot < table->subtableZ[topbot].next)
00612 topbot = table->subtableZ[topbot].next;
00613
00614 table->subtableZ[topbot].next = table->subtableZ[i].next;
00615 table->subtableZ[i].next = i + 1;
00616 i = topbot - 1;
00617
00618 }
00619
00620
00621 if (x == x_low) {
00622
00623 while ((unsigned) x < table->subtableZ[x].next)
00624 x = table->subtableZ[x].next;
00625
00626 i = table->subtableZ[x].next;
00627 init_group_size = x - i + 1;
00628
00629 move_down = cuddZddSymmSifting_down(table, x, x_high,
00630 initial_size);
00631
00632 if (move_down == ZDD_MV_OOM)
00633 goto cuddZddSymmSiftingAuxOutOfMem;
00634
00635 if (move_down == NULL ||
00636 table->subtableZ[move_down->y].next != move_down->y) {
00637
00638
00639 if (move_down != NULL)
00640 x = move_down->y;
00641 else
00642 x = table->subtableZ[x].next;
00643 i = x;
00644 while ((unsigned) i < table->subtableZ[i].next) {
00645 i = table->subtableZ[i].next;
00646 }
00647 final_group_size = i - x + 1;
00648
00649 if (init_group_size == final_group_size) {
00650
00651
00652 result = cuddZddSymmSiftingBackward(table,
00653 move_down, initial_size);
00654 }
00655 else {
00656 initial_size = table->keysZ;
00657 move_up = cuddZddSymmSifting_up(table, x, x_low,
00658 initial_size);
00659 result = cuddZddSymmSiftingBackward(table, move_up,
00660 initial_size);
00661 }
00662 }
00663 else {
00664 result = cuddZddSymmSiftingBackward(table, move_down,
00665 initial_size);
00666
00667 }
00668 if (!result)
00669 goto cuddZddSymmSiftingAuxOutOfMem;
00670 }
00671 else if (x == x_high) {
00672
00673 while ((unsigned) x < table->subtableZ[x].next)
00674 x = table->subtableZ[x].next;
00675 x = table->subtableZ[x].next;
00676
00677 i = x;
00678 while ((unsigned) i < table->subtableZ[i].next) {
00679 i = table->subtableZ[i].next;
00680 }
00681 init_group_size = i - x + 1;
00682
00683 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00684
00685 if (move_up == ZDD_MV_OOM)
00686 goto cuddZddSymmSiftingAuxOutOfMem;
00687
00688 if (move_up == NULL ||
00689 table->subtableZ[move_up->x].next != move_up->x) {
00690
00691
00692 if (move_up != NULL)
00693 x = move_up->x;
00694 else {
00695 while ((unsigned) x < table->subtableZ[x].next)
00696 x = table->subtableZ[x].next;
00697 }
00698 i = table->subtableZ[x].next;
00699 final_group_size = x - i + 1;
00700
00701 if (init_group_size == final_group_size) {
00702
00703
00704 result = cuddZddSymmSiftingBackward(table, move_up,
00705 initial_size);
00706 }
00707 else {
00708 initial_size = table->keysZ;
00709 move_down = cuddZddSymmSifting_down(table, x, x_high,
00710 initial_size);
00711 result = cuddZddSymmSiftingBackward(table, move_down,
00712 initial_size);
00713 }
00714 }
00715 else {
00716 result = cuddZddSymmSiftingBackward(table, move_up,
00717 initial_size);
00718
00719 }
00720 if (!result)
00721 goto cuddZddSymmSiftingAuxOutOfMem;
00722 }
00723 else if ((x - x_low) > (x_high - x)) {
00724
00725
00726 while ((unsigned) x < table->subtableZ[x].next)
00727 x = table->subtableZ[x].next;
00728
00729 move_down = cuddZddSymmSifting_down(table, x, x_high,
00730 initial_size);
00731
00732 if (move_down == ZDD_MV_OOM)
00733 goto cuddZddSymmSiftingAuxOutOfMem;
00734
00735 if (move_down != NULL) {
00736 x = move_down->y;
00737 }
00738 else {
00739 x = table->subtableZ[x].next;
00740 }
00741 i = x;
00742 while ((unsigned) i < table->subtableZ[i].next) {
00743 i = table->subtableZ[i].next;
00744 }
00745 init_group_size = i - x + 1;
00746
00747 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00748 if (move_up == ZDD_MV_OOM)
00749 goto cuddZddSymmSiftingAuxOutOfMem;
00750
00751 if (move_up == NULL ||
00752 table->subtableZ[move_up->x].next != move_up->x) {
00753
00754
00755 if (move_up != NULL) {
00756 x = move_up->x;
00757 }
00758 else {
00759 while ((unsigned) x < table->subtableZ[x].next)
00760 x = table->subtableZ[x].next;
00761 }
00762 i = table->subtableZ[x].next;
00763 final_group_size = x - i + 1;
00764
00765 if (init_group_size == final_group_size) {
00766
00767
00768 result = cuddZddSymmSiftingBackward(table, move_up,
00769 initial_size);
00770 }
00771 else {
00772 while (move_down != NULL) {
00773 move = move_down->next;
00774 cuddDeallocNode(table, (DdNode *)move_down);
00775 move_down = move;
00776 }
00777 initial_size = table->keysZ;
00778 move_down = cuddZddSymmSifting_down(table, x, x_high,
00779 initial_size);
00780 result = cuddZddSymmSiftingBackward(table, move_down,
00781 initial_size);
00782 }
00783 }
00784 else {
00785 result = cuddZddSymmSiftingBackward(table, move_up,
00786 initial_size);
00787
00788 }
00789 if (!result)
00790 goto cuddZddSymmSiftingAuxOutOfMem;
00791 }
00792 else {
00793
00794 while ((unsigned) x < table->subtableZ[x].next)
00795 x = table->subtableZ[x].next;
00796 x = table->subtableZ[x].next;
00797
00798 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00799
00800 if (move_up == ZDD_MV_OOM)
00801 goto cuddZddSymmSiftingAuxOutOfMem;
00802
00803 if (move_up != NULL) {
00804 x = move_up->x;
00805 }
00806 else {
00807 while ((unsigned) x < table->subtableZ[x].next)
00808 x = table->subtableZ[x].next;
00809 }
00810 i = table->subtableZ[x].next;
00811 init_group_size = x - i + 1;
00812
00813 move_down = cuddZddSymmSifting_down(table, x, x_high,
00814 initial_size);
00815 if (move_down == ZDD_MV_OOM)
00816 goto cuddZddSymmSiftingAuxOutOfMem;
00817
00818 if (move_down == NULL ||
00819 table->subtableZ[move_down->y].next != move_down->y) {
00820
00821
00822 if (move_down != NULL) {
00823 x = move_down->y;
00824 }
00825 else {
00826 x = table->subtableZ[x].next;
00827 }
00828 i = x;
00829 while ((unsigned) i < table->subtableZ[i].next) {
00830 i = table->subtableZ[i].next;
00831 }
00832 final_group_size = i - x + 1;
00833
00834 if (init_group_size == final_group_size) {
00835
00836
00837 result = cuddZddSymmSiftingBackward(table, move_down,
00838 initial_size);
00839 }
00840 else {
00841 while (move_up != NULL) {
00842 move = move_up->next;
00843 cuddDeallocNode(table, (DdNode *)move_up);
00844 move_up = move;
00845 }
00846 initial_size = table->keysZ;
00847 move_up = cuddZddSymmSifting_up(table, x, x_low,
00848 initial_size);
00849 result = cuddZddSymmSiftingBackward(table, move_up,
00850 initial_size);
00851 }
00852 }
00853 else {
00854 result = cuddZddSymmSiftingBackward(table, move_down,
00855 initial_size);
00856
00857 }
00858 if (!result)
00859 goto cuddZddSymmSiftingAuxOutOfMem;
00860 }
00861
00862 while (move_down != NULL) {
00863 move = move_down->next;
00864 cuddDeallocNode(table, (DdNode *)move_down);
00865 move_down = move;
00866 }
00867 while (move_up != NULL) {
00868 move = move_up->next;
00869 cuddDeallocNode(table, (DdNode *)move_up);
00870 move_up = move;
00871 }
00872
00873 return(1);
00874
00875 cuddZddSymmSiftingAuxOutOfMem:
00876 if (move_down != ZDD_MV_OOM) {
00877 while (move_down != NULL) {
00878 move = move_down->next;
00879 cuddDeallocNode(table, (DdNode *)move_down);
00880 move_down = move;
00881 }
00882 }
00883 if (move_up != ZDD_MV_OOM) {
00884 while (move_up != NULL) {
00885 move = move_up->next;
00886 cuddDeallocNode(table, (DdNode *)move_up);
00887 move_up = move;
00888 }
00889 }
00890
00891 return(0);
00892
00893 }
00894
00895
00912 static int
00913 cuddZddSymmSiftingConvAux(
00914 DdManager * table,
00915 int x,
00916 int x_low,
00917 int x_high)
00918 {
00919 Move *move;
00920 Move *move_up;
00921 Move *move_down;
00922 int initial_size;
00923 int result;
00924 int i;
00925 int init_group_size, final_group_size;
00926
00927 initial_size = table->keysZ;
00928
00929 move_down = NULL;
00930 move_up = NULL;
00931
00932 if (x == x_low) {
00933 i = table->subtableZ[x].next;
00934 init_group_size = x - i + 1;
00935
00936 move_down = cuddZddSymmSifting_down(table, x, x_high,
00937 initial_size);
00938
00939 if (move_down == ZDD_MV_OOM)
00940 goto cuddZddSymmSiftingConvAuxOutOfMem;
00941
00942 if (move_down == NULL ||
00943 table->subtableZ[move_down->y].next != move_down->y) {
00944
00945
00946 if (move_down != NULL)
00947 x = move_down->y;
00948 else {
00949 while ((unsigned) x < table->subtableZ[x].next);
00950 x = table->subtableZ[x].next;
00951 x = table->subtableZ[x].next;
00952 }
00953 i = x;
00954 while ((unsigned) i < table->subtableZ[i].next) {
00955 i = table->subtableZ[i].next;
00956 }
00957 final_group_size = i - x + 1;
00958
00959 if (init_group_size == final_group_size) {
00960
00961
00962 result = cuddZddSymmSiftingBackward(table, move_down,
00963 initial_size);
00964 }
00965 else {
00966 initial_size = table->keysZ;
00967 move_up = cuddZddSymmSifting_up(table, x, x_low,
00968 initial_size);
00969 result = cuddZddSymmSiftingBackward(table, move_up,
00970 initial_size);
00971 }
00972 }
00973 else {
00974 result = cuddZddSymmSiftingBackward(table, move_down,
00975 initial_size);
00976
00977 }
00978 if (!result)
00979 goto cuddZddSymmSiftingConvAuxOutOfMem;
00980 }
00981 else if (x == x_high) {
00982
00983 while ((unsigned) x < table->subtableZ[x].next)
00984 x = table->subtableZ[x].next;
00985 x = table->subtableZ[x].next;
00986
00987 i = x;
00988 while ((unsigned) i < table->subtableZ[i].next) {
00989 i = table->subtableZ[i].next;
00990 }
00991 init_group_size = i - x + 1;
00992
00993 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00994
00995 if (move_up == ZDD_MV_OOM)
00996 goto cuddZddSymmSiftingConvAuxOutOfMem;
00997
00998 if (move_up == NULL ||
00999 table->subtableZ[move_up->x].next != move_up->x) {
01000
01001
01002 if (move_up != NULL)
01003 x = move_up->x;
01004 else {
01005 while ((unsigned) x < table->subtableZ[x].next)
01006 x = table->subtableZ[x].next;
01007 }
01008 i = table->subtableZ[x].next;
01009 final_group_size = x - i + 1;
01010
01011 if (init_group_size == final_group_size) {
01012
01013
01014 result = cuddZddSymmSiftingBackward(table, move_up,
01015 initial_size);
01016 }
01017 else {
01018 initial_size = table->keysZ;
01019 move_down = cuddZddSymmSifting_down(table, x, x_high,
01020 initial_size);
01021 result = cuddZddSymmSiftingBackward(table, move_down,
01022 initial_size);
01023 }
01024 }
01025 else {
01026 result = cuddZddSymmSiftingBackward(table, move_up,
01027 initial_size);
01028
01029 }
01030 if (!result)
01031 goto cuddZddSymmSiftingConvAuxOutOfMem;
01032 }
01033 else if ((x - x_low) > (x_high - x)) {
01034
01035 move_down = cuddZddSymmSifting_down(table, x, x_high,
01036 initial_size);
01037
01038 if (move_down == ZDD_MV_OOM)
01039 goto cuddZddSymmSiftingConvAuxOutOfMem;
01040
01041 if (move_down != NULL) {
01042 x = move_down->y;
01043 }
01044 else {
01045 while ((unsigned) x < table->subtableZ[x].next)
01046 x = table->subtableZ[x].next;
01047 x = table->subtableZ[x].next;
01048 }
01049 i = x;
01050 while ((unsigned) i < table->subtableZ[i].next) {
01051 i = table->subtableZ[i].next;
01052 }
01053 init_group_size = i - x + 1;
01054
01055 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01056 if (move_up == ZDD_MV_OOM)
01057 goto cuddZddSymmSiftingConvAuxOutOfMem;
01058
01059 if (move_up == NULL ||
01060 table->subtableZ[move_up->x].next != move_up->x) {
01061
01062
01063 if (move_up != NULL) {
01064 x = move_up->x;
01065 }
01066 else {
01067 while ((unsigned) x < table->subtableZ[x].next)
01068 x = table->subtableZ[x].next;
01069 }
01070 i = table->subtableZ[x].next;
01071 final_group_size = x - i + 1;
01072
01073 if (init_group_size == final_group_size) {
01074
01075
01076 result = cuddZddSymmSiftingBackward(table, move_up,
01077 initial_size);
01078 }
01079 else {
01080 while (move_down != NULL) {
01081 move = move_down->next;
01082 cuddDeallocNode(table, (DdNode *)move_down);
01083 move_down = move;
01084 }
01085 initial_size = table->keysZ;
01086 move_down = cuddZddSymmSifting_down(table, x, x_high,
01087 initial_size);
01088 result = cuddZddSymmSiftingBackward(table, move_down,
01089 initial_size);
01090 }
01091 }
01092 else {
01093 result = cuddZddSymmSiftingBackward(table, move_up,
01094 initial_size);
01095
01096 }
01097 if (!result)
01098 goto cuddZddSymmSiftingConvAuxOutOfMem;
01099 }
01100 else {
01101
01102 x = table->subtableZ[x].next;
01103
01104 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01105
01106 if (move_up == ZDD_MV_OOM)
01107 goto cuddZddSymmSiftingConvAuxOutOfMem;
01108
01109 if (move_up != NULL) {
01110 x = move_up->x;
01111 }
01112 else {
01113 while ((unsigned) x < table->subtableZ[x].next)
01114 x = table->subtableZ[x].next;
01115 }
01116 i = table->subtableZ[x].next;
01117 init_group_size = x - i + 1;
01118
01119 move_down = cuddZddSymmSifting_down(table, x, x_high,
01120 initial_size);
01121 if (move_down == ZDD_MV_OOM)
01122 goto cuddZddSymmSiftingConvAuxOutOfMem;
01123
01124 if (move_down == NULL ||
01125 table->subtableZ[move_down->y].next != move_down->y) {
01126
01127
01128 if (move_down != NULL) {
01129 x = move_down->y;
01130 }
01131 else {
01132 while ((unsigned) x < table->subtableZ[x].next)
01133 x = table->subtableZ[x].next;
01134 x = table->subtableZ[x].next;
01135 }
01136 i = x;
01137 while ((unsigned) i < table->subtableZ[i].next) {
01138 i = table->subtableZ[i].next;
01139 }
01140 final_group_size = i - x + 1;
01141
01142 if (init_group_size == final_group_size) {
01143
01144
01145 result = cuddZddSymmSiftingBackward(table, move_down,
01146 initial_size);
01147 }
01148 else {
01149 while (move_up != NULL) {
01150 move = move_up->next;
01151 cuddDeallocNode(table, (DdNode *)move_up);
01152 move_up = move;
01153 }
01154 initial_size = table->keysZ;
01155 move_up = cuddZddSymmSifting_up(table, x, x_low,
01156 initial_size);
01157 result = cuddZddSymmSiftingBackward(table, move_up,
01158 initial_size);
01159 }
01160 }
01161 else {
01162 result = cuddZddSymmSiftingBackward(table, move_down,
01163 initial_size);
01164
01165 }
01166 if (!result)
01167 goto cuddZddSymmSiftingConvAuxOutOfMem;
01168 }
01169
01170 while (move_down != NULL) {
01171 move = move_down->next;
01172 cuddDeallocNode(table, (DdNode *)move_down);
01173 move_down = move;
01174 }
01175 while (move_up != NULL) {
01176 move = move_up->next;
01177 cuddDeallocNode(table, (DdNode *)move_up);
01178 move_up = move;
01179 }
01180
01181 return(1);
01182
01183 cuddZddSymmSiftingConvAuxOutOfMem:
01184 if (move_down != ZDD_MV_OOM) {
01185 while (move_down != NULL) {
01186 move = move_down->next;
01187 cuddDeallocNode(table, (DdNode *)move_down);
01188 move_down = move;
01189 }
01190 }
01191 if (move_up != ZDD_MV_OOM) {
01192 while (move_up != NULL) {
01193 move = move_up->next;
01194 cuddDeallocNode(table, (DdNode *)move_up);
01195 move_up = move;
01196 }
01197 }
01198
01199 return(0);
01200
01201 }
01202
01203
01221 static Move *
01222 cuddZddSymmSifting_up(
01223 DdManager * table,
01224 int x,
01225 int x_low,
01226 int initial_size)
01227 {
01228 Move *moves;
01229 Move *move;
01230 int y;
01231 int size;
01232 int limit_size = initial_size;
01233 int i, gytop;
01234
01235 moves = NULL;
01236 y = cuddZddNextLow(table, x);
01237 while (y >= x_low) {
01238 gytop = table->subtableZ[y].next;
01239 if (cuddZddSymmCheck(table, y, x)) {
01240
01241 table->subtableZ[y].next = x;
01242 i = table->subtableZ[x].next;
01243 while (table->subtableZ[i].next != (unsigned) x)
01244 i = table->subtableZ[i].next;
01245 table->subtableZ[i].next = gytop;
01246 }
01247 else if ((table->subtableZ[x].next == (unsigned) x) &&
01248 (table->subtableZ[y].next == (unsigned) y)) {
01249
01250 size = cuddZddSwapInPlace(table, y, x);
01251 if (size == 0)
01252 goto cuddZddSymmSifting_upOutOfMem;
01253 move = (Move *)cuddDynamicAllocNode(table);
01254 if (move == NULL)
01255 goto cuddZddSymmSifting_upOutOfMem;
01256 move->x = y;
01257 move->y = x;
01258 move->size = size;
01259 move->next = moves;
01260 moves = move;
01261 if ((double)size >
01262 (double)limit_size * table->maxGrowth)
01263 return(moves);
01264 if (size < limit_size)
01265 limit_size = size;
01266 }
01267 else {
01268 size = zdd_group_move(table, y, x, &moves);
01269 if ((double)size >
01270 (double)limit_size * table->maxGrowth)
01271 return(moves);
01272 if (size < limit_size)
01273 limit_size = size;
01274 }
01275 x = gytop;
01276 y = cuddZddNextLow(table, x);
01277 }
01278
01279 return(moves);
01280
01281 cuddZddSymmSifting_upOutOfMem:
01282 while (moves != NULL) {
01283 move = moves->next;
01284 cuddDeallocNode(table, (DdNode *)moves);
01285 moves = move;
01286 }
01287 return(ZDD_MV_OOM);
01288
01289 }
01290
01291
01309 static Move *
01310 cuddZddSymmSifting_down(
01311 DdManager * table,
01312 int x,
01313 int x_high,
01314 int initial_size)
01315 {
01316 Move *moves;
01317 Move *move;
01318 int y;
01319 int size;
01320 int limit_size = initial_size;
01321 int i, gxtop, gybot;
01322
01323 moves = NULL;
01324 y = cuddZddNextHigh(table, x);
01325 while (y <= x_high) {
01326 gybot = table->subtableZ[y].next;
01327 while (table->subtableZ[gybot].next != (unsigned) y)
01328 gybot = table->subtableZ[gybot].next;
01329 if (cuddZddSymmCheck(table, x, y)) {
01330
01331 gxtop = table->subtableZ[x].next;
01332 table->subtableZ[x].next = y;
01333 i = table->subtableZ[y].next;
01334 while (table->subtableZ[i].next != (unsigned) y)
01335 i = table->subtableZ[i].next;
01336 table->subtableZ[i].next = gxtop;
01337 }
01338 else if ((table->subtableZ[x].next == (unsigned) x) &&
01339 (table->subtableZ[y].next == (unsigned) y)) {
01340
01341 size = cuddZddSwapInPlace(table, x, y);
01342 if (size == 0)
01343 goto cuddZddSymmSifting_downOutOfMem;
01344 move = (Move *)cuddDynamicAllocNode(table);
01345 if (move == NULL)
01346 goto cuddZddSymmSifting_downOutOfMem;
01347 move->x = x;
01348 move->y = y;
01349 move->size = size;
01350 move->next = moves;
01351 moves = move;
01352 if ((double)size >
01353 (double)limit_size * table->maxGrowth)
01354 return(moves);
01355 if (size < limit_size)
01356 limit_size = size;
01357 x = y;
01358 y = cuddZddNextHigh(table, x);
01359 }
01360 else {
01361 size = zdd_group_move(table, x, y, &moves);
01362 if ((double)size >
01363 (double)limit_size * table->maxGrowth)
01364 return(moves);
01365 if (size < limit_size)
01366 limit_size = size;
01367 }
01368 x = gybot;
01369 y = cuddZddNextHigh(table, x);
01370 }
01371
01372 return(moves);
01373
01374 cuddZddSymmSifting_downOutOfMem:
01375 while (moves != NULL) {
01376 move = moves->next;
01377 cuddDeallocNode(table, (DdNode *)moves);
01378 moves = move;
01379 }
01380 return(ZDD_MV_OOM);
01381
01382 }
01383
01384
01400 static int
01401 cuddZddSymmSiftingBackward(
01402 DdManager * table,
01403 Move * moves,
01404 int size)
01405 {
01406 int i;
01407 int i_best;
01408 Move *move;
01409 int res;
01410
01411 i_best = -1;
01412 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01413 if (move->size < size) {
01414 i_best = i;
01415 size = move->size;
01416 }
01417 }
01418
01419 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01420 if (i == i_best) break;
01421 if ((table->subtableZ[move->x].next == move->x) &&
01422 (table->subtableZ[move->y].next == move->y)) {
01423 res = cuddZddSwapInPlace(table, move->x, move->y);
01424 if (!res) return(0);
01425 }
01426 else {
01427 res = zdd_group_move_backward(table, move->x, move->y);
01428 }
01429 if (i_best == -1 && res == size)
01430 break;
01431 }
01432
01433 return(1);
01434
01435 }
01436
01437
01452 static int
01453 zdd_group_move(
01454 DdManager * table,
01455 int x,
01456 int y,
01457 Move ** moves)
01458 {
01459 Move *move;
01460 int size;
01461 int i, temp, gxtop, gxbot, gytop, gybot, yprev;
01462 int swapx, swapy;
01463
01464 #ifdef DD_DEBUG
01465 assert(x < y);
01466 #endif
01467
01468 gxtop = table->subtableZ[x].next;
01469 gytop = y;
01470 gxbot = x;
01471 gybot = table->subtableZ[y].next;
01472 while (table->subtableZ[gybot].next != (unsigned) y)
01473 gybot = table->subtableZ[gybot].next;
01474 yprev = gybot;
01475
01476 while (x <= y) {
01477 while (y > gxtop) {
01478
01479 temp = table->subtableZ[x].next;
01480 if (temp == x)
01481 temp = y;
01482 i = gxtop;
01483 for (;;) {
01484 if (table->subtableZ[i].next == (unsigned) x) {
01485 table->subtableZ[i].next = y;
01486 break;
01487 } else {
01488 i = table->subtableZ[i].next;
01489 }
01490 }
01491 if (table->subtableZ[y].next != (unsigned) y) {
01492 table->subtableZ[x].next = table->subtableZ[y].next;
01493 } else {
01494 table->subtableZ[x].next = x;
01495 }
01496
01497 if (yprev != y) {
01498 table->subtableZ[yprev].next = x;
01499 } else {
01500 yprev = x;
01501 }
01502 table->subtableZ[y].next = temp;
01503
01504 size = cuddZddSwapInPlace(table, x, y);
01505 if (size == 0)
01506 goto zdd_group_moveOutOfMem;
01507 swapx = x;
01508 swapy = y;
01509 y = x;
01510 x--;
01511 }
01512
01513
01514 if (table->subtableZ[y].next <= (unsigned) y) {
01515 gybot = y;
01516 } else {
01517 y = table->subtableZ[y].next;
01518 }
01519
01520 yprev = gxtop;
01521 gxtop++;
01522 gxbot++;
01523 x = gxbot;
01524 }
01525 move = (Move *)cuddDynamicAllocNode(table);
01526 if (move == NULL)
01527 goto zdd_group_moveOutOfMem;
01528 move->x = swapx;
01529 move->y = swapy;
01530 move->size = table->keysZ;
01531 move->next = *moves;
01532 *moves = move;
01533
01534 return(table->keysZ);
01535
01536 zdd_group_moveOutOfMem:
01537 while (*moves != NULL) {
01538 move = (*moves)->next;
01539 cuddDeallocNode(table, (DdNode *)(*moves));
01540 *moves = move;
01541 }
01542 return(0);
01543
01544 }
01545
01546
01560 static int
01561 zdd_group_move_backward(
01562 DdManager * table,
01563 int x,
01564 int y)
01565 {
01566 int size;
01567 int i, temp, gxtop, gxbot, gytop, gybot, yprev;
01568
01569 #ifdef DD_DEBUG
01570 assert(x < y);
01571 #endif
01572
01573 gxtop = table->subtableZ[x].next;
01574 gytop = y;
01575 gxbot = x;
01576 gybot = table->subtableZ[y].next;
01577 while (table->subtableZ[gybot].next != (unsigned) y)
01578 gybot = table->subtableZ[gybot].next;
01579 yprev = gybot;
01580
01581 while (x <= y) {
01582 while (y > gxtop) {
01583
01584 temp = table->subtableZ[x].next;
01585 if (temp == x)
01586 temp = y;
01587 i = gxtop;
01588 for (;;) {
01589 if (table->subtableZ[i].next == (unsigned) x) {
01590 table->subtableZ[i].next = y;
01591 break;
01592 } else {
01593 i = table->subtableZ[i].next;
01594 }
01595 }
01596 if (table->subtableZ[y].next != (unsigned) y) {
01597 table->subtableZ[x].next = table->subtableZ[y].next;
01598 } else {
01599 table->subtableZ[x].next = x;
01600 }
01601
01602 if (yprev != y) {
01603 table->subtableZ[yprev].next = x;
01604 } else {
01605 yprev = x;
01606 }
01607 table->subtableZ[y].next = temp;
01608
01609 size = cuddZddSwapInPlace(table, x, y);
01610 if (size == 0)
01611 return(0);
01612 y = x;
01613 x--;
01614 }
01615
01616
01617 if (table->subtableZ[y].next <= (unsigned) y) {
01618 gybot = y;
01619 } else {
01620 y = table->subtableZ[y].next;
01621 }
01622
01623 yprev = gxtop;
01624 gxtop++;
01625 gxbot++;
01626 x = gxbot;
01627 }
01628
01629 return(size);
01630
01631 }
01632
01633
01644 static void
01645 cuddZddSymmSummary(
01646 DdManager * table,
01647 int lower,
01648 int upper,
01649 int * symvars,
01650 int * symgroups)
01651 {
01652 int i,x,gbot;
01653 int TotalSymm = 0;
01654 int TotalSymmGroups = 0;
01655
01656 for (i = lower; i <= upper; i++) {
01657 if (table->subtableZ[i].next != (unsigned) i) {
01658 TotalSymmGroups++;
01659 x = i;
01660 do {
01661 TotalSymm++;
01662 gbot = x;
01663 x = table->subtableZ[x].next;
01664 } while (x != i);
01665 #ifdef DD_DEBUG
01666 assert(table->subtableZ[gbot].next == (unsigned) i);
01667 #endif
01668 i = gbot;
01669 }
01670 }
01671 *symvars = TotalSymm;
01672 *symgroups = TotalSymmGroups;
01673
01674 return;
01675
01676 }
01677