00001
00070 #include "util.h"
00071 #include "cuddInt.h"
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #ifndef lint
00090 static char rcsid[] DD_UNUSED = "$Id: cuddZddGroup.c,v 1.20 2009/02/19 16:25:36 fabio Exp $";
00091 #endif
00092
00093 static int *entry;
00094 extern int zddTotalNumberSwapping;
00095 #ifdef DD_STATS
00096 static int extsymmcalls;
00097 static int extsymm;
00098 static int secdiffcalls;
00099 static int secdiff;
00100 static int secdiffmisfire;
00101 #endif
00102 #ifdef DD_DEBUG
00103 static int pr = 0;
00104
00105 #endif
00106
00107
00108
00109
00110
00113
00114
00115
00116
00117 static int zddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
00118 #ifdef DD_STATS
00119 static int zddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
00120 #endif
00121 static int zddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
00122 static void zddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
00123 static int zddUniqueCompareGroup (int *ptrX, int *ptrY);
00124 static int zddGroupSifting (DdManager *table, int lower, int upper);
00125 static int zddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh);
00126 static int zddGroupSiftingUp (DdManager *table, int y, int xLow, Move **moves);
00127 static int zddGroupSiftingDown (DdManager *table, int x, int xHigh, Move **moves);
00128 static int zddGroupMove (DdManager *table, int x, int y, Move **moves);
00129 static int zddGroupMoveBackward (DdManager *table, int x, int y);
00130 static int zddGroupSiftingBackward (DdManager *table, Move *moves, int size);
00131 static void zddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
00132
00136
00137
00138
00139
00140
00158 MtrNode *
00159 Cudd_MakeZddTreeNode(
00160 DdManager * dd ,
00161 unsigned int low ,
00162 unsigned int size ,
00163 unsigned int type )
00164 {
00165 MtrNode *group;
00166 MtrNode *tree;
00167 unsigned int level;
00168
00169
00170
00171
00172
00173
00174 level = (low < (unsigned int) dd->sizeZ) ? dd->permZ[low] : low;
00175
00176 if (level + size - 1> (int) MTR_MAXHIGH)
00177 return(NULL);
00178
00179
00180 tree = dd->treeZ;
00181 if (tree == NULL) {
00182 dd->treeZ = tree = Mtr_InitGroupTree(0, dd->sizeZ);
00183 if (tree == NULL)
00184 return(NULL);
00185 tree->index = dd->invpermZ[0];
00186 }
00187
00188
00189
00190
00191 tree->size = ddMax(tree->size, level + size);
00192
00193
00194 group = Mtr_MakeGroup(tree, level, size, type);
00195 if (group == NULL)
00196 return(NULL);
00197
00198
00199
00200
00201
00202 group->index = (MtrHalfWord) low;
00203
00204 return(group);
00205
00206 }
00207
00208
00209
00210
00211
00212
00213
00227 int
00228 cuddZddTreeSifting(
00229 DdManager * table ,
00230 Cudd_ReorderingType method )
00231 {
00232 int i;
00233 int nvars;
00234 int result;
00235 int tempTree;
00236
00237
00238
00239
00240
00241 tempTree = table->treeZ == NULL;
00242 if (tempTree) {
00243 table->treeZ = Mtr_InitGroupTree(0,table->sizeZ);
00244 table->treeZ->index = table->invpermZ[0];
00245 }
00246 nvars = table->sizeZ;
00247
00248 #ifdef DD_DEBUG
00249 if (pr > 0 && !tempTree)
00250 (void) fprintf(table->out,"cuddZddTreeSifting:");
00251 Mtr_PrintGroups(table->treeZ,pr <= 0);
00252 #endif
00253 #if 0
00254
00255 if (table->tree && table->treeZ) {
00256 (void) fprintf(table->out,"\n");
00257 Mtr_PrintGroups(table->tree, 0);
00258 cuddPrintVarGroups(table,table->tree,0,0);
00259 for (i = 0; i < table->size; i++) {
00260 (void) fprintf(table->out,"%s%d",
00261 (i == 0) ? "" : ",", table->invperm[i]);
00262 }
00263 (void) fprintf(table->out,"\n");
00264 for (i = 0; i < table->size; i++) {
00265 (void) fprintf(table->out,"%s%d",
00266 (i == 0) ? "" : ",", table->perm[i]);
00267 }
00268 (void) fprintf(table->out,"\n\n");
00269 Mtr_PrintGroups(table->treeZ,0);
00270 cuddPrintVarGroups(table,table->treeZ,1,0);
00271 for (i = 0; i < table->sizeZ; i++) {
00272 (void) fprintf(table->out,"%s%d",
00273 (i == 0) ? "" : ",", table->invpermZ[i]);
00274 }
00275 (void) fprintf(table->out,"\n");
00276 for (i = 0; i < table->sizeZ; i++) {
00277 (void) fprintf(table->out,"%s%d",
00278 (i == 0) ? "" : ",", table->permZ[i]);
00279 }
00280 (void) fprintf(table->out,"\n");
00281 }
00282
00283 #endif
00284 #ifdef DD_STATS
00285 extsymmcalls = 0;
00286 extsymm = 0;
00287 secdiffcalls = 0;
00288 secdiff = 0;
00289 secdiffmisfire = 0;
00290
00291 (void) fprintf(table->out,"\n");
00292 if (!tempTree)
00293 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
00294 zddCountInternalMtrNodes(table,table->treeZ));
00295 #endif
00296
00297
00298
00299
00300
00301 for (i = 0; i < nvars; i++)
00302 table->subtableZ[i].next = i;
00303
00304
00305 result = zddTreeSiftingAux(table, table->treeZ, method);
00306
00307 #ifdef DD_STATS
00308 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00309 (table->groupcheck == CUDD_GROUP_CHECK7 ||
00310 table->groupcheck == CUDD_GROUP_CHECK5)) {
00311 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00312 (void) fprintf(table->out,"extsymm = %d",extsymm);
00313 }
00314 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00315 table->groupcheck == CUDD_GROUP_CHECK7) {
00316 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00317 (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00318 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00319 }
00320 #endif
00321
00322 if (tempTree)
00323 Cudd_FreeZddTree(table);
00324 return(result);
00325
00326 }
00327
00328
00329
00330
00331
00332
00333
00344 static int
00345 zddTreeSiftingAux(
00346 DdManager * table,
00347 MtrNode * treenode,
00348 Cudd_ReorderingType method)
00349 {
00350 MtrNode *auxnode;
00351 int res;
00352
00353 #ifdef DD_DEBUG
00354 Mtr_PrintGroups(treenode,1);
00355 #endif
00356
00357 auxnode = treenode;
00358 while (auxnode != NULL) {
00359 if (auxnode->child != NULL) {
00360 if (!zddTreeSiftingAux(table, auxnode->child, method))
00361 return(0);
00362 res = zddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
00363 if (res == 0)
00364 return(0);
00365 } else if (auxnode->size > 1) {
00366 if (!zddReorderChildren(table, auxnode, method))
00367 return(0);
00368 }
00369 auxnode = auxnode->younger;
00370 }
00371
00372 return(1);
00373
00374 }
00375
00376
00377 #ifdef DD_STATS
00378
00388 static int
00389 zddCountInternalMtrNodes(
00390 DdManager * table,
00391 MtrNode * treenode)
00392 {
00393 MtrNode *auxnode;
00394 int count,nodeCount;
00395
00396
00397 nodeCount = 0;
00398 auxnode = treenode;
00399 while (auxnode != NULL) {
00400 if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
00401 nodeCount++;
00402 count = zddCountInternalMtrNodes(table,auxnode->child);
00403 nodeCount += count;
00404 }
00405 auxnode = auxnode->younger;
00406 }
00407
00408 return(nodeCount);
00409
00410 }
00411 #endif
00412
00413
00428 static int
00429 zddReorderChildren(
00430 DdManager * table,
00431 MtrNode * treenode,
00432 Cudd_ReorderingType method)
00433 {
00434 int lower;
00435 int upper;
00436 int result;
00437 unsigned int initialSize;
00438
00439 zddFindNodeHiLo(table,treenode,&lower,&upper);
00440
00441 if (upper == -1)
00442 return(1);
00443
00444 if (treenode->flags == MTR_FIXED) {
00445 result = 1;
00446 } else {
00447 #ifdef DD_STATS
00448 (void) fprintf(table->out," ");
00449 #endif
00450 switch (method) {
00451 case CUDD_REORDER_RANDOM:
00452 case CUDD_REORDER_RANDOM_PIVOT:
00453 result = cuddZddSwapping(table,lower,upper,method);
00454 break;
00455 case CUDD_REORDER_SIFT:
00456 result = cuddZddSifting(table,lower,upper);
00457 break;
00458 case CUDD_REORDER_SIFT_CONVERGE:
00459 do {
00460 initialSize = table->keysZ;
00461 result = cuddZddSifting(table,lower,upper);
00462 if (initialSize <= table->keysZ)
00463 break;
00464 #ifdef DD_STATS
00465 else
00466 (void) fprintf(table->out,"\n");
00467 #endif
00468 } while (result != 0);
00469 break;
00470 case CUDD_REORDER_SYMM_SIFT:
00471 result = cuddZddSymmSifting(table,lower,upper);
00472 break;
00473 case CUDD_REORDER_SYMM_SIFT_CONV:
00474 result = cuddZddSymmSiftingConv(table,lower,upper);
00475 break;
00476 case CUDD_REORDER_GROUP_SIFT:
00477 result = zddGroupSifting(table,lower,upper);
00478 break;
00479 case CUDD_REORDER_LINEAR:
00480 result = cuddZddLinearSifting(table,lower,upper);
00481 break;
00482 case CUDD_REORDER_LINEAR_CONVERGE:
00483 do {
00484 initialSize = table->keysZ;
00485 result = cuddZddLinearSifting(table,lower,upper);
00486 if (initialSize <= table->keysZ)
00487 break;
00488 #ifdef DD_STATS
00489 else
00490 (void) fprintf(table->out,"\n");
00491 #endif
00492 } while (result != 0);
00493 break;
00494 default:
00495 return(0);
00496 }
00497 }
00498
00499
00500
00501
00502
00503 zddMergeGroups(table,treenode,lower,upper);
00504
00505 #ifdef DD_DEBUG
00506 if (pr > 0) (void) fprintf(table->out,"zddReorderChildren:");
00507 #endif
00508
00509 return(result);
00510
00511 }
00512
00513
00529 static void
00530 zddFindNodeHiLo(
00531 DdManager * table,
00532 MtrNode * treenode,
00533 int * lower,
00534 int * upper)
00535 {
00536 int low;
00537 int high;
00538
00539
00540
00541
00542
00543 if ((int) treenode->low >= table->sizeZ) {
00544 *lower = table->sizeZ;
00545 *upper = -1;
00546 return;
00547 }
00548
00549 *lower = low = (unsigned int) table->permZ[treenode->index];
00550 high = (int) (low + treenode->size - 1);
00551
00552 if (high >= table->sizeZ) {
00553
00554
00555
00556
00557
00558
00559
00560 MtrNode *auxnode = treenode->child;
00561 if (auxnode == NULL) {
00562 *upper = (unsigned int) table->sizeZ - 1;
00563 } else {
00564
00565
00566
00567
00568
00569 while (auxnode != NULL) {
00570 int thisLower = table->permZ[auxnode->low];
00571 int thisUpper = thisLower + auxnode->size - 1;
00572 if (thisUpper >= table->sizeZ && thisLower < table->sizeZ)
00573 *upper = (unsigned int) thisLower - 1;
00574 auxnode = auxnode->younger;
00575 }
00576 }
00577 } else {
00578
00579 *upper = (unsigned int) high;
00580 }
00581
00582 #ifdef DD_DEBUG
00583
00584 assert(treenode->size >= *upper - *lower + 1);
00585 #endif
00586
00587 return;
00588
00589 }
00590
00591
00604 static int
00605 zddUniqueCompareGroup(
00606 int * ptrX,
00607 int * ptrY)
00608 {
00609 #if 0
00610 if (entry[*ptrY] == entry[*ptrX]) {
00611 return((*ptrX) - (*ptrY));
00612 }
00613 #endif
00614 return(entry[*ptrY] - entry[*ptrX]);
00615
00616 }
00617
00618
00632 static int
00633 zddGroupSifting(
00634 DdManager * table,
00635 int lower,
00636 int upper)
00637 {
00638 int *var;
00639 int i,j,x,xInit;
00640 int nvars;
00641 int classes;
00642 int result;
00643 int *sifted;
00644 #ifdef DD_STATS
00645 unsigned previousSize;
00646 #endif
00647 int xindex;
00648
00649 nvars = table->sizeZ;
00650
00651
00652 entry = NULL;
00653 sifted = NULL;
00654 var = ALLOC(int,nvars);
00655 if (var == NULL) {
00656 table->errorCode = CUDD_MEMORY_OUT;
00657 goto zddGroupSiftingOutOfMem;
00658 }
00659 entry = ALLOC(int,nvars);
00660 if (entry == NULL) {
00661 table->errorCode = CUDD_MEMORY_OUT;
00662 goto zddGroupSiftingOutOfMem;
00663 }
00664 sifted = ALLOC(int,nvars);
00665 if (sifted == NULL) {
00666 table->errorCode = CUDD_MEMORY_OUT;
00667 goto zddGroupSiftingOutOfMem;
00668 }
00669
00670
00671 for (i = 0, classes = 0; i < nvars; i++) {
00672 sifted[i] = 0;
00673 x = table->permZ[i];
00674 if ((unsigned) x >= table->subtableZ[x].next) {
00675 entry[i] = table->subtableZ[x].keys;
00676 var[classes] = i;
00677 classes++;
00678 }
00679 }
00680
00681 qsort((void *)var,classes,sizeof(int),(DD_QSFP)zddUniqueCompareGroup);
00682
00683
00684 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00685 if (zddTotalNumberSwapping >= table->siftMaxSwap)
00686 break;
00687 xindex = var[i];
00688 if (sifted[xindex] == 1)
00689 continue;
00690 x = table->permZ[xindex];
00691 if (x < lower || x > upper)
00692 continue;
00693 #ifdef DD_STATS
00694 previousSize = table->keysZ;
00695 #endif
00696 #ifdef DD_DEBUG
00697
00698 assert((unsigned) x >= table->subtableZ[x].next);
00699 #endif
00700 result = zddGroupSiftingAux(table,x,lower,upper);
00701 if (!result) goto zddGroupSiftingOutOfMem;
00702
00703 #ifdef DD_STATS
00704 if (table->keysZ < previousSize) {
00705 (void) fprintf(table->out,"-");
00706 } else if (table->keysZ > previousSize) {
00707 (void) fprintf(table->out,"+");
00708 } else {
00709 (void) fprintf(table->out,"=");
00710 }
00711 fflush(table->out);
00712 #endif
00713
00714
00715 x = table->permZ[xindex];
00716 if ((unsigned) x != table->subtableZ[x].next) {
00717 xInit = x;
00718 do {
00719 j = table->invpermZ[x];
00720 sifted[j] = 1;
00721 x = table->subtableZ[x].next;
00722 } while (x != xInit);
00723 }
00724
00725 #ifdef DD_DEBUG
00726 if (pr > 0) (void) fprintf(table->out,"zddGroupSifting:");
00727 #endif
00728 }
00729
00730 FREE(sifted);
00731 FREE(var);
00732 FREE(entry);
00733
00734 return(1);
00735
00736 zddGroupSiftingOutOfMem:
00737 if (entry != NULL) FREE(entry);
00738 if (var != NULL) FREE(var);
00739 if (sifted != NULL) FREE(sifted);
00740
00741 return(0);
00742
00743 }
00744
00745
00761 static int
00762 zddGroupSiftingAux(
00763 DdManager * table,
00764 int x,
00765 int xLow,
00766 int xHigh)
00767 {
00768 Move *move;
00769 Move *moves;
00770 int initialSize;
00771 int result;
00772
00773
00774 #ifdef DD_DEBUG
00775 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
00776 assert((unsigned) x >= table->subtableZ[x].next);
00777 #endif
00778
00779 initialSize = table->keysZ;
00780 moves = NULL;
00781
00782 if (x == xLow) {
00783 #ifdef DD_DEBUG
00784
00785 assert((unsigned) x == table->subtableZ[x].next);
00786 #endif
00787 if (x == xHigh) return(1);
00788
00789 if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00790 goto zddGroupSiftingAuxOutOfMem;
00791
00792
00793
00794 result = zddGroupSiftingBackward(table,moves,initialSize);
00795 #ifdef DD_DEBUG
00796 assert(table->keysZ <= (unsigned) initialSize);
00797 #endif
00798 if (!result) goto zddGroupSiftingAuxOutOfMem;
00799
00800 } else if (cuddZddNextHigh(table,x) > xHigh) {
00801 #ifdef DD_DEBUG
00802
00803 assert((unsigned) x >= table->subtableZ[x].next);
00804 #endif
00805
00806 x = table->subtableZ[x].next;
00807
00808 if (!zddGroupSiftingUp(table,x,xLow,&moves))
00809 goto zddGroupSiftingAuxOutOfMem;
00810
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 if (x - xLow > xHigh - x) {
00820 if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00821 goto zddGroupSiftingAuxOutOfMem;
00822
00823
00824
00825 if (moves) {
00826 x = moves->y;
00827 }
00828 while ((unsigned) x < table->subtableZ[x].next)
00829 x = table->subtableZ[x].next;
00830 x = table->subtableZ[x].next;
00831 #ifdef DD_DEBUG
00832
00833 assert((unsigned) x <= table->subtableZ[x].next);
00834 #endif
00835
00836 if (!zddGroupSiftingUp(table,x,xLow,&moves))
00837 goto zddGroupSiftingAuxOutOfMem;
00838
00839
00840 result = zddGroupSiftingBackward(table,moves,initialSize);
00841 #ifdef DD_DEBUG
00842 assert(table->keysZ <= (unsigned) initialSize);
00843 #endif
00844 if (!result) goto zddGroupSiftingAuxOutOfMem;
00845
00846 } else {
00847
00848 x = table->subtableZ[x].next;
00849
00850 if (!zddGroupSiftingUp(table,x,xLow,&moves))
00851 goto zddGroupSiftingAuxOutOfMem;
00852
00853
00854 if (moves) {
00855 x = moves->x;
00856 }
00857 while ((unsigned) x < table->subtableZ[x].next)
00858 x = table->subtableZ[x].next;
00859 #ifdef DD_DEBUG
00860
00861 assert((unsigned) x >= table->subtableZ[x].next);
00862 #endif
00863
00864 if (!zddGroupSiftingDown(table,x,xHigh,&moves))
00865 goto zddGroupSiftingAuxOutOfMem;
00866
00867
00868 result = zddGroupSiftingBackward(table,moves,initialSize);
00869 #ifdef DD_DEBUG
00870 assert(table->keysZ <= (unsigned) initialSize);
00871 #endif
00872 if (!result) goto zddGroupSiftingAuxOutOfMem;
00873 }
00874
00875 while (moves != NULL) {
00876 move = moves->next;
00877 cuddDeallocMove(table, moves);
00878 moves = move;
00879 }
00880
00881 return(1);
00882
00883 zddGroupSiftingAuxOutOfMem:
00884 while (moves != NULL) {
00885 move = moves->next;
00886 cuddDeallocMove(table, moves);
00887 moves = move;
00888 }
00889
00890 return(0);
00891
00892 }
00893
00894
00910 static int
00911 zddGroupSiftingUp(
00912 DdManager * table,
00913 int y,
00914 int xLow,
00915 Move ** moves)
00916 {
00917 Move *move;
00918 int x;
00919 int size;
00920 int gxtop;
00921 int limitSize;
00922
00923 limitSize = table->keysZ;
00924
00925 x = cuddZddNextLow(table,y);
00926 while (x >= xLow) {
00927 gxtop = table->subtableZ[x].next;
00928 if (table->subtableZ[x].next == (unsigned) x &&
00929 table->subtableZ[y].next == (unsigned) y) {
00930
00931 size = cuddZddSwapInPlace(table,x,y);
00932 #ifdef DD_DEBUG
00933 assert(table->subtableZ[x].next == (unsigned) x);
00934 assert(table->subtableZ[y].next == (unsigned) y);
00935 #endif
00936 if (size == 0) goto zddGroupSiftingUpOutOfMem;
00937 move = (Move *)cuddDynamicAllocNode(table);
00938 if (move == NULL) goto zddGroupSiftingUpOutOfMem;
00939 move->x = x;
00940 move->y = y;
00941 move->flags = MTR_DEFAULT;
00942 move->size = size;
00943 move->next = *moves;
00944 *moves = move;
00945
00946 #ifdef DD_DEBUG
00947 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
00948 #endif
00949 if ((double) size > (double) limitSize * table->maxGrowth)
00950 return(1);
00951 if (size < limitSize) limitSize = size;
00952 } else {
00953 size = zddGroupMove(table,x,y,moves);
00954 if (size == 0) goto zddGroupSiftingUpOutOfMem;
00955 if ((double) size > (double) limitSize * table->maxGrowth)
00956 return(1);
00957 if (size < limitSize) limitSize = size;
00958 }
00959 y = gxtop;
00960 x = cuddZddNextLow(table,y);
00961 }
00962
00963 return(1);
00964
00965 zddGroupSiftingUpOutOfMem:
00966 while (*moves != NULL) {
00967 move = (*moves)->next;
00968 cuddDeallocMove(table, *moves);
00969 *moves = move;
00970 }
00971 return(0);
00972
00973 }
00974
00975
00987 static int
00988 zddGroupSiftingDown(
00989 DdManager * table,
00990 int x,
00991 int xHigh,
00992 Move ** moves)
00993 {
00994 Move *move;
00995 int y;
00996 int size;
00997 int limitSize;
00998 int gybot;
00999
01000
01001
01002 limitSize = size = table->keysZ;
01003 y = cuddZddNextHigh(table,x);
01004 while (y <= xHigh) {
01005
01006 gybot = table->subtableZ[y].next;
01007 while (table->subtableZ[gybot].next != (unsigned) y)
01008 gybot = table->subtableZ[gybot].next;
01009
01010 if (table->subtableZ[x].next == (unsigned) x &&
01011 table->subtableZ[y].next == (unsigned) y) {
01012
01013 size = cuddZddSwapInPlace(table,x,y);
01014 #ifdef DD_DEBUG
01015 assert(table->subtableZ[x].next == (unsigned) x);
01016 assert(table->subtableZ[y].next == (unsigned) y);
01017 #endif
01018 if (size == 0) goto zddGroupSiftingDownOutOfMem;
01019
01020
01021 move = (Move *) cuddDynamicAllocNode(table);
01022 if (move == NULL) goto zddGroupSiftingDownOutOfMem;
01023 move->x = x;
01024 move->y = y;
01025 move->flags = MTR_DEFAULT;
01026 move->size = size;
01027 move->next = *moves;
01028 *moves = move;
01029
01030 #ifdef DD_DEBUG
01031 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingDown (2 single groups):\n");
01032 #endif
01033 if ((double) size > (double) limitSize * table->maxGrowth)
01034 return(1);
01035 if (size < limitSize) limitSize = size;
01036 x = y;
01037 y = cuddZddNextHigh(table,x);
01038 } else {
01039 size = zddGroupMove(table,x,y,moves);
01040 if (size == 0) goto zddGroupSiftingDownOutOfMem;
01041 if ((double) size > (double) limitSize * table->maxGrowth)
01042 return(1);
01043 if (size < limitSize) limitSize = size;
01044 }
01045 x = gybot;
01046 y = cuddZddNextHigh(table,x);
01047 }
01048
01049 return(1);
01050
01051 zddGroupSiftingDownOutOfMem:
01052 while (*moves != NULL) {
01053 move = (*moves)->next;
01054 cuddDeallocMove(table, *moves);
01055 *moves = move;
01056 }
01057
01058 return(0);
01059
01060 }
01061
01062
01073 static int
01074 zddGroupMove(
01075 DdManager * table,
01076 int x,
01077 int y,
01078 Move ** moves)
01079 {
01080 Move *move;
01081 int size;
01082 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01083 int swapx,swapy;
01084 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01085 int initialSize,bestSize;
01086 #endif
01087
01088 #ifdef DD_DEBUG
01089
01090 assert(x < y);
01091 #endif
01092
01093 xbot = x;
01094 xtop = table->subtableZ[x].next;
01095 xsize = xbot - xtop + 1;
01096 ybot = y;
01097 while ((unsigned) ybot < table->subtableZ[ybot].next)
01098 ybot = table->subtableZ[ybot].next;
01099 ytop = y;
01100 ysize = ybot - ytop + 1;
01101
01102 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01103 initialSize = bestSize = table->keysZ;
01104 #endif
01105
01106 for (i = 1; i <= ysize; i++) {
01107 for (j = 1; j <= xsize; j++) {
01108 size = cuddZddSwapInPlace(table,x,y);
01109 if (size == 0) goto zddGroupMoveOutOfMem;
01110 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01111 if (size < bestSize)
01112 bestSize = size;
01113 #endif
01114 swapx = x; swapy = y;
01115 y = x;
01116 x = cuddZddNextLow(table,y);
01117 }
01118 y = ytop + i;
01119 x = cuddZddNextLow(table,y);
01120 }
01121 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01122 if ((bestSize < initialSize) && (bestSize < size))
01123 (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
01124 #endif
01125
01126
01127 y = xtop;
01128 for (i = 0; i < ysize - 1; i++) {
01129 table->subtableZ[y].next = cuddZddNextHigh(table,y);
01130 y = cuddZddNextHigh(table,y);
01131 }
01132 table->subtableZ[y].next = xtop;
01133
01134 x = cuddZddNextHigh(table,y);
01135 newxtop = x;
01136 for (i = 0; i < xsize - 1; i++) {
01137 table->subtableZ[x].next = cuddZddNextHigh(table,x);
01138 x = cuddZddNextHigh(table,x);
01139 }
01140 table->subtableZ[x].next = newxtop;
01141
01142 #ifdef DD_DEBUG
01143 if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
01144 #endif
01145
01146
01147 move = (Move *) cuddDynamicAllocNode(table);
01148 if (move == NULL) goto zddGroupMoveOutOfMem;
01149 move->x = swapx;
01150 move->y = swapy;
01151 move->flags = MTR_DEFAULT;
01152 move->size = table->keysZ;
01153 move->next = *moves;
01154 *moves = move;
01155
01156 return(table->keysZ);
01157
01158 zddGroupMoveOutOfMem:
01159 while (*moves != NULL) {
01160 move = (*moves)->next;
01161 cuddDeallocMove(table, *moves);
01162 *moves = move;
01163 }
01164 return(0);
01165
01166 }
01167
01168
01179 static int
01180 zddGroupMoveBackward(
01181 DdManager * table,
01182 int x,
01183 int y)
01184 {
01185 int size;
01186 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01187
01188
01189 #ifdef DD_DEBUG
01190
01191 assert(x < y);
01192 #endif
01193
01194
01195 xbot = x;
01196 xtop = table->subtableZ[x].next;
01197 xsize = xbot - xtop + 1;
01198 ybot = y;
01199 while ((unsigned) ybot < table->subtableZ[ybot].next)
01200 ybot = table->subtableZ[ybot].next;
01201 ytop = y;
01202 ysize = ybot - ytop + 1;
01203
01204
01205 for (i = 1; i <= ysize; i++) {
01206 for (j = 1; j <= xsize; j++) {
01207 size = cuddZddSwapInPlace(table,x,y);
01208 if (size == 0)
01209 return(0);
01210 y = x;
01211 x = cuddZddNextLow(table,y);
01212 }
01213 y = ytop + i;
01214 x = cuddZddNextLow(table,y);
01215 }
01216
01217
01218 y = xtop;
01219 for (i = 0; i < ysize - 1; i++) {
01220 table->subtableZ[y].next = cuddZddNextHigh(table,y);
01221 y = cuddZddNextHigh(table,y);
01222 }
01223 table->subtableZ[y].next = xtop;
01224
01225 x = cuddZddNextHigh(table,y);
01226 newxtop = x;
01227 for (i = 0; i < xsize - 1; i++) {
01228 table->subtableZ[x].next = cuddZddNextHigh(table,x);
01229 x = cuddZddNextHigh(table,x);
01230 }
01231 table->subtableZ[x].next = newxtop;
01232
01233 #ifdef DD_DEBUG
01234 if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
01235 #endif
01236
01237 return(1);
01238
01239 }
01240
01241
01253 static int
01254 zddGroupSiftingBackward(
01255 DdManager * table,
01256 Move * moves,
01257 int size)
01258 {
01259 Move *move;
01260 int res;
01261
01262
01263 for (move = moves; move != NULL; move = move->next) {
01264 if (move->size < size) {
01265 size = move->size;
01266 }
01267 }
01268
01269 for (move = moves; move != NULL; move = move->next) {
01270 if (move->size == size) return(1);
01271 if ((table->subtableZ[move->x].next == move->x) &&
01272 (table->subtableZ[move->y].next == move->y)) {
01273 res = cuddZddSwapInPlace(table,(int)move->x,(int)move->y);
01274 if (!res) return(0);
01275 #ifdef DD_DEBUG
01276 if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingBackward:\n");
01277 assert(table->subtableZ[move->x].next == move->x);
01278 assert(table->subtableZ[move->y].next == move->y);
01279 #endif
01280 } else {
01281 res = zddGroupMoveBackward(table,(int)move->x,(int)move->y);
01282 if (!res) return(0);
01283 }
01284 }
01285
01286 return(1);
01287
01288 }
01289
01290
01301 static void
01302 zddMergeGroups(
01303 DdManager * table,
01304 MtrNode * treenode,
01305 int low,
01306 int high)
01307 {
01308 int i;
01309 MtrNode *auxnode;
01310 int saveindex;
01311 int newindex;
01312
01313
01314
01315
01316 if (treenode != table->treeZ) {
01317 for (i = low; i < high; i++)
01318 table->subtableZ[i].next = i+1;
01319 table->subtableZ[high].next = low;
01320 }
01321
01322
01323
01324 saveindex = treenode->index;
01325 newindex = table->invpermZ[low];
01326 auxnode = treenode;
01327 do {
01328 auxnode->index = newindex;
01329 if (auxnode->parent == NULL ||
01330 (int) auxnode->parent->index != saveindex)
01331 break;
01332 auxnode = auxnode->parent;
01333 } while (1);
01334 return;
01335
01336 }