00001
00076 #include "util.h"
00077 #include "cuddInt.h"
00078
00079
00080
00081
00082
00083 #define DD_MAX_SUBTABLE_SPARSITY 8
00084 #define DD_SHRINK_FACTOR 2
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 #ifndef lint
00101 static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.47 2004/08/13 18:04:53 fabio Exp $";
00102 #endif
00103
00104 int *zdd_entry;
00105
00106 int zddTotalNumberSwapping;
00107
00108 static DdNode *empty;
00109
00110
00111
00112
00113
00114
00115
00118
00119
00120
00121
00122 static Move * zddSwapAny (DdManager *table, int x, int y);
00123 static int cuddZddSiftingAux (DdManager *table, int x, int x_low, int x_high);
00124 static Move * cuddZddSiftingUp (DdManager *table, int x, int x_low, int initial_size);
00125 static Move * cuddZddSiftingDown (DdManager *table, int x, int x_high, int initial_size);
00126 static int cuddZddSiftingBackward (DdManager *table, Move *moves, int size);
00127 static void zddReorderPreprocess (DdManager *table);
00128 static int zddReorderPostprocess (DdManager *table);
00129 static int zddShuffle (DdManager *table, int *permutation);
00130 static int zddSiftUp (DdManager *table, int x, int xLow);
00131 static void zddFixTree (DdManager *table, MtrNode *treenode);
00132
00136
00137
00138
00139
00140
00166 int
00167 Cudd_zddReduceHeap(
00168 DdManager * table ,
00169 Cudd_ReorderingType heuristic ,
00170 int minsize )
00171 {
00172 DdHook *hook;
00173 int result;
00174 unsigned int nextDyn;
00175 #ifdef DD_STATS
00176 unsigned int initialSize;
00177 unsigned int finalSize;
00178 #endif
00179 long localTime;
00180
00181
00182 if (table->keysZ - table->deadZ < (unsigned) minsize)
00183 return(1);
00184
00185 if (heuristic == CUDD_REORDER_SAME) {
00186 heuristic = table->autoMethodZ;
00187 }
00188 if (heuristic == CUDD_REORDER_NONE) {
00189 return(1);
00190 }
00191
00192
00193
00194
00195 table->reorderings++;
00196 empty = table->zero;
00197
00198 localTime = util_cpu_time();
00199
00200
00201 hook = table->preReorderingHook;
00202 while (hook != NULL) {
00203 int res = (hook->f)(table, "ZDD", (void *)heuristic);
00204 if (res == 0) return(0);
00205 hook = hook->next;
00206 }
00207
00208
00209 zddReorderPreprocess(table);
00210 zddTotalNumberSwapping = 0;
00211
00212 #ifdef DD_STATS
00213 initialSize = table->keysZ;
00214
00215 switch(heuristic) {
00216 case CUDD_REORDER_RANDOM:
00217 case CUDD_REORDER_RANDOM_PIVOT:
00218 (void) fprintf(table->out,"#:I_RANDOM ");
00219 break;
00220 case CUDD_REORDER_SIFT:
00221 case CUDD_REORDER_SIFT_CONVERGE:
00222 case CUDD_REORDER_SYMM_SIFT:
00223 case CUDD_REORDER_SYMM_SIFT_CONV:
00224 (void) fprintf(table->out,"#:I_SIFTING ");
00225 break;
00226 case CUDD_REORDER_LINEAR:
00227 case CUDD_REORDER_LINEAR_CONVERGE:
00228 (void) fprintf(table->out,"#:I_LINSIFT ");
00229 break;
00230 default:
00231 (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
00232 return(0);
00233 }
00234 (void) fprintf(table->out,"%8d: initial size",initialSize);
00235 #endif
00236
00237 result = cuddZddTreeSifting(table,heuristic);
00238
00239 #ifdef DD_STATS
00240 (void) fprintf(table->out,"\n");
00241 finalSize = table->keysZ;
00242 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
00243 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
00244 ((double)(util_cpu_time() - localTime)/1000.0));
00245 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
00246 zddTotalNumberSwapping);
00247 #endif
00248
00249 if (result == 0)
00250 return(0);
00251
00252 if (!zddReorderPostprocess(table))
00253 return(0);
00254
00255 if (table->realignZ) {
00256 if (!cuddBddAlignToZdd(table))
00257 return(0);
00258 }
00259
00260 nextDyn = table->keysZ * DD_DYN_RATIO;
00261 if (table->reorderings < 20 || nextDyn > table->nextDyn)
00262 table->nextDyn = nextDyn;
00263 else
00264 table->nextDyn += 20;
00265
00266 table->reordered = 1;
00267
00268
00269 hook = table->postReorderingHook;
00270 while (hook != NULL) {
00271 int res = (hook->f)(table, "ZDD", (void *)localTime);
00272 if (res == 0) return(0);
00273 hook = hook->next;
00274 }
00275
00276 table->reordTime += util_cpu_time() - localTime;
00277
00278 return(result);
00279
00280 }
00281
00282
00299 int
00300 Cudd_zddShuffleHeap(
00301 DdManager * table ,
00302 int * permutation )
00303 {
00304
00305 int result;
00306
00307 empty = table->zero;
00308 zddReorderPreprocess(table);
00309
00310 result = zddShuffle(table,permutation);
00311
00312 if (!zddReorderPostprocess(table)) return(0);
00313
00314 return(result);
00315
00316 }
00317
00318
00319
00320
00321
00322
00323
00347 int
00348 cuddZddAlignToBdd(
00349 DdManager * table )
00350 {
00351 int *invpermZ;
00352 int M;
00353 int i,j;
00354 int result;
00355
00356
00357 if (table->sizeZ == 0)
00358 return(1);
00359
00360 empty = table->zero;
00361 M = table->sizeZ / table->size;
00362
00363
00364
00365 if (M * table->size != table->sizeZ)
00366 return(0);
00367
00368 invpermZ = ALLOC(int,table->sizeZ);
00369 if (invpermZ == NULL) {
00370 table->errorCode = CUDD_MEMORY_OUT;
00371 return(0);
00372 }
00373 for (i = 0; i < table->size; i++) {
00374 int index = table->invperm[i];
00375 int indexZ = index * M;
00376 int levelZ = table->permZ[indexZ];
00377 levelZ = (levelZ / M) * M;
00378 for (j = 0; j < M; j++) {
00379 invpermZ[M * i + j] = table->invpermZ[levelZ + j];
00380 }
00381 }
00382
00383
00384
00385 cuddGarbageCollect(table,0);
00386
00387 result = zddShuffle(table, invpermZ);
00388 FREE(invpermZ);
00389
00390 zddFixTree(table,table->treeZ);
00391 return(result);
00392
00393 }
00394
00395
00408 int
00409 cuddZddNextHigh(
00410 DdManager * table,
00411 int x)
00412 {
00413 return(x + 1);
00414
00415 }
00416
00417
00430 int
00431 cuddZddNextLow(
00432 DdManager * table,
00433 int x)
00434 {
00435 return(x - 1);
00436
00437 }
00438
00439
00454 int
00455 cuddZddUniqueCompare(
00456 int * ptr_x,
00457 int * ptr_y)
00458 {
00459 return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
00460
00461 }
00462
00463
00479 int
00480 cuddZddSwapInPlace(
00481 DdManager * table,
00482 int x,
00483 int y)
00484 {
00485 DdNodePtr *xlist, *ylist;
00486 int xindex, yindex;
00487 int xslots, yslots;
00488 int xshift, yshift;
00489 int oldxkeys, oldykeys;
00490 int newxkeys, newykeys;
00491 int i;
00492 int posn;
00493 DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
00494 DdNode *newf1, *newf0, *next;
00495 DdNodePtr g, *lastP, *previousP;
00496
00497 #ifdef DD_DEBUG
00498 assert(x < y);
00499 assert(cuddZddNextHigh(table,x) == y);
00500 assert(table->subtableZ[x].keys != 0);
00501 assert(table->subtableZ[y].keys != 0);
00502 assert(table->subtableZ[x].dead == 0);
00503 assert(table->subtableZ[y].dead == 0);
00504 #endif
00505
00506 zddTotalNumberSwapping++;
00507
00508
00509 xindex = table->invpermZ[x];
00510 xlist = table->subtableZ[x].nodelist;
00511 oldxkeys = table->subtableZ[x].keys;
00512 xslots = table->subtableZ[x].slots;
00513 xshift = table->subtableZ[x].shift;
00514 newxkeys = 0;
00515
00516 yindex = table->invpermZ[y];
00517 ylist = table->subtableZ[y].nodelist;
00518 oldykeys = table->subtableZ[y].keys;
00519 yslots = table->subtableZ[y].slots;
00520 yshift = table->subtableZ[y].shift;
00521 newykeys = oldykeys;
00522
00523
00524
00525
00526
00527
00528
00529 g = NULL;
00530 lastP = &g;
00531 for (i = 0; i < xslots; i++) {
00532 previousP = &(xlist[i]);
00533 f = *previousP;
00534 while (f != NULL) {
00535 next = f->next;
00536 f1 = cuddT(f); f0 = cuddE(f);
00537 if ((f1->index != (DdHalfWord) yindex) &&
00538 (f0->index != (DdHalfWord) yindex)) {
00539 newxkeys++;
00540 *previousP = f;
00541 previousP = &(f->next);
00542 } else {
00543 f->index = yindex;
00544 *lastP = f;
00545 lastP = &(f->next);
00546 }
00547 f = next;
00548 }
00549 *previousP = NULL;
00550 }
00551 *lastP = NULL;
00552
00553
00554 #ifdef DD_COUNT
00555 table->swapSteps += oldxkeys - newxkeys;
00556 #endif
00557
00558
00559
00560
00561 f = g;
00562 while (f != NULL) {
00563 next = f->next;
00564
00565 f1 = cuddT(f);
00566 if ((int) f1->index == yindex) {
00567 f11 = cuddT(f1); f10 = cuddE(f1);
00568 } else {
00569 f11 = empty; f10 = f1;
00570 }
00571 f0 = cuddE(f);
00572 if ((int) f0->index == yindex) {
00573 f01 = cuddT(f0); f00 = cuddE(f0);
00574 } else {
00575 f01 = empty; f00 = f0;
00576 }
00577
00578
00579 cuddSatDec(f1->ref);
00580
00581 if (f11 == empty) {
00582 if (f01 != empty) {
00583 newf1 = f01;
00584 cuddSatInc(newf1->ref);
00585 }
00586
00587
00588
00589 } else {
00590
00591 posn = ddHash(f11, f01, xshift);
00592
00593 newf1 = xlist[posn];
00594 while (newf1 != NULL) {
00595 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
00596 cuddSatInc(newf1->ref);
00597 break;
00598 }
00599 newf1 = newf1->next;
00600 }
00601 if (newf1 == NULL) {
00602 newf1 = cuddDynamicAllocNode(table);
00603 if (newf1 == NULL)
00604 goto zddSwapOutOfMem;
00605 newf1->index = xindex; newf1->ref = 1;
00606 cuddT(newf1) = f11;
00607 cuddE(newf1) = f01;
00608
00609
00610
00611 newxkeys++;
00612 newf1->next = xlist[posn];
00613 xlist[posn] = newf1;
00614 cuddSatInc(f11->ref);
00615 cuddSatInc(f01->ref);
00616 }
00617 }
00618 cuddT(f) = newf1;
00619
00620
00621
00622 cuddSatDec(f0->ref);
00623
00624 if (f10 == empty) {
00625 newf0 = f00;
00626 cuddSatInc(newf0->ref);
00627 } else {
00628
00629 posn = ddHash(f10, f00, xshift);
00630
00631 newf0 = xlist[posn];
00632 while (newf0 != NULL) {
00633 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
00634 cuddSatInc(newf0->ref);
00635 break;
00636 }
00637 newf0 = newf0->next;
00638 }
00639 if (newf0 == NULL) {
00640 newf0 = cuddDynamicAllocNode(table);
00641 if (newf0 == NULL)
00642 goto zddSwapOutOfMem;
00643 newf0->index = xindex; newf0->ref = 1;
00644 cuddT(newf0) = f10; cuddE(newf0) = f00;
00645
00646
00647
00648 newxkeys++;
00649 newf0->next = xlist[posn];
00650 xlist[posn] = newf0;
00651 cuddSatInc(f10->ref);
00652 cuddSatInc(f00->ref);
00653 }
00654 }
00655 cuddE(f) = newf0;
00656
00657
00658
00659
00660
00661 posn = ddHash(newf1, newf0, yshift);
00662 newykeys++;
00663 f->next = ylist[posn];
00664 ylist[posn] = f;
00665 f = next;
00666 }
00667
00668
00669
00670
00671 for (i = 0; i < yslots; i++) {
00672 previousP = &(ylist[i]);
00673 f = *previousP;
00674 while (f != NULL) {
00675 next = f->next;
00676 if (f->ref == 0) {
00677 cuddSatDec(cuddT(f)->ref);
00678 cuddSatDec(cuddE(f)->ref);
00679 cuddDeallocNode(table, f);
00680 newykeys--;
00681 } else {
00682 *previousP = f;
00683 previousP = &(f->next);
00684 }
00685 f = next;
00686 }
00687 *previousP = NULL;
00688 }
00689
00690
00691 table->subtableZ[x].nodelist = ylist;
00692 table->subtableZ[x].slots = yslots;
00693 table->subtableZ[x].shift = yshift;
00694 table->subtableZ[x].keys = newykeys;
00695 table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
00696
00697 table->subtableZ[y].nodelist = xlist;
00698 table->subtableZ[y].slots = xslots;
00699 table->subtableZ[y].shift = xshift;
00700 table->subtableZ[y].keys = newxkeys;
00701 table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
00702
00703 table->permZ[xindex] = y; table->permZ[yindex] = x;
00704 table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
00705
00706 table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
00707
00708
00709 table->univ[y] = cuddT(table->univ[x]);
00710
00711 return (table->keysZ);
00712
00713 zddSwapOutOfMem:
00714 (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
00715
00716 return (0);
00717
00718 }
00719
00720
00741 int
00742 cuddZddSwapping(
00743 DdManager * table,
00744 int lower,
00745 int upper,
00746 Cudd_ReorderingType heuristic)
00747 {
00748 int i, j;
00749 int max, keys;
00750 int nvars;
00751 int x, y;
00752 int iterate;
00753 int previousSize;
00754 Move *moves, *move;
00755 int pivot;
00756 int modulo;
00757 int result;
00758
00759 #ifdef DD_DEBUG
00760
00761 assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
00762 #endif
00763
00764 nvars = upper - lower + 1;
00765 iterate = nvars;
00766
00767 for (i = 0; i < iterate; i++) {
00768 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
00769
00770 for (max = -1, j = lower; j <= upper; j++) {
00771 if ((keys = table->subtableZ[j].keys) > max) {
00772 max = keys;
00773 pivot = j;
00774 }
00775 }
00776
00777 modulo = upper - pivot;
00778 if (modulo == 0) {
00779 y = pivot;
00780 } else {
00781
00782 y = pivot + 1 + (int) (Cudd_Random() % modulo);
00783 }
00784
00785 modulo = pivot - lower - 1;
00786 if (modulo < 1) {
00787 x = lower;
00788 } else {
00789 do {
00790 x = (int) Cudd_Random() % modulo;
00791 } while (x == y);
00792
00793
00794 }
00795 } else {
00796 x = (int) (Cudd_Random() % nvars) + lower;
00797 do {
00798 y = (int) (Cudd_Random() % nvars) + lower;
00799 } while (x == y);
00800 }
00801
00802 previousSize = table->keysZ;
00803 moves = zddSwapAny(table, x, y);
00804 if (moves == NULL)
00805 goto cuddZddSwappingOutOfMem;
00806
00807 result = cuddZddSiftingBackward(table, moves, previousSize);
00808 if (!result)
00809 goto cuddZddSwappingOutOfMem;
00810
00811 while (moves != NULL) {
00812 move = moves->next;
00813 cuddDeallocMove(table, moves);
00814 moves = move;
00815 }
00816 #ifdef DD_STATS
00817 if (table->keysZ < (unsigned) previousSize) {
00818 (void) fprintf(table->out,"-");
00819 } else if (table->keysZ > (unsigned) previousSize) {
00820 (void) fprintf(table->out,"+");
00821 } else {
00822 (void) fprintf(table->out,"=");
00823 }
00824 fflush(table->out);
00825 #endif
00826 }
00827
00828 return(1);
00829
00830 cuddZddSwappingOutOfMem:
00831 while (moves != NULL) {
00832 move = moves->next;
00833 cuddDeallocMove(table, moves);
00834 moves = move;
00835 }
00836 return(0);
00837
00838 }
00839
00840
00862 int
00863 cuddZddSifting(
00864 DdManager * table,
00865 int lower,
00866 int upper)
00867 {
00868 int i;
00869 int *var;
00870 int size;
00871 int x;
00872 int result;
00873 #ifdef DD_STATS
00874 int previousSize;
00875 #endif
00876
00877 size = table->sizeZ;
00878
00879
00880 var = NULL;
00881 zdd_entry = ALLOC(int, size);
00882 if (zdd_entry == NULL) {
00883 table->errorCode = CUDD_MEMORY_OUT;
00884 goto cuddZddSiftingOutOfMem;
00885 }
00886 var = ALLOC(int, size);
00887 if (var == NULL) {
00888 table->errorCode = CUDD_MEMORY_OUT;
00889 goto cuddZddSiftingOutOfMem;
00890 }
00891
00892 for (i = 0; i < size; i++) {
00893 x = table->permZ[i];
00894 zdd_entry[i] = table->subtableZ[x].keys;
00895 var[i] = i;
00896 }
00897
00898 qsort((void *)var, size, sizeof(int), (DD_QSFP)cuddZddUniqueCompare);
00899
00900
00901 for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
00902 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00903 break;
00904 x = table->permZ[var[i]];
00905 if (x < lower || x > upper) continue;
00906 #ifdef DD_STATS
00907 previousSize = table->keysZ;
00908 #endif
00909 result = cuddZddSiftingAux(table, x, lower, upper);
00910 if (!result)
00911 goto cuddZddSiftingOutOfMem;
00912 #ifdef DD_STATS
00913 if (table->keysZ < (unsigned) previousSize) {
00914 (void) fprintf(table->out,"-");
00915 } else if (table->keysZ > (unsigned) previousSize) {
00916 (void) fprintf(table->out,"+");
00917 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
00918 } else {
00919 (void) fprintf(table->out,"=");
00920 }
00921 fflush(table->out);
00922 #endif
00923 }
00924
00925 FREE(var);
00926 FREE(zdd_entry);
00927
00928 return(1);
00929
00930 cuddZddSiftingOutOfMem:
00931
00932 if (zdd_entry != NULL) FREE(zdd_entry);
00933 if (var != NULL) FREE(var);
00934
00935 return(0);
00936
00937 }
00938
00939
00940
00941
00942
00943
00944
00956 static Move *
00957 zddSwapAny(
00958 DdManager * table,
00959 int x,
00960 int y)
00961 {
00962 Move *move, *moves;
00963 int tmp, size;
00964 int x_ref, y_ref;
00965 int x_next, y_next;
00966 int limit_size;
00967
00968 if (x > y) {
00969 tmp = x; x = y; y = tmp;
00970 }
00971
00972 x_ref = x; y_ref = y;
00973
00974 x_next = cuddZddNextHigh(table, x);
00975 y_next = cuddZddNextLow(table, y);
00976 moves = NULL;
00977 limit_size = table->keysZ;
00978
00979 for (;;) {
00980 if (x_next == y_next) {
00981 size = cuddZddSwapInPlace(table, x, x_next);
00982 if (size == 0)
00983 goto zddSwapAnyOutOfMem;
00984 move = (Move *) cuddDynamicAllocNode(table);
00985 if (move == NULL)
00986 goto zddSwapAnyOutOfMem;
00987 move->x = x;
00988 move->y = x_next;
00989 move->size = size;
00990 move->next = moves;
00991 moves = move;
00992
00993 size = cuddZddSwapInPlace(table, y_next, y);
00994 if (size == 0)
00995 goto zddSwapAnyOutOfMem;
00996 move = (Move *)cuddDynamicAllocNode(table);
00997 if (move == NULL)
00998 goto zddSwapAnyOutOfMem;
00999 move->x = y_next;
01000 move->y = y;
01001 move->size = size;
01002 move->next = moves;
01003 moves = move;
01004
01005 size = cuddZddSwapInPlace(table, x, x_next);
01006 if (size == 0)
01007 goto zddSwapAnyOutOfMem;
01008 move = (Move *)cuddDynamicAllocNode(table);
01009 if (move == NULL)
01010 goto zddSwapAnyOutOfMem;
01011 move->x = x;
01012 move->y = x_next;
01013 move->size = size;
01014 move->next = moves;
01015 moves = move;
01016
01017 tmp = x; x = y; y = tmp;
01018
01019 } else if (x == y_next) {
01020 size = cuddZddSwapInPlace(table, x, x_next);
01021 if (size == 0)
01022 goto zddSwapAnyOutOfMem;
01023 move = (Move *)cuddDynamicAllocNode(table);
01024 if (move == NULL)
01025 goto zddSwapAnyOutOfMem;
01026 move->x = x;
01027 move->y = x_next;
01028 move->size = size;
01029 move->next = moves;
01030 moves = move;
01031
01032 tmp = x; x = y; y = tmp;
01033 } else {
01034 size = cuddZddSwapInPlace(table, x, x_next);
01035 if (size == 0)
01036 goto zddSwapAnyOutOfMem;
01037 move = (Move *)cuddDynamicAllocNode(table);
01038 if (move == NULL)
01039 goto zddSwapAnyOutOfMem;
01040 move->x = x;
01041 move->y = x_next;
01042 move->size = size;
01043 move->next = moves;
01044 moves = move;
01045
01046 size = cuddZddSwapInPlace(table, y_next, y);
01047 if (size == 0)
01048 goto zddSwapAnyOutOfMem;
01049 move = (Move *)cuddDynamicAllocNode(table);
01050 if (move == NULL)
01051 goto zddSwapAnyOutOfMem;
01052 move->x = y_next;
01053 move->y = y;
01054 move->size = size;
01055 move->next = moves;
01056 moves = move;
01057
01058 x = x_next; y = y_next;
01059 }
01060
01061 x_next = cuddZddNextHigh(table, x);
01062 y_next = cuddZddNextLow(table, y);
01063 if (x_next > y_ref)
01064 break;
01065
01066 if ((double) size > table->maxGrowth * (double) limit_size)
01067 break;
01068 if (size < limit_size)
01069 limit_size = size;
01070 }
01071 if (y_next >= x_ref) {
01072 size = cuddZddSwapInPlace(table, y_next, y);
01073 if (size == 0)
01074 goto zddSwapAnyOutOfMem;
01075 move = (Move *)cuddDynamicAllocNode(table);
01076 if (move == NULL)
01077 goto zddSwapAnyOutOfMem;
01078 move->x = y_next;
01079 move->y = y;
01080 move->size = size;
01081 move->next = moves;
01082 moves = move;
01083 }
01084
01085 return(moves);
01086
01087 zddSwapAnyOutOfMem:
01088 while (moves != NULL) {
01089 move = moves->next;
01090 cuddDeallocMove(table, moves);
01091 moves = move;
01092 }
01093 return(NULL);
01094
01095 }
01096
01097
01112 static int
01113 cuddZddSiftingAux(
01114 DdManager * table,
01115 int x,
01116 int x_low,
01117 int x_high)
01118 {
01119 Move *move;
01120 Move *moveUp;
01121 Move *moveDown;
01122
01123 int initial_size;
01124 int result;
01125
01126 initial_size = table->keysZ;
01127
01128 #ifdef DD_DEBUG
01129 assert(table->subtableZ[x].keys > 0);
01130 #endif
01131
01132 moveDown = NULL;
01133 moveUp = NULL;
01134
01135 if (x == x_low) {
01136 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
01137
01138 if (moveDown == NULL)
01139 goto cuddZddSiftingAuxOutOfMem;
01140 result = cuddZddSiftingBackward(table, moveDown,
01141 initial_size);
01142
01143 if (!result)
01144 goto cuddZddSiftingAuxOutOfMem;
01145
01146 }
01147 else if (x == x_high) {
01148 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
01149
01150 if (moveUp == NULL)
01151 goto cuddZddSiftingAuxOutOfMem;
01152 result = cuddZddSiftingBackward(table, moveUp, initial_size);
01153
01154 if (!result)
01155 goto cuddZddSiftingAuxOutOfMem;
01156 }
01157 else if ((x - x_low) > (x_high - x)) {
01158
01159 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
01160
01161 if (moveDown == NULL)
01162 goto cuddZddSiftingAuxOutOfMem;
01163 moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
01164 initial_size);
01165 if (moveUp == NULL)
01166 goto cuddZddSiftingAuxOutOfMem;
01167 result = cuddZddSiftingBackward(table, moveUp, initial_size);
01168
01169 if (!result)
01170 goto cuddZddSiftingAuxOutOfMem;
01171 }
01172 else {
01173 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
01174
01175 if (moveUp == NULL)
01176 goto cuddZddSiftingAuxOutOfMem;
01177 moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
01178 initial_size);
01179
01180 if (moveDown == NULL)
01181 goto cuddZddSiftingAuxOutOfMem;
01182 result = cuddZddSiftingBackward(table, moveDown,
01183 initial_size);
01184
01185 if (!result)
01186 goto cuddZddSiftingAuxOutOfMem;
01187 }
01188
01189 while (moveDown != NULL) {
01190 move = moveDown->next;
01191 cuddDeallocMove(table, moveDown);
01192 moveDown = move;
01193 }
01194 while (moveUp != NULL) {
01195 move = moveUp->next;
01196 cuddDeallocMove(table, moveUp);
01197 moveUp = move;
01198 }
01199
01200 return(1);
01201
01202 cuddZddSiftingAuxOutOfMem:
01203 while (moveDown != NULL) {
01204 move = moveDown->next;
01205 cuddDeallocMove(table, moveDown);
01206 moveDown = move;
01207 }
01208 while (moveUp != NULL) {
01209 move = moveUp->next;
01210 cuddDeallocMove(table, moveUp);
01211 moveUp = move;
01212 }
01213
01214 return(0);
01215
01216 }
01217
01218
01232 static Move *
01233 cuddZddSiftingUp(
01234 DdManager * table,
01235 int x,
01236 int x_low,
01237 int initial_size)
01238 {
01239 Move *moves;
01240 Move *move;
01241 int y;
01242 int size;
01243 int limit_size = initial_size;
01244
01245 moves = NULL;
01246 y = cuddZddNextLow(table, x);
01247 while (y >= x_low) {
01248 size = cuddZddSwapInPlace(table, y, x);
01249 if (size == 0)
01250 goto cuddZddSiftingUpOutOfMem;
01251 move = (Move *)cuddDynamicAllocNode(table);
01252 if (move == NULL)
01253 goto cuddZddSiftingUpOutOfMem;
01254 move->x = y;
01255 move->y = x;
01256 move->size = size;
01257 move->next = moves;
01258 moves = move;
01259
01260 if ((double)size > (double)limit_size * table->maxGrowth)
01261 break;
01262 if (size < limit_size)
01263 limit_size = size;
01264
01265 x = y;
01266 y = cuddZddNextLow(table, x);
01267 }
01268 return(moves);
01269
01270 cuddZddSiftingUpOutOfMem:
01271 while (moves != NULL) {
01272 move = moves->next;
01273 cuddDeallocMove(table, moves);
01274 moves = move;
01275 }
01276 return(NULL);
01277
01278 }
01279
01280
01295 static Move *
01296 cuddZddSiftingDown(
01297 DdManager * table,
01298 int x,
01299 int x_high,
01300 int initial_size)
01301 {
01302 Move *moves;
01303 Move *move;
01304 int y;
01305 int size;
01306 int limit_size = initial_size;
01307
01308 moves = NULL;
01309 y = cuddZddNextHigh(table, x);
01310 while (y <= x_high) {
01311 size = cuddZddSwapInPlace(table, x, y);
01312 if (size == 0)
01313 goto cuddZddSiftingDownOutOfMem;
01314 move = (Move *)cuddDynamicAllocNode(table);
01315 if (move == NULL)
01316 goto cuddZddSiftingDownOutOfMem;
01317 move->x = x;
01318 move->y = y;
01319 move->size = size;
01320 move->next = moves;
01321 moves = move;
01322
01323 if ((double)size > (double)limit_size * table->maxGrowth)
01324 break;
01325 if (size < limit_size)
01326 limit_size = size;
01327
01328 x = y;
01329 y = cuddZddNextHigh(table, x);
01330 }
01331 return(moves);
01332
01333 cuddZddSiftingDownOutOfMem:
01334 while (moves != NULL) {
01335 move = moves->next;
01336 cuddDeallocMove(table, moves);
01337 moves = move;
01338 }
01339 return(NULL);
01340
01341 }
01342
01343
01359 static int
01360 cuddZddSiftingBackward(
01361 DdManager * table,
01362 Move * moves,
01363 int size)
01364 {
01365 int i;
01366 int i_best;
01367 Move *move;
01368 int res;
01369
01370
01371 i_best = -1;
01372 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01373 if (move->size < size) {
01374 i_best = i;
01375 size = move->size;
01376 }
01377 }
01378
01379 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01380 if (i == i_best)
01381 break;
01382 res = cuddZddSwapInPlace(table, move->x, move->y);
01383 if (!res)
01384 return(0);
01385 if (i_best == -1 && res == size)
01386 break;
01387 }
01388
01389 return(1);
01390
01391 }
01392
01393
01405 static void
01406 zddReorderPreprocess(
01407 DdManager * table)
01408 {
01409
01410
01411 cuddCacheFlush(table);
01412
01413
01414 cuddGarbageCollect(table,0);
01415
01416 return;
01417
01418 }
01419
01420
01434 static int
01435 zddReorderPostprocess(
01436 DdManager * table)
01437 {
01438 int i, j, posn;
01439 DdNodePtr *nodelist, *oldnodelist;
01440 DdNode *node, *next;
01441 unsigned int slots, oldslots;
01442 extern DD_OOMFP MMoutOfMemory;
01443 DD_OOMFP saveHandler;
01444
01445 #ifdef DD_VERBOSE
01446 (void) fflush(table->out);
01447 #endif
01448
01449
01450
01451
01452
01453
01454
01455 if (table->reclaimed > table->allocated * 0.5) return(1);
01456
01457
01458 for (i = 0; i < table->sizeZ; i++) {
01459 int shift;
01460 oldslots = table->subtableZ[i].slots;
01461 if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
01462 oldslots <= table->initSlots) continue;
01463 oldnodelist = table->subtableZ[i].nodelist;
01464 slots = oldslots >> 1;
01465 saveHandler = MMoutOfMemory;
01466 MMoutOfMemory = Cudd_OutOfMem;
01467 nodelist = ALLOC(DdNodePtr, slots);
01468 MMoutOfMemory = saveHandler;
01469 if (nodelist == NULL) {
01470 return(1);
01471 }
01472 table->subtableZ[i].nodelist = nodelist;
01473 table->subtableZ[i].slots = slots;
01474 table->subtableZ[i].shift++;
01475 table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
01476 #ifdef DD_VERBOSE
01477 (void) fprintf(table->err,
01478 "shrunk layer %d (%d keys) from %d to %d slots\n",
01479 i, table->subtableZ[i].keys, oldslots, slots);
01480 #endif
01481
01482 for (j = 0; (unsigned) j < slots; j++) {
01483 nodelist[j] = NULL;
01484 }
01485 shift = table->subtableZ[i].shift;
01486 for (j = 0; (unsigned) j < oldslots; j++) {
01487 node = oldnodelist[j];
01488 while (node != NULL) {
01489 next = node->next;
01490 posn = ddHash(cuddT(node), cuddE(node), shift);
01491 node->next = nodelist[posn];
01492 nodelist[posn] = node;
01493 node = next;
01494 }
01495 }
01496 FREE(oldnodelist);
01497
01498 table->memused += (slots - oldslots) * sizeof(DdNode *);
01499 table->slots += slots - oldslots;
01500 table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
01501 table->cacheSlack = (int) ddMin(table->maxCacheHard,
01502 DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) -
01503 2 * (int) table->cacheSlots;
01504 }
01505
01506
01507
01508
01509 return(1);
01510
01511 }
01512
01513
01529 static int
01530 zddShuffle(
01531 DdManager * table,
01532 int * permutation)
01533 {
01534 int index;
01535 int level;
01536 int position;
01537 int numvars;
01538 int result;
01539 #ifdef DD_STATS
01540 long localTime;
01541 int initialSize;
01542 int finalSize;
01543 int previousSize;
01544 #endif
01545
01546 zddTotalNumberSwapping = 0;
01547 #ifdef DD_STATS
01548 localTime = util_cpu_time();
01549 initialSize = table->keysZ;
01550 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
01551 initialSize);
01552 #endif
01553
01554 numvars = table->sizeZ;
01555
01556 for (level = 0; level < numvars; level++) {
01557 index = permutation[level];
01558 position = table->permZ[index];
01559 #ifdef DD_STATS
01560 previousSize = table->keysZ;
01561 #endif
01562 result = zddSiftUp(table,position,level);
01563 if (!result) return(0);
01564 #ifdef DD_STATS
01565 if (table->keysZ < (unsigned) previousSize) {
01566 (void) fprintf(table->out,"-");
01567 } else if (table->keysZ > (unsigned) previousSize) {
01568 (void) fprintf(table->out,"+");
01569 } else {
01570 (void) fprintf(table->out,"=");
01571 }
01572 fflush(table->out);
01573 #endif
01574 }
01575
01576 #ifdef DD_STATS
01577 (void) fprintf(table->out,"\n");
01578 finalSize = table->keysZ;
01579 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
01580 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
01581 ((double)(util_cpu_time() - localTime)/1000.0));
01582 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
01583 zddTotalNumberSwapping);
01584 #endif
01585
01586 return(1);
01587
01588 }
01589
01590
01604 static int
01605 zddSiftUp(
01606 DdManager * table,
01607 int x,
01608 int xLow)
01609 {
01610 int y;
01611 int size;
01612
01613 y = cuddZddNextLow(table,x);
01614 while (y >= xLow) {
01615 size = cuddZddSwapInPlace(table,y,x);
01616 if (size == 0) {
01617 return(0);
01618 }
01619 x = y;
01620 y = cuddZddNextLow(table,x);
01621 }
01622 return(1);
01623
01624 }
01625
01626
01640 static void
01641 zddFixTree(
01642 DdManager * table,
01643 MtrNode * treenode)
01644 {
01645 if (treenode == NULL) return;
01646 treenode->low = ((int) treenode->index < table->sizeZ) ?
01647 table->permZ[treenode->index] : treenode->index;
01648 if (treenode->child != NULL) {
01649 zddFixTree(table, treenode->child);
01650 }
01651 if (treenode->younger != NULL)
01652 zddFixTree(table, treenode->younger);
01653 if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
01654 treenode->parent->low = treenode->low;
01655 treenode->parent->index = treenode->index;
01656 }
01657 return;
01658
01659 }
01660