00001
00049 #include "util_hack.h"
00050 #include "cuddInt.h"
00051
00052
00053
00054
00055
00056 #define DD_MAX_SUBTABLE_SPARSITY 8
00057 #define DD_SHRINK_FACTOR 2
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #ifndef lint
00074 static char rcsid[] DD_UNUSED = "$Id: cuddZddReord.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $";
00075 #endif
00076
00077 int *zdd_entry;
00078
00079 int zddTotalNumberSwapping;
00080
00081 static DdNode *empty;
00082
00083
00084
00085
00086
00087
00088
00091
00092
00093
00094
00095 static Move * zddSwapAny ARGS((DdManager *table, int x, int y));
00096 static int cuddZddSiftingAux ARGS((DdManager *table, int x, int x_low, int x_high));
00097 static Move * cuddZddSiftingUp ARGS((DdManager *table, int x, int x_low, int initial_size));
00098 static Move * cuddZddSiftingDown ARGS((DdManager *table, int x, int x_high, int initial_size));
00099 static int cuddZddSiftingBackward ARGS((DdManager *table, Move *moves, int size));
00100 static void zddReorderPreprocess ARGS((DdManager *table));
00101 static int zddReorderPostprocess ARGS((DdManager *table));
00102 static int zddShuffle ARGS((DdManager *table, int *permutation));
00103 static int zddSiftUp ARGS((DdManager *table, int x, int xLow));
00104 static void zddFixTree ARGS((DdManager *table, MtrNode *treenode));
00105
00109
00110
00111
00112
00113
00139 int
00140 Cudd_zddReduceHeap(
00141 DdManager * table ,
00142 Cudd_ReorderingType heuristic ,
00143 int minsize )
00144 {
00145 DdHook *hook;
00146 int result;
00147 unsigned int nextDyn;
00148 #ifdef DD_STATS
00149 unsigned int initialSize;
00150 unsigned int finalSize;
00151 #endif
00152 long localTime;
00153
00154
00155 if (table->keysZ - table->deadZ < (unsigned) minsize)
00156 return(1);
00157
00158 if (heuristic == CUDD_REORDER_SAME) {
00159 heuristic = table->autoMethodZ;
00160 }
00161 if (heuristic == CUDD_REORDER_NONE) {
00162 return(1);
00163 }
00164
00165
00166
00167
00168 table->reorderings++;
00169 empty = table->zero;
00170
00171 localTime = util_cpu_time();
00172
00173
00174 hook = table->preReorderingHook;
00175 while (hook != NULL) {
00176 int res = (hook->f)(table, "ZDD", (void *)heuristic);
00177 if (res == 0) return(0);
00178 hook = hook->next;
00179 }
00180
00181
00182 zddReorderPreprocess(table);
00183 zddTotalNumberSwapping = 0;
00184
00185 #ifdef DD_STATS
00186 initialSize = table->keysZ;
00187
00188 switch(heuristic) {
00189 case CUDD_REORDER_RANDOM:
00190 case CUDD_REORDER_RANDOM_PIVOT:
00191 (void) fprintf(table->out,"#:I_RANDOM ");
00192 break;
00193 case CUDD_REORDER_SIFT:
00194 case CUDD_REORDER_SIFT_CONVERGE:
00195 case CUDD_REORDER_SYMM_SIFT:
00196 case CUDD_REORDER_SYMM_SIFT_CONV:
00197 (void) fprintf(table->out,"#:I_SIFTING ");
00198 break;
00199 case CUDD_REORDER_LINEAR:
00200 case CUDD_REORDER_LINEAR_CONVERGE:
00201 (void) fprintf(table->out,"#:I_LINSIFT ");
00202 break;
00203 default:
00204 (void) fprintf(table->err,"Unsupported ZDD reordering method\n");
00205 return(0);
00206 }
00207 (void) fprintf(table->out,"%8d: initial size",initialSize);
00208 #endif
00209
00210 result = cuddZddTreeSifting(table,heuristic);
00211
00212 #ifdef DD_STATS
00213 (void) fprintf(table->out,"\n");
00214 finalSize = table->keysZ;
00215 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
00216 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
00217 ((double)(util_cpu_time() - localTime)/1000.0));
00218 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
00219 zddTotalNumberSwapping);
00220 #endif
00221
00222 if (result == 0)
00223 return(0);
00224
00225 if (!zddReorderPostprocess(table))
00226 return(0);
00227
00228 if (table->realignZ) {
00229 if (!cuddBddAlignToZdd(table))
00230 return(0);
00231 }
00232
00233 nextDyn = table->keysZ * DD_DYN_RATIO;
00234 if (table->reorderings < 20 || nextDyn > table->nextDyn)
00235 table->nextDyn = nextDyn;
00236 else
00237 table->nextDyn += 20;
00238
00239 table->reordered = 1;
00240
00241
00242 hook = table->postReorderingHook;
00243 while (hook != NULL) {
00244 int res = (hook->f)(table, "ZDD", (void *)localTime);
00245 if (res == 0) return(0);
00246 hook = hook->next;
00247 }
00248
00249 table->reordTime += util_cpu_time() - localTime;
00250
00251 return(result);
00252
00253 }
00254
00255
00272 int
00273 Cudd_zddShuffleHeap(
00274 DdManager * table ,
00275 int * permutation )
00276 {
00277
00278 int result;
00279
00280 empty = table->zero;
00281 zddReorderPreprocess(table);
00282
00283 result = zddShuffle(table,permutation);
00284
00285 if (!zddReorderPostprocess(table)) return(0);
00286
00287 return(result);
00288
00289 }
00290
00291
00292
00293
00294
00295
00296
00320 int
00321 cuddZddAlignToBdd(
00322 DdManager * table )
00323 {
00324 int *invpermZ;
00325 int M;
00326 int i,j;
00327 int result;
00328
00329
00330 if (table->sizeZ == 0)
00331 return(1);
00332
00333 empty = table->zero;
00334 M = table->sizeZ / table->size;
00335
00336
00337
00338 if (M * table->size != table->sizeZ)
00339 return(0);
00340
00341 invpermZ = ALLOC(int,table->sizeZ);
00342 if (invpermZ == NULL) {
00343 table->errorCode = CUDD_MEMORY_OUT;
00344 return(0);
00345 }
00346 for (i = 0; i < table->size; i++) {
00347 int index = table->invperm[i];
00348 int indexZ = index * M;
00349 int levelZ = table->permZ[indexZ];
00350 levelZ = (levelZ / M) * M;
00351 for (j = 0; j < M; j++) {
00352 invpermZ[M * i + j] = table->invpermZ[levelZ + j];
00353 }
00354 }
00355
00356
00357
00358 cuddGarbageCollectZdd(table,0);
00359
00360 result = zddShuffle(table, invpermZ);
00361 FREE(invpermZ);
00362
00363 zddFixTree(table,table->treeZ);
00364 return(result);
00365
00366 }
00367
00368
00381 int
00382 cuddZddNextHigh(
00383 DdManager * table,
00384 int x)
00385 {
00386 return(x + 1);
00387
00388 }
00389
00390
00403 int
00404 cuddZddNextLow(
00405 DdManager * table,
00406 int x)
00407 {
00408 return(x - 1);
00409
00410 }
00411
00412
00427 int
00428 cuddZddUniqueCompare(
00429 int * ptr_x,
00430 int * ptr_y)
00431 {
00432 return(zdd_entry[*ptr_y] - zdd_entry[*ptr_x]);
00433
00434 }
00435
00436
00452 int
00453 cuddZddSwapInPlace(
00454 DdManager * table,
00455 int x,
00456 int y)
00457 {
00458 DdNodePtr *xlist, *ylist;
00459 int xindex, yindex;
00460 int xslots, yslots;
00461 int xshift, yshift;
00462 int oldxkeys, oldykeys;
00463 int newxkeys, newykeys;
00464 int i;
00465 int posn;
00466 DdNode *f, *f1, *f0, *f11, *f10, *f01, *f00;
00467 DdNode *newf1, *newf0, *next;
00468 DdNodePtr g, *lastP, *previousP;
00469
00470 #ifdef DD_DEBUG
00471 assert(x < y);
00472 assert(cuddZddNextHigh(table,x) == y);
00473 assert(table->subtableZ[x].keys != 0);
00474 assert(table->subtableZ[y].keys != 0);
00475 assert(table->subtableZ[x].dead == 0);
00476 assert(table->subtableZ[y].dead == 0);
00477 #endif
00478
00479 zddTotalNumberSwapping++;
00480
00481
00482 xindex = table->invpermZ[x];
00483 xlist = table->subtableZ[x].nodelist;
00484 oldxkeys = table->subtableZ[x].keys;
00485 xslots = table->subtableZ[x].slots;
00486 xshift = table->subtableZ[x].shift;
00487 newxkeys = 0;
00488
00489 yindex = table->invpermZ[y];
00490 ylist = table->subtableZ[y].nodelist;
00491 oldykeys = table->subtableZ[y].keys;
00492 yslots = table->subtableZ[y].slots;
00493 yshift = table->subtableZ[y].shift;
00494 newykeys = oldykeys;
00495
00496
00497
00498
00499
00500
00501
00502 g = NULL;
00503 lastP = &g;
00504 for (i = 0; i < xslots; i++) {
00505 previousP = &(xlist[i]);
00506 f = *previousP;
00507 while (f != NULL) {
00508 next = f->next;
00509 f1 = cuddT(f); f0 = cuddE(f);
00510 if ((f1->index != (DdHalfWord) yindex) &&
00511 (f0->index != (DdHalfWord) yindex)) {
00512 newxkeys++;
00513 *previousP = f;
00514 previousP = &(f->next);
00515 } else {
00516 f->index = yindex;
00517 *lastP = f;
00518 lastP = &(f->next);
00519 }
00520 f = next;
00521 }
00522 *previousP = NULL;
00523 }
00524 *lastP = NULL;
00525
00526
00527 #ifdef DD_COUNT
00528 table->swapSteps += oldxkeys - newxkeys;
00529 #endif
00530
00531
00532
00533
00534 f = g;
00535 while (f != NULL) {
00536 next = f->next;
00537
00538 f1 = cuddT(f);
00539 if ((int) f1->index == yindex) {
00540 f11 = cuddT(f1); f10 = cuddE(f1);
00541 } else {
00542 f11 = empty; f10 = f1;
00543 }
00544 f0 = cuddE(f);
00545 if ((int) f0->index == yindex) {
00546 f01 = cuddT(f0); f00 = cuddE(f0);
00547 } else {
00548 f01 = empty; f00 = f0;
00549 }
00550
00551
00552 cuddSatDec(f1->ref);
00553
00554 if (f11 == empty) {
00555 if (f01 != empty) {
00556 newf1 = f01;
00557 cuddSatInc(newf1->ref);
00558 }
00559
00560
00561
00562 } else {
00563
00564 posn = ddHash(f11, f01, xshift);
00565
00566 newf1 = xlist[posn];
00567 while (newf1 != NULL) {
00568 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
00569 cuddSatInc(newf1->ref);
00570 break;
00571 }
00572 newf1 = newf1->next;
00573 }
00574 if (newf1 == NULL) {
00575 newf1 = cuddDynamicAllocNode(table);
00576 if (newf1 == NULL)
00577 goto zddSwapOutOfMem;
00578 newf1->index = xindex; newf1->ref = 1;
00579 cuddT(newf1) = f11;
00580 cuddE(newf1) = f01;
00581
00582
00583
00584 newxkeys++;
00585 newf1->next = xlist[posn];
00586 xlist[posn] = newf1;
00587 cuddSatInc(f11->ref);
00588 cuddSatInc(f01->ref);
00589 }
00590 }
00591 cuddT(f) = newf1;
00592
00593
00594
00595 cuddSatDec(f0->ref);
00596
00597 if (f10 == empty) {
00598 newf0 = f00;
00599 cuddSatInc(newf0->ref);
00600 } else {
00601
00602 posn = ddHash(f10, f00, xshift);
00603
00604 newf0 = xlist[posn];
00605 while (newf0 != NULL) {
00606 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
00607 cuddSatInc(newf0->ref);
00608 break;
00609 }
00610 newf0 = newf0->next;
00611 }
00612 if (newf0 == NULL) {
00613 newf0 = cuddDynamicAllocNode(table);
00614 if (newf0 == NULL)
00615 goto zddSwapOutOfMem;
00616 newf0->index = xindex; newf0->ref = 1;
00617 cuddT(newf0) = f10; cuddE(newf0) = f00;
00618
00619
00620
00621 newxkeys++;
00622 newf0->next = xlist[posn];
00623 xlist[posn] = newf0;
00624 cuddSatInc(f10->ref);
00625 cuddSatInc(f00->ref);
00626 }
00627 }
00628 cuddE(f) = newf0;
00629
00630
00631
00632
00633
00634 posn = ddHash(newf1, newf0, yshift);
00635 newykeys++;
00636 f->next = ylist[posn];
00637 ylist[posn] = f;
00638 f = next;
00639 }
00640
00641
00642
00643
00644 for (i = 0; i < yslots; i++) {
00645 previousP = &(ylist[i]);
00646 f = *previousP;
00647 while (f != NULL) {
00648 next = f->next;
00649 if (f->ref == 0) {
00650 cuddSatDec(cuddT(f)->ref);
00651 cuddSatDec(cuddE(f)->ref);
00652 cuddDeallocNode(table, f);
00653 newykeys--;
00654 } else {
00655 *previousP = f;
00656 previousP = &(f->next);
00657 }
00658 f = next;
00659 }
00660 *previousP = NULL;
00661 }
00662
00663
00664 table->subtableZ[x].nodelist = ylist;
00665 table->subtableZ[x].slots = yslots;
00666 table->subtableZ[x].shift = yshift;
00667 table->subtableZ[x].keys = newykeys;
00668 table->subtableZ[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
00669
00670 table->subtableZ[y].nodelist = xlist;
00671 table->subtableZ[y].slots = xslots;
00672 table->subtableZ[y].shift = xshift;
00673 table->subtableZ[y].keys = newxkeys;
00674 table->subtableZ[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
00675
00676 table->permZ[xindex] = y; table->permZ[yindex] = x;
00677 table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;
00678
00679 table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;
00680
00681
00682 table->univ[y] = cuddT(table->univ[x]);
00683
00684 return (table->keysZ);
00685
00686 zddSwapOutOfMem:
00687 (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");
00688
00689 return (0);
00690
00691 }
00692
00693
00714 int
00715 cuddZddSwapping(
00716 DdManager * table,
00717 int lower,
00718 int upper,
00719 Cudd_ReorderingType heuristic)
00720 {
00721 int i, j;
00722 int max, keys;
00723 int nvars;
00724 int x, y;
00725 int iterate;
00726 int previousSize;
00727 Move *moves, *move;
00728 int pivot;
00729 int modulo;
00730 int result;
00731
00732 #ifdef DD_DEBUG
00733
00734 assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
00735 #endif
00736
00737 nvars = upper - lower + 1;
00738 iterate = nvars;
00739
00740 for (i = 0; i < iterate; i++) {
00741 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
00742
00743 for (max = -1, j = lower; j <= upper; j++) {
00744 if ((keys = table->subtableZ[j].keys) > max) {
00745 max = keys;
00746 pivot = j;
00747 }
00748 }
00749
00750 modulo = upper - pivot;
00751 if (modulo == 0) {
00752 y = pivot;
00753 } else {
00754
00755 y = pivot + 1 + (int) (Cudd_Random() % modulo);
00756 }
00757
00758 modulo = pivot - lower - 1;
00759 if (modulo < 1) {
00760 x = lower;
00761 } else {
00762 do {
00763 x = (int) Cudd_Random() % modulo;
00764 } while (x == y);
00765
00766
00767 }
00768 } else {
00769 x = (int) (Cudd_Random() % nvars) + lower;
00770 do {
00771 y = (int) (Cudd_Random() % nvars) + lower;
00772 } while (x == y);
00773 }
00774
00775 previousSize = table->keysZ;
00776 moves = zddSwapAny(table, x, y);
00777 if (moves == NULL)
00778 goto cuddZddSwappingOutOfMem;
00779
00780 result = cuddZddSiftingBackward(table, moves, previousSize);
00781 if (!result)
00782 goto cuddZddSwappingOutOfMem;
00783
00784 while (moves != NULL) {
00785 move = moves->next;
00786 cuddDeallocNode(table, (DdNode *) moves);
00787 moves = move;
00788 }
00789 #ifdef DD_STATS
00790 if (table->keysZ < (unsigned) previousSize) {
00791 (void) fprintf(table->out,"-");
00792 } else if (table->keysZ > (unsigned) previousSize) {
00793 (void) fprintf(table->out,"+");
00794 } else {
00795 (void) fprintf(table->out,"=");
00796 }
00797 fflush(table->out);
00798 #endif
00799 }
00800
00801 return(1);
00802
00803 cuddZddSwappingOutOfMem:
00804 while (moves != NULL) {
00805 move = moves->next;
00806 cuddDeallocNode(table, (DdNode *) moves);
00807 moves = move;
00808 }
00809 return(0);
00810
00811 }
00812
00813
00835 int
00836 cuddZddSifting(
00837 DdManager * table,
00838 int lower,
00839 int upper)
00840 {
00841 int i;
00842 int *var;
00843 int size;
00844 int x;
00845 int result;
00846 #ifdef DD_STATS
00847 int previousSize;
00848 #endif
00849
00850 size = table->sizeZ;
00851
00852
00853 var = NULL;
00854 zdd_entry = ALLOC(int, size);
00855 if (zdd_entry == NULL) {
00856 table->errorCode = CUDD_MEMORY_OUT;
00857 goto cuddZddSiftingOutOfMem;
00858 }
00859 var = ALLOC(int, size);
00860 if (var == NULL) {
00861 table->errorCode = CUDD_MEMORY_OUT;
00862 goto cuddZddSiftingOutOfMem;
00863 }
00864
00865 for (i = 0; i < size; i++) {
00866 x = table->permZ[i];
00867 zdd_entry[i] = table->subtableZ[x].keys;
00868 var[i] = i;
00869 }
00870
00871 qsort((void *)var, size, sizeof(int), (int (*)(const void *, const void *))cuddZddUniqueCompare);
00872
00873
00874 for (i = 0; i < ddMin(table->siftMaxVar, size); i++) {
00875 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00876 break;
00877 x = table->permZ[var[i]];
00878 if (x < lower || x > upper) continue;
00879 #ifdef DD_STATS
00880 previousSize = table->keysZ;
00881 #endif
00882 result = cuddZddSiftingAux(table, x, lower, upper);
00883 if (!result)
00884 goto cuddZddSiftingOutOfMem;
00885 #ifdef DD_STATS
00886 if (table->keysZ < (unsigned) previousSize) {
00887 (void) fprintf(table->out,"-");
00888 } else if (table->keysZ > (unsigned) previousSize) {
00889 (void) fprintf(table->out,"+");
00890 (void) fprintf(table->out,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keysZ , var[i]);
00891 } else {
00892 (void) fprintf(table->out,"=");
00893 }
00894 fflush(table->out);
00895 #endif
00896 }
00897
00898 FREE(var);
00899 FREE(zdd_entry);
00900
00901 return(1);
00902
00903 cuddZddSiftingOutOfMem:
00904
00905 if (zdd_entry != NULL) FREE(zdd_entry);
00906 if (var != NULL) FREE(var);
00907
00908 return(0);
00909
00910 }
00911
00912
00913
00914
00915
00916
00917
00929 static Move *
00930 zddSwapAny(
00931 DdManager * table,
00932 int x,
00933 int y)
00934 {
00935 Move *move, *moves;
00936 int tmp, size;
00937 int x_ref, y_ref;
00938 int x_next, y_next;
00939 int limit_size;
00940
00941 if (x > y) {
00942 tmp = x; x = y; y = tmp;
00943 }
00944
00945 x_ref = x; y_ref = y;
00946
00947 x_next = cuddZddNextHigh(table, x);
00948 y_next = cuddZddNextLow(table, y);
00949 moves = NULL;
00950 limit_size = table->keysZ;
00951
00952 for (;;) {
00953 if (x_next == y_next) {
00954 size = cuddZddSwapInPlace(table, x, x_next);
00955 if (size == 0)
00956 goto zddSwapAnyOutOfMem;
00957 move = (Move *) cuddDynamicAllocNode(table);
00958 if (move == NULL)
00959 goto zddSwapAnyOutOfMem;
00960 move->x = x;
00961 move->y = x_next;
00962 move->size = size;
00963 move->next = moves;
00964 moves = move;
00965
00966 size = cuddZddSwapInPlace(table, y_next, y);
00967 if (size == 0)
00968 goto zddSwapAnyOutOfMem;
00969 move = (Move *)cuddDynamicAllocNode(table);
00970 if (move == NULL)
00971 goto zddSwapAnyOutOfMem;
00972 move->x = y_next;
00973 move->y = y;
00974 move->size = size;
00975 move->next = moves;
00976 moves = move;
00977
00978 size = cuddZddSwapInPlace(table, x, x_next);
00979 if (size == 0)
00980 goto zddSwapAnyOutOfMem;
00981 move = (Move *)cuddDynamicAllocNode(table);
00982 if (move == NULL)
00983 goto zddSwapAnyOutOfMem;
00984 move->x = x;
00985 move->y = x_next;
00986 move->size = size;
00987 move->next = moves;
00988 moves = move;
00989
00990 tmp = x; x = y; y = tmp;
00991
00992 } else if (x == y_next) {
00993 size = cuddZddSwapInPlace(table, x, x_next);
00994 if (size == 0)
00995 goto zddSwapAnyOutOfMem;
00996 move = (Move *)cuddDynamicAllocNode(table);
00997 if (move == NULL)
00998 goto zddSwapAnyOutOfMem;
00999 move->x = x;
01000 move->y = x_next;
01001 move->size = size;
01002 move->next = moves;
01003 moves = move;
01004
01005 tmp = x; x = y; y = tmp;
01006 } else {
01007 size = cuddZddSwapInPlace(table, x, x_next);
01008 if (size == 0)
01009 goto zddSwapAnyOutOfMem;
01010 move = (Move *)cuddDynamicAllocNode(table);
01011 if (move == NULL)
01012 goto zddSwapAnyOutOfMem;
01013 move->x = x;
01014 move->y = x_next;
01015 move->size = size;
01016 move->next = moves;
01017 moves = move;
01018
01019 size = cuddZddSwapInPlace(table, y_next, y);
01020 if (size == 0)
01021 goto zddSwapAnyOutOfMem;
01022 move = (Move *)cuddDynamicAllocNode(table);
01023 if (move == NULL)
01024 goto zddSwapAnyOutOfMem;
01025 move->x = y_next;
01026 move->y = y;
01027 move->size = size;
01028 move->next = moves;
01029 moves = move;
01030
01031 x = x_next; y = y_next;
01032 }
01033
01034 x_next = cuddZddNextHigh(table, x);
01035 y_next = cuddZddNextLow(table, y);
01036 if (x_next > y_ref)
01037 break;
01038
01039 if ((double) size > table->maxGrowth * (double) limit_size)
01040 break;
01041 if (size < limit_size)
01042 limit_size = size;
01043 }
01044 if (y_next >= x_ref) {
01045 size = cuddZddSwapInPlace(table, y_next, y);
01046 if (size == 0)
01047 goto zddSwapAnyOutOfMem;
01048 move = (Move *)cuddDynamicAllocNode(table);
01049 if (move == NULL)
01050 goto zddSwapAnyOutOfMem;
01051 move->x = y_next;
01052 move->y = y;
01053 move->size = size;
01054 move->next = moves;
01055 moves = move;
01056 }
01057
01058 return(moves);
01059
01060 zddSwapAnyOutOfMem:
01061 while (moves != NULL) {
01062 move = moves->next;
01063 cuddDeallocNode(table, (DdNode *)moves);
01064 moves = move;
01065 }
01066 return(NULL);
01067
01068 }
01069
01070
01085 static int
01086 cuddZddSiftingAux(
01087 DdManager * table,
01088 int x,
01089 int x_low,
01090 int x_high)
01091 {
01092 Move *move;
01093 Move *moveUp;
01094 Move *moveDown;
01095
01096 int initial_size;
01097 int result;
01098
01099 initial_size = table->keysZ;
01100
01101 #ifdef DD_DEBUG
01102 assert(table->subtableZ[x].keys > 0);
01103 #endif
01104
01105 moveDown = NULL;
01106 moveUp = NULL;
01107
01108 if (x == x_low) {
01109 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
01110
01111 if (moveDown == NULL)
01112 goto cuddZddSiftingAuxOutOfMem;
01113 result = cuddZddSiftingBackward(table, moveDown,
01114 initial_size);
01115
01116 if (!result)
01117 goto cuddZddSiftingAuxOutOfMem;
01118
01119 }
01120 else if (x == x_high) {
01121 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
01122
01123 if (moveUp == NULL)
01124 goto cuddZddSiftingAuxOutOfMem;
01125 result = cuddZddSiftingBackward(table, moveUp, initial_size);
01126
01127 if (!result)
01128 goto cuddZddSiftingAuxOutOfMem;
01129 }
01130 else if ((x - x_low) > (x_high - x)) {
01131
01132 moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
01133
01134 if (moveDown == NULL)
01135 goto cuddZddSiftingAuxOutOfMem;
01136 moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
01137 initial_size);
01138 if (moveUp == NULL)
01139 goto cuddZddSiftingAuxOutOfMem;
01140 result = cuddZddSiftingBackward(table, moveUp, initial_size);
01141
01142 if (!result)
01143 goto cuddZddSiftingAuxOutOfMem;
01144 }
01145 else {
01146 moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
01147
01148 if (moveUp == NULL)
01149 goto cuddZddSiftingAuxOutOfMem;
01150 moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
01151 initial_size);
01152
01153 if (moveDown == NULL)
01154 goto cuddZddSiftingAuxOutOfMem;
01155 result = cuddZddSiftingBackward(table, moveDown,
01156 initial_size);
01157
01158 if (!result)
01159 goto cuddZddSiftingAuxOutOfMem;
01160 }
01161
01162 while (moveDown != NULL) {
01163 move = moveDown->next;
01164 cuddDeallocNode(table, (DdNode *)moveDown);
01165 moveDown = move;
01166 }
01167 while (moveUp != NULL) {
01168 move = moveUp->next;
01169 cuddDeallocNode(table, (DdNode *)moveUp);
01170 moveUp = move;
01171 }
01172
01173 return(1);
01174
01175 cuddZddSiftingAuxOutOfMem:
01176 while (moveDown != NULL) {
01177 move = moveDown->next;
01178 cuddDeallocNode(table, (DdNode *)moveDown);
01179 moveDown = move;
01180 }
01181 while (moveUp != NULL) {
01182 move = moveUp->next;
01183 cuddDeallocNode(table, (DdNode *)moveUp);
01184 moveUp = move;
01185 }
01186
01187 return(0);
01188
01189 }
01190
01191
01205 static Move *
01206 cuddZddSiftingUp(
01207 DdManager * table,
01208 int x,
01209 int x_low,
01210 int initial_size)
01211 {
01212 Move *moves;
01213 Move *move;
01214 int y;
01215 int size;
01216 int limit_size = initial_size;
01217
01218 moves = NULL;
01219 y = cuddZddNextLow(table, x);
01220 while (y >= x_low) {
01221 size = cuddZddSwapInPlace(table, y, x);
01222 if (size == 0)
01223 goto cuddZddSiftingUpOutOfMem;
01224 move = (Move *)cuddDynamicAllocNode(table);
01225 if (move == NULL)
01226 goto cuddZddSiftingUpOutOfMem;
01227 move->x = y;
01228 move->y = x;
01229 move->size = size;
01230 move->next = moves;
01231 moves = move;
01232
01233 if ((double)size > (double)limit_size * table->maxGrowth)
01234 break;
01235 if (size < limit_size)
01236 limit_size = size;
01237
01238 x = y;
01239 y = cuddZddNextLow(table, x);
01240 }
01241 return(moves);
01242
01243 cuddZddSiftingUpOutOfMem:
01244 while (moves != NULL) {
01245 move = moves->next;
01246 cuddDeallocNode(table, (DdNode *)moves);
01247 moves = move;
01248 }
01249 return(NULL);
01250
01251 }
01252
01253
01268 static Move *
01269 cuddZddSiftingDown(
01270 DdManager * table,
01271 int x,
01272 int x_high,
01273 int initial_size)
01274 {
01275 Move *moves;
01276 Move *move;
01277 int y;
01278 int size;
01279 int limit_size = initial_size;
01280
01281 moves = NULL;
01282 y = cuddZddNextHigh(table, x);
01283 while (y <= x_high) {
01284 size = cuddZddSwapInPlace(table, x, y);
01285 if (size == 0)
01286 goto cuddZddSiftingDownOutOfMem;
01287 move = (Move *)cuddDynamicAllocNode(table);
01288 if (move == NULL)
01289 goto cuddZddSiftingDownOutOfMem;
01290 move->x = x;
01291 move->y = y;
01292 move->size = size;
01293 move->next = moves;
01294 moves = move;
01295
01296 if ((double)size > (double)limit_size * table->maxGrowth)
01297 break;
01298 if (size < limit_size)
01299 limit_size = size;
01300
01301 x = y;
01302 y = cuddZddNextHigh(table, x);
01303 }
01304 return(moves);
01305
01306 cuddZddSiftingDownOutOfMem:
01307 while (moves != NULL) {
01308 move = moves->next;
01309 cuddDeallocNode(table, (DdNode *)moves);
01310 moves = move;
01311 }
01312 return(NULL);
01313
01314 }
01315
01316
01332 static int
01333 cuddZddSiftingBackward(
01334 DdManager * table,
01335 Move * moves,
01336 int size)
01337 {
01338 int i;
01339 int i_best;
01340 Move *move;
01341 int res;
01342
01343
01344 i_best = -1;
01345 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01346 if (move->size < size) {
01347 i_best = i;
01348 size = move->size;
01349 }
01350 }
01351
01352 for (move = moves, i = 0; move != NULL; move = move->next, i++) {
01353 if (i == i_best)
01354 break;
01355 res = cuddZddSwapInPlace(table, move->x, move->y);
01356 if (!res)
01357 return(0);
01358 if (i_best == -1 && res == size)
01359 break;
01360 }
01361
01362 return(1);
01363
01364 }
01365
01366
01378 static void
01379 zddReorderPreprocess(
01380 DdManager * table)
01381 {
01382
01383
01384 cuddCacheFlush(table);
01385
01386
01387 cuddGarbageCollectZdd(table,0);
01388
01389 return;
01390
01391 }
01392
01393
01407 static int
01408 zddReorderPostprocess(
01409 DdManager * table)
01410 {
01411 int i, j, posn;
01412 DdNodePtr *nodelist, *oldnodelist;
01413 DdNode *node, *next;
01414 unsigned int slots, oldslots;
01415 extern void (*MMoutOfMemory)(long);
01416 void (*saveHandler)(long);
01417
01418 #ifdef DD_VERBOSE
01419 (void) fflush(table->out);
01420 #endif
01421
01422
01423
01424
01425
01426
01427
01428 if (table->reclaimed > table->allocated * 0.5) return(1);
01429
01430
01431 for (i = 0; i < table->sizeZ; i++) {
01432 int shift;
01433 oldslots = table->subtableZ[i].slots;
01434 if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
01435 oldslots <= table->initSlots) continue;
01436 oldnodelist = table->subtableZ[i].nodelist;
01437 slots = oldslots >> 1;
01438 saveHandler = MMoutOfMemory;
01439 MMoutOfMemory = Cudd_OutOfMem;
01440 nodelist = ALLOC(DdNodePtr, slots);
01441 MMoutOfMemory = saveHandler;
01442 if (nodelist == NULL) {
01443 return(1);
01444 }
01445 table->subtableZ[i].nodelist = nodelist;
01446 table->subtableZ[i].slots = slots;
01447 table->subtableZ[i].shift++;
01448 table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
01449 #ifdef DD_VERBOSE
01450 (void) fprintf(table->err,
01451 "shrunk layer %d (%d keys) from %d to %d slots\n",
01452 i, table->subtableZ[i].keys, oldslots, slots);
01453 #endif
01454
01455 for (j = 0; (unsigned) j < slots; j++) {
01456 nodelist[j] = NULL;
01457 }
01458 shift = table->subtableZ[i].shift;
01459 for (j = 0; (unsigned) j < oldslots; j++) {
01460 node = oldnodelist[j];
01461 while (node != NULL) {
01462 next = node->next;
01463 posn = ddHash(cuddT(node), cuddE(node), shift);
01464 node->next = nodelist[posn];
01465 nodelist[posn] = node;
01466 node = next;
01467 }
01468 }
01469 FREE(oldnodelist);
01470
01471 table->memused += (slots - oldslots) * sizeof(DdNode *);
01472 table->slots += slots - oldslots;
01473 table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
01474 table->cacheSlack = (int) ddMin(table->maxCacheHard,
01475 DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) -
01476 2 * (int) table->cacheSlots;
01477 }
01478
01479
01480
01481
01482 return(1);
01483
01484 }
01485
01486
01502 static int
01503 zddShuffle(
01504 DdManager * table,
01505 int * permutation)
01506 {
01507 int index;
01508 int level;
01509 int position;
01510 int numvars;
01511 int result;
01512 #ifdef DD_STATS
01513 long localTime;
01514 int initialSize;
01515 int finalSize;
01516 int previousSize;
01517 #endif
01518
01519 zddTotalNumberSwapping = 0;
01520 #ifdef DD_STATS
01521 localTime = util_cpu_time();
01522 initialSize = table->keysZ;
01523 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
01524 initialSize);
01525 #endif
01526
01527 numvars = table->sizeZ;
01528
01529 for (level = 0; level < numvars; level++) {
01530 index = permutation[level];
01531 position = table->permZ[index];
01532 #ifdef DD_STATS
01533 previousSize = table->keysZ;
01534 #endif
01535 result = zddSiftUp(table,position,level);
01536 if (!result) return(0);
01537 #ifdef DD_STATS
01538 if (table->keysZ < (unsigned) previousSize) {
01539 (void) fprintf(table->out,"-");
01540 } else if (table->keysZ > (unsigned) previousSize) {
01541 (void) fprintf(table->out,"+");
01542 } else {
01543 (void) fprintf(table->out,"=");
01544 }
01545 fflush(table->out);
01546 #endif
01547 }
01548
01549 #ifdef DD_STATS
01550 (void) fprintf(table->out,"\n");
01551 finalSize = table->keysZ;
01552 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
01553 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
01554 ((double)(util_cpu_time() - localTime)/1000.0));
01555 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
01556 zddTotalNumberSwapping);
01557 #endif
01558
01559 return(1);
01560
01561 }
01562
01563
01577 static int
01578 zddSiftUp(
01579 DdManager * table,
01580 int x,
01581 int xLow)
01582 {
01583 int y;
01584 int size;
01585
01586 y = cuddZddNextLow(table,x);
01587 while (y >= xLow) {
01588 size = cuddZddSwapInPlace(table,y,x);
01589 if (size == 0) {
01590 return(0);
01591 }
01592 x = y;
01593 y = cuddZddNextLow(table,x);
01594 }
01595 return(1);
01596
01597 }
01598
01599
01613 static void
01614 zddFixTree(
01615 DdManager * table,
01616 MtrNode * treenode)
01617 {
01618 if (treenode == NULL) return;
01619 treenode->low = ((int) treenode->index < table->sizeZ) ?
01620 table->permZ[treenode->index] : treenode->index;
01621 if (treenode->child != NULL) {
01622 zddFixTree(table, treenode->child);
01623 }
01624 if (treenode->younger != NULL)
01625 zddFixTree(table, treenode->younger);
01626 if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
01627 treenode->parent->low = treenode->low;
01628 treenode->parent->index = treenode->index;
01629 }
01630 return;
01631
01632 }
01633