00001
00075 #include "util.h"
00076 #include "cuddInt.h"
00077
00078
00079
00080
00081
00082 #define DD_MAX_SUBTABLE_SPARSITY 8
00083 #define DD_SHRINK_FACTOR 2
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 #ifndef lint
00098 static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.69 2009/02/21 18:24:10 fabio Exp $";
00099 #endif
00100
00101 static int *entry;
00102
00103 int ddTotalNumberSwapping;
00104 #ifdef DD_STATS
00105 int ddTotalNISwaps;
00106 #endif
00107
00108
00109
00110
00111
00114
00115
00116
00117
00118 static int ddUniqueCompare (int *ptrX, int *ptrY);
00119 static Move * ddSwapAny (DdManager *table, int x, int y);
00120 static int ddSiftingAux (DdManager *table, int x, int xLow, int xHigh);
00121 static Move * ddSiftingUp (DdManager *table, int y, int xLow);
00122 static Move * ddSiftingDown (DdManager *table, int x, int xHigh);
00123 static int ddSiftingBackward (DdManager *table, int size, Move *moves);
00124 static int ddReorderPreprocess (DdManager *table);
00125 static int ddReorderPostprocess (DdManager *table);
00126 static int ddShuffle (DdManager *table, int *permutation);
00127 static int ddSiftUp (DdManager *table, int x, int xLow);
00128 static void bddFixTree (DdManager *table, MtrNode *treenode);
00129 static int ddUpdateMtrTree (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
00130 static int ddCheckPermuation (DdManager *table, MtrNode *treenode, int *perm, int *invperm);
00131
00135
00136
00137
00138
00139
00171 int
00172 Cudd_ReduceHeap(
00173 DdManager * table ,
00174 Cudd_ReorderingType heuristic ,
00175 int minsize )
00176 {
00177 DdHook *hook;
00178 int result;
00179 unsigned int nextDyn;
00180 #ifdef DD_STATS
00181 unsigned int initialSize;
00182 unsigned int finalSize;
00183 #endif
00184 long localTime;
00185
00186
00187 if (table->keys - table->dead < (unsigned) minsize)
00188 return(1);
00189
00190 if (heuristic == CUDD_REORDER_SAME) {
00191 heuristic = table->autoMethod;
00192 }
00193 if (heuristic == CUDD_REORDER_NONE) {
00194 return(1);
00195 }
00196
00197
00198
00199
00200 table->reorderings++;
00201
00202 localTime = util_cpu_time();
00203
00204
00205 hook = table->preReorderingHook;
00206 while (hook != NULL) {
00207 int res = (hook->f)(table, "BDD", (void *)heuristic);
00208 if (res == 0) return(0);
00209 hook = hook->next;
00210 }
00211
00212 if (!ddReorderPreprocess(table)) return(0);
00213 ddTotalNumberSwapping = 0;
00214
00215 if (table->keys > table->peakLiveNodes) {
00216 table->peakLiveNodes = table->keys;
00217 }
00218 #ifdef DD_STATS
00219 initialSize = table->keys - table->isolated;
00220 ddTotalNISwaps = 0;
00221
00222 switch(heuristic) {
00223 case CUDD_REORDER_RANDOM:
00224 case CUDD_REORDER_RANDOM_PIVOT:
00225 (void) fprintf(table->out,"#:I_RANDOM ");
00226 break;
00227 case CUDD_REORDER_SIFT:
00228 case CUDD_REORDER_SIFT_CONVERGE:
00229 case CUDD_REORDER_SYMM_SIFT:
00230 case CUDD_REORDER_SYMM_SIFT_CONV:
00231 case CUDD_REORDER_GROUP_SIFT:
00232 case CUDD_REORDER_GROUP_SIFT_CONV:
00233 (void) fprintf(table->out,"#:I_SIFTING ");
00234 break;
00235 case CUDD_REORDER_WINDOW2:
00236 case CUDD_REORDER_WINDOW3:
00237 case CUDD_REORDER_WINDOW4:
00238 case CUDD_REORDER_WINDOW2_CONV:
00239 case CUDD_REORDER_WINDOW3_CONV:
00240 case CUDD_REORDER_WINDOW4_CONV:
00241 (void) fprintf(table->out,"#:I_WINDOW ");
00242 break;
00243 case CUDD_REORDER_ANNEALING:
00244 (void) fprintf(table->out,"#:I_ANNEAL ");
00245 break;
00246 case CUDD_REORDER_GENETIC:
00247 (void) fprintf(table->out,"#:I_GENETIC ");
00248 break;
00249 case CUDD_REORDER_LINEAR:
00250 case CUDD_REORDER_LINEAR_CONVERGE:
00251 (void) fprintf(table->out,"#:I_LINSIFT ");
00252 break;
00253 case CUDD_REORDER_EXACT:
00254 (void) fprintf(table->out,"#:I_EXACT ");
00255 break;
00256 default:
00257 return(0);
00258 }
00259 (void) fprintf(table->out,"%8d: initial size",initialSize);
00260 #endif
00261
00262
00263 if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
00264 double saveGrowth = table->maxGrowth;
00265 table->maxGrowth = table->maxGrowthAlt;
00266 result = cuddTreeSifting(table,heuristic);
00267 table->maxGrowth = saveGrowth;
00268 } else {
00269 result = cuddTreeSifting(table,heuristic);
00270 }
00271
00272 #ifdef DD_STATS
00273 (void) fprintf(table->out,"\n");
00274 finalSize = table->keys - table->isolated;
00275 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
00276 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
00277 ((double)(util_cpu_time() - localTime)/1000.0));
00278 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
00279 ddTotalNumberSwapping);
00280 (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
00281 #endif
00282
00283 if (result == 0)
00284 return(0);
00285
00286 if (!ddReorderPostprocess(table))
00287 return(0);
00288
00289 if (table->realign) {
00290 if (!cuddZddAlignToBdd(table))
00291 return(0);
00292 }
00293
00294 nextDyn = (table->keys - table->constants.keys + 1) *
00295 DD_DYN_RATIO + table->constants.keys;
00296 if (table->reorderings < 20 || nextDyn > table->nextDyn)
00297 table->nextDyn = nextDyn;
00298 else
00299 table->nextDyn += 20;
00300 table->reordered = 1;
00301
00302
00303 hook = table->postReorderingHook;
00304 while (hook != NULL) {
00305 int res = (hook->f)(table, "BDD", (void *)localTime);
00306 if (res == 0) return(0);
00307 hook = hook->next;
00308 }
00309
00310 table->reordTime += util_cpu_time() - localTime;
00311
00312 return(result);
00313
00314 }
00315
00316
00333 int
00334 Cudd_ShuffleHeap(
00335 DdManager * table ,
00336 int * permutation )
00337 {
00338
00339 int result;
00340 int i;
00341 int identity = 1;
00342 int *perm;
00343
00344
00345 for (i = 0; i < table->size; i++) {
00346 if (permutation[i] != table->invperm[i]) {
00347 identity = 0;
00348 break;
00349 }
00350 }
00351 if (identity == 1) {
00352 return(1);
00353 }
00354 if (!ddReorderPreprocess(table)) return(0);
00355 if (table->keys > table->peakLiveNodes) {
00356 table->peakLiveNodes = table->keys;
00357 }
00358
00359 perm = ALLOC(int, table->size);
00360 for (i = 0; i < table->size; i++)
00361 perm[permutation[i]] = i;
00362 if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
00363 FREE(perm);
00364 return(0);
00365 }
00366 if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
00367 FREE(perm);
00368 return(0);
00369 }
00370 FREE(perm);
00371
00372 result = ddShuffle(table,permutation);
00373
00374 if (!ddReorderPostprocess(table)) return(0);
00375
00376 return(result);
00377
00378 }
00379
00380
00381
00382
00383
00384
00385
00401 DdNode *
00402 cuddDynamicAllocNode(
00403 DdManager * table)
00404 {
00405 int i;
00406 DdNodePtr *mem;
00407 DdNode *list, *node;
00408 extern DD_OOMFP MMoutOfMemory;
00409 DD_OOMFP saveHandler;
00410
00411 if (table->nextFree == NULL) {
00412
00413 saveHandler = MMoutOfMemory;
00414 MMoutOfMemory = Cudd_OutOfMem;
00415 mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
00416 MMoutOfMemory = saveHandler;
00417 if (mem == NULL && table->stash != NULL) {
00418 FREE(table->stash);
00419 table->stash = NULL;
00420
00421 table->maxCacheHard = table->cacheSlots - 1;
00422 table->cacheSlack = - (int) (table->cacheSlots + 1);
00423 for (i = 0; i < table->size; i++) {
00424 table->subtables[i].maxKeys <<= 2;
00425 }
00426 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
00427 }
00428 if (mem == NULL) {
00429
00430
00431
00432
00433 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
00434 table->errorCode = CUDD_MEMORY_OUT;
00435 #ifdef DD_VERBOSE
00436 (void) fprintf(table->err,
00437 "cuddDynamicAllocNode: out of memory");
00438 (void) fprintf(table->err,"Memory in use = %lu\n",
00439 table->memused);
00440 #endif
00441 return(NULL);
00442 } else {
00443 unsigned long offset;
00444 table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
00445 mem[0] = (DdNode *) table->memoryList;
00446 table->memoryList = mem;
00447
00448
00449
00450
00451
00452 offset = (unsigned long) mem & (sizeof(DdNode) - 1);
00453 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
00454 #ifdef DD_DEBUG
00455 assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
00456 #endif
00457 list = (DdNode *) mem;
00458
00459 i = 1;
00460 do {
00461 list[i - 1].ref = 0;
00462 list[i - 1].next = &list[i];
00463 } while (++i < DD_MEM_CHUNK);
00464
00465 list[DD_MEM_CHUNK-1].ref = 0;
00466 list[DD_MEM_CHUNK - 1].next = NULL;
00467
00468 table->nextFree = &list[0];
00469 }
00470 }
00471
00472 node = table->nextFree;
00473 table->nextFree = node->next;
00474 return (node);
00475
00476 }
00477
00478
00498 int
00499 cuddSifting(
00500 DdManager * table,
00501 int lower,
00502 int upper)
00503 {
00504 int i;
00505 int *var;
00506 int size;
00507 int x;
00508 int result;
00509 #ifdef DD_STATS
00510 int previousSize;
00511 #endif
00512
00513 size = table->size;
00514
00515
00516 var = NULL;
00517 entry = ALLOC(int,size);
00518 if (entry == NULL) {
00519 table->errorCode = CUDD_MEMORY_OUT;
00520 goto cuddSiftingOutOfMem;
00521 }
00522 var = ALLOC(int,size);
00523 if (var == NULL) {
00524 table->errorCode = CUDD_MEMORY_OUT;
00525 goto cuddSiftingOutOfMem;
00526 }
00527
00528 for (i = 0; i < size; i++) {
00529 x = table->perm[i];
00530 entry[i] = table->subtables[x].keys;
00531 var[i] = i;
00532 }
00533
00534 qsort((void *)var,size,sizeof(int),(DD_QSFP)ddUniqueCompare);
00535
00536
00537 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00538 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00539 break;
00540 x = table->perm[var[i]];
00541
00542 if (x < lower || x > upper || table->subtables[x].bindVar == 1)
00543 continue;
00544 #ifdef DD_STATS
00545 previousSize = table->keys - table->isolated;
00546 #endif
00547 result = ddSiftingAux(table, x, lower, upper);
00548 if (!result) goto cuddSiftingOutOfMem;
00549 #ifdef DD_STATS
00550 if (table->keys < (unsigned) previousSize + table->isolated) {
00551 (void) fprintf(table->out,"-");
00552 } else if (table->keys > (unsigned) previousSize + table->isolated) {
00553 (void) fprintf(table->out,"+");
00554 (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00555 } else {
00556 (void) fprintf(table->out,"=");
00557 }
00558 fflush(table->out);
00559 #endif
00560 }
00561
00562 FREE(var);
00563 FREE(entry);
00564
00565 return(1);
00566
00567 cuddSiftingOutOfMem:
00568
00569 if (entry != NULL) FREE(entry);
00570 if (var != NULL) FREE(var);
00571
00572 return(0);
00573
00574 }
00575
00576
00595 int
00596 cuddSwapping(
00597 DdManager * table,
00598 int lower,
00599 int upper,
00600 Cudd_ReorderingType heuristic)
00601 {
00602 int i, j;
00603 int max, keys;
00604 int nvars;
00605 int x, y;
00606 int iterate;
00607 int previousSize;
00608 Move *moves, *move;
00609 int pivot;
00610 int modulo;
00611 int result;
00612
00613 #ifdef DD_DEBUG
00614
00615 assert(lower >= 0 && upper < table->size && lower <= upper);
00616 #endif
00617
00618 nvars = upper - lower + 1;
00619 iterate = nvars;
00620
00621 for (i = 0; i < iterate; i++) {
00622 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00623 break;
00624 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
00625 max = -1;
00626 for (j = lower; j <= upper; j++) {
00627 if ((keys = table->subtables[j].keys) > max) {
00628 max = keys;
00629 pivot = j;
00630 }
00631 }
00632
00633 modulo = upper - pivot;
00634 if (modulo == 0) {
00635 y = pivot;
00636 } else{
00637 y = pivot + 1 + ((int) Cudd_Random() % modulo);
00638 }
00639
00640 modulo = pivot - lower - 1;
00641 if (modulo < 1) {
00642 x = lower;
00643 } else{
00644 do {
00645 x = (int) Cudd_Random() % modulo;
00646 } while (x == y);
00647 }
00648 } else {
00649 x = ((int) Cudd_Random() % nvars) + lower;
00650 do {
00651 y = ((int) Cudd_Random() % nvars) + lower;
00652 } while (x == y);
00653 }
00654 previousSize = table->keys - table->isolated;
00655 moves = ddSwapAny(table,x,y);
00656 if (moves == NULL) goto cuddSwappingOutOfMem;
00657 result = ddSiftingBackward(table,previousSize,moves);
00658 if (!result) goto cuddSwappingOutOfMem;
00659 while (moves != NULL) {
00660 move = moves->next;
00661 cuddDeallocMove(table, moves);
00662 moves = move;
00663 }
00664 #ifdef DD_STATS
00665 if (table->keys < (unsigned) previousSize + table->isolated) {
00666 (void) fprintf(table->out,"-");
00667 } else if (table->keys > (unsigned) previousSize + table->isolated) {
00668 (void) fprintf(table->out,"+");
00669 } else {
00670 (void) fprintf(table->out,"=");
00671 }
00672 fflush(table->out);
00673 #endif
00674 #if 0
00675 (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
00676 table->keys - table->isolated);
00677 #endif
00678 }
00679
00680 return(1);
00681
00682 cuddSwappingOutOfMem:
00683 while (moves != NULL) {
00684 move = moves->next;
00685 cuddDeallocMove(table, moves);
00686 moves = move;
00687 }
00688
00689 return(0);
00690
00691 }
00692
00693
00706 int
00707 cuddNextHigh(
00708 DdManager * table,
00709 int x)
00710 {
00711 return(x+1);
00712
00713 }
00714
00715
00728 int
00729 cuddNextLow(
00730 DdManager * table,
00731 int x)
00732 {
00733 return(x-1);
00734
00735 }
00736
00737
00751 int
00752 cuddSwapInPlace(
00753 DdManager * table,
00754 int x,
00755 int y)
00756 {
00757 DdNodePtr *xlist, *ylist;
00758 int xindex, yindex;
00759 int xslots, yslots;
00760 int xshift, yshift;
00761 int oldxkeys, oldykeys;
00762 int newxkeys, newykeys;
00763 int comple, newcomplement;
00764 int i;
00765 Cudd_VariableType varType;
00766 Cudd_LazyGroupType groupType;
00767 int posn;
00768 int isolated;
00769 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00770 DdNode *g,*next;
00771 DdNodePtr *previousP;
00772 DdNode *tmp;
00773 DdNode *sentinel = &(table->sentinel);
00774 extern DD_OOMFP MMoutOfMemory;
00775 DD_OOMFP saveHandler;
00776
00777 #ifdef DD_DEBUG
00778 int count,idcheck;
00779 #endif
00780
00781 #ifdef DD_DEBUG
00782 assert(x < y);
00783 assert(cuddNextHigh(table,x) == y);
00784 assert(table->subtables[x].keys != 0);
00785 assert(table->subtables[y].keys != 0);
00786 assert(table->subtables[x].dead == 0);
00787 assert(table->subtables[y].dead == 0);
00788 #endif
00789
00790 ddTotalNumberSwapping++;
00791
00792
00793 xindex = table->invperm[x];
00794 xlist = table->subtables[x].nodelist;
00795 oldxkeys = table->subtables[x].keys;
00796 xslots = table->subtables[x].slots;
00797 xshift = table->subtables[x].shift;
00798
00799
00800 yindex = table->invperm[y];
00801 ylist = table->subtables[y].nodelist;
00802 oldykeys = table->subtables[y].keys;
00803 yslots = table->subtables[y].slots;
00804 yshift = table->subtables[y].shift;
00805
00806 if (!cuddTestInteract(table,xindex,yindex)) {
00807 #ifdef DD_STATS
00808 ddTotalNISwaps++;
00809 #endif
00810 newxkeys = oldxkeys;
00811 newykeys = oldykeys;
00812 } else {
00813 newxkeys = 0;
00814 newykeys = oldykeys;
00815
00816
00817
00818
00819
00820
00821
00822 isolated = - ((table->vars[xindex]->ref == 1) +
00823 (table->vars[yindex]->ref == 1));
00824
00825
00826
00827
00828
00829 g = NULL;
00830 if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
00831 oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
00832 for (i = 0; i < xslots; i++) {
00833 previousP = &(xlist[i]);
00834 f = *previousP;
00835 while (f != sentinel) {
00836 next = f->next;
00837 f1 = cuddT(f); f0 = cuddE(f);
00838 if (f1->index != (DdHalfWord) yindex &&
00839 Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
00840
00841 newxkeys++;
00842 *previousP = f;
00843 previousP = &(f->next);
00844 } else {
00845 f->index = yindex;
00846 f->next = g;
00847 g = f;
00848 }
00849 f = next;
00850 }
00851 *previousP = sentinel;
00852 }
00853 } else {
00854 DdNode *h = NULL;
00855 DdNodePtr *newxlist;
00856 unsigned int newxslots;
00857 int newxshift;
00858
00859
00860 for (i = 0; i < xslots; i++) {
00861 f = xlist[i];
00862 while (f != sentinel) {
00863 next = f->next;
00864 f1 = cuddT(f); f0 = cuddE(f);
00865 if (f1->index != (DdHalfWord) yindex &&
00866 Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
00867
00868 f->next = h;
00869 h = f;
00870 newxkeys++;
00871 } else {
00872 f->index = yindex;
00873 f->next = g;
00874 g = f;
00875 }
00876 f = next;
00877 }
00878 }
00879
00880 newxshift = xshift;
00881 newxslots = xslots;
00882 while ((unsigned) oldxkeys > DD_MAX_SUBTABLE_DENSITY * newxslots) {
00883 newxshift--;
00884 newxslots <<= 1;
00885 }
00886 while ((unsigned) oldxkeys < newxslots &&
00887 newxslots > table->initSlots) {
00888 newxshift++;
00889 newxslots >>= 1;
00890 }
00891
00892 saveHandler = MMoutOfMemory;
00893 MMoutOfMemory = Cudd_OutOfMem;
00894 newxlist = ALLOC(DdNodePtr, newxslots);
00895 MMoutOfMemory = saveHandler;
00896 if (newxlist == NULL) {
00897 (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
00898 newxlist = xlist;
00899 newxslots = xslots;
00900 newxshift = xshift;
00901 } else {
00902 table->slots += ((int) newxslots - xslots);
00903 table->minDead = (unsigned)
00904 (table->gcFrac * (double) table->slots);
00905 table->cacheSlack = (int)
00906 ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO
00907 * table->slots) - 2 * (int) table->cacheSlots;
00908 table->memused +=
00909 ((int) newxslots - xslots) * sizeof(DdNodePtr);
00910 FREE(xlist);
00911 xslots = newxslots;
00912 xshift = newxshift;
00913 xlist = newxlist;
00914 }
00915
00916 for (i = 0; i < xslots; i++) {
00917 xlist[i] = sentinel;
00918 }
00919
00920 f = h;
00921 while (f != NULL) {
00922 next = f->next;
00923 f1 = cuddT(f);
00924 f0 = cuddE(f);
00925
00926 posn = ddHash(f1, f0, xshift);
00927
00928 previousP = &(xlist[posn]);
00929 tmp = *previousP;
00930 while (f1 < cuddT(tmp)) {
00931 previousP = &(tmp->next);
00932 tmp = *previousP;
00933 }
00934 while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
00935 previousP = &(tmp->next);
00936 tmp = *previousP;
00937 }
00938 f->next = *previousP;
00939 *previousP = f;
00940 f = next;
00941 }
00942 }
00943
00944 #ifdef DD_COUNT
00945 table->swapSteps += oldxkeys - newxkeys;
00946 #endif
00947
00948
00949
00950
00951 f = g;
00952 while (f != NULL) {
00953 next = f->next;
00954
00955 f1 = cuddT(f);
00956 #ifdef DD_DEBUG
00957 assert(!(Cudd_IsComplement(f1)));
00958 #endif
00959 if ((int) f1->index == yindex) {
00960 f11 = cuddT(f1); f10 = cuddE(f1);
00961 } else {
00962 f11 = f10 = f1;
00963 }
00964 #ifdef DD_DEBUG
00965 assert(!(Cudd_IsComplement(f11)));
00966 #endif
00967 f0 = cuddE(f);
00968 comple = Cudd_IsComplement(f0);
00969 f0 = Cudd_Regular(f0);
00970 if ((int) f0->index == yindex) {
00971 f01 = cuddT(f0); f00 = cuddE(f0);
00972 } else {
00973 f01 = f00 = f0;
00974 }
00975 if (comple) {
00976 f01 = Cudd_Not(f01);
00977 f00 = Cudd_Not(f00);
00978 }
00979
00980 cuddSatDec(f1->ref);
00981
00982 if (f11 == f01) {
00983 newf1 = f11;
00984 cuddSatInc(newf1->ref);
00985 } else {
00986
00987 posn = ddHash(f11, f01, xshift);
00988
00989 previousP = &(xlist[posn]);
00990 newf1 = *previousP;
00991 while (f11 < cuddT(newf1)) {
00992 previousP = &(newf1->next);
00993 newf1 = *previousP;
00994 }
00995 while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
00996 previousP = &(newf1->next);
00997 newf1 = *previousP;
00998 }
00999 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
01000 cuddSatInc(newf1->ref);
01001 } else {
01002 newf1 = cuddDynamicAllocNode(table);
01003 if (newf1 == NULL)
01004 goto cuddSwapOutOfMem;
01005 newf1->index = xindex; newf1->ref = 1;
01006 cuddT(newf1) = f11;
01007 cuddE(newf1) = f01;
01008
01009
01010
01011 newxkeys++;
01012 newf1->next = *previousP;
01013 *previousP = newf1;
01014 cuddSatInc(f11->ref);
01015 tmp = Cudd_Regular(f01);
01016 cuddSatInc(tmp->ref);
01017 }
01018 }
01019 cuddT(f) = newf1;
01020 #ifdef DD_DEBUG
01021 assert(!(Cudd_IsComplement(newf1)));
01022 #endif
01023
01024
01025
01026 tmp = Cudd_Regular(f0);
01027 cuddSatDec(tmp->ref);
01028
01029 if (f10 == f00) {
01030 newf0 = f00;
01031 tmp = Cudd_Regular(newf0);
01032 cuddSatInc(tmp->ref);
01033 } else {
01034
01035 newcomplement = Cudd_IsComplement(f10);
01036 if (newcomplement) {
01037 f10 = Cudd_Not(f10);
01038 f00 = Cudd_Not(f00);
01039 }
01040
01041 posn = ddHash(f10, f00, xshift);
01042
01043 previousP = &(xlist[posn]);
01044 newf0 = *previousP;
01045 while (f10 < cuddT(newf0)) {
01046 previousP = &(newf0->next);
01047 newf0 = *previousP;
01048 }
01049 while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
01050 previousP = &(newf0->next);
01051 newf0 = *previousP;
01052 }
01053 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
01054 cuddSatInc(newf0->ref);
01055 } else {
01056 newf0 = cuddDynamicAllocNode(table);
01057 if (newf0 == NULL)
01058 goto cuddSwapOutOfMem;
01059 newf0->index = xindex; newf0->ref = 1;
01060 cuddT(newf0) = f10;
01061 cuddE(newf0) = f00;
01062
01063
01064
01065 newxkeys++;
01066 newf0->next = *previousP;
01067 *previousP = newf0;
01068 cuddSatInc(f10->ref);
01069 tmp = Cudd_Regular(f00);
01070 cuddSatInc(tmp->ref);
01071 }
01072 if (newcomplement) {
01073 newf0 = Cudd_Not(newf0);
01074 }
01075 }
01076 cuddE(f) = newf0;
01077
01078
01079
01080
01081
01082 posn = ddHash(newf1, newf0, yshift);
01083 newykeys++;
01084 previousP = &(ylist[posn]);
01085 tmp = *previousP;
01086 while (newf1 < cuddT(tmp)) {
01087 previousP = &(tmp->next);
01088 tmp = *previousP;
01089 }
01090 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
01091 previousP = &(tmp->next);
01092 tmp = *previousP;
01093 }
01094 f->next = *previousP;
01095 *previousP = f;
01096 f = next;
01097 }
01098
01099
01100
01101
01102 for (i = 0; i < yslots; i++) {
01103 previousP = &(ylist[i]);
01104 f = *previousP;
01105 while (f != sentinel) {
01106 next = f->next;
01107 if (f->ref == 0) {
01108 tmp = cuddT(f);
01109 cuddSatDec(tmp->ref);
01110 tmp = Cudd_Regular(cuddE(f));
01111 cuddSatDec(tmp->ref);
01112 cuddDeallocNode(table,f);
01113 newykeys--;
01114 } else {
01115 *previousP = f;
01116 previousP = &(f->next);
01117 }
01118 f = next;
01119 }
01120 *previousP = sentinel;
01121 }
01122
01123 #ifdef DD_DEBUG
01124 #if 0
01125 (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
01126 #endif
01127 count = 0;
01128 idcheck = 0;
01129 for (i = 0; i < yslots; i++) {
01130 f = ylist[i];
01131 while (f != sentinel) {
01132 count++;
01133 if (f->index != (DdHalfWord) yindex)
01134 idcheck++;
01135 f = f->next;
01136 }
01137 }
01138 if (count != newykeys) {
01139 (void) fprintf(table->out,
01140 "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
01141 oldykeys,newykeys,count);
01142 }
01143 if (idcheck != 0)
01144 (void) fprintf(table->out,
01145 "Error in id's of ylist\twrong id's = %d\n",
01146 idcheck);
01147 count = 0;
01148 idcheck = 0;
01149 for (i = 0; i < xslots; i++) {
01150 f = xlist[i];
01151 while (f != sentinel) {
01152 count++;
01153 if (f->index != (DdHalfWord) xindex)
01154 idcheck++;
01155 f = f->next;
01156 }
01157 }
01158 if (count != newxkeys) {
01159 (void) fprintf(table->out,
01160 "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
01161 oldxkeys,newxkeys,count);
01162 }
01163 if (idcheck != 0)
01164 (void) fprintf(table->out,
01165 "Error in id's of xlist\twrong id's = %d\n",
01166 idcheck);
01167 #endif
01168
01169 isolated += (table->vars[xindex]->ref == 1) +
01170 (table->vars[yindex]->ref == 1);
01171 table->isolated += isolated;
01172 }
01173
01174
01175 table->subtables[x].nodelist = ylist;
01176 table->subtables[x].slots = yslots;
01177 table->subtables[x].shift = yshift;
01178 table->subtables[x].keys = newykeys;
01179 table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
01180 i = table->subtables[x].bindVar;
01181 table->subtables[x].bindVar = table->subtables[y].bindVar;
01182 table->subtables[y].bindVar = i;
01183
01184 varType = table->subtables[x].varType;
01185 table->subtables[x].varType = table->subtables[y].varType;
01186 table->subtables[y].varType = varType;
01187 i = table->subtables[x].pairIndex;
01188 table->subtables[x].pairIndex = table->subtables[y].pairIndex;
01189 table->subtables[y].pairIndex = i;
01190 i = table->subtables[x].varHandled;
01191 table->subtables[x].varHandled = table->subtables[y].varHandled;
01192 table->subtables[y].varHandled = i;
01193 groupType = table->subtables[x].varToBeGrouped;
01194 table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
01195 table->subtables[y].varToBeGrouped = groupType;
01196
01197 table->subtables[y].nodelist = xlist;
01198 table->subtables[y].slots = xslots;
01199 table->subtables[y].shift = xshift;
01200 table->subtables[y].keys = newxkeys;
01201 table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
01202
01203 table->perm[xindex] = y; table->perm[yindex] = x;
01204 table->invperm[x] = yindex; table->invperm[y] = xindex;
01205
01206 table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
01207
01208 return(table->keys - table->isolated);
01209
01210 cuddSwapOutOfMem:
01211 (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
01212
01213 return (0);
01214
01215 }
01216
01217
01241 int
01242 cuddBddAlignToZdd(
01243 DdManager * table )
01244 {
01245 int *invperm;
01246 int M;
01247 int i;
01248 int result;
01249
01250
01251 if (table->size == 0)
01252 return(1);
01253
01254 M = table->sizeZ / table->size;
01255
01256
01257
01258 if (M * table->size != table->sizeZ)
01259 return(0);
01260
01261 invperm = ALLOC(int,table->size);
01262 if (invperm == NULL) {
01263 table->errorCode = CUDD_MEMORY_OUT;
01264 return(0);
01265 }
01266 for (i = 0; i < table->sizeZ; i += M) {
01267 int indexZ = table->invpermZ[i];
01268 int index = indexZ / M;
01269 invperm[i / M] = index;
01270 }
01271
01272
01273
01274 cuddGarbageCollect(table,0);
01275
01276
01277 table->isolated = 0;
01278 for (i = 0; i < table->size; i++) {
01279 if (table->vars[i]->ref == 1) table->isolated++;
01280 }
01281
01282
01283 result = cuddInitInteract(table);
01284 if (result == 0) return(0);
01285
01286 result = ddShuffle(table, invperm);
01287 FREE(invperm);
01288
01289 FREE(table->interact);
01290
01291 bddFixTree(table,table->tree);
01292 return(result);
01293
01294 }
01295
01296
01297
01298
01299
01300
01313 static int
01314 ddUniqueCompare(
01315 int * ptrX,
01316 int * ptrY)
01317 {
01318 #if 0
01319 if (entry[*ptrY] == entry[*ptrX]) {
01320 return((*ptrX) - (*ptrY));
01321 }
01322 #endif
01323 return(entry[*ptrY] - entry[*ptrX]);
01324
01325 }
01326
01327
01337 static Move *
01338 ddSwapAny(
01339 DdManager * table,
01340 int x,
01341 int y)
01342 {
01343 Move *move, *moves;
01344 int xRef,yRef;
01345 int xNext,yNext;
01346 int size;
01347 int limitSize;
01348 int tmp;
01349
01350 if (x >y) {
01351 tmp = x; x = y; y = tmp;
01352 }
01353
01354 xRef = x; yRef = y;
01355
01356 xNext = cuddNextHigh(table,x);
01357 yNext = cuddNextLow(table,y);
01358 moves = NULL;
01359 limitSize = table->keys - table->isolated;
01360
01361 for (;;) {
01362 if ( xNext == yNext) {
01363 size = cuddSwapInPlace(table,x,xNext);
01364 if (size == 0) goto ddSwapAnyOutOfMem;
01365 move = (Move *) cuddDynamicAllocNode(table);
01366 if (move == NULL) goto ddSwapAnyOutOfMem;
01367 move->x = x;
01368 move->y = xNext;
01369 move->size = size;
01370 move->next = moves;
01371 moves = move;
01372
01373 size = cuddSwapInPlace(table,yNext,y);
01374 if (size == 0) goto ddSwapAnyOutOfMem;
01375 move = (Move *) cuddDynamicAllocNode(table);
01376 if (move == NULL) goto ddSwapAnyOutOfMem;
01377 move->x = yNext;
01378 move->y = y;
01379 move->size = size;
01380 move->next = moves;
01381 moves = move;
01382
01383 size = cuddSwapInPlace(table,x,xNext);
01384 if (size == 0) goto ddSwapAnyOutOfMem;
01385 move = (Move *) cuddDynamicAllocNode(table);
01386 if (move == NULL) goto ddSwapAnyOutOfMem;
01387 move->x = x;
01388 move->y = xNext;
01389 move->size = size;
01390 move->next = moves;
01391 moves = move;
01392
01393 tmp = x; x = y; y = tmp;
01394
01395 } else if (x == yNext) {
01396
01397 size = cuddSwapInPlace(table,x,xNext);
01398 if (size == 0) goto ddSwapAnyOutOfMem;
01399 move = (Move *) cuddDynamicAllocNode(table);
01400 if (move == NULL) goto ddSwapAnyOutOfMem;
01401 move->x = x;
01402 move->y = xNext;
01403 move->size = size;
01404 move->next = moves;
01405 moves = move;
01406
01407 tmp = x; x = y; y = tmp;
01408
01409 } else {
01410 size = cuddSwapInPlace(table,x,xNext);
01411 if (size == 0) goto ddSwapAnyOutOfMem;
01412 move = (Move *) cuddDynamicAllocNode(table);
01413 if (move == NULL) goto ddSwapAnyOutOfMem;
01414 move->x = x;
01415 move->y = xNext;
01416 move->size = size;
01417 move->next = moves;
01418 moves = move;
01419
01420 size = cuddSwapInPlace(table,yNext,y);
01421 if (size == 0) goto ddSwapAnyOutOfMem;
01422 move = (Move *) cuddDynamicAllocNode(table);
01423 if (move == NULL) goto ddSwapAnyOutOfMem;
01424 move->x = yNext;
01425 move->y = y;
01426 move->size = size;
01427 move->next = moves;
01428 moves = move;
01429
01430 x = xNext;
01431 y = yNext;
01432 }
01433
01434 xNext = cuddNextHigh(table,x);
01435 yNext = cuddNextLow(table,y);
01436 if (xNext > yRef) break;
01437
01438 if ((double) size > table->maxGrowth * (double) limitSize) break;
01439 if (size < limitSize) limitSize = size;
01440 }
01441 if (yNext>=xRef) {
01442 size = cuddSwapInPlace(table,yNext,y);
01443 if (size == 0) goto ddSwapAnyOutOfMem;
01444 move = (Move *) cuddDynamicAllocNode(table);
01445 if (move == NULL) goto ddSwapAnyOutOfMem;
01446 move->x = yNext;
01447 move->y = y;
01448 move->size = size;
01449 move->next = moves;
01450 moves = move;
01451 }
01452
01453 return(moves);
01454
01455 ddSwapAnyOutOfMem:
01456 while (moves != NULL) {
01457 move = moves->next;
01458 cuddDeallocMove(table, moves);
01459 moves = move;
01460 }
01461 return(NULL);
01462
01463 }
01464
01465
01478 static int
01479 ddSiftingAux(
01480 DdManager * table,
01481 int x,
01482 int xLow,
01483 int xHigh)
01484 {
01485
01486 Move *move;
01487 Move *moveUp;
01488 Move *moveDown;
01489 int initialSize;
01490 int result;
01491
01492 initialSize = table->keys - table->isolated;
01493
01494 moveDown = NULL;
01495 moveUp = NULL;
01496
01497 if (x == xLow) {
01498 moveDown = ddSiftingDown(table,x,xHigh);
01499
01500 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01501
01502 result = ddSiftingBackward(table,initialSize,moveDown);
01503 if (!result) goto ddSiftingAuxOutOfMem;
01504
01505 } else if (x == xHigh) {
01506 moveUp = ddSiftingUp(table,x,xLow);
01507
01508 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01509
01510 result = ddSiftingBackward(table,initialSize,moveUp);
01511 if (!result) goto ddSiftingAuxOutOfMem;
01512
01513 } else if ((x - xLow) > (xHigh - x)) {
01514 moveDown = ddSiftingDown(table,x,xHigh);
01515
01516 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01517 if (moveDown != NULL) {
01518 x = moveDown->y;
01519 }
01520 moveUp = ddSiftingUp(table,x,xLow);
01521 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01522
01523 result = ddSiftingBackward(table,initialSize,moveUp);
01524 if (!result) goto ddSiftingAuxOutOfMem;
01525
01526 } else {
01527 moveUp = ddSiftingUp(table,x,xLow);
01528
01529 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01530 if (moveUp != NULL) {
01531 x = moveUp->x;
01532 }
01533 moveDown = ddSiftingDown(table,x,xHigh);
01534 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01535
01536 result = ddSiftingBackward(table,initialSize,moveDown);
01537 if (!result) goto ddSiftingAuxOutOfMem;
01538 }
01539
01540 while (moveDown != NULL) {
01541 move = moveDown->next;
01542 cuddDeallocMove(table, moveDown);
01543 moveDown = move;
01544 }
01545 while (moveUp != NULL) {
01546 move = moveUp->next;
01547 cuddDeallocMove(table, moveUp);
01548 moveUp = move;
01549 }
01550
01551 return(1);
01552
01553 ddSiftingAuxOutOfMem:
01554 if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
01555 while (moveDown != NULL) {
01556 move = moveDown->next;
01557 cuddDeallocMove(table, moveDown);
01558 moveDown = move;
01559 }
01560 }
01561 if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
01562 while (moveUp != NULL) {
01563 move = moveUp->next;
01564 cuddDeallocMove(table, moveUp);
01565 moveUp = move;
01566 }
01567 }
01568
01569 return(0);
01570
01571 }
01572
01573
01585 static Move *
01586 ddSiftingUp(
01587 DdManager * table,
01588 int y,
01589 int xLow)
01590 {
01591 Move *moves;
01592 Move *move;
01593 int x;
01594 int size;
01595 int limitSize;
01596 int xindex, yindex;
01597 int isolated;
01598 int L;
01599 #ifdef DD_DEBUG
01600 int checkL;
01601 int z;
01602 int zindex;
01603 #endif
01604
01605 moves = NULL;
01606 yindex = table->invperm[y];
01607
01608
01609
01610
01611
01612
01613
01614 limitSize = L = table->keys - table->isolated;
01615 for (x = xLow + 1; x < y; x++) {
01616 xindex = table->invperm[x];
01617 if (cuddTestInteract(table,xindex,yindex)) {
01618 isolated = table->vars[xindex]->ref == 1;
01619 L -= table->subtables[x].keys - isolated;
01620 }
01621 }
01622 isolated = table->vars[yindex]->ref == 1;
01623 L -= table->subtables[y].keys - isolated;
01624
01625 x = cuddNextLow(table,y);
01626 while (x >= xLow && L <= limitSize) {
01627 xindex = table->invperm[x];
01628 #ifdef DD_DEBUG
01629 checkL = table->keys - table->isolated;
01630 for (z = xLow + 1; z < y; z++) {
01631 zindex = table->invperm[z];
01632 if (cuddTestInteract(table,zindex,yindex)) {
01633 isolated = table->vars[zindex]->ref == 1;
01634 checkL -= table->subtables[z].keys - isolated;
01635 }
01636 }
01637 isolated = table->vars[yindex]->ref == 1;
01638 checkL -= table->subtables[y].keys - isolated;
01639 assert(L == checkL);
01640 #endif
01641 size = cuddSwapInPlace(table,x,y);
01642 if (size == 0) goto ddSiftingUpOutOfMem;
01643
01644 if (cuddTestInteract(table,xindex,yindex)) {
01645 isolated = table->vars[xindex]->ref == 1;
01646 L += table->subtables[y].keys - isolated;
01647 }
01648 move = (Move *) cuddDynamicAllocNode(table);
01649 if (move == NULL) goto ddSiftingUpOutOfMem;
01650 move->x = x;
01651 move->y = y;
01652 move->size = size;
01653 move->next = moves;
01654 moves = move;
01655 if ((double) size > (double) limitSize * table->maxGrowth) break;
01656 if (size < limitSize) limitSize = size;
01657 y = x;
01658 x = cuddNextLow(table,y);
01659 }
01660 return(moves);
01661
01662 ddSiftingUpOutOfMem:
01663 while (moves != NULL) {
01664 move = moves->next;
01665 cuddDeallocMove(table, moves);
01666 moves = move;
01667 }
01668 return((Move *) CUDD_OUT_OF_MEM);
01669
01670 }
01671
01672
01685 static Move *
01686 ddSiftingDown(
01687 DdManager * table,
01688 int x,
01689 int xHigh)
01690 {
01691 Move *moves;
01692 Move *move;
01693 int y;
01694 int size;
01695 int R;
01696 int limitSize;
01697 int xindex, yindex;
01698 int isolated;
01699 #ifdef DD_DEBUG
01700 int checkR;
01701 int z;
01702 int zindex;
01703 #endif
01704
01705 moves = NULL;
01706
01707 xindex = table->invperm[x];
01708 limitSize = size = table->keys - table->isolated;
01709 R = 0;
01710 for (y = xHigh; y > x; y--) {
01711 yindex = table->invperm[y];
01712 if (cuddTestInteract(table,xindex,yindex)) {
01713 isolated = table->vars[yindex]->ref == 1;
01714 R += table->subtables[y].keys - isolated;
01715 }
01716 }
01717
01718 y = cuddNextHigh(table,x);
01719 while (y <= xHigh && size - R < limitSize) {
01720 #ifdef DD_DEBUG
01721 checkR = 0;
01722 for (z = xHigh; z > x; z--) {
01723 zindex = table->invperm[z];
01724 if (cuddTestInteract(table,xindex,zindex)) {
01725 isolated = table->vars[zindex]->ref == 1;
01726 checkR += table->subtables[z].keys - isolated;
01727 }
01728 }
01729 assert(R == checkR);
01730 #endif
01731
01732 yindex = table->invperm[y];
01733 if (cuddTestInteract(table,xindex,yindex)) {
01734 isolated = table->vars[yindex]->ref == 1;
01735 R -= table->subtables[y].keys - isolated;
01736 }
01737 size = cuddSwapInPlace(table,x,y);
01738 if (size == 0) goto ddSiftingDownOutOfMem;
01739 move = (Move *) cuddDynamicAllocNode(table);
01740 if (move == NULL) goto ddSiftingDownOutOfMem;
01741 move->x = x;
01742 move->y = y;
01743 move->size = size;
01744 move->next = moves;
01745 moves = move;
01746 if ((double) size > (double) limitSize * table->maxGrowth) break;
01747 if (size < limitSize) limitSize = size;
01748 x = y;
01749 y = cuddNextHigh(table,x);
01750 }
01751 return(moves);
01752
01753 ddSiftingDownOutOfMem:
01754 while (moves != NULL) {
01755 move = moves->next;
01756 cuddDeallocMove(table, moves);
01757 moves = move;
01758 }
01759 return((Move *) CUDD_OUT_OF_MEM);
01760
01761 }
01762
01763
01777 static int
01778 ddSiftingBackward(
01779 DdManager * table,
01780 int size,
01781 Move * moves)
01782 {
01783 Move *move;
01784 int res;
01785
01786 for (move = moves; move != NULL; move = move->next) {
01787 if (move->size < size) {
01788 size = move->size;
01789 }
01790 }
01791
01792 for (move = moves; move != NULL; move = move->next) {
01793 if (move->size == size) return(1);
01794 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01795 if (!res) return(0);
01796 }
01797
01798 return(1);
01799
01800 }
01801
01802
01816 static int
01817 ddReorderPreprocess(
01818 DdManager * table)
01819 {
01820 int i;
01821 int res;
01822
01823
01824 cuddCacheFlush(table);
01825 cuddLocalCacheClearAll(table);
01826
01827
01828 cuddGarbageCollect(table,0);
01829
01830
01831 table->isolated = 0;
01832 for (i = 0; i < table->size; i++) {
01833 if (table->vars[i]->ref == 1) table->isolated++;
01834 }
01835
01836
01837 res = cuddInitInteract(table);
01838 if (res == 0) return(0);
01839
01840 return(1);
01841
01842 }
01843
01844
01854 static int
01855 ddReorderPostprocess(
01856 DdManager * table)
01857 {
01858
01859 #ifdef DD_VERBOSE
01860 (void) fflush(table->out);
01861 #endif
01862
01863
01864 FREE(table->interact);
01865
01866 return(1);
01867
01868 }
01869
01870
01887 static int
01888 ddShuffle(
01889 DdManager * table,
01890 int * permutation)
01891 {
01892 int index;
01893 int level;
01894 int position;
01895 int numvars;
01896 int result;
01897 #ifdef DD_STATS
01898 long localTime;
01899 int initialSize;
01900 int finalSize;
01901 int previousSize;
01902 #endif
01903
01904 ddTotalNumberSwapping = 0;
01905 #ifdef DD_STATS
01906 localTime = util_cpu_time();
01907 initialSize = table->keys - table->isolated;
01908 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
01909 initialSize);
01910 ddTotalNISwaps = 0;
01911 #endif
01912
01913 numvars = table->size;
01914
01915 for (level = 0; level < numvars; level++) {
01916 index = permutation[level];
01917 position = table->perm[index];
01918 #ifdef DD_STATS
01919 previousSize = table->keys - table->isolated;
01920 #endif
01921 result = ddSiftUp(table,position,level);
01922 if (!result) return(0);
01923 #ifdef DD_STATS
01924 if (table->keys < (unsigned) previousSize + table->isolated) {
01925 (void) fprintf(table->out,"-");
01926 } else if (table->keys > (unsigned) previousSize + table->isolated) {
01927 (void) fprintf(table->out,"+");
01928 } else {
01929 (void) fprintf(table->out,"=");
01930 }
01931 fflush(table->out);
01932 #endif
01933 }
01934
01935 #ifdef DD_STATS
01936 (void) fprintf(table->out,"\n");
01937 finalSize = table->keys - table->isolated;
01938 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
01939 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
01940 ((double)(util_cpu_time() - localTime)/1000.0));
01941 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
01942 ddTotalNumberSwapping);
01943 (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
01944 #endif
01945
01946 return(1);
01947
01948 }
01949
01950
01964 static int
01965 ddSiftUp(
01966 DdManager * table,
01967 int x,
01968 int xLow)
01969 {
01970 int y;
01971 int size;
01972
01973 y = cuddNextLow(table,x);
01974 while (y >= xLow) {
01975 size = cuddSwapInPlace(table,y,x);
01976 if (size == 0) {
01977 return(0);
01978 }
01979 x = y;
01980 y = cuddNextLow(table,x);
01981 }
01982 return(1);
01983
01984 }
01985
01986
02000 static void
02001 bddFixTree(
02002 DdManager * table,
02003 MtrNode * treenode)
02004 {
02005 if (treenode == NULL) return;
02006 treenode->low = ((int) treenode->index < table->size) ?
02007 table->perm[treenode->index] : treenode->index;
02008 if (treenode->child != NULL) {
02009 bddFixTree(table, treenode->child);
02010 }
02011 if (treenode->younger != NULL)
02012 bddFixTree(table, treenode->younger);
02013 if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
02014 treenode->parent->low = treenode->low;
02015 treenode->parent->index = treenode->index;
02016 }
02017 return;
02018
02019 }
02020
02021
02034 static int
02035 ddUpdateMtrTree(
02036 DdManager * table,
02037 MtrNode * treenode,
02038 int * perm,
02039 int * invperm)
02040 {
02041 unsigned int i, size;
02042 int index, level, minLevel, maxLevel, minIndex;
02043
02044 if (treenode == NULL) return(1);
02045
02046 minLevel = CUDD_MAXINDEX;
02047 maxLevel = 0;
02048 minIndex = -1;
02049
02050 for (i = treenode->low; i < treenode->low + treenode->size; i++) {
02051 index = table->invperm[i];
02052 level = perm[index];
02053 if (level < minLevel) {
02054 minLevel = level;
02055 minIndex = index;
02056 }
02057 if (level > maxLevel)
02058 maxLevel = level;
02059 }
02060 size = maxLevel - minLevel + 1;
02061 if (minIndex == -1) return(0);
02062 if (size == treenode->size) {
02063 treenode->low = minLevel;
02064 treenode->index = minIndex;
02065 } else {
02066 return(0);
02067 }
02068
02069 if (treenode->child != NULL) {
02070 if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
02071 return(0);
02072 }
02073 if (treenode->younger != NULL) {
02074 if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
02075 return(0);
02076 }
02077 return(1);
02078 }
02079
02080
02093 static int
02094 ddCheckPermuation(
02095 DdManager * table,
02096 MtrNode * treenode,
02097 int * perm,
02098 int * invperm)
02099 {
02100 unsigned int i, size;
02101 int index, level, minLevel, maxLevel;
02102
02103 if (treenode == NULL) return(1);
02104
02105 minLevel = table->size;
02106 maxLevel = 0;
02107
02108 for (i = treenode->low; i < treenode->low + treenode->size; i++) {
02109 index = table->invperm[i];
02110 level = perm[index];
02111 if (level < minLevel)
02112 minLevel = level;
02113 if (level > maxLevel)
02114 maxLevel = level;
02115 }
02116 size = maxLevel - minLevel + 1;
02117 if (size != treenode->size)
02118 return(0);
02119
02120 if (treenode->child != NULL) {
02121 if (!ddCheckPermuation(table, treenode->child, perm, invperm))
02122 return(0);
02123 }
02124 if (treenode->younger != NULL) {
02125 if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
02126 return(0);
02127 }
02128 return(1);
02129 }