00001
00048 #include "util_hack.h"
00049 #include "cuddInt.h"
00050
00051
00052
00053
00054
00055 #define DD_MAX_SUBTABLE_SPARSITY 8
00056 #define DD_SHRINK_FACTOR 2
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #ifndef lint
00071 static char rcsid[] DD_UNUSED = "$Id: cuddReorder.c,v 1.1.1.1 2003/02/24 22:23:53 wjiang Exp $";
00072 #endif
00073
00074 static int *entry;
00075
00076 int ddTotalNumberSwapping;
00077 #ifdef DD_STATS
00078 int ddTotalNISwaps;
00079 #endif
00080
00081
00082
00083
00084
00087
00088
00089
00090
00091 static int ddUniqueCompare ARGS((int *ptrX, int *ptrY));
00092 static Move * ddSwapAny ARGS((DdManager *table, int x, int y));
00093 static int ddSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh));
00094 static Move * ddSiftingUp ARGS((DdManager *table, int y, int xLow));
00095 static Move * ddSiftingDown ARGS((DdManager *table, int x, int xHigh));
00096 static int ddSiftingBackward ARGS((DdManager *table, int size, Move *moves));
00097 static int ddReorderPreprocess ARGS((DdManager *table));
00098 static int ddReorderPostprocess ARGS((DdManager *table));
00099 static int ddShuffle ARGS((DdManager *table, int *permutation));
00100 static int ddSiftUp ARGS((DdManager *table, int x, int xLow));
00101 static void bddFixTree ARGS((DdManager *table, MtrNode *treenode));
00102 static int ddUpdateMtrTree ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm));
00103 static int ddCheckPermuation ARGS((DdManager *table, MtrNode *treenode, int *perm, int *invperm));
00104
00108
00109
00110
00111
00112
00144 int
00145 Cudd_ReduceHeap(
00146 DdManager * table ,
00147 Cudd_ReorderingType heuristic ,
00148 int minsize )
00149 {
00150 DdHook *hook;
00151 int result;
00152 unsigned int nextDyn;
00153 #ifdef DD_STATS
00154 unsigned int initialSize;
00155 unsigned int finalSize;
00156 #endif
00157 long localTime;
00158
00159
00160 if (table->keys - table->dead < (unsigned) minsize)
00161 return(1);
00162
00163 if (heuristic == CUDD_REORDER_SAME) {
00164 heuristic = table->autoMethod;
00165 }
00166 if (heuristic == CUDD_REORDER_NONE) {
00167 return(1);
00168 }
00169
00170
00171
00172
00173 table->reorderings++;
00174
00175 localTime = util_cpu_time();
00176
00177
00178 hook = table->preReorderingHook;
00179 while (hook != NULL) {
00180 int res = (hook->f)(table, "BDD", (void *)heuristic);
00181 if (res == 0) return(0);
00182 hook = hook->next;
00183 }
00184
00185 if (!ddReorderPreprocess(table)) return(0);
00186 ddTotalNumberSwapping = 0;
00187
00188 if (table->keys > table->peakLiveNodes) {
00189 table->peakLiveNodes = table->keys;
00190 }
00191 #ifdef DD_STATS
00192 initialSize = table->keys - table->isolated;
00193 ddTotalNISwaps = 0;
00194
00195 switch(heuristic) {
00196 case CUDD_REORDER_RANDOM:
00197 case CUDD_REORDER_RANDOM_PIVOT:
00198 (void) fprintf(table->out,"#:I_RANDOM ");
00199 break;
00200 case CUDD_REORDER_SIFT:
00201 case CUDD_REORDER_SIFT_CONVERGE:
00202 case CUDD_REORDER_SYMM_SIFT:
00203 case CUDD_REORDER_SYMM_SIFT_CONV:
00204 case CUDD_REORDER_GROUP_SIFT:
00205 case CUDD_REORDER_GROUP_SIFT_CONV:
00206 (void) fprintf(table->out,"#:I_SIFTING ");
00207 break;
00208 case CUDD_REORDER_WINDOW2:
00209 case CUDD_REORDER_WINDOW3:
00210 case CUDD_REORDER_WINDOW4:
00211 case CUDD_REORDER_WINDOW2_CONV:
00212 case CUDD_REORDER_WINDOW3_CONV:
00213 case CUDD_REORDER_WINDOW4_CONV:
00214 (void) fprintf(table->out,"#:I_WINDOW ");
00215 break;
00216 case CUDD_REORDER_ANNEALING:
00217 (void) fprintf(table->out,"#:I_ANNEAL ");
00218 break;
00219 case CUDD_REORDER_GENETIC:
00220 (void) fprintf(table->out,"#:I_GENETIC ");
00221 break;
00222 case CUDD_REORDER_LINEAR:
00223 case CUDD_REORDER_LINEAR_CONVERGE:
00224 (void) fprintf(table->out,"#:I_LINSIFT ");
00225 break;
00226 case CUDD_REORDER_EXACT:
00227 (void) fprintf(table->out,"#:I_EXACT ");
00228 break;
00229 default:
00230 return(0);
00231 }
00232 (void) fprintf(table->out,"%8d: initial size",initialSize);
00233 #endif
00234
00235
00236 if (table->reordCycle && table->reorderings % table->reordCycle == 0) {
00237 double saveGrowth = table->maxGrowth;
00238 table->maxGrowth = table->maxGrowthAlt;
00239 result = cuddTreeSifting(table,heuristic);
00240 table->maxGrowth = saveGrowth;
00241 } else {
00242 result = cuddTreeSifting(table,heuristic);
00243 }
00244
00245 #ifdef DD_STATS
00246 (void) fprintf(table->out,"\n");
00247 finalSize = table->keys - table->isolated;
00248 (void) fprintf(table->out,"#:F_REORDER %8d: final size\n",finalSize);
00249 (void) fprintf(table->out,"#:T_REORDER %8g: total time (sec)\n",
00250 ((double)(util_cpu_time() - localTime)/1000.0));
00251 (void) fprintf(table->out,"#:N_REORDER %8d: total swaps\n",
00252 ddTotalNumberSwapping);
00253 (void) fprintf(table->out,"#:M_REORDER %8d: NI swaps\n",ddTotalNISwaps);
00254 #endif
00255
00256 if (result == 0)
00257 return(0);
00258
00259 if (!ddReorderPostprocess(table))
00260 return(0);
00261
00262 if (table->realign) {
00263 if (!cuddZddAlignToBdd(table))
00264 return(0);
00265 }
00266
00267 nextDyn = (table->keys - table->constants.keys + 1) *
00268 DD_DYN_RATIO + table->constants.keys;
00269 if (table->reorderings < 20 || nextDyn > table->nextDyn)
00270 table->nextDyn = nextDyn;
00271 else
00272 table->nextDyn += 20;
00273 table->reordered = 1;
00274
00275
00276 hook = table->postReorderingHook;
00277 while (hook != NULL) {
00278 int res = (hook->f)(table, "BDD", (void *)localTime);
00279 if (res == 0) return(0);
00280 hook = hook->next;
00281 }
00282
00283 table->reordTime += util_cpu_time() - localTime;
00284
00285 return(result);
00286
00287 }
00288
00289
00306 int
00307 Cudd_ShuffleHeap(
00308 DdManager * table ,
00309 int * permutation )
00310 {
00311
00312 int result;
00313 int i;
00314 int identity = 1;
00315 int *perm;
00316
00317
00318 for (i = 0; i < table->size; i++) {
00319 if (permutation[i] != table->invperm[i]) {
00320 identity = 0;
00321 break;
00322 }
00323 }
00324 if (identity == 1) {
00325 return(1);
00326 }
00327 if (!ddReorderPreprocess(table)) return(0);
00328 if (table->keys > table->peakLiveNodes) {
00329 table->peakLiveNodes = table->keys;
00330 }
00331
00332 perm = ALLOC(int, table->size);
00333 for (i = 0; i < table->size; i++)
00334 perm[permutation[i]] = i;
00335 if (!ddCheckPermuation(table,table->tree,perm,permutation)) {
00336 FREE(perm);
00337 return(0);
00338 }
00339 if (!ddUpdateMtrTree(table,table->tree,perm,permutation)) {
00340 FREE(perm);
00341 return(0);
00342 }
00343 FREE(perm);
00344
00345 result = ddShuffle(table,permutation);
00346
00347 if (!ddReorderPostprocess(table)) return(0);
00348
00349 return(result);
00350
00351 }
00352
00353
00354
00355
00356
00357
00358
00374 DdNode *
00375 cuddDynamicAllocNode(
00376 DdManager * table)
00377 {
00378 int i;
00379 DdNodePtr *mem;
00380 DdNode *list, *node;
00381 extern void (*MMoutOfMemory)(long);
00382 void (*saveHandler)(long);
00383
00384 if (table->nextFree == NULL) {
00385
00386 saveHandler = MMoutOfMemory;
00387 MMoutOfMemory = Cudd_OutOfMem;
00388 mem = (DdNodePtr *) ALLOC(DdNode, DD_MEM_CHUNK + 1);
00389 MMoutOfMemory = saveHandler;
00390 if (mem == NULL && table->stash != NULL) {
00391 FREE(table->stash);
00392 table->stash = NULL;
00393
00394 table->maxCacheHard = table->cacheSlots - 1;
00395 table->cacheSlack = -(table->cacheSlots + 1);
00396 for (i = 0; i < table->size; i++) {
00397 table->subtables[i].maxKeys <<= 2;
00398 }
00399 mem = (DdNodePtr *) ALLOC(DdNode,DD_MEM_CHUNK + 1);
00400 }
00401 if (mem == NULL) {
00402
00403
00404
00405
00406 (*MMoutOfMemory)(sizeof(DdNode)*(DD_MEM_CHUNK + 1));
00407 table->errorCode = CUDD_MEMORY_OUT;
00408 #ifdef DD_VERBOSE
00409 (void) fprintf(table->err,
00410 "cuddDynamicAllocNode: out of memory");
00411 (void) fprintf(table->err,"Memory in use = %ld\n",
00412 table->memused);
00413 #endif
00414 return(NULL);
00415 } else {
00416 unsigned long offset;
00417 table->memused += (DD_MEM_CHUNK + 1) * sizeof(DdNode);
00418 mem[0] = (DdNode *) table->memoryList;
00419 table->memoryList = mem;
00420
00421
00422
00423
00424
00425 offset = (unsigned long) mem & (sizeof(DdNode) - 1);
00426 mem += (sizeof(DdNode) - offset) / sizeof(DdNodePtr);
00427 #ifdef DD_DEBUG
00428 assert(((unsigned long) mem & (sizeof(DdNode) - 1)) == 0);
00429 #endif
00430 list = (DdNode *) mem;
00431
00432 i = 1;
00433 do {
00434 list[i - 1].next = &list[i];
00435 } while (++i < DD_MEM_CHUNK);
00436
00437 list[DD_MEM_CHUNK - 1].next = NULL;
00438
00439 table->nextFree = &list[0];
00440 }
00441 }
00442
00443 node = table->nextFree;
00444 table->nextFree = node->next;
00445 return (node);
00446
00447 }
00448
00449
00469 int
00470 cuddSifting(
00471 DdManager * table,
00472 int lower,
00473 int upper)
00474 {
00475 int i;
00476 int *var;
00477 int size;
00478 int x;
00479 int result;
00480 #ifdef DD_STATS
00481 int previousSize;
00482 #endif
00483
00484 size = table->size;
00485
00486
00487 var = NULL;
00488 entry = ALLOC(int,size);
00489 if (entry == NULL) {
00490 table->errorCode = CUDD_MEMORY_OUT;
00491 goto cuddSiftingOutOfMem;
00492 }
00493 var = ALLOC(int,size);
00494 if (var == NULL) {
00495 table->errorCode = CUDD_MEMORY_OUT;
00496 goto cuddSiftingOutOfMem;
00497 }
00498
00499 for (i = 0; i < size; i++) {
00500 x = table->perm[i];
00501 entry[i] = table->subtables[x].keys;
00502 var[i] = i;
00503 }
00504
00505 qsort((void *)var,size,sizeof(int),(int (*)(const void *, const void *))ddUniqueCompare);
00506
00507
00508 for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
00509 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00510 break;
00511 x = table->perm[var[i]];
00512
00513 if (x < lower || x > upper || table->subtables[x].bindVar == 1)
00514 continue;
00515 #ifdef DD_STATS
00516 previousSize = table->keys - table->isolated;
00517 #endif
00518 result = ddSiftingAux(table, x, lower, upper);
00519 if (!result) goto cuddSiftingOutOfMem;
00520 #ifdef DD_STATS
00521 if (table->keys < (unsigned) previousSize + table->isolated) {
00522 (void) fprintf(table->out,"-");
00523 } else if (table->keys > (unsigned) previousSize + table->isolated) {
00524 (void) fprintf(table->out,"+");
00525 (void) fprintf(table->err,"\nSize increased from %d to %d while sifting variable %d\n", previousSize, table->keys - table->isolated, var[i]);
00526 } else {
00527 (void) fprintf(table->out,"=");
00528 }
00529 fflush(table->out);
00530 #endif
00531 }
00532
00533 FREE(var);
00534 FREE(entry);
00535
00536 return(1);
00537
00538 cuddSiftingOutOfMem:
00539
00540 if (entry != NULL) FREE(entry);
00541 if (var != NULL) FREE(var);
00542
00543 return(0);
00544
00545 }
00546
00547
00566 int
00567 cuddSwapping(
00568 DdManager * table,
00569 int lower,
00570 int upper,
00571 Cudd_ReorderingType heuristic)
00572 {
00573 int i, j;
00574 int max, keys;
00575 int nvars;
00576 int x, y;
00577 int iterate;
00578 int previousSize;
00579 Move *moves, *move;
00580 int pivot;
00581 int modulo;
00582 int result;
00583
00584 #ifdef DD_DEBUG
00585
00586 assert(lower >= 0 && upper < table->size && lower <= upper);
00587 #endif
00588
00589 nvars = upper - lower + 1;
00590 iterate = nvars;
00591
00592 for (i = 0; i < iterate; i++) {
00593 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00594 break;
00595 if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
00596 max = -1;
00597 for (j = lower; j <= upper; j++) {
00598 if ((keys = table->subtables[j].keys) > max) {
00599 max = keys;
00600 pivot = j;
00601 }
00602 }
00603
00604 modulo = upper - pivot;
00605 if (modulo == 0) {
00606 y = pivot;
00607 } else{
00608 y = pivot + 1 + ((int) Cudd_Random() % modulo);
00609 }
00610
00611 modulo = pivot - lower - 1;
00612 if (modulo < 1) {
00613 x = lower;
00614 } else{
00615 do {
00616 x = (int) Cudd_Random() % modulo;
00617 } while (x == y);
00618 }
00619 } else {
00620 x = ((int) Cudd_Random() % nvars) + lower;
00621 do {
00622 y = ((int) Cudd_Random() % nvars) + lower;
00623 } while (x == y);
00624 }
00625 previousSize = table->keys - table->isolated;
00626 moves = ddSwapAny(table,x,y);
00627 if (moves == NULL) goto cuddSwappingOutOfMem;
00628 result = ddSiftingBackward(table,previousSize,moves);
00629 if (!result) goto cuddSwappingOutOfMem;
00630 while (moves != NULL) {
00631 move = moves->next;
00632 cuddDeallocNode(table, (DdNode *) moves);
00633 moves = move;
00634 }
00635 #ifdef DD_STATS
00636 if (table->keys < (unsigned) previousSize + table->isolated) {
00637 (void) fprintf(table->out,"-");
00638 } else if (table->keys > (unsigned) previousSize + table->isolated) {
00639 (void) fprintf(table->out,"+");
00640 } else {
00641 (void) fprintf(table->out,"=");
00642 }
00643 fflush(table->out);
00644 #endif
00645 #if 0
00646 (void) fprintf(table->out,"#:t_SWAPPING %8d: tmp size\n",
00647 table->keys - table->isolated);
00648 #endif
00649 }
00650
00651 return(1);
00652
00653 cuddSwappingOutOfMem:
00654 while (moves != NULL) {
00655 move = moves->next;
00656 cuddDeallocNode(table, (DdNode *) moves);
00657 moves = move;
00658 }
00659
00660 return(0);
00661
00662 }
00663
00664
00677 int
00678 cuddNextHigh(
00679 DdManager * table,
00680 int x)
00681 {
00682 return(x+1);
00683
00684 }
00685
00686
00699 int
00700 cuddNextLow(
00701 DdManager * table,
00702 int x)
00703 {
00704 return(x-1);
00705
00706 }
00707
00708
00722 int
00723 cuddSwapInPlace(
00724 DdManager * table,
00725 int x,
00726 int y)
00727 {
00728 DdNodePtr *xlist, *ylist;
00729 int xindex, yindex;
00730 int xslots, yslots;
00731 int xshift, yshift;
00732 int oldxkeys, oldykeys;
00733 int newxkeys, newykeys;
00734 int comple, newcomplement;
00735 int i;
00736 Cudd_VariableType varType;
00737 Cudd_LazyGroupType groupType;
00738 int posn;
00739 int isolated;
00740 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10,*newf1,*newf0;
00741 DdNode *g,*next;
00742 DdNodePtr *previousP;
00743 DdNode *tmp;
00744 DdNode *sentinel = &(table->sentinel);
00745 extern void (*MMoutOfMemory)(long);
00746 void (*saveHandler)(long);
00747
00748 #if DD_DEBUG
00749 int count,idcheck;
00750 #endif
00751
00752 #ifdef DD_DEBUG
00753 assert(x < y);
00754 assert(cuddNextHigh(table,x) == y);
00755 assert(table->subtables[x].keys != 0);
00756 assert(table->subtables[y].keys != 0);
00757 assert(table->subtables[x].dead == 0);
00758 assert(table->subtables[y].dead == 0);
00759 #endif
00760
00761 ddTotalNumberSwapping++;
00762
00763
00764 xindex = table->invperm[x];
00765 xlist = table->subtables[x].nodelist;
00766 oldxkeys = table->subtables[x].keys;
00767 xslots = table->subtables[x].slots;
00768 xshift = table->subtables[x].shift;
00769
00770
00771 yindex = table->invperm[y];
00772 ylist = table->subtables[y].nodelist;
00773 oldykeys = table->subtables[y].keys;
00774 yslots = table->subtables[y].slots;
00775 yshift = table->subtables[y].shift;
00776
00777 if (!cuddTestInteract(table,xindex,yindex)) {
00778 #ifdef DD_STATS
00779 ddTotalNISwaps++;
00780 #endif
00781 newxkeys = oldxkeys;
00782 newykeys = oldykeys;
00783 } else {
00784 newxkeys = 0;
00785 newykeys = oldykeys;
00786
00787
00788
00789
00790
00791
00792
00793 isolated = - ((table->vars[xindex]->ref == 1) +
00794 (table->vars[yindex]->ref == 1));
00795
00796
00797
00798
00799
00800 g = NULL;
00801 if ((oldxkeys >= xslots || (unsigned) xslots == table->initSlots) &&
00802 oldxkeys <= DD_MAX_SUBTABLE_DENSITY * xslots) {
00803 for (i = 0; i < xslots; i++) {
00804 previousP = &(xlist[i]);
00805 f = *previousP;
00806 while (f != sentinel) {
00807 next = f->next;
00808 f1 = cuddT(f); f0 = cuddE(f);
00809 if (f1->index != (DdHalfWord) yindex &&
00810 Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
00811
00812 newxkeys++;
00813 *previousP = f;
00814 previousP = &(f->next);
00815 } else {
00816 f->index = yindex;
00817 f->next = g;
00818 g = f;
00819 }
00820 f = next;
00821 }
00822 *previousP = sentinel;
00823 }
00824 } else {
00825 DdNode *h = NULL;
00826 DdNodePtr *newxlist;
00827 unsigned int newxslots;
00828 int newxshift;
00829
00830
00831 for (i = 0; i < xslots; i++) {
00832 f = xlist[i];
00833 while (f != sentinel) {
00834 next = f->next;
00835 f1 = cuddT(f); f0 = cuddE(f);
00836 if (f1->index != (DdHalfWord) yindex &&
00837 Cudd_Regular(f0)->index != (DdHalfWord) yindex) {
00838
00839 f->next = h;
00840 h = f;
00841 newxkeys++;
00842 } else {
00843 f->index = yindex;
00844 f->next = g;
00845 g = f;
00846 }
00847 f = next;
00848 }
00849 }
00850
00851 if (oldxkeys > DD_MAX_SUBTABLE_DENSITY * xslots) {
00852 newxshift = xshift - 1;
00853 newxslots = xslots << 1;
00854 } else {
00855 newxshift = xshift + 1;
00856 newxslots = xslots >> 1;
00857 }
00858
00859 saveHandler = MMoutOfMemory;
00860 MMoutOfMemory = Cudd_OutOfMem;
00861 newxlist = ALLOC(DdNodePtr, newxslots);
00862 MMoutOfMemory = saveHandler;
00863 if (newxlist == NULL) {
00864 (void) fprintf(table->err, "Unable to resize subtable %d for lack of memory\n", i);
00865 newxlist = xlist;
00866 newxslots = xslots;
00867 newxshift = xshift;
00868 } else {
00869 table->slots += (newxslots - xslots);
00870 table->minDead = (unsigned)
00871 (table->gcFrac * (double) table->slots);
00872 table->cacheSlack = (int)
00873 ddMin(table->maxCacheHard, DD_MAX_CACHE_TO_SLOTS_RATIO
00874 * table->slots) - 2 * (int) table->cacheSlots;
00875 table->memused += (newxslots - xslots) * sizeof(DdNodePtr);
00876 FREE(xlist);
00877 xslots = newxslots;
00878 xshift = newxshift;
00879 xlist = newxlist;
00880 }
00881
00882 for (i = 0; i < xslots; i++) {
00883 xlist[i] = sentinel;
00884 }
00885
00886 f = h;
00887 while (f != NULL) {
00888 next = f->next;
00889 f1 = cuddT(f);
00890 f0 = cuddE(f);
00891
00892 posn = ddHash(f1, f0, xshift);
00893
00894 previousP = &(xlist[posn]);
00895 tmp = *previousP;
00896 while (f1 < cuddT(tmp)) {
00897 previousP = &(tmp->next);
00898 tmp = *previousP;
00899 }
00900 while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
00901 previousP = &(tmp->next);
00902 tmp = *previousP;
00903 }
00904 f->next = *previousP;
00905 *previousP = f;
00906 f = next;
00907 }
00908 }
00909
00910 #ifdef DD_COUNT
00911 table->swapSteps += oldxkeys - newxkeys;
00912 #endif
00913
00914
00915
00916
00917 f = g;
00918 while (f != NULL) {
00919 next = f->next;
00920
00921 f1 = cuddT(f);
00922 #ifdef DD_DEBUG
00923 assert(!(Cudd_IsComplement(f1)));
00924 #endif
00925 if ((int) f1->index == yindex) {
00926 f11 = cuddT(f1); f10 = cuddE(f1);
00927 } else {
00928 f11 = f10 = f1;
00929 }
00930 #ifdef DD_DEBUG
00931 assert(!(Cudd_IsComplement(f11)));
00932 #endif
00933 f0 = cuddE(f);
00934 comple = Cudd_IsComplement(f0);
00935 f0 = Cudd_Regular(f0);
00936 if ((int) f0->index == yindex) {
00937 f01 = cuddT(f0); f00 = cuddE(f0);
00938 } else {
00939 f01 = f00 = f0;
00940 }
00941 if (comple) {
00942 f01 = Cudd_Not(f01);
00943 f00 = Cudd_Not(f00);
00944 }
00945
00946 cuddSatDec(f1->ref);
00947
00948 if (f11 == f01) {
00949 newf1 = f11;
00950 cuddSatInc(newf1->ref);
00951 } else {
00952
00953 posn = ddHash(f11, f01, xshift);
00954
00955 previousP = &(xlist[posn]);
00956 newf1 = *previousP;
00957 while (f11 < cuddT(newf1)) {
00958 previousP = &(newf1->next);
00959 newf1 = *previousP;
00960 }
00961 while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
00962 previousP = &(newf1->next);
00963 newf1 = *previousP;
00964 }
00965 if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
00966 cuddSatInc(newf1->ref);
00967 } else {
00968 newf1 = cuddDynamicAllocNode(table);
00969 if (newf1 == NULL)
00970 goto cuddSwapOutOfMem;
00971 newf1->index = xindex; newf1->ref = 1;
00972 cuddT(newf1) = f11;
00973 cuddE(newf1) = f01;
00974
00975
00976
00977 newxkeys++;
00978 newf1->next = *previousP;
00979 *previousP = newf1;
00980 cuddSatInc(f11->ref);
00981 tmp = Cudd_Regular(f01);
00982 cuddSatInc(tmp->ref);
00983 }
00984 }
00985 cuddT(f) = newf1;
00986 #ifdef DD_DEBUG
00987 assert(!(Cudd_IsComplement(newf1)));
00988 #endif
00989
00990
00991
00992 tmp = Cudd_Regular(f0);
00993 cuddSatDec(tmp->ref);
00994
00995 if (f10 == f00) {
00996 newf0 = f00;
00997 tmp = Cudd_Regular(newf0);
00998 cuddSatInc(tmp->ref);
00999 } else {
01000
01001 newcomplement = Cudd_IsComplement(f10);
01002 if (newcomplement) {
01003 f10 = Cudd_Not(f10);
01004 f00 = Cudd_Not(f00);
01005 }
01006
01007 posn = ddHash(f10, f00, xshift);
01008
01009 previousP = &(xlist[posn]);
01010 newf0 = *previousP;
01011 while (f10 < cuddT(newf0)) {
01012 previousP = &(newf0->next);
01013 newf0 = *previousP;
01014 }
01015 while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
01016 previousP = &(newf0->next);
01017 newf0 = *previousP;
01018 }
01019 if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
01020 cuddSatInc(newf0->ref);
01021 } else {
01022 newf0 = cuddDynamicAllocNode(table);
01023 if (newf0 == NULL)
01024 goto cuddSwapOutOfMem;
01025 newf0->index = xindex; newf0->ref = 1;
01026 cuddT(newf0) = f10;
01027 cuddE(newf0) = f00;
01028
01029
01030
01031 newxkeys++;
01032 newf0->next = *previousP;
01033 *previousP = newf0;
01034 cuddSatInc(f10->ref);
01035 tmp = Cudd_Regular(f00);
01036 cuddSatInc(tmp->ref);
01037 }
01038 if (newcomplement) {
01039 newf0 = Cudd_Not(newf0);
01040 }
01041 }
01042 cuddE(f) = newf0;
01043
01044
01045
01046
01047
01048 posn = ddHash(newf1, newf0, yshift);
01049 newykeys++;
01050 previousP = &(ylist[posn]);
01051 tmp = *previousP;
01052 while (newf1 < cuddT(tmp)) {
01053 previousP = &(tmp->next);
01054 tmp = *previousP;
01055 }
01056 while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
01057 previousP = &(tmp->next);
01058 tmp = *previousP;
01059 }
01060 f->next = *previousP;
01061 *previousP = f;
01062 f = next;
01063 }
01064
01065
01066
01067
01068 for (i = 0; i < yslots; i++) {
01069 previousP = &(ylist[i]);
01070 f = *previousP;
01071 while (f != sentinel) {
01072 next = f->next;
01073 if (f->ref == 0) {
01074 tmp = cuddT(f);
01075 cuddSatDec(tmp->ref);
01076 tmp = Cudd_Regular(cuddE(f));
01077 cuddSatDec(tmp->ref);
01078 cuddDeallocNode(table,f);
01079 newykeys--;
01080 } else {
01081 *previousP = f;
01082 previousP = &(f->next);
01083 }
01084 f = next;
01085 }
01086 *previousP = sentinel;
01087 }
01088
01089 #if DD_DEBUG
01090 #if 0
01091 (void) fprintf(table->out,"Swapping %d and %d\n",x,y);
01092 #endif
01093 count = 0;
01094 idcheck = 0;
01095 for (i = 0; i < yslots; i++) {
01096 f = ylist[i];
01097 while (f != sentinel) {
01098 count++;
01099 if (f->index != (DdHalfWord) yindex)
01100 idcheck++;
01101 f = f->next;
01102 }
01103 }
01104 if (count != newykeys) {
01105 (void) fprintf(table->out,
01106 "Error in finding newykeys\toldykeys = %d\tnewykeys = %d\tactual = %d\n",
01107 oldykeys,newykeys,count);
01108 }
01109 if (idcheck != 0)
01110 (void) fprintf(table->out,
01111 "Error in id's of ylist\twrong id's = %d\n",
01112 idcheck);
01113 count = 0;
01114 idcheck = 0;
01115 for (i = 0; i < xslots; i++) {
01116 f = xlist[i];
01117 while (f != sentinel) {
01118 count++;
01119 if (f->index != (DdHalfWord) xindex)
01120 idcheck++;
01121 f = f->next;
01122 }
01123 }
01124 if (count != newxkeys) {
01125 (void) fprintf(table->out,
01126 "Error in finding newxkeys\toldxkeys = %d \tnewxkeys = %d \tactual = %d\n",
01127 oldxkeys,newxkeys,count);
01128 }
01129 if (idcheck != 0)
01130 (void) fprintf(table->out,
01131 "Error in id's of xlist\twrong id's = %d\n",
01132 idcheck);
01133 #endif
01134
01135 isolated += (table->vars[xindex]->ref == 1) +
01136 (table->vars[yindex]->ref == 1);
01137 table->isolated += isolated;
01138 }
01139
01140
01141 table->subtables[x].nodelist = ylist;
01142 table->subtables[x].slots = yslots;
01143 table->subtables[x].shift = yshift;
01144 table->subtables[x].keys = newykeys;
01145 table->subtables[x].maxKeys = yslots * DD_MAX_SUBTABLE_DENSITY;
01146 i = table->subtables[x].bindVar;
01147 table->subtables[x].bindVar = table->subtables[y].bindVar;
01148 table->subtables[y].bindVar = i;
01149
01150 varType = table->subtables[x].varType;
01151 table->subtables[x].varType = table->subtables[y].varType;
01152 table->subtables[y].varType = varType;
01153 i = table->subtables[x].pairIndex;
01154 table->subtables[x].pairIndex = table->subtables[y].pairIndex;
01155 table->subtables[y].pairIndex = i;
01156 i = table->subtables[x].varHandled;
01157 table->subtables[x].varHandled = table->subtables[y].varHandled;
01158 table->subtables[y].varHandled = i;
01159 groupType = table->subtables[x].varToBeGrouped;
01160 table->subtables[x].varToBeGrouped = table->subtables[y].varToBeGrouped;
01161 table->subtables[y].varToBeGrouped = groupType;
01162
01163 table->subtables[y].nodelist = xlist;
01164 table->subtables[y].slots = xslots;
01165 table->subtables[y].shift = xshift;
01166 table->subtables[y].keys = newxkeys;
01167 table->subtables[y].maxKeys = xslots * DD_MAX_SUBTABLE_DENSITY;
01168
01169 table->perm[xindex] = y; table->perm[yindex] = x;
01170 table->invperm[x] = yindex; table->invperm[y] = xindex;
01171
01172 table->keys += newxkeys + newykeys - oldxkeys - oldykeys;
01173
01174 return(table->keys - table->isolated);
01175
01176 cuddSwapOutOfMem:
01177 (void) fprintf(table->err,"Error: cuddSwapInPlace out of memory\n");
01178
01179 return (0);
01180
01181 }
01182
01183
01207 int
01208 cuddBddAlignToZdd(
01209 DdManager * table )
01210 {
01211 int *invperm;
01212 int M;
01213 int i;
01214 int result;
01215
01216
01217 if (table->size == 0)
01218 return(1);
01219
01220 M = table->sizeZ / table->size;
01221
01222
01223
01224 if (M * table->size != table->sizeZ)
01225 return(0);
01226
01227 invperm = ALLOC(int,table->size);
01228 if (invperm == NULL) {
01229 table->errorCode = CUDD_MEMORY_OUT;
01230 return(0);
01231 }
01232 for (i = 0; i < table->sizeZ; i += M) {
01233 int indexZ = table->invpermZ[i];
01234 int index = indexZ / M;
01235 invperm[i / M] = index;
01236 }
01237
01238
01239
01240 cuddGarbageCollect(table,0);
01241
01242
01243 table->isolated = 0;
01244 for (i = 0; i < table->size; i++) {
01245 if (table->vars[i]->ref == 1) table->isolated++;
01246 }
01247
01248
01249 result = cuddInitInteract(table);
01250 if (result == 0) return(0);
01251
01252 result = ddShuffle(table, invperm);
01253 FREE(invperm);
01254
01255 FREE(table->interact);
01256
01257 bddFixTree(table,table->tree);
01258 return(result);
01259
01260 }
01261
01262
01263
01264
01265
01266
01279 static int
01280 ddUniqueCompare(
01281 int * ptrX,
01282 int * ptrY)
01283 {
01284 #if 0
01285 if (entry[*ptrY] == entry[*ptrX]) {
01286 return((*ptrX) - (*ptrY));
01287 }
01288 #endif
01289 return(entry[*ptrY] - entry[*ptrX]);
01290
01291 }
01292
01293
01303 static Move *
01304 ddSwapAny(
01305 DdManager * table,
01306 int x,
01307 int y)
01308 {
01309 Move *move, *moves;
01310 int xRef,yRef;
01311 int xNext,yNext;
01312 int size;
01313 int limitSize;
01314 int tmp;
01315
01316 if (x >y) {
01317 tmp = x; x = y; y = tmp;
01318 }
01319
01320 xRef = x; yRef = y;
01321
01322 xNext = cuddNextHigh(table,x);
01323 yNext = cuddNextLow(table,y);
01324 moves = NULL;
01325 limitSize = table->keys - table->isolated;
01326
01327 for (;;) {
01328 if ( xNext == yNext) {
01329 size = cuddSwapInPlace(table,x,xNext);
01330 if (size == 0) goto ddSwapAnyOutOfMem;
01331 move = (Move *) cuddDynamicAllocNode(table);
01332 if (move == NULL) goto ddSwapAnyOutOfMem;
01333 move->x = x;
01334 move->y = xNext;
01335 move->size = size;
01336 move->next = moves;
01337 moves = move;
01338
01339 size = cuddSwapInPlace(table,yNext,y);
01340 if (size == 0) goto ddSwapAnyOutOfMem;
01341 move = (Move *) cuddDynamicAllocNode(table);
01342 if (move == NULL) goto ddSwapAnyOutOfMem;
01343 move->x = yNext;
01344 move->y = y;
01345 move->size = size;
01346 move->next = moves;
01347 moves = move;
01348
01349 size = cuddSwapInPlace(table,x,xNext);
01350 if (size == 0) goto ddSwapAnyOutOfMem;
01351 move = (Move *) cuddDynamicAllocNode(table);
01352 if (move == NULL) goto ddSwapAnyOutOfMem;
01353 move->x = x;
01354 move->y = xNext;
01355 move->size = size;
01356 move->next = moves;
01357 moves = move;
01358
01359 tmp = x; x = y; y = tmp;
01360
01361 } else if (x == yNext) {
01362
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 tmp = x; x = y; y = tmp;
01374
01375 } else {
01376 size = cuddSwapInPlace(table,x,xNext);
01377 if (size == 0) goto ddSwapAnyOutOfMem;
01378 move = (Move *) cuddDynamicAllocNode(table);
01379 if (move == NULL) goto ddSwapAnyOutOfMem;
01380 move->x = x;
01381 move->y = xNext;
01382 move->size = size;
01383 move->next = moves;
01384 moves = move;
01385
01386 size = cuddSwapInPlace(table,yNext,y);
01387 if (size == 0) goto ddSwapAnyOutOfMem;
01388 move = (Move *) cuddDynamicAllocNode(table);
01389 if (move == NULL) goto ddSwapAnyOutOfMem;
01390 move->x = yNext;
01391 move->y = y;
01392 move->size = size;
01393 move->next = moves;
01394 moves = move;
01395
01396 x = xNext;
01397 y = yNext;
01398 }
01399
01400 xNext = cuddNextHigh(table,x);
01401 yNext = cuddNextLow(table,y);
01402 if (xNext > yRef) break;
01403
01404 if ((double) size > table->maxGrowth * (double) limitSize) break;
01405 if (size < limitSize) limitSize = size;
01406 }
01407 if (yNext>=xRef) {
01408 size = cuddSwapInPlace(table,yNext,y);
01409 if (size == 0) goto ddSwapAnyOutOfMem;
01410 move = (Move *) cuddDynamicAllocNode(table);
01411 if (move == NULL) goto ddSwapAnyOutOfMem;
01412 move->x = yNext;
01413 move->y = y;
01414 move->size = size;
01415 move->next = moves;
01416 moves = move;
01417 }
01418
01419 return(moves);
01420
01421 ddSwapAnyOutOfMem:
01422 while (moves != NULL) {
01423 move = moves->next;
01424 cuddDeallocNode(table, (DdNode *) moves);
01425 moves = move;
01426 }
01427 return(NULL);
01428
01429 }
01430
01431
01444 static int
01445 ddSiftingAux(
01446 DdManager * table,
01447 int x,
01448 int xLow,
01449 int xHigh)
01450 {
01451
01452 Move *move;
01453 Move *moveUp;
01454 Move *moveDown;
01455 int initialSize;
01456 int result;
01457
01458 initialSize = table->keys - table->isolated;
01459
01460 moveDown = NULL;
01461 moveUp = NULL;
01462
01463 if (x == xLow) {
01464 moveDown = ddSiftingDown(table,x,xHigh);
01465
01466 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01467
01468 result = ddSiftingBackward(table,initialSize,moveDown);
01469 if (!result) goto ddSiftingAuxOutOfMem;
01470
01471 } else if (x == xHigh) {
01472 moveUp = ddSiftingUp(table,x,xLow);
01473
01474 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01475
01476 result = ddSiftingBackward(table,initialSize,moveUp);
01477 if (!result) goto ddSiftingAuxOutOfMem;
01478
01479 } else if ((x - xLow) > (xHigh - x)) {
01480 moveDown = ddSiftingDown(table,x,xHigh);
01481
01482 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01483 if (moveDown != NULL) {
01484 x = moveDown->y;
01485 }
01486 moveUp = ddSiftingUp(table,x,xLow);
01487 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01488
01489 result = ddSiftingBackward(table,initialSize,moveUp);
01490 if (!result) goto ddSiftingAuxOutOfMem;
01491
01492 } else {
01493 moveUp = ddSiftingUp(table,x,xLow);
01494
01495 if (moveUp == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01496 if (moveUp != NULL) {
01497 x = moveUp->x;
01498 }
01499 moveDown = ddSiftingDown(table,x,xHigh);
01500 if (moveDown == (Move *) CUDD_OUT_OF_MEM) goto ddSiftingAuxOutOfMem;
01501
01502 result = ddSiftingBackward(table,initialSize,moveDown);
01503 if (!result) goto ddSiftingAuxOutOfMem;
01504 }
01505
01506 while (moveDown != NULL) {
01507 move = moveDown->next;
01508 cuddDeallocNode(table, (DdNode *) moveDown);
01509 moveDown = move;
01510 }
01511 while (moveUp != NULL) {
01512 move = moveUp->next;
01513 cuddDeallocNode(table, (DdNode *) moveUp);
01514 moveUp = move;
01515 }
01516
01517 return(1);
01518
01519 ddSiftingAuxOutOfMem:
01520 if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
01521 while (moveDown != NULL) {
01522 move = moveDown->next;
01523 cuddDeallocNode(table, (DdNode *) moveDown);
01524 moveDown = move;
01525 }
01526 }
01527 if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
01528 while (moveUp != NULL) {
01529 move = moveUp->next;
01530 cuddDeallocNode(table, (DdNode *) moveUp);
01531 moveUp = move;
01532 }
01533 }
01534
01535 return(0);
01536
01537 }
01538
01539
01551 static Move *
01552 ddSiftingUp(
01553 DdManager * table,
01554 int y,
01555 int xLow)
01556 {
01557 Move *moves;
01558 Move *move;
01559 int x;
01560 int size;
01561 int limitSize;
01562 int xindex, yindex;
01563 int isolated;
01564 int L;
01565 #ifdef DD_DEBUG
01566 int checkL;
01567 int z;
01568 int zindex;
01569 #endif
01570
01571 moves = NULL;
01572 yindex = table->invperm[y];
01573
01574
01575
01576
01577
01578
01579
01580 limitSize = L = table->keys - table->isolated;
01581 for (x = xLow + 1; x < y; x++) {
01582 xindex = table->invperm[x];
01583 if (cuddTestInteract(table,xindex,yindex)) {
01584 isolated = table->vars[xindex]->ref == 1;
01585 L -= table->subtables[x].keys - isolated;
01586 }
01587 }
01588 isolated = table->vars[yindex]->ref == 1;
01589 L -= table->subtables[y].keys - isolated;
01590
01591 x = cuddNextLow(table,y);
01592 while (x >= xLow && L <= limitSize) {
01593 xindex = table->invperm[x];
01594 #ifdef DD_DEBUG
01595 checkL = table->keys - table->isolated;
01596 for (z = xLow + 1; z < y; z++) {
01597 zindex = table->invperm[z];
01598 if (cuddTestInteract(table,zindex,yindex)) {
01599 isolated = table->vars[zindex]->ref == 1;
01600 checkL -= table->subtables[z].keys - isolated;
01601 }
01602 }
01603 isolated = table->vars[yindex]->ref == 1;
01604 checkL -= table->subtables[y].keys - isolated;
01605 assert(L == checkL);
01606 #endif
01607 size = cuddSwapInPlace(table,x,y);
01608 if (size == 0) goto ddSiftingUpOutOfMem;
01609
01610 if (cuddTestInteract(table,xindex,yindex)) {
01611 isolated = table->vars[xindex]->ref == 1;
01612 L += table->subtables[y].keys - isolated;
01613 }
01614 move = (Move *) cuddDynamicAllocNode(table);
01615 if (move == NULL) goto ddSiftingUpOutOfMem;
01616 move->x = x;
01617 move->y = y;
01618 move->size = size;
01619 move->next = moves;
01620 moves = move;
01621 if ((double) size > (double) limitSize * table->maxGrowth) break;
01622 if (size < limitSize) limitSize = size;
01623 y = x;
01624 x = cuddNextLow(table,y);
01625 }
01626 return(moves);
01627
01628 ddSiftingUpOutOfMem:
01629 while (moves != NULL) {
01630 move = moves->next;
01631 cuddDeallocNode(table, (DdNode *) moves);
01632 moves = move;
01633 }
01634 return((Move *) CUDD_OUT_OF_MEM);
01635
01636 }
01637
01638
01651 static Move *
01652 ddSiftingDown(
01653 DdManager * table,
01654 int x,
01655 int xHigh)
01656 {
01657 Move *moves;
01658 Move *move;
01659 int y;
01660 int size;
01661 int R;
01662 int limitSize;
01663 int xindex, yindex;
01664 int isolated;
01665 #ifdef DD_DEBUG
01666 int checkR;
01667 int z;
01668 int zindex;
01669 #endif
01670
01671 moves = NULL;
01672
01673 xindex = table->invperm[x];
01674 limitSize = size = table->keys - table->isolated;
01675 R = 0;
01676 for (y = xHigh; y > x; y--) {
01677 yindex = table->invperm[y];
01678 if (cuddTestInteract(table,xindex,yindex)) {
01679 isolated = table->vars[yindex]->ref == 1;
01680 R += table->subtables[y].keys - isolated;
01681 }
01682 }
01683
01684 y = cuddNextHigh(table,x);
01685 while (y <= xHigh && size - R < limitSize) {
01686 #ifdef DD_DEBUG
01687 checkR = 0;
01688 for (z = xHigh; z > x; z--) {
01689 zindex = table->invperm[z];
01690 if (cuddTestInteract(table,xindex,zindex)) {
01691 isolated = table->vars[zindex]->ref == 1;
01692 checkR += table->subtables[z].keys - isolated;
01693 }
01694 }
01695 assert(R == checkR);
01696 #endif
01697
01698 yindex = table->invperm[y];
01699 if (cuddTestInteract(table,xindex,yindex)) {
01700 isolated = table->vars[yindex]->ref == 1;
01701 R -= table->subtables[y].keys - isolated;
01702 }
01703 size = cuddSwapInPlace(table,x,y);
01704 if (size == 0) goto ddSiftingDownOutOfMem;
01705 move = (Move *) cuddDynamicAllocNode(table);
01706 if (move == NULL) goto ddSiftingDownOutOfMem;
01707 move->x = x;
01708 move->y = y;
01709 move->size = size;
01710 move->next = moves;
01711 moves = move;
01712 if ((double) size > (double) limitSize * table->maxGrowth) break;
01713 if (size < limitSize) limitSize = size;
01714 x = y;
01715 y = cuddNextHigh(table,x);
01716 }
01717 return(moves);
01718
01719 ddSiftingDownOutOfMem:
01720 while (moves != NULL) {
01721 move = moves->next;
01722 cuddDeallocNode(table, (DdNode *) moves);
01723 moves = move;
01724 }
01725 return((Move *) CUDD_OUT_OF_MEM);
01726
01727 }
01728
01729
01743 static int
01744 ddSiftingBackward(
01745 DdManager * table,
01746 int size,
01747 Move * moves)
01748 {
01749 Move *move;
01750 int res;
01751
01752 for (move = moves; move != NULL; move = move->next) {
01753 if (move->size < size) {
01754 size = move->size;
01755 }
01756 }
01757
01758 for (move = moves; move != NULL; move = move->next) {
01759 if (move->size == size) return(1);
01760 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01761 if (!res) return(0);
01762 }
01763
01764 return(1);
01765
01766 }
01767
01768
01782 static int
01783 ddReorderPreprocess(
01784 DdManager * table)
01785 {
01786 int i;
01787 int res;
01788
01789
01790 cuddCacheFlush(table);
01791 cuddLocalCacheClearAll(table);
01792
01793
01794 cuddGarbageCollect(table,0);
01795
01796
01797 table->isolated = 0;
01798 for (i = 0; i < table->size; i++) {
01799 if (table->vars[i]->ref == 1) table->isolated++;
01800 }
01801
01802
01803 res = cuddInitInteract(table);
01804 if (res == 0) return(0);
01805
01806 return(1);
01807
01808 }
01809
01810
01820 static int
01821 ddReorderPostprocess(
01822 DdManager * table)
01823 {
01824
01825 #ifdef DD_VERBOSE
01826 (void) fflush(table->out);
01827 #endif
01828
01829
01830 FREE(table->interact);
01831
01832 return(1);
01833
01834 }
01835
01836
01853 static int
01854 ddShuffle(
01855 DdManager * table,
01856 int * permutation)
01857 {
01858 int index;
01859 int level;
01860 int position;
01861 int numvars;
01862 int result;
01863 #ifdef DD_STATS
01864 long localTime;
01865 int initialSize;
01866 int finalSize;
01867 int previousSize;
01868 #endif
01869
01870 ddTotalNumberSwapping = 0;
01871 #ifdef DD_STATS
01872 localTime = util_cpu_time();
01873 initialSize = table->keys - table->isolated;
01874 (void) fprintf(table->out,"#:I_SHUFFLE %8d: initial size\n",
01875 initialSize);
01876 ddTotalNISwaps = 0;
01877 #endif
01878
01879 numvars = table->size;
01880
01881 for (level = 0; level < numvars; level++) {
01882 index = permutation[level];
01883 position = table->perm[index];
01884 #ifdef DD_STATS
01885 previousSize = table->keys - table->isolated;
01886 #endif
01887 result = ddSiftUp(table,position,level);
01888 if (!result) return(0);
01889 #ifdef DD_STATS
01890 if (table->keys < (unsigned) previousSize + table->isolated) {
01891 (void) fprintf(table->out,"-");
01892 } else if (table->keys > (unsigned) previousSize + table->isolated) {
01893 (void) fprintf(table->out,"+");
01894 } else {
01895 (void) fprintf(table->out,"=");
01896 }
01897 fflush(table->out);
01898 #endif
01899 }
01900
01901 #ifdef DD_STATS
01902 (void) fprintf(table->out,"\n");
01903 finalSize = table->keys - table->isolated;
01904 (void) fprintf(table->out,"#:F_SHUFFLE %8d: final size\n",finalSize);
01905 (void) fprintf(table->out,"#:T_SHUFFLE %8g: total time (sec)\n",
01906 ((double)(util_cpu_time() - localTime)/1000.0));
01907 (void) fprintf(table->out,"#:N_SHUFFLE %8d: total swaps\n",
01908 ddTotalNumberSwapping);
01909 (void) fprintf(table->out,"#:M_SHUFFLE %8d: NI swaps\n",ddTotalNISwaps);
01910 #endif
01911
01912 return(1);
01913
01914 }
01915
01916
01930 static int
01931 ddSiftUp(
01932 DdManager * table,
01933 int x,
01934 int xLow)
01935 {
01936 int y;
01937 int size;
01938
01939 y = cuddNextLow(table,x);
01940 while (y >= xLow) {
01941 size = cuddSwapInPlace(table,y,x);
01942 if (size == 0) {
01943 return(0);
01944 }
01945 x = y;
01946 y = cuddNextLow(table,x);
01947 }
01948 return(1);
01949
01950 }
01951
01952
01966 static void
01967 bddFixTree(
01968 DdManager * table,
01969 MtrNode * treenode)
01970 {
01971 if (treenode == NULL) return;
01972 treenode->low = ((int) treenode->index < table->size) ?
01973 table->perm[treenode->index] : treenode->index;
01974 if (treenode->child != NULL) {
01975 bddFixTree(table, treenode->child);
01976 }
01977 if (treenode->younger != NULL)
01978 bddFixTree(table, treenode->younger);
01979 if (treenode->parent != NULL && treenode->low < treenode->parent->low) {
01980 treenode->parent->low = treenode->low;
01981 treenode->parent->index = treenode->index;
01982 }
01983 return;
01984
01985 }
01986
01987
02000 static int
02001 ddUpdateMtrTree(
02002 DdManager * table,
02003 MtrNode * treenode,
02004 int * perm,
02005 int * invperm)
02006 {
02007 int i, size, index, level;
02008 int minLevel, maxLevel, minIndex;
02009
02010 if (treenode == NULL) return(1);
02011
02012
02013 for (i = treenode->low; i < treenode->low + treenode->size; i++) {
02014 index = table->invperm[i];
02015 level = perm[index];
02016 if (level < minLevel) {
02017 minLevel = level;
02018 minIndex = index;
02019 }
02020 if (level > maxLevel)
02021 maxLevel = level;
02022 }
02023 size = maxLevel - minLevel + 1;
02024 if (size == treenode->size) {
02025 treenode->low = minLevel;
02026 treenode->index = minIndex;
02027 } else
02028 return(0);
02029
02030 if (treenode->child != NULL) {
02031 if (!ddUpdateMtrTree(table, treenode->child, perm, invperm))
02032 return(0);
02033 }
02034 if (treenode->younger != NULL) {
02035 if (!ddUpdateMtrTree(table, treenode->younger, perm, invperm))
02036 return(0);
02037 }
02038 return(1);
02039 }
02040
02041
02054 static int
02055 ddCheckPermuation(
02056 DdManager * table,
02057 MtrNode * treenode,
02058 int * perm,
02059 int * invperm)
02060 {
02061 int i, size, index, level;
02062 int minLevel, maxLevel;
02063
02064 if (treenode == NULL) return(1);
02065
02066 minLevel = table->size;
02067 maxLevel = 0;
02068
02069 for (i = treenode->low; i < treenode->low + treenode->size; i++) {
02070 index = table->invperm[i];
02071 level = perm[index];
02072 if (level < minLevel)
02073 minLevel = level;
02074 if (level > maxLevel)
02075 maxLevel = level;
02076 }
02077 size = maxLevel - minLevel + 1;
02078 if (size != treenode->size)
02079 return(0);
02080
02081 if (treenode->child != NULL) {
02082 if (!ddCheckPermuation(table, treenode->child, perm, invperm))
02083 return(0);
02084 }
02085 if (treenode->younger != NULL) {
02086 if (!ddCheckPermuation(table, treenode->younger, perm, invperm))
02087 return(0);
02088 }
02089 return(1);
02090 }