00001
00070 #include "util.h"
00071 #include "cuddInt.h"
00072
00073
00074
00075
00076
00077 #define ZDD_MV_OOM (Move *)1
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 #ifndef lint
00092 static char rcsid[] DD_UNUSED = "$Id: cuddZddSymm.c,v 1.29 2004/08/13 18:04:54 fabio Exp $";
00093 #endif
00094
00095 extern int *zdd_entry;
00096
00097 extern int zddTotalNumberSwapping;
00098
00099 static DdNode *empty;
00100
00101
00102
00103
00104
00105
00108
00109
00110
00111
00112 static int cuddZddSymmSiftingAux (DdManager *table, int x, int x_low, int x_high);
00113 static int cuddZddSymmSiftingConvAux (DdManager *table, int x, int x_low, int x_high);
00114 static Move * cuddZddSymmSifting_up (DdManager *table, int x, int x_low, int initial_size);
00115 static Move * cuddZddSymmSifting_down (DdManager *table, int x, int x_high, int initial_size);
00116 static int cuddZddSymmSiftingBackward (DdManager *table, Move *moves, int size);
00117 static int zdd_group_move (DdManager *table, int x, int y, Move **moves);
00118 static int zdd_group_move_backward (DdManager *table, int x, int y);
00119 static void cuddZddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
00120
00124
00125
00126
00127
00128
00140 void
00141 Cudd_zddSymmProfile(
00142 DdManager * table,
00143 int lower,
00144 int upper)
00145 {
00146 int i, x, gbot;
00147 int TotalSymm = 0;
00148 int TotalSymmGroups = 0;
00149
00150 for (i = lower; i < upper; i++) {
00151 if (table->subtableZ[i].next != (unsigned) i) {
00152 x = i;
00153 (void) fprintf(table->out,"Group:");
00154 do {
00155 (void) fprintf(table->out," %d", table->invpermZ[x]);
00156 TotalSymm++;
00157 gbot = x;
00158 x = table->subtableZ[x].next;
00159 } while (x != i);
00160 TotalSymmGroups++;
00161 #ifdef DD_DEBUG
00162 assert(table->subtableZ[gbot].next == (unsigned) i);
00163 #endif
00164 i = gbot;
00165 (void) fprintf(table->out,"\n");
00166 }
00167 }
00168 (void) fprintf(table->out,"Total Symmetric = %d\n", TotalSymm);
00169 (void) fprintf(table->out,"Total Groups = %d\n", TotalSymmGroups);
00170
00171 }
00172
00173
00174
00175
00176
00177
00178
00192 int
00193 cuddZddSymmCheck(
00194 DdManager * table,
00195 int x,
00196 int y)
00197 {
00198 int i;
00199 DdNode *f, *f0, *f1, *f01, *f00, *f11, *f10;
00200 int yindex;
00201 int xsymmy = 1;
00202 int xsymmyp = 1;
00203 int arccount = 0;
00204 int TotalRefCount = 0;
00205 int symm_found;
00206
00207 empty = table->zero;
00208
00209 yindex = table->invpermZ[y];
00210 for (i = table->subtableZ[x].slots - 1; i >= 0; i--) {
00211 f = table->subtableZ[x].nodelist[i];
00212 while (f != NULL) {
00213
00214 f1 = cuddT(f);
00215 f0 = cuddE(f);
00216 if ((int) f1->index == yindex) {
00217 f11 = cuddT(f1);
00218 f10 = cuddE(f1);
00219 if (f10 != empty)
00220 arccount++;
00221 } else {
00222 if ((int) f0->index != yindex) {
00223 return(0);
00224 }
00225 f11 = empty;
00226 f10 = f1;
00227 }
00228 if ((int) f0->index == yindex) {
00229 f01 = cuddT(f0);
00230 f00 = cuddE(f0);
00231 if (f00 != empty)
00232 arccount++;
00233 } else {
00234 f01 = empty;
00235 f00 = f0;
00236 }
00237 if (f01 != f10)
00238 xsymmy = 0;
00239 if (f11 != f00)
00240 xsymmyp = 0;
00241 if ((xsymmy == 0) && (xsymmyp == 0))
00242 return(0);
00243
00244 f = f->next;
00245 }
00246 }
00247
00248
00249
00250
00251 for (i = table->subtableZ[y].slots - 1; i >= 0; i--) {
00252 f = table->subtableZ[y].nodelist[i];
00253 while (f != NIL(DdNode)) {
00254 if (cuddE(f) != empty)
00255 TotalRefCount += f->ref;
00256 f = f->next;
00257 }
00258 }
00259
00260 symm_found = (arccount == TotalRefCount);
00261 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
00262 if (symm_found) {
00263 int xindex = table->invpermZ[x];
00264 (void) fprintf(table->out,
00265 "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
00266 xindex,yindex,x,y);
00267 }
00268 #endif
00269
00270 return(symm_found);
00271
00272 }
00273
00274
00297 int
00298 cuddZddSymmSifting(
00299 DdManager * table,
00300 int lower,
00301 int upper)
00302 {
00303 int i;
00304 int *var;
00305 int nvars;
00306 int x;
00307 int result;
00308 int symvars;
00309 int symgroups;
00310 int iteration;
00311 #ifdef DD_STATS
00312 int previousSize;
00313 #endif
00314
00315 nvars = table->sizeZ;
00316
00317
00318 var = NULL;
00319 zdd_entry = ALLOC(int, nvars);
00320 if (zdd_entry == NULL) {
00321 table->errorCode = CUDD_MEMORY_OUT;
00322 goto cuddZddSymmSiftingOutOfMem;
00323 }
00324 var = ALLOC(int, nvars);
00325 if (var == NULL) {
00326 table->errorCode = CUDD_MEMORY_OUT;
00327 goto cuddZddSymmSiftingOutOfMem;
00328 }
00329
00330 for (i = 0; i < nvars; i++) {
00331 x = table->permZ[i];
00332 zdd_entry[i] = table->subtableZ[x].keys;
00333 var[i] = i;
00334 }
00335
00336 qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00337
00338
00339 for (i = lower; i <= upper; i++)
00340 table->subtableZ[i].next = i;
00341
00342 iteration = ddMin(table->siftMaxVar, nvars);
00343 for (i = 0; i < iteration; i++) {
00344 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00345 break;
00346 x = table->permZ[var[i]];
00347 #ifdef DD_STATS
00348 previousSize = table->keysZ;
00349 #endif
00350 if (x < lower || x > upper) continue;
00351 if (table->subtableZ[x].next == (unsigned) x) {
00352 result = cuddZddSymmSiftingAux(table, x, lower, upper);
00353 if (!result)
00354 goto cuddZddSymmSiftingOutOfMem;
00355 #ifdef DD_STATS
00356 if (table->keysZ < (unsigned) previousSize) {
00357 (void) fprintf(table->out,"-");
00358 } else if (table->keysZ > (unsigned) previousSize) {
00359 (void) fprintf(table->out,"+");
00360 #ifdef DD_VERBOSE
00361 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00362 #endif
00363 } else {
00364 (void) fprintf(table->out,"=");
00365 }
00366 fflush(table->out);
00367 #endif
00368 }
00369 }
00370
00371 FREE(var);
00372 FREE(zdd_entry);
00373
00374 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00375
00376 #ifdef DD_STATS
00377 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",symvars);
00378 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",symgroups);
00379 #endif
00380
00381 return(1+symvars);
00382
00383 cuddZddSymmSiftingOutOfMem:
00384
00385 if (zdd_entry != NULL)
00386 FREE(zdd_entry);
00387 if (var != NULL)
00388 FREE(var);
00389
00390 return(0);
00391
00392 }
00393
00394
00418 int
00419 cuddZddSymmSiftingConv(
00420 DdManager * table,
00421 int lower,
00422 int upper)
00423 {
00424 int i;
00425 int *var;
00426 int nvars;
00427 int initialSize;
00428 int x;
00429 int result;
00430 int symvars;
00431 int symgroups;
00432 int classes;
00433 int iteration;
00434 #ifdef DD_STATS
00435 int previousSize;
00436 #endif
00437
00438 initialSize = table->keysZ;
00439
00440 nvars = table->sizeZ;
00441
00442
00443 var = NULL;
00444 zdd_entry = ALLOC(int, nvars);
00445 if (zdd_entry == NULL) {
00446 table->errorCode = CUDD_MEMORY_OUT;
00447 goto cuddZddSymmSiftingConvOutOfMem;
00448 }
00449 var = ALLOC(int, nvars);
00450 if (var == NULL) {
00451 table->errorCode = CUDD_MEMORY_OUT;
00452 goto cuddZddSymmSiftingConvOutOfMem;
00453 }
00454
00455 for (i = 0; i < nvars; i++) {
00456 x = table->permZ[i];
00457 zdd_entry[i] = table->subtableZ[x].keys;
00458 var[i] = i;
00459 }
00460
00461 qsort((void *)var, nvars, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00462
00463
00464
00465
00466 for (i = lower; i <= upper; i++)
00467 table->subtableZ[i].next = i;
00468
00469 iteration = ddMin(table->siftMaxVar, table->sizeZ);
00470 for (i = 0; i < iteration; i++) {
00471 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00472 break;
00473 x = table->permZ[var[i]];
00474 if (x < lower || x > upper) continue;
00475
00476 if (table->subtableZ[x].next == (unsigned) x) {
00477 #ifdef DD_STATS
00478 previousSize = table->keysZ;
00479 #endif
00480 result = cuddZddSymmSiftingAux(table, x, lower, upper);
00481 if (!result)
00482 goto cuddZddSymmSiftingConvOutOfMem;
00483 #ifdef DD_STATS
00484 if (table->keysZ < (unsigned) previousSize) {
00485 (void) fprintf(table->out,"-");
00486 } else if (table->keysZ > (unsigned) previousSize) {
00487 (void) fprintf(table->out,"+");
00488 #ifdef DD_VERBOSE
00489 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00490 #endif
00491 } else {
00492 (void) fprintf(table->out,"=");
00493 }
00494 fflush(table->out);
00495 #endif
00496 }
00497 }
00498
00499
00500 while ((unsigned) initialSize > table->keysZ) {
00501 initialSize = table->keysZ;
00502 #ifdef DD_STATS
00503 (void) fprintf(table->out,"\n");
00504 #endif
00505
00506 for (x = lower, classes = 0; x <= upper; x++, classes++) {
00507 while ((unsigned) x < table->subtableZ[x].next)
00508 x = table->subtableZ[x].next;
00509
00510
00511
00512
00513 i = table->invpermZ[x];
00514 zdd_entry[i] = table->subtableZ[x].keys;
00515 var[classes] = i;
00516 }
00517
00518 qsort((void *)var,classes,sizeof(int),(DD_QSFP)cuddZddUniqueCompare);
00519
00520
00521 iteration = ddMin(table->siftMaxVar, nvars);
00522 for (i = 0; i < iteration; i++) {
00523 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00524 break;
00525 x = table->permZ[var[i]];
00526 if ((unsigned) x >= table->subtableZ[x].next) {
00527 #ifdef DD_STATS
00528 previousSize = table->keysZ;
00529 #endif
00530 result = cuddZddSymmSiftingConvAux(table, x, lower, upper);
00531 if (!result)
00532 goto cuddZddSymmSiftingConvOutOfMem;
00533 #ifdef DD_STATS
00534 if (table->keysZ < (unsigned) previousSize) {
00535 (void) fprintf(table->out,"-");
00536 } else if (table->keysZ > (unsigned) previousSize) {
00537 (void) fprintf(table->out,"+");
00538 #ifdef DD_VERBOSE
00539 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ, var[i]);
00540 #endif
00541 } else {
00542 (void) fprintf(table->out,"=");
00543 }
00544 fflush(table->out);
00545 #endif
00546 }
00547 }
00548 }
00549
00550 cuddZddSymmSummary(table, lower, upper, &symvars, &symgroups);
00551
00552 #ifdef DD_STATS
00553 (void) fprintf(table->out,"\n#:S_SIFTING %8d: symmetric variables\n",
00554 symvars);
00555 (void) fprintf(table->out,"#:G_SIFTING %8d: symmetric groups\n",
00556 symgroups);
00557 #endif
00558
00559 FREE(var);
00560 FREE(zdd_entry);
00561
00562 return(1+symvars);
00563
00564 cuddZddSymmSiftingConvOutOfMem:
00565
00566 if (zdd_entry != NULL)
00567 FREE(zdd_entry);
00568 if (var != NULL)
00569 FREE(var);
00570
00571 return(0);
00572
00573 }
00574
00575
00576
00577
00578
00579
00580
00596 static int
00597 cuddZddSymmSiftingAux(
00598 DdManager * table,
00599 int x,
00600 int x_low,
00601 int x_high)
00602 {
00603 Move *move;
00604 Move *move_up;
00605 Move *move_down;
00606 int initial_size;
00607 int result;
00608 int i;
00609 int topbot;
00610 int init_group_size, final_group_size;
00611
00612 initial_size = table->keysZ;
00613
00614 move_down = NULL;
00615 move_up = NULL;
00616
00617
00618 for (i = x; i > x_low; i--) {
00619 if (!cuddZddSymmCheck(table, i - 1, i))
00620 break;
00621
00622 topbot = table->subtableZ[i - 1].next;
00623 table->subtableZ[i - 1].next = i;
00624 table->subtableZ[x].next = topbot;
00625
00626
00627 i = topbot + 1;
00628 }
00629
00630 for (i = x; i < x_high; i++) {
00631 if (!cuddZddSymmCheck(table, i, i + 1))
00632 break;
00633
00634 topbot = i + 1;
00635 while ((unsigned) topbot < table->subtableZ[topbot].next)
00636 topbot = table->subtableZ[topbot].next;
00637
00638 table->subtableZ[topbot].next = table->subtableZ[i].next;
00639 table->subtableZ[i].next = i + 1;
00640 i = topbot - 1;
00641
00642 }
00643
00644
00645 if (x == x_low) {
00646
00647 while ((unsigned) x < table->subtableZ[x].next)
00648 x = table->subtableZ[x].next;
00649
00650 i = table->subtableZ[x].next;
00651 init_group_size = x - i + 1;
00652
00653 move_down = cuddZddSymmSifting_down(table, x, x_high,
00654 initial_size);
00655
00656 if (move_down == ZDD_MV_OOM)
00657 goto cuddZddSymmSiftingAuxOutOfMem;
00658
00659 if (move_down == NULL ||
00660 table->subtableZ[move_down->y].next != move_down->y) {
00661
00662
00663 if (move_down != NULL)
00664 x = move_down->y;
00665 else
00666 x = table->subtableZ[x].next;
00667 i = x;
00668 while ((unsigned) i < table->subtableZ[i].next) {
00669 i = table->subtableZ[i].next;
00670 }
00671 final_group_size = i - x + 1;
00672
00673 if (init_group_size == final_group_size) {
00674
00675
00676 result = cuddZddSymmSiftingBackward(table,
00677 move_down, initial_size);
00678 }
00679 else {
00680 initial_size = table->keysZ;
00681 move_up = cuddZddSymmSifting_up(table, x, x_low,
00682 initial_size);
00683 result = cuddZddSymmSiftingBackward(table, move_up,
00684 initial_size);
00685 }
00686 }
00687 else {
00688 result = cuddZddSymmSiftingBackward(table, move_down,
00689 initial_size);
00690
00691 }
00692 if (!result)
00693 goto cuddZddSymmSiftingAuxOutOfMem;
00694 }
00695 else if (x == x_high) {
00696
00697 while ((unsigned) x < table->subtableZ[x].next)
00698 x = table->subtableZ[x].next;
00699 x = table->subtableZ[x].next;
00700
00701 i = x;
00702 while ((unsigned) i < table->subtableZ[i].next) {
00703 i = table->subtableZ[i].next;
00704 }
00705 init_group_size = i - x + 1;
00706
00707 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00708
00709 if (move_up == ZDD_MV_OOM)
00710 goto cuddZddSymmSiftingAuxOutOfMem;
00711
00712 if (move_up == NULL ||
00713 table->subtableZ[move_up->x].next != move_up->x) {
00714
00715
00716 if (move_up != NULL)
00717 x = move_up->x;
00718 else {
00719 while ((unsigned) x < table->subtableZ[x].next)
00720 x = table->subtableZ[x].next;
00721 }
00722 i = table->subtableZ[x].next;
00723 final_group_size = x - i + 1;
00724
00725 if (init_group_size == final_group_size) {
00726
00727
00728 result = cuddZddSymmSiftingBackward(table, move_up,
00729 initial_size);
00730 }
00731 else {
00732 initial_size = table->keysZ;
00733 move_down = cuddZddSymmSifting_down(table, x, x_high,
00734 initial_size);
00735 result = cuddZddSymmSiftingBackward(table, move_down,
00736 initial_size);
00737 }
00738 }
00739 else {
00740 result = cuddZddSymmSiftingBackward(table, move_up,
00741 initial_size);
00742
00743 }
00744 if (!result)
00745 goto cuddZddSymmSiftingAuxOutOfMem;
00746 }
00747 else if ((x - x_low) > (x_high - x)) {
00748
00749
00750 while ((unsigned) x < table->subtableZ[x].next)
00751 x = table->subtableZ[x].next;
00752
00753 move_down = cuddZddSymmSifting_down(table, x, x_high,
00754 initial_size);
00755
00756 if (move_down == ZDD_MV_OOM)
00757 goto cuddZddSymmSiftingAuxOutOfMem;
00758
00759 if (move_down != NULL) {
00760 x = move_down->y;
00761 }
00762 else {
00763 x = table->subtableZ[x].next;
00764 }
00765 i = x;
00766 while ((unsigned) i < table->subtableZ[i].next) {
00767 i = table->subtableZ[i].next;
00768 }
00769 init_group_size = i - x + 1;
00770
00771 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00772 if (move_up == ZDD_MV_OOM)
00773 goto cuddZddSymmSiftingAuxOutOfMem;
00774
00775 if (move_up == NULL ||
00776 table->subtableZ[move_up->x].next != move_up->x) {
00777
00778
00779 if (move_up != NULL) {
00780 x = move_up->x;
00781 }
00782 else {
00783 while ((unsigned) x < table->subtableZ[x].next)
00784 x = table->subtableZ[x].next;
00785 }
00786 i = table->subtableZ[x].next;
00787 final_group_size = x - i + 1;
00788
00789 if (init_group_size == final_group_size) {
00790
00791
00792 result = cuddZddSymmSiftingBackward(table, move_up,
00793 initial_size);
00794 }
00795 else {
00796 while (move_down != NULL) {
00797 move = move_down->next;
00798 cuddDeallocMove(table, move_down);
00799 move_down = move;
00800 }
00801 initial_size = table->keysZ;
00802 move_down = cuddZddSymmSifting_down(table, x, x_high,
00803 initial_size);
00804 result = cuddZddSymmSiftingBackward(table, move_down,
00805 initial_size);
00806 }
00807 }
00808 else {
00809 result = cuddZddSymmSiftingBackward(table, move_up,
00810 initial_size);
00811
00812 }
00813 if (!result)
00814 goto cuddZddSymmSiftingAuxOutOfMem;
00815 }
00816 else {
00817
00818 while ((unsigned) x < table->subtableZ[x].next)
00819 x = table->subtableZ[x].next;
00820 x = table->subtableZ[x].next;
00821
00822 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
00823
00824 if (move_up == ZDD_MV_OOM)
00825 goto cuddZddSymmSiftingAuxOutOfMem;
00826
00827 if (move_up != NULL) {
00828 x = move_up->x;
00829 }
00830 else {
00831 while ((unsigned) x < table->subtableZ[x].next)
00832 x = table->subtableZ[x].next;
00833 }
00834 i = table->subtableZ[x].next;
00835 init_group_size = x - i + 1;
00836
00837 move_down = cuddZddSymmSifting_down(table, x, x_high,
00838 initial_size);
00839 if (move_down == ZDD_MV_OOM)
00840 goto cuddZddSymmSiftingAuxOutOfMem;
00841
00842 if (move_down == NULL ||
00843 table->subtableZ[move_down->y].next != move_down->y) {
00844
00845
00846 if (move_down != NULL) {
00847 x = move_down->y;
00848 }
00849 else {
00850 x = table->subtableZ[x].next;
00851 }
00852 i = x;
00853 while ((unsigned) i < table->subtableZ[i].next) {
00854 i = table->subtableZ[i].next;
00855 }
00856 final_group_size = i - x + 1;
00857
00858 if (init_group_size == final_group_size) {
00859
00860
00861 result = cuddZddSymmSiftingBackward(table, move_down,
00862 initial_size);
00863 }
00864 else {
00865 while (move_up != NULL) {
00866 move = move_up->next;
00867 cuddDeallocMove(table, move_up);
00868 move_up = move;
00869 }
00870 initial_size = table->keysZ;
00871 move_up = cuddZddSymmSifting_up(table, x, x_low,
00872 initial_size);
00873 result = cuddZddSymmSiftingBackward(table, move_up,
00874 initial_size);
00875 }
00876 }
00877 else {
00878 result = cuddZddSymmSiftingBackward(table, move_down,
00879 initial_size);
00880
00881 }
00882 if (!result)
00883 goto cuddZddSymmSiftingAuxOutOfMem;
00884 }
00885
00886 while (move_down != NULL) {
00887 move = move_down->next;
00888 cuddDeallocMove(table, move_down);
00889 move_down = move;
00890 }
00891 while (move_up != NULL) {
00892 move = move_up->next;
00893 cuddDeallocMove(table, move_up);
00894 move_up = move;
00895 }
00896
00897 return(1);
00898
00899 cuddZddSymmSiftingAuxOutOfMem:
00900 if (move_down != ZDD_MV_OOM) {
00901 while (move_down != NULL) {
00902 move = move_down->next;
00903 cuddDeallocMove(table, move_down);
00904 move_down = move;
00905 }
00906 }
00907 if (move_up != ZDD_MV_OOM) {
00908 while (move_up != NULL) {
00909 move = move_up->next;
00910 cuddDeallocMove(table, move_up);
00911 move_up = move;
00912 }
00913 }
00914
00915 return(0);
00916
00917 }
00918
00919
00936 static int
00937 cuddZddSymmSiftingConvAux(
00938 DdManager * table,
00939 int x,
00940 int x_low,
00941 int x_high)
00942 {
00943 Move *move;
00944 Move *move_up;
00945 Move *move_down;
00946 int initial_size;
00947 int result;
00948 int i;
00949 int init_group_size, final_group_size;
00950
00951 initial_size = table->keysZ;
00952
00953 move_down = NULL;
00954 move_up = NULL;
00955
00956 if (x == x_low) {
00957 i = table->subtableZ[x].next;
00958 init_group_size = x - i + 1;
00959
00960 move_down = cuddZddSymmSifting_down(table, x, x_high,
00961 initial_size);
00962
00963 if (move_down == ZDD_MV_OOM)
00964 goto cuddZddSymmSiftingConvAuxOutOfMem;
00965
00966 if (move_down == NULL ||
00967 table->subtableZ[move_down->y].next != move_down->y) {
00968
00969
00970 if (move_down != NULL)
00971 x = move_down->y;
00972 else {
00973 while ((unsigned) x < table->subtableZ[x].next)
00974 x = table->subtableZ[x].next;
00975 x = table->subtableZ[x].next;
00976 }
00977 i = x;
00978 while ((unsigned) i < table->subtableZ[i].next) {
00979 i = table->subtableZ[i].next;
00980 }
00981 final_group_size = i - x + 1;
00982
00983 if (init_group_size == final_group_size) {
00984
00985
00986 result = cuddZddSymmSiftingBackward(table, move_down,
00987 initial_size);
00988 }
00989 else {
00990 initial_size = table->keysZ;
00991 move_up = cuddZddSymmSifting_up(table, x, x_low,
00992 initial_size);
00993 result = cuddZddSymmSiftingBackward(table, move_up,
00994 initial_size);
00995 }
00996 }
00997 else {
00998 result = cuddZddSymmSiftingBackward(table, move_down,
00999 initial_size);
01000
01001 }
01002 if (!result)
01003 goto cuddZddSymmSiftingConvAuxOutOfMem;
01004 }
01005 else if (x == x_high) {
01006
01007 while ((unsigned) x < table->subtableZ[x].next)
01008 x = table->subtableZ[x].next;
01009 x = table->subtableZ[x].next;
01010
01011 i = x;
01012 while ((unsigned) i < table->subtableZ[i].next) {
01013 i = table->subtableZ[i].next;
01014 }
01015 init_group_size = i - x + 1;
01016
01017 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01018
01019 if (move_up == ZDD_MV_OOM)
01020 goto cuddZddSymmSiftingConvAuxOutOfMem;
01021
01022 if (move_up == NULL ||
01023 table->subtableZ[move_up->x].next != move_up->x) {
01024
01025
01026 if (move_up != NULL)
01027 x = move_up->x;
01028 else {
01029 while ((unsigned) x < table->subtableZ[x].next)
01030 x = table->subtableZ[x].next;
01031 }
01032 i = table->subtableZ[x].next;
01033 final_group_size = x - i + 1;
01034
01035 if (init_group_size == final_group_size) {
01036
01037
01038 result = cuddZddSymmSiftingBackward(table, move_up,
01039 initial_size);
01040 }
01041 else {
01042 initial_size = table->keysZ;
01043 move_down = cuddZddSymmSifting_down(table, x, x_high,
01044 initial_size);
01045 result = cuddZddSymmSiftingBackward(table, move_down,
01046 initial_size);
01047 }
01048 }
01049 else {
01050 result = cuddZddSymmSiftingBackward(table, move_up,
01051 initial_size);
01052
01053 }
01054 if (!result)
01055 goto cuddZddSymmSiftingConvAuxOutOfMem;
01056 }
01057 else if ((x - x_low) > (x_high - x)) {
01058
01059 move_down = cuddZddSymmSifting_down(table, x, x_high,
01060 initial_size);
01061
01062 if (move_down == ZDD_MV_OOM)
01063 goto cuddZddSymmSiftingConvAuxOutOfMem;
01064
01065 if (move_down != NULL) {
01066 x = move_down->y;
01067 }
01068 else {
01069 while ((unsigned) x < table->subtableZ[x].next)
01070 x = table->subtableZ[x].next;
01071 x = table->subtableZ[x].next;
01072 }
01073 i = x;
01074 while ((unsigned) i < table->subtableZ[i].next) {
01075 i = table->subtableZ[i].next;
01076 }
01077 init_group_size = i - x + 1;
01078
01079 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01080 if (move_up == ZDD_MV_OOM)
01081 goto cuddZddSymmSiftingConvAuxOutOfMem;
01082
01083 if (move_up == NULL ||
01084 table->subtableZ[move_up->x].next != move_up->x) {
01085
01086
01087 if (move_up != NULL) {
01088 x = move_up->x;
01089 }
01090 else {
01091 while ((unsigned) x < table->subtableZ[x].next)
01092 x = table->subtableZ[x].next;
01093 }
01094 i = table->subtableZ[x].next;
01095 final_group_size = x - i + 1;
01096
01097 if (init_group_size == final_group_size) {
01098
01099
01100 result = cuddZddSymmSiftingBackward(table, move_up,
01101 initial_size);
01102 }
01103 else {
01104 while (move_down != NULL) {
01105 move = move_down->next;
01106 cuddDeallocMove(table, move_down);
01107 move_down = move;
01108 }
01109 initial_size = table->keysZ;
01110 move_down = cuddZddSymmSifting_down(table, x, x_high,
01111 initial_size);
01112 result = cuddZddSymmSiftingBackward(table, move_down,
01113 initial_size);
01114 }
01115 }
01116 else {
01117 result = cuddZddSymmSiftingBackward(table, move_up,
01118 initial_size);
01119
01120 }
01121 if (!result)
01122 goto cuddZddSymmSiftingConvAuxOutOfMem;
01123 }
01124 else {
01125
01126 x = table->subtableZ[x].next;
01127
01128 move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
01129
01130 if (move_up == ZDD_MV_OOM)
01131 goto cuddZddSymmSiftingConvAuxOutOfMem;
01132
01133 if (move_up != NULL) {
01134 x = move_up->x;
01135 }
01136 else {
01137 while ((unsigned) x < table->subtableZ[x].next)
01138 x = table->subtableZ[x].next;
01139 }
01140 i = table->subtableZ[x].next;
01141 init_group_size = x - i + 1;
01142
01143 move_down = cuddZddSymmSifting_down(table, x, x_high,
01144 initial_size);
01145 if (move_down == ZDD_MV_OOM)
01146 goto cuddZddSymmSiftingConvAuxOutOfMem;
01147
01148 if (move_down == NULL ||
01149 table->subtableZ[move_down->y].next != move_down->y) {
01150
01151
01152 if (move_down != NULL) {
01153 x = move_down->y;
01154 }
01155 else {
01156 while ((unsigned) x < table->subtableZ[x].next)
01157 x = table->subtableZ[x].next;
01158 x = table->subtableZ[x].next;
01159 }
01160 i = x;
01161 while ((unsigned) i < table->subtableZ[i].next) {
01162 i = table->subtableZ[i].next;
01163 }
01164 final_group_size = i - x + 1;
01165
01166 if (init_group_size == final_group_size) {
01167
01168
01169 result = cuddZddSymmSiftingBackward(table, move_down,
01170 initial_size);
01171 }
01172 else {
01173 while (move_up != NULL) {
01174 move = move_up->next;
01175 cuddDeallocMove(table, move_up);
01176 move_up = move;
01177 }
01178 initial_size = table->keysZ;
01179 move_up = cuddZddSymmSifting_up(table, x, x_low,
01180 initial_size);
01181 result = cuddZddSymmSiftingBackward(table, move_up,
01182 initial_size);
01183 }
01184 }
01185 else {
01186 result = cuddZddSymmSiftingBackward(table, move_down,
01187 initial_size);
01188
01189 }
01190 if (!result)
01191 goto cuddZddSymmSiftingConvAuxOutOfMem;
01192 }
01193
01194 while (move_down != NULL) {
01195 move = move_down->next;
01196 cuddDeallocMove(table, move_down);
01197 move_down = move;
01198 }
01199 while (move_up != NULL) {
01200 move = move_up->next;
01201 cuddDeallocMove(table, move_up);
01202 move_up = move;
01203 }
01204
01205 return(1);
01206
01207 cuddZddSymmSiftingConvAuxOutOfMem:
01208 if (move_down != ZDD_MV_OOM) {
01209 while (move_down != NULL) {
01210 move = move_down->next;
01211 cuddDeallocMove(table, move_down);
01212 move_down = move;
01213 }
01214 }
01215 if (move_up != ZDD_MV_OOM) {
01216 while (move_up != NULL) {
01217 move = move_up->next;
01218 cuddDeallocMove(table, move_up);
01219 move_up = move;
01220 }
01221 }
01222
01223 return(0);
01224
01225 }
01226
01227
01245 static Move *
01246 cuddZddSymmSifting_up(
01247 DdManager * table,
01248 int x,
01249 int x_low,
01250 int initial_size)
01251 {
01252 Move *moves;
01253 Move *move;
01254 int y;
01255 int size;
01256 int limit_size = initial_size;
01257 int i, gytop;
01258
01259 moves = NULL;
01260 y = cuddZddNextLow(table, x);
01261 while (y >= x_low) {
01262 gytop = table->subtableZ[y].next;
01263 if (cuddZddSymmCheck(table, y, x)) {
01264
01265 table->subtableZ[y].next = x;
01266 i = table->subtableZ[x].next;
01267 while (table->subtableZ[i].next != (unsigned) x)
01268 i = table->subtableZ[i].next;
01269 table->subtableZ[i].next = gytop;
01270 }
01271 else if ((table->subtableZ[x].next == (unsigned) x) &&
01272 (table->subtableZ[y].next == (unsigned) y)) {
01273
01274 size = cuddZddSwapInPlace(table, y, x);
01275 if (size == 0)
01276 goto cuddZddSymmSifting_upOutOfMem;
01277 move = (Move *)cuddDynamicAllocNode(table);
01278 if (move == NULL)
01279 goto cuddZddSymmSifting_upOutOfMem;
01280 move->x = y;
01281 move->y = x;
01282 move->size = size;
01283 move->next = moves;
01284 moves = move;
01285 if ((double)size >
01286 (double)limit_size * table->maxGrowth)
01287 return(moves);
01288 if (size < limit_size)
01289 limit_size = size;
01290 }
01291 else {
01292 size = zdd_group_move(table, y, x, &moves);
01293 if ((double)size >
01294 (double)limit_size * table->maxGrowth)
01295 return(moves);
01296 if (size < limit_size)
01297 limit_size = size;
01298 }
01299 x = gytop;
01300 y = cuddZddNextLow(table, x);
01301 }
01302
01303 return(moves);
01304
01305 cuddZddSymmSifting_upOutOfMem:
01306 while (moves != NULL) {
01307 move = moves->next;
01308 cuddDeallocMove(table, moves);
01309 moves = move;
01310 }
01311 return(ZDD_MV_OOM);
01312
01313 }
01314
01315
01333 static Move *
01334 cuddZddSymmSifting_down(
01335 DdManager * table,
01336 int x,
01337 int x_high,
01338 int initial_size)
01339 {
01340 Move *moves;
01341 Move *move;
01342 int y;
01343 int size;
01344 int limit_size = initial_size;
01345 int i, gxtop, gybot;
01346
01347 moves = NULL;
01348 y = cuddZddNextHigh(table, x);
01349 while (y <= x_high) {
01350 gybot = table->subtableZ[y].next;
01351 while (table->subtableZ[gybot].next != (unsigned) y)
01352 gybot = table->subtableZ[gybot].next;
01353 if (cuddZddSymmCheck(table, x, y)) {
01354
01355 gxtop = table->subtableZ[x].next;
01356 table->subtableZ[x].next = y;
01357 i = table->subtableZ[y].next;
01358 while (table->subtableZ[i].next != (unsigned) y)
01359 i = table->subtableZ[i].next;
01360 table->subtableZ[i].next = gxtop;
01361 }
01362 else if ((table->subtableZ[x].next == (unsigned) x) &&
01363 (table->subtableZ[y].next == (unsigned) y)) {
01364
01365 size = cuddZddSwapInPlace(table, x, y);
01366 if (size == 0)
01367 goto cuddZddSymmSifting_downOutOfMem;
01368 move = (Move *)cuddDynamicAllocNode(table);
01369 if (move == NULL)
01370 goto cuddZddSymmSifting_downOutOfMem;
01371 move->x = x;
01372 move->y = y;
01373 move->size = size;
01374 move->next = moves;
01375 moves = move;
01376 if ((double)size >
01377 (double)limit_size * table->maxGrowth)
01378 return(moves);
01379 if (size < limit_size)
01380 limit_size = size;
01381 x = y;
01382 y = cuddZddNextHigh(table, x);
01383 }
01384 else {
01385 size = zdd_group_move(table, x, y, &moves);
01386 if ((double)size >
01387 (double)limit_size * table->maxGrowth)
01388 return(moves);
01389 if (size < limit_size)
01390 limit_size = size;
01391 }
01392 x = gybot;
01393 y = cuddZddNextHigh(table, x);
01394 }
01395
01396 return(moves);
01397
01398 cuddZddSymmSifting_downOutOfMem:
01399 while (moves != NULL) {
01400 move = moves->next;
01401 cuddDeallocMove(table, moves);
01402 moves = move;
01403 }
01404 return(ZDD_MV_OOM);
01405
01406 }
01407
01408
01424 static int
01425 cuddZddSymmSiftingBackward(
01426 DdManager * table,
01427 Move * moves,
01428 int size)
01429 {
01430 int i;
01431 int i_best;
01432 Move *move;
01433 int res;
01434
01435 i_best = -1;
01436 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01437 if (move->size < size) {
01438 i_best = i;
01439 size = move->size;
01440 }
01441 }
01442
01443 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01444 if (i == i_best) break;
01445 if ((table->subtableZ[move->x].next == move->x) &&
01446 (table->subtableZ[move->y].next == move->y)) {
01447 res = cuddZddSwapInPlace(table, move->x, move->y);
01448 if (!res) return(0);
01449 }
01450 else {
01451 res = zdd_group_move_backward(table, move->x, move->y);
01452 }
01453 if (i_best == -1 && res == size)
01454 break;
01455 }
01456
01457 return(1);
01458
01459 }
01460
01461
01476 static int
01477 zdd_group_move(
01478 DdManager * table,
01479 int x,
01480 int y,
01481 Move ** moves)
01482 {
01483 Move *move;
01484 int size;
01485 int i, temp, gxtop, gxbot, gybot, yprev;
01486 int swapx, swapy;
01487
01488 #ifdef DD_DEBUG
01489 assert(x < y);
01490 #endif
01491
01492 gxtop = table->subtableZ[x].next;
01493 gxbot = x;
01494 gybot = table->subtableZ[y].next;
01495 while (table->subtableZ[gybot].next != (unsigned) y)
01496 gybot = table->subtableZ[gybot].next;
01497 yprev = gybot;
01498
01499 while (x <= y) {
01500 while (y > gxtop) {
01501
01502 temp = table->subtableZ[x].next;
01503 if (temp == x)
01504 temp = y;
01505 i = gxtop;
01506 for (;;) {
01507 if (table->subtableZ[i].next == (unsigned) x) {
01508 table->subtableZ[i].next = y;
01509 break;
01510 } else {
01511 i = table->subtableZ[i].next;
01512 }
01513 }
01514 if (table->subtableZ[y].next != (unsigned) y) {
01515 table->subtableZ[x].next = table->subtableZ[y].next;
01516 } else {
01517 table->subtableZ[x].next = x;
01518 }
01519
01520 if (yprev != y) {
01521 table->subtableZ[yprev].next = x;
01522 } else {
01523 yprev = x;
01524 }
01525 table->subtableZ[y].next = temp;
01526
01527 size = cuddZddSwapInPlace(table, x, y);
01528 if (size == 0)
01529 goto zdd_group_moveOutOfMem;
01530 swapx = x;
01531 swapy = y;
01532 y = x;
01533 x--;
01534 }
01535
01536
01537 if (table->subtableZ[y].next <= (unsigned) y) {
01538 gybot = y;
01539 } else {
01540 y = table->subtableZ[y].next;
01541 }
01542
01543 yprev = gxtop;
01544 gxtop++;
01545 gxbot++;
01546 x = gxbot;
01547 }
01548 move = (Move *)cuddDynamicAllocNode(table);
01549 if (move == NULL)
01550 goto zdd_group_moveOutOfMem;
01551 move->x = swapx;
01552 move->y = swapy;
01553 move->size = table->keysZ;
01554 move->next = *moves;
01555 *moves = move;
01556
01557 return(table->keysZ);
01558
01559 zdd_group_moveOutOfMem:
01560 while (*moves != NULL) {
01561 move = (*moves)->next;
01562 cuddDeallocMove(table, *moves);
01563 *moves = move;
01564 }
01565 return(0);
01566
01567 }
01568
01569
01583 static int
01584 zdd_group_move_backward(
01585 DdManager * table,
01586 int x,
01587 int y)
01588 {
01589 int size;
01590 int i, temp, gxtop, gxbot, gybot, yprev;
01591
01592 #ifdef DD_DEBUG
01593 assert(x < y);
01594 #endif
01595
01596 gxtop = table->subtableZ[x].next;
01597 gxbot = x;
01598 gybot = table->subtableZ[y].next;
01599 while (table->subtableZ[gybot].next != (unsigned) y)
01600 gybot = table->subtableZ[gybot].next;
01601 yprev = gybot;
01602
01603 while (x <= y) {
01604 while (y > gxtop) {
01605
01606 temp = table->subtableZ[x].next;
01607 if (temp == x)
01608 temp = y;
01609 i = gxtop;
01610 for (;;) {
01611 if (table->subtableZ[i].next == (unsigned) x) {
01612 table->subtableZ[i].next = y;
01613 break;
01614 } else {
01615 i = table->subtableZ[i].next;
01616 }
01617 }
01618 if (table->subtableZ[y].next != (unsigned) y) {
01619 table->subtableZ[x].next = table->subtableZ[y].next;
01620 } else {
01621 table->subtableZ[x].next = x;
01622 }
01623
01624 if (yprev != y) {
01625 table->subtableZ[yprev].next = x;
01626 } else {
01627 yprev = x;
01628 }
01629 table->subtableZ[y].next = temp;
01630
01631 size = cuddZddSwapInPlace(table, x, y);
01632 if (size == 0)
01633 return(0);
01634 y = x;
01635 x--;
01636 }
01637
01638
01639 if (table->subtableZ[y].next <= (unsigned) y) {
01640 gybot = y;
01641 } else {
01642 y = table->subtableZ[y].next;
01643 }
01644
01645 yprev = gxtop;
01646 gxtop++;
01647 gxbot++;
01648 x = gxbot;
01649 }
01650
01651 return(size);
01652
01653 }
01654
01655
01666 static void
01667 cuddZddSymmSummary(
01668 DdManager * table,
01669 int lower,
01670 int upper,
01671 int * symvars,
01672 int * symgroups)
01673 {
01674 int i,x,gbot;
01675 int TotalSymm = 0;
01676 int TotalSymmGroups = 0;
01677
01678 for (i = lower; i <= upper; i++) {
01679 if (table->subtableZ[i].next != (unsigned) i) {
01680 TotalSymmGroups++;
01681 x = i;
01682 do {
01683 TotalSymm++;
01684 gbot = x;
01685 x = table->subtableZ[x].next;
01686 } while (x != i);
01687 #ifdef DD_DEBUG
01688 assert(table->subtableZ[gbot].next == (unsigned) i);
01689 #endif
01690 i = gbot;
01691 }
01692 }
01693 *symvars = TotalSymm;
01694 *symgroups = TotalSymmGroups;
01695
01696 return;
01697
01698 }
01699