00001
00043 #include "util_hack.h"
00044 #include "cuddInt.h"
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 #ifndef lint
00063 static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.1.1.1 2003/02/24 22:23:54 wjiang Exp $";
00064 #endif
00065
00066 static int *entry;
00067 extern int zddTotalNumberSwapping;
00068 #ifdef DD_STATS
00069 static int extsymmcalls;
00070 static int extsymm;
00071 static int secdiffcalls;
00072 static int secdiff;
00073 static int secdiffmisfire;
00074 #endif
00075 #ifdef DD_DEBUG
00076 static int pr = 0;
00077
00078 #endif
00079
00080
00081
00082
00083
00086
00087
00088
00089
00090 static int zddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method));
00091 #ifdef DD_STATS
00092 static int zddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode));
00093 #endif
00094 static int zddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method));
00095 static void zddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper));
00096 static int zddUniqueCompareGroup ARGS((int *ptrX, int *ptrY));
00097 static int zddGroupSifting ARGS((DdManager *table, int lower, int upper));
00098 static int zddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh));
00099 static int zddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, Move **moves));
00100 static int zddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, Move **moves));
00101 static int zddGroupMove ARGS((DdManager *table, int x, int y, Move **moves));
00102 static int zddGroupMoveBackward ARGS((DdManager *table, int x, int y));
00103 static int zddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size));
00104 static void zddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high));
00105
00109
00110
00111
00112
00113
00131 MtrNode *
00132 Cudd_MakeZddTreeNode(
00133 DdManager * dd ,
00134 unsigned int low ,
00135 unsigned int size ,
00136 unsigned int type )
00137 {
00138 MtrNode *group;
00139 MtrNode *tree;
00140 unsigned int level;
00141
00142
00143
00144
00145
00146
00147 level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
00148
00149 if (level + size - 1> (int) MTR_MAXHIGH)
00150 return(NULL);
00151
00152
00153 tree = dd->treeZ;
00154 if (tree == NULL) {
00155 dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
00156 if (tree == NULL)
00157 return(NULL);
00158 tree->index = dd->invpermZ[0];
00159 }
00160
00161
00162
00163
00164 tree->size = ddMax(tree->size, level + size);
00165
00166
00167 group = Mtr_MakeGroup(tree, level, size, type);
00168 if (group == NULL)
00169 return(NULL);
00170
00171
00172
00173
00174
00175 group->index = (MtrHalfWord) low;
00176
00177 return(group);
00178
00179 }
00180
00181
00182
00183
00184
00185
00186
00200 int
00201 cuddZddTreeSifting(
00202 DdManager * table ,
00203 Cudd_ReorderingType method )
00204 {
00205 int i;
00206 int nvars;
00207 int result;
00208 int tempTree;
00209
00210
00211
00212
00213
00214 tempTree = table->treeZ == NULL;
00215 if (tempTree) {
00216 table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
00217 table->treeZ->index = table->invpermZ[0];
00218 }
00219 nvars = table->sizeZ;
00220
00221 #ifdef DD_DEBUG
00222 if (pr > 0 && !tempTree)
00223 (void) fprintf(table->out,"cuddZddTreeSifting:");
00224 Mtr_PrintGroups(table->treeZ,pr <= 0);
00225 #endif
00226 #if 0
00227
00228 if (table->tree && table->treeZ) {
00229 (void) fprintf(table->out,"\n");
00230 Mtr_PrintGroups(table->tree, 0);
00231 cuddPrintVarGroups(table,table->tree,0,0);
00232 for (i = 0; i < table->size; i++) {
00233 (void) fprintf(table->out,"%s%d",
00234 (i == 0) ? "" : ",", table->invperm[i]);
00235 }
00236 (void) fprintf(table->out,"\n");
00237 for (i = 0; i < table->size; i++) {
00238 (void) fprintf(table->out,"%s%d",
00239 (i == 0) ? "" : ",", table->perm[i]);
00240 }
00241 (void) fprintf(table->out,"\n\n");
00242 Mtr_PrintGroups(table->treeZ,0);
00243 cuddPrintVarGroups(table,table->treeZ,1,0);
00244 for (i = 0; i < table->sizeZ; i++) {
00245 (void) fprintf(table->out,"%s%d",
00246 (i == 0) ? "" : ",", table->invpermZ[i]);
00247 }
00248 (void) fprintf(table->out,"\n");
00249 for (i = 0; i < table->sizeZ; i++) {
00250 (void) fprintf(table->out,"%s%d",
00251 (i == 0) ? "" : ",", table->permZ[i]);
00252 }
00253 (void) fprintf(table->out,"\n");
00254 }
00255
00256 #endif
00257 #ifdef DD_STATS
00258 extsymmcalls = 0;
00259 extsymm = 0;
00260 secdiffcalls = 0;
00261 secdiff = 0;
00262 secdiffmisfire = 0;
00263
00264 (void) fprintf(table->out,"\n");
00265 if (!tempTree)
00266 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
00267 zddCountInternalMtrNodes(table,table->treeZ));
00268 #endif
00269
00270
00271
00272
00273
00274 for (i = 0; i < nvars; i++)
00275 table->subtableZ[i].next = i;
00276
00277
00278 result = zddTreeSiftingAux(table, table->treeZ, method);
00279
00280 #ifdef DD_STATS
00281 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00282 (table->groupcheck == CUDD_GROUP_CHECK7 ||
00283 table->groupcheck == CUDD_GROUP_CHECK5)) {
00284 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00285 (void) fprintf(table->out,"extsymm = %d",extsymm);
00286 }
00287 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00288 table->groupcheck == CUDD_GROUP_CHECK7) {
00289 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00290 (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00291 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00292 }
00293 #endif
00294
00295 if (tempTree)
00296 Cudd_FreeZddTree(table);
00297 return(result);
00298
00299 }
00300
00301
00302
00303
00304
00305
00306
00317 static int
00318 zddTreeSiftingAux(
00319 DdManager * table,
00320 MtrNode * treenode,
00321 Cudd_ReorderingType method)
00322 {
00323 MtrNode *auxnode;
00324 int res;
00325
00326 #ifdef DD_DEBUG
00327 Mtr_PrintGroups(treenode,1);
00328 #endif
00329
00330 auxnode = treenode;
00331 while (auxnode != NULL) {
00332 if (auxnode->child != NULL) {
00333 if (!zddTreeSiftingAux(table, auxnode->child, method))
00334 return(0);
00335 res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
00336 if (res == 0)
00337 return(0);
00338 } else if (auxnode->size > 1) {
00339 if (!zddReorderChildren(table, auxnode, method))
00340 return(0);
00341 }
00342 auxnode = auxnode->younger;
00343 }
00344
00345 return(1);
00346
00347 }
00348
00349
00350 #ifdef DD_STATS
00351
00361 static int
00362 zddCountInternalMtrNodes(
00363 DdManager * table,
00364 MtrNode * treenode)
00365 {
00366 MtrNode *auxnode;
00367 int count,nodeCount;
00368
00369
00370 nodeCount = 0;
00371 auxnode = treenode;
00372 while (auxnode != NULL) {
00373 if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
00374 nodeCount++;
00375 count = zddCountInternalMtrNodes(table,auxnode->child);
00376 nodeCount += count;
00377 }
00378 auxnode = auxnode->younger;
00379 }
00380
00381 return(nodeCount);
00382
00383 }
00384 #endif
00385
00386
00401 static int
00402 zddReorderChildren(
00403 DdManager * table,
00404 MtrNode * treenode,
00405 Cudd_ReorderingType method)
00406 {
00407 int lower;
00408 int upper;
00409 int result;
00410 unsigned int initialSize;
00411
00412 zddFindNodeHiLo(table,treenode,&lower,&upper);
00413
00414 if (upper == -1)
00415 return(1);
00416
00417 if (treenode->flags == MTR_FIXED) {
00418 result = 1;
00419 } else {
00420 #ifdef DD_STATS
00421 (void) fprintf(table->out," ");
00422 #endif
00423 switch (method) {
00424 case CUDD_REORDER_RANDOM:
00425 case CUDD_REORDER_RANDOM_PIVOT:
00426 result = cuddZddSwapping(table,lower,upper,method);
00427 break;
00428 case CUDD_REORDER_SIFT:
00429 result = cuddZddSifting(table,lower,upper);
00430 break;
00431 case CUDD_REORDER_SIFT_CONVERGE:
00432 do {
00433 initialSize = table->keysZ;
00434 result = cuddZddSifting(table,lower,upper);
00435 if (initialSize <= table->keysZ)
00436 break;
00437 #ifdef DD_STATS
00438 else
00439 (void) fprintf(table->out,"\n");
00440 #endif
00441 } while (result != 0);
00442 break;
00443 case CUDD_REORDER_SYMM_SIFT:
00444 result = cuddZddSymmSifting(table,lower,upper);
00445 break;
00446 case CUDD_REORDER_SYMM_SIFT_CONV:
00447 result = cuddZddSymmSiftingConv(table,lower,upper);
00448 break;
00449 case CUDD_REORDER_GROUP_SIFT:
00450 result = zddGroupSifting(table,lower,upper);
00451 break;
00452 case CUDD_REORDER_LINEAR:
00453 result = cuddZddLinearSifting(table,lower,upper);
00454 break;
00455 case CUDD_REORDER_LINEAR_CONVERGE:
00456 do {
00457 initialSize = table->keysZ;
00458 result = cuddZddLinearSifting(table,lower,upper);
00459 if (initialSize <= table->keysZ)
00460 break;
00461 #ifdef DD_STATS
00462 else
00463 (void) fprintf(table->out,"\n");
00464 #endif
00465 } while (result != 0);
00466 break;
00467 default:
00468 return(0);
00469 }
00470 }
00471
00472
00473
00474
00475
00476 zddMergeGroups(table,treenode,lower,upper);
00477
00478 #ifdef DD_DEBUG
00479 if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
00480 #endif
00481
00482 return(result);
00483
00484 }
00485
00486
00502 static void
00503 zddFindNodeHiLo(
00504 DdManager * table,
00505 MtrNode * treenode,
00506 int * lower,
00507 int * upper)
00508 {
00509 int low;
00510 int high;
00511
00512
00513
00514
00515
00516 if ((int) treenode->low >= table->sizeZ) {
00517 *lower = table->sizeZ;
00518 *upper = -1;
00519 return;
00520 }
00521
00522 *lower = low = (unsigned int) table->permZ[treenode->index];
00523 high = (int) (low + treenode->size - 1);
00524
00525 if (high >= table->sizeZ) {
00526
00527
00528
00529
00530
00531
00532
00533 MtrNode *auxnode = treenode->child;
00534 if (auxnode == NULL) {
00535 *upper = (unsigned int) table->sizeZ - 1;
00536 } else {
00537
00538
00539
00540
00541
00542 while (auxnode != NULL) {
00543 int thisLower = table->permZ[auxnode->low];
00544 int thisUpper = thisLower + auxnode->size - 1;
00545 if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
00546 *upper = (unsigned int) thisLower - 1;
00547 auxnode = auxnode->younger;
00548 }
00549 }
00550 } else {
00551
00552 *upper = (unsigned int) high;
00553 }
00554
00555 #ifdef DD_DEBUG
00556
00557 assert(treenode->size >= *upper - *lower + 1);
00558 #endif
00559
00560 return;
00561
00562 }
00563
00564
00577 static int
00578 zddUniqueCompareGroup(
00579 int * ptrX,
00580 int * ptrY)
00581 {
00582 #if 0
00583 if (entry[*ptrY] == entry[*ptrX]) {
00584 return((*ptrX) - (*ptrY));
00585 }
00586 #endif
00587 return(entry[*ptrY] - entry[*ptrX]);
00588
00589 }
00590
00591
00605 static int
00606 zddGroupSifting(
00607 DdManager * table,
00608 int lower,
00609 int upper)
00610 {
00611 int *var;
00612 int i,j,x,xInit;
00613 int nvars;
00614 int classes;
00615 int result;
00616 int *sifted;
00617 #ifdef DD_STATS
00618 unsigned previousSize;
00619 #endif
00620 int xindex;
00621
00622 nvars = table->sizeZ;
00623
00624
00625 entry = NULL;
00626 sifted = NULL;
00627 var = ALLOC(int,nvars);
00628 if (var == NULL) {
00629 table->errorCode = CUDD_MEMORY_OUT;
00630 goto zddGroupSiftingOutOfMem;
00631 }
00632 entry = ALLOC(int,nvars);
00633 if (entry == NULL) {
00634 table->errorCode = CUDD_MEMORY_OUT;
00635 goto zddGroupSiftingOutOfMem;
00636 }
00637 sifted = ALLOC(int,nvars);
00638 if (sifted == NULL) {
00639 table->errorCode = CUDD_MEMORY_OUT;
00640 goto zddGroupSiftingOutOfMem;
00641 }
00642
00643
00644 for (i = 0, classes = 0; i < nvars; i++) {
00645 sifted[i] = 0;
00646 x = table->permZ[i];
00647 if ((unsigned) x >= table->subtableZ[x].next) {
00648 entry[i] = table->subtableZ[x].keys;
00649 var[classes] = i;
00650 classes++;
00651 }
00652 }
00653
00654 qsort((void *)var,classes,sizeof(int),(int (*)(const void *, const void *))zddUniqueCompareGroup);
00655
00656
00657 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00658 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00659 break;
00660 xindex = var[i];
00661 if (sifted[xindex] == 1)
00662 continue;
00663 x = table->permZ[xindex];
00664 if (x < lower || x > upper)
00665 continue;
00666 #ifdef DD_STATS
00667 previousSize = table->keysZ;
00668 #endif
00669 #ifdef DD_DEBUG
00670
00671 assert((unsigned) x >= table->subtableZ[x].next);
00672 #endif
00673 result = zddGroupSiftingAux(table,x,lower,upper);
00674 if (!result) goto zddGroupSiftingOutOfMem;
00675
00676 #ifdef DD_STATS
00677 if (table->keysZ < previousSize) {
00678 (void) fprintf(table->out,"-");
00679 } else if (table->keysZ > previousSize) {
00680 (void) fprintf(table->out,"+");
00681 } else {
00682 (void) fprintf(table->out,"=");
00683 }
00684 fflush(table->out);
00685 #endif
00686
00687
00688 x = table->permZ[xindex];
00689 if ((unsigned) x != table->subtableZ[x].next) {
00690 xInit = x;
00691 do {
00692 j = table->invpermZ[x];
00693 sifted[j] = 1;
00694 x = table->subtableZ[x].next;
00695 } while (x != xInit);
00696 }
00697
00698 #ifdef DD_DEBUG
00699 if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
00700 #endif
00701 }
00702
00703 FREE(sifted);
00704 FREE(var);
00705 FREE(entry);
00706
00707 return(1);
00708
00709 zddGroupSiftingOutOfMem:
00710 if (entry != NULL) FREE(entry);
00711 if (var != NULL) FREE(var);
00712 if (sifted != NULL) FREE(sifted);
00713
00714 return(0);
00715
00716 }
00717
00718
00734 static int
00735 zddGroupSiftingAux(
00736 DdManager * table,
00737 int x,
00738 int xLow,
00739 int xHigh)
00740 {
00741 Move *move;
00742 Move *moves;
00743 int initialSize;
00744 int result;
00745
00746
00747 #ifdef DD_DEBUG
00748 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
00749 assert((unsigned) x >= table->subtableZ[x].next);
00750 #endif
00751
00752 initialSize = table->keysZ;
00753 moves = NULL;
00754
00755 if (x == xLow) {
00756 #ifdef DD_DEBUG
00757
00758 assert((unsigned) x == table->subtableZ[x].next);
00759 #endif
00760 if (x == xHigh) return(1);
00761
00762 if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00763 goto zddGroupSiftingAuxOutOfMem;
00764
00765
00766
00767 result = zddGroupSiftingBackward(table,moves,initialSize);
00768 #ifdef DD_DEBUG
00769 assert(table->keysZ <= (unsigned) initialSize);
00770 #endif
00771 if (!result) goto zddGroupSiftingAuxOutOfMem;
00772
00773 } else if (cuddZddNextHigh(table,x) > xHigh) {
00774 #ifdef DD_DEBUG
00775
00776 assert((unsigned) x >= table->subtableZ[x].next);
00777 #endif
00778
00779 x = table->subtableZ[x].next;
00780
00781 if (!zddGroupSiftingUp(table,x,xLow,&moves))
00782 goto zddGroupSiftingAuxOutOfMem;
00783
00784
00785
00786 result = zddGroupSiftingBackward(table,moves,initialSize);
00787 #ifdef DD_DEBUG
00788 assert(table->keysZ <= (unsigned) initialSize);
00789 #endif
00790 if (!result) goto zddGroupSiftingAuxOutOfMem;
00791
00792 } else if (x - xLow > xHigh - x) {
00793 if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00794 goto zddGroupSiftingAuxOutOfMem;
00795
00796
00797
00798 if (moves) {
00799 x = moves->y;
00800 }
00801 while ((unsigned) x < table->subtableZ[x].next)
00802 x = table->subtableZ[x].next;
00803 x = table->subtableZ[x].next;
00804 #ifdef DD_DEBUG
00805
00806 assert((unsigned) x <= table->subtableZ[x].next);
00807 #endif
00808
00809 if (!zddGroupSiftingUp(table,x,xLow,&moves))
00810 goto zddGroupSiftingAuxOutOfMem;
00811
00812
00813 result = zddGroupSiftingBackward(table,moves,initialSize);
00814 #ifdef DD_DEBUG
00815 assert(table->keysZ <= (unsigned) initialSize);
00816 #endif
00817 if (!result) goto zddGroupSiftingAuxOutOfMem;
00818
00819 } else {
00820
00821 x = table->subtableZ[x].next;
00822
00823 if (!zddGroupSiftingUp(table,x,xLow,&moves))
00824 goto zddGroupSiftingAuxOutOfMem;
00825
00826
00827 if (moves) {
00828 x = moves->x;
00829 }
00830 while ((unsigned) x < table->subtableZ[x].next)
00831 x = table->subtableZ[x].next;
00832 #ifdef DD_DEBUG
00833
00834 assert((unsigned) x >= table->subtableZ[x].next);
00835 #endif
00836
00837 if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00838 goto zddGroupSiftingAuxOutOfMem;
00839
00840
00841 result = zddGroupSiftingBackward(table,moves,initialSize);
00842 #ifdef DD_DEBUG
00843 assert(table->keysZ <= (unsigned) initialSize);
00844 #endif
00845 if (!result) goto zddGroupSiftingAuxOutOfMem;
00846 }
00847
00848 while (moves != NULL) {
00849 move = moves->next;
00850 cuddDeallocNode(table, (DdNode *) moves);
00851 moves = move;
00852 }
00853
00854 return(1);
00855
00856 zddGroupSiftingAuxOutOfMem:
00857 while (moves != NULL) {
00858 move = moves->next;
00859 cuddDeallocNode(table, (DdNode *) moves);
00860 moves = move;
00861 }
00862
00863 return(0);
00864
00865 }
00866
00867
00883 static int
00884 zddGroupSiftingUp(
00885 DdManager * table,
00886 int y,
00887 int xLow,
00888 Move ** moves)
00889 {
00890 Move *move;
00891 int x;
00892 int size;
00893 int gxtop;
00894 int limitSize;
00895 int xindex, yindex;
00896
00897 yindex = table->invpermZ[y];
00898
00899 limitSize = table->keysZ;
00900
00901 x = cuddZddNextLow(table,y);
00902 while (x >= xLow) {
00903 gxtop = table->subtableZ[x].next;
00904 if (table->subtableZ[x].next == (unsigned) x &&
00905 table->subtableZ[y].next == (unsigned) y) {
00906
00907 xindex = table->invpermZ[x];
00908 size = cuddZddSwapInPlace(table,x,y);
00909 #ifdef DD_DEBUG
00910 assert(table->subtableZ[x].next == (unsigned) x);
00911 assert(table->subtableZ[y].next == (unsigned) y);
00912 #endif
00913 if (size == 0) goto zddGroupSiftingUpOutOfMem;
00914 move = (Move *)cuddDynamicAllocNode(table);
00915 if (move == NULL) goto zddGroupSiftingUpOutOfMem;
00916 move->x = x;
00917 move->y = y;
00918 move->flags = MTR_DEFAULT;
00919 move->size = size;
00920 move->next = *moves;
00921 *moves = move;
00922
00923 #ifdef DD_DEBUG
00924 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
00925 #endif
00926 if ((double) size > (double) limitSize * table->maxGrowth)
00927 return(1);
00928 if (size < limitSize) limitSize = size;
00929 } else {
00930 size = zddGroupMove(table,x,y,moves);
00931 if (size == 0) goto zddGroupSiftingUpOutOfMem;
00932 if ((double) size > (double) limitSize * table->maxGrowth)
00933 return(1);
00934 if (size < limitSize) limitSize = size;
00935 }
00936 y = gxtop;
00937 x = cuddZddNextLow(table,y);
00938 }
00939
00940 return(1);
00941
00942 zddGroupSiftingUpOutOfMem:
00943 while (*moves != NULL) {
00944 move = (*moves)->next;
00945 cuddDeallocNode(table, (DdNode *) *moves);
00946 *moves = move;
00947 }
00948 return(0);
00949
00950 }
00951
00952
00964 static int
00965 zddGroupSiftingDown(
00966 DdManager * table,
00967 int x,
00968 int xHigh,
00969 Move ** moves)
00970 {
00971 Move *move;
00972 int y;
00973 int size;
00974 int limitSize;
00975 int gxtop,gybot;
00976 int xindex;
00977
00978
00979
00980 xindex = table->invpermZ[x];
00981 gxtop = table->subtableZ[x].next;
00982 limitSize = size = table->keysZ;
00983 y = cuddZddNextHigh(table,x);
00984 while (y <= xHigh) {
00985
00986 gybot = table->subtableZ[y].next;
00987 while (table->subtableZ[gybot].next != (unsigned) y)
00988 gybot = table->subtableZ[gybot].next;
00989
00990 if (table->subtableZ[x].next == (unsigned) x &&
00991 table->subtableZ[y].next == (unsigned) y) {
00992
00993 size = cuddZddSwapInPlace(table,x,y);
00994 #ifdef DD_DEBUG
00995 assert(table->subtableZ[x].next == (unsigned) x);
00996 assert(table->subtableZ[y].next == (unsigned) y);
00997 #endif
00998 if (size == 0) goto zddGroupSiftingDownOutOfMem;
00999
01000
01001 move = (Move *) cuddDynamicAllocNode(table);
01002 if (move == NULL) goto zddGroupSiftingDownOutOfMem;
01003 move->x = x;
01004 move->y = y;
01005 move->flags = MTR_DEFAULT;
01006 move->size = size;
01007 move->next = *moves;
01008 *moves = move;
01009
01010 #ifdef DD_DEBUG
01011 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
01012 #endif
01013 if ((double) size > (double) limitSize * table->maxGrowth)
01014 return(1);
01015 if (size < limitSize) limitSize = size;
01016 x = y;
01017 y = cuddZddNextHigh(table,x);
01018 } else {
01019 size = zddGroupMove(table,x,y,moves);
01020 if (size == 0) goto zddGroupSiftingDownOutOfMem;
01021 if ((double) size > (double) limitSize * table->maxGrowth)
01022 return(1);
01023 if (size < limitSize) limitSize = size;
01024 }
01025 x = gybot;
01026 y = cuddZddNextHigh(table,x);
01027 }
01028
01029 return(1);
01030
01031 zddGroupSiftingDownOutOfMem:
01032 while (*moves != NULL) {
01033 move = (*moves)->next;
01034 cuddDeallocNode(table, (DdNode *) *moves);
01035 *moves = move;
01036 }
01037
01038 return(0);
01039
01040 }
01041
01042
01053 static int
01054 zddGroupMove(
01055 DdManager * table,
01056 int x,
01057 int y,
01058 Move ** moves)
01059 {
01060 Move *move;
01061 int size;
01062 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01063 int swapx,swapy;
01064 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01065 int initialSize,bestSize;
01066 #endif
01067
01068 #if DD_DEBUG
01069
01070 assert(x < y);
01071 #endif
01072
01073 xbot = x;
01074 xtop = table->subtableZ[x].next;
01075 xsize = xbot - xtop + 1;
01076 ybot = y;
01077 while ((unsigned) ybot < table->subtableZ[ybot].next)
01078 ybot = table->subtableZ[ybot].next;
01079 ytop = y;
01080 ysize = ybot - ytop + 1;
01081
01082 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01083 initialSize = bestSize = table->keysZ;
01084 #endif
01085
01086 for (i = 1; i <= ysize; i++) {
01087 for (j = 1; j <= xsize; j++) {
01088 size = cuddZddSwapInPlace(table,x,y);
01089 if (size == 0) goto zddGroupMoveOutOfMem;
01090 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01091 if (size < bestSize)
01092 bestSize = size;
01093 #endif
01094 swapx = x; swapy = y;
01095 y = x;
01096 x = cuddZddNextLow(table,y);
01097 }
01098 y = ytop + i;
01099 x = cuddZddNextLow(table,y);
01100 }
01101 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01102 if ((bestSize < initialSize) && (bestSize < size))
01103 (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
01104 #endif
01105
01106
01107 y = xtop;
01108 for (i = 0; i < ysize - 1; i++) {
01109 table->subtableZ[y].next = cuddZddNextHigh(table,y);
01110 y = cuddZddNextHigh(table,y);
01111 }
01112 table->subtableZ[y].next = xtop;
01113
01114 x = cuddZddNextHigh(table,y);
01115 newxtop = x;
01116 for (i = 0; i < xsize - 1; i++) {
01117 table->subtableZ[x].next = cuddZddNextHigh(table,x);
01118 x = cuddZddNextHigh(table,x);
01119 }
01120 table->subtableZ[x].next = newxtop;
01121
01122 #ifdef DD_DEBUG
01123 if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
01124 #endif
01125
01126
01127 move = (Move *) cuddDynamicAllocNode(table);
01128 if (move == NULL) goto zddGroupMoveOutOfMem;
01129 move->x = swapx;
01130 move->y = swapy;
01131 move->flags = MTR_DEFAULT;
01132 move->size = table->keysZ;
01133 move->next = *moves;
01134 *moves = move;
01135
01136 return(table->keysZ);
01137
01138 zddGroupMoveOutOfMem:
01139 while (*moves != NULL) {
01140 move = (*moves)->next;
01141 cuddDeallocNode(table, (DdNode *) *moves);
01142 *moves = move;
01143 }
01144 return(0);
01145
01146 }
01147
01148
01159 static int
01160 zddGroupMoveBackward(
01161 DdManager * table,
01162 int x,
01163 int y)
01164 {
01165 int size;
01166 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01167
01168
01169 #if DD_DEBUG
01170
01171 assert(x < y);
01172 #endif
01173
01174
01175 xbot = x;
01176 xtop = table->subtableZ[x].next;
01177 xsize = xbot - xtop + 1;
01178 ybot = y;
01179 while ((unsigned) ybot < table->subtableZ[ybot].next)
01180 ybot = table->subtableZ[ybot].next;
01181 ytop = y;
01182 ysize = ybot - ytop + 1;
01183
01184
01185 for (i = 1; i <= ysize; i++) {
01186 for (j = 1; j <= xsize; j++) {
01187 size = cuddZddSwapInPlace(table,x,y);
01188 if (size == 0)
01189 return(0);
01190 y = x;
01191 x = cuddZddNextLow(table,y);
01192 }
01193 y = ytop + i;
01194 x = cuddZddNextLow(table,y);
01195 }
01196
01197
01198 y = xtop;
01199 for (i = 0; i < ysize - 1; i++) {
01200 table->subtableZ[y].next = cuddZddNextHigh(table,y);
01201 y = cuddZddNextHigh(table,y);
01202 }
01203 table->subtableZ[y].next = xtop;
01204
01205 x = cuddZddNextHigh(table,y);
01206 newxtop = x;
01207 for (i = 0; i < xsize - 1; i++) {
01208 table->subtableZ[x].next = cuddZddNextHigh(table,x);
01209 x = cuddZddNextHigh(table,x);
01210 }
01211 table->subtableZ[x].next = newxtop;
01212
01213 #ifdef DD_DEBUG
01214 if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
01215 #endif
01216
01217 return(1);
01218
01219 }
01220
01221
01233 static int
01234 zddGroupSiftingBackward(
01235 DdManager * table,
01236 Move * moves,
01237 int size)
01238 {
01239 Move *move;
01240 int res;
01241
01242
01243 for (move = moves; move != NULL; move = move->next) {
01244 if (move->size < size) {
01245 size = move->size;
01246 }
01247 }
01248
01249 for (move = moves; move != NULL; move = move->next) {
01250 if (move->size == size) return(1);
01251 if ((table->subtableZ[move->x].next == move->x) &&
01252 (table->subtableZ[move->y].next == move->y)) {
01253 res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
01254 if (!res) return(0);
01255 #ifdef DD_DEBUG
01256 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
01257 assert(table->subtableZ[move->x].next == move->x);
01258 assert(table->subtableZ[move->y].next == move->y);
01259 #endif
01260 } else {
01261 res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
01262 if (!res) return(0);
01263 }
01264 }
01265
01266 return(1);
01267
01268 }
01269
01270
01281 static void
01282 zddMergeGroups(
01283 DdManager * table,
01284 MtrNode * treenode,
01285 int low,
01286 int high)
01287 {
01288 int i;
01289 MtrNode *auxnode;
01290 int saveindex;
01291 int newindex;
01292
01293
01294
01295
01296 if (treenode != table->treeZ) {
01297 for (i = low; i < high; i++)
01298 table->subtableZ[i].next = i+1;
01299 table->subtableZ[high].next = low;
01300 }
01301
01302
01303
01304 saveindex = treenode->index;
01305 newindex = table->invpermZ[low];
01306 auxnode = treenode;
01307 do {
01308 auxnode->index = newindex;
01309 if (auxnode->parent == NULL ||
01310 (int) auxnode->parent->index != saveindex)
01311 break;
01312 auxnode = auxnode->parent;
01313 } while (1);
01314 return;
01315
01316 }
01317