00001
00052 #include "util_hack.h"
00053 #include "cuddInt.h"
00054
00055
00056
00057
00058
00059
00060 #define DD_NORMAL_SIFT 0
00061 #define DD_LAZY_SIFT 1
00062
00063
00064 #define DD_SIFT_DOWN 0
00065 #define DD_SIFT_UP 1
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 #ifndef lint
00080 static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.1.1.1 2003/02/24 22:23:52 wjiang Exp $";
00081 #endif
00082
00083 static int *entry;
00084 extern int ddTotalNumberSwapping;
00085 #ifdef DD_STATS
00086 extern int ddTotalNISwaps;
00087 static int extsymmcalls;
00088 static int extsymm;
00089 static int secdiffcalls;
00090 static int secdiff;
00091 static int secdiffmisfire;
00092 #endif
00093 #ifdef DD_DEBUG
00094 static int pr = 0;
00095
00096 #endif
00097 static int originalSize;
00098 static int originalLevel;
00099
00100
00101
00102
00103
00106
00107
00108
00109
00110 static int ddTreeSiftingAux ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method));
00111 #ifdef DD_STATS
00112 static int ddCountInternalMtrNodes ARGS((DdManager *table, MtrNode *treenode));
00113 #endif
00114 static int ddReorderChildren ARGS((DdManager *table, MtrNode *treenode, Cudd_ReorderingType method));
00115 static void ddFindNodeHiLo ARGS((DdManager *table, MtrNode *treenode, int *lower, int *upper));
00116 static int ddUniqueCompareGroup ARGS((int *ptrX, int *ptrY));
00117 static int ddGroupSifting ARGS((DdManager *table, int lower, int upper, int (*checkFunction)(DdManager *, int, int), int lazyFlag));
00118 static void ddCreateGroup ARGS((DdManager *table, int x, int y));
00119 static int ddGroupSiftingAux ARGS((DdManager *table, int x, int xLow, int xHigh, int (*checkFunction)(DdManager *, int, int), int lazyFlag));
00120 static int ddGroupSiftingUp ARGS((DdManager *table, int y, int xLow, int (*checkFunction)(DdManager *, int, int), Move **moves));
00121 static int ddGroupSiftingDown ARGS((DdManager *table, int x, int xHigh, int (*checkFunction)(DdManager *, int, int), Move **moves));
00122 static int ddGroupMove ARGS((DdManager *table, int x, int y, Move **moves));
00123 static int ddGroupMoveBackward ARGS((DdManager *table, int x, int y));
00124 static int ddGroupSiftingBackward ARGS((DdManager *table, Move *moves, int size, int upFlag, int lazyFlag));
00125 static void ddMergeGroups ARGS((DdManager *table, MtrNode *treenode, int low, int high));
00126 static void ddDissolveGroup ARGS((DdManager *table, int x, int y));
00127 static int ddNoCheck ARGS((DdManager *table, int x, int y));
00128 static int ddSecDiffCheck ARGS((DdManager *table, int x, int y));
00129 static int ddExtSymmCheck ARGS((DdManager *table, int x, int y));
00130 static int ddVarGroupCheck ARGS((DdManager * table, int x, int y));
00131 static int ddSetVarHandled ARGS((DdManager *dd, int index));
00132 static int ddResetVarHandled ARGS((DdManager *dd, int index));
00133 static int ddIsVarHandled ARGS((DdManager *dd, int index));
00134
00138
00139
00140
00141
00142
00160 MtrNode *
00161 Cudd_MakeTreeNode(
00162 DdManager * dd ,
00163 unsigned int low ,
00164 unsigned int size ,
00165 unsigned int type )
00166 {
00167 MtrNode *group;
00168 MtrNode *tree;
00169 unsigned int level;
00170
00171
00172
00173
00174
00175
00176 level = (low < (unsigned int) dd->size) ? dd->perm[low] : low;
00177
00178 if (level + size - 1> (int) MTR_MAXHIGH)
00179 return(NULL);
00180
00181
00182 tree = dd->tree;
00183 if (tree == NULL) {
00184 dd->tree = tree = Mtr_InitGroupTree(0, dd->size);
00185 if (tree == NULL)
00186 return(NULL);
00187 tree->index = dd->invperm[0];
00188 }
00189
00190
00191
00192
00193 tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size));
00194
00195
00196 group = Mtr_MakeGroup(tree, level, size, type);
00197 if (group == NULL)
00198 return(NULL);
00199
00200
00201
00202
00203
00204 group->index = (MtrHalfWord) low;
00205
00206 return(group);
00207
00208 }
00209
00210
00211
00212
00213
00214
00215
00228 int
00229 cuddTreeSifting(
00230 DdManager * table ,
00231 Cudd_ReorderingType method )
00232 {
00233 int i;
00234 int nvars;
00235 int result;
00236 int tempTree;
00237
00238
00239
00240
00241
00242 tempTree = table->tree == NULL;
00243 if (tempTree) {
00244 table->tree = Mtr_InitGroupTree(0,table->size);
00245 table->tree->index = table->invperm[0];
00246 }
00247 nvars = table->size;
00248
00249 #ifdef DD_DEBUG
00250 if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
00251 Mtr_PrintGroups(table->tree,pr <= 0);
00252 #endif
00253
00254 #ifdef DD_STATS
00255 extsymmcalls = 0;
00256 extsymm = 0;
00257 secdiffcalls = 0;
00258 secdiff = 0;
00259 secdiffmisfire = 0;
00260
00261 (void) fprintf(table->out,"\n");
00262 if (!tempTree)
00263 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
00264 ddCountInternalMtrNodes(table,table->tree));
00265 #endif
00266
00267
00268
00269
00270
00271 for (i = 0; i < nvars; i++)
00272 table->subtables[i].next = i;
00273
00274
00275
00276 result = ddTreeSiftingAux(table, table->tree, method);
00277
00278 #ifdef DD_STATS
00279 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00280 (table->groupcheck == CUDD_GROUP_CHECK7 ||
00281 table->groupcheck == CUDD_GROUP_CHECK5)) {
00282 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00283 (void) fprintf(table->out,"extsymm = %d",extsymm);
00284 }
00285 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00286 table->groupcheck == CUDD_GROUP_CHECK7) {
00287 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00288 (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00289 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00290 }
00291 #endif
00292
00293 if (tempTree)
00294 Cudd_FreeTree(table);
00295 return(result);
00296
00297 }
00298
00299
00300
00301
00302
00303
00304
00315 static int
00316 ddTreeSiftingAux(
00317 DdManager * table,
00318 MtrNode * treenode,
00319 Cudd_ReorderingType method)
00320 {
00321 MtrNode *auxnode;
00322 int res;
00323 Cudd_AggregationType saveCheck;
00324
00325 #ifdef DD_DEBUG
00326 Mtr_PrintGroups(treenode,1);
00327 #endif
00328
00329 auxnode = treenode;
00330 while (auxnode != NULL) {
00331 if (auxnode->child != NULL) {
00332 if (!ddTreeSiftingAux(table, auxnode->child, method))
00333 return(0);
00334 saveCheck = table->groupcheck;
00335 table->groupcheck = CUDD_NO_CHECK;
00336 if (method != CUDD_REORDER_LAZY_SIFT)
00337 res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
00338 else
00339 res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT);
00340 table->groupcheck = saveCheck;
00341
00342 if (res == 0)
00343 return(0);
00344 } else if (auxnode->size > 1) {
00345 if (!ddReorderChildren(table, auxnode, method))
00346 return(0);
00347 }
00348 auxnode = auxnode->younger;
00349 }
00350
00351 return(1);
00352
00353 }
00354
00355
00356 #ifdef DD_STATS
00357
00367 static int
00368 ddCountInternalMtrNodes(
00369 DdManager * table,
00370 MtrNode * treenode)
00371 {
00372 MtrNode *auxnode;
00373 int count,nodeCount;
00374
00375
00376 nodeCount = 0;
00377 auxnode = treenode;
00378 while (auxnode != NULL) {
00379 if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
00380 nodeCount++;
00381 count = ddCountInternalMtrNodes(table,auxnode->child);
00382 nodeCount += count;
00383 }
00384 auxnode = auxnode->younger;
00385 }
00386
00387 return(nodeCount);
00388
00389 }
00390 #endif
00391
00392
00407 static int
00408 ddReorderChildren(
00409 DdManager * table,
00410 MtrNode * treenode,
00411 Cudd_ReorderingType method)
00412 {
00413 int lower;
00414 int upper;
00415 int result;
00416 unsigned int initialSize;
00417
00418 ddFindNodeHiLo(table,treenode,&lower,&upper);
00419
00420 if (upper == -1)
00421 return(1);
00422
00423 if (treenode->flags == MTR_FIXED) {
00424 result = 1;
00425 } else {
00426 #ifdef DD_STATS
00427 (void) fprintf(table->out," ");
00428 #endif
00429 switch (method) {
00430 case CUDD_REORDER_RANDOM:
00431 case CUDD_REORDER_RANDOM_PIVOT:
00432 result = cuddSwapping(table,lower,upper,method);
00433 break;
00434 case CUDD_REORDER_SIFT:
00435 result = cuddSifting(table,lower,upper);
00436 break;
00437 case CUDD_REORDER_SIFT_CONVERGE:
00438 do {
00439 initialSize = table->keys - table->isolated;
00440 result = cuddSifting(table,lower,upper);
00441 if (initialSize <= table->keys - table->isolated)
00442 break;
00443 #ifdef DD_STATS
00444 else
00445 (void) fprintf(table->out,"\n");
00446 #endif
00447 } while (result != 0);
00448 break;
00449 case CUDD_REORDER_SYMM_SIFT:
00450 result = cuddSymmSifting(table,lower,upper);
00451 break;
00452 case CUDD_REORDER_SYMM_SIFT_CONV:
00453 result = cuddSymmSiftingConv(table,lower,upper);
00454 break;
00455 case CUDD_REORDER_GROUP_SIFT:
00456 if (table->groupcheck == CUDD_NO_CHECK) {
00457 result = ddGroupSifting(table,lower,upper,ddNoCheck,
00458 DD_NORMAL_SIFT);
00459 } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
00460 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00461 DD_NORMAL_SIFT);
00462 } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
00463 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00464 DD_NORMAL_SIFT);
00465 } else {
00466 (void) fprintf(table->err,
00467 "Unknown group ckecking method\n");
00468 result = 0;
00469 }
00470 break;
00471 case CUDD_REORDER_GROUP_SIFT_CONV:
00472 do {
00473 initialSize = table->keys - table->isolated;
00474 if (table->groupcheck == CUDD_NO_CHECK) {
00475 result = ddGroupSifting(table,lower,upper,ddNoCheck,
00476 DD_NORMAL_SIFT);
00477 } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
00478 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00479 DD_NORMAL_SIFT);
00480 } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
00481 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00482 DD_NORMAL_SIFT);
00483 } else {
00484 (void) fprintf(table->err,
00485 "Unknown group ckecking method\n");
00486 result = 0;
00487 }
00488 #ifdef DD_STATS
00489 (void) fprintf(table->out,"\n");
00490 #endif
00491 result = cuddWindowReorder(table,lower,upper,
00492 CUDD_REORDER_WINDOW4);
00493 if (initialSize <= table->keys - table->isolated)
00494 break;
00495 #ifdef DD_STATS
00496 else
00497 (void) fprintf(table->out,"\n");
00498 #endif
00499 } while (result != 0);
00500 break;
00501 case CUDD_REORDER_WINDOW2:
00502 case CUDD_REORDER_WINDOW3:
00503 case CUDD_REORDER_WINDOW4:
00504 case CUDD_REORDER_WINDOW2_CONV:
00505 case CUDD_REORDER_WINDOW3_CONV:
00506 case CUDD_REORDER_WINDOW4_CONV:
00507 result = cuddWindowReorder(table,lower,upper,method);
00508 break;
00509 case CUDD_REORDER_ANNEALING:
00510 result = cuddAnnealing(table,lower,upper);
00511 break;
00512 case CUDD_REORDER_GENETIC:
00513 result = cuddGa(table,lower,upper);
00514 break;
00515 case CUDD_REORDER_LINEAR:
00516 result = cuddLinearAndSifting(table,lower,upper);
00517 break;
00518 case CUDD_REORDER_LINEAR_CONVERGE:
00519 do {
00520 initialSize = table->keys - table->isolated;
00521 result = cuddLinearAndSifting(table,lower,upper);
00522 if (initialSize <= table->keys - table->isolated)
00523 break;
00524 #ifdef DD_STATS
00525 else
00526 (void) fprintf(table->out,"\n");
00527 #endif
00528 } while (result != 0);
00529 break;
00530 case CUDD_REORDER_EXACT:
00531 result = cuddExact(table,lower,upper);
00532 break;
00533 case CUDD_REORDER_LAZY_SIFT:
00534 result = ddGroupSifting(table,lower,upper,ddVarGroupCheck,
00535 DD_LAZY_SIFT);
00536 break;
00537 default:
00538 return(0);
00539 }
00540 }
00541
00542
00543
00544
00545
00546 ddMergeGroups(table,treenode,lower,upper);
00547
00548 #ifdef DD_DEBUG
00549 if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:");
00550 #endif
00551
00552 return(result);
00553
00554 }
00555
00556
00571 static void
00572 ddFindNodeHiLo(
00573 DdManager * table,
00574 MtrNode * treenode,
00575 int * lower,
00576 int * upper)
00577 {
00578 int low;
00579 int high;
00580
00581
00582
00583
00584
00585 if ((int) treenode->low >= table->size) {
00586 *lower = table->size;
00587 *upper = -1;
00588 return;
00589 }
00590
00591 *lower = low = (unsigned int) table->perm[treenode->index];
00592 high = (int) (low + treenode->size - 1);
00593
00594 if (high >= table->size) {
00595
00596
00597
00598
00599
00600
00601
00602 MtrNode *auxnode = treenode->child;
00603 if (auxnode == NULL) {
00604 *upper = (unsigned int) table->size - 1;
00605 } else {
00606
00607
00608
00609
00610
00611 while (auxnode != NULL) {
00612 int thisLower = table->perm[auxnode->low];
00613 int thisUpper = thisLower + auxnode->size - 1;
00614 if (thisUpper >= table->size && thisLower < table->size)
00615 *upper = (unsigned int) thisLower - 1;
00616 auxnode = auxnode->younger;
00617 }
00618 }
00619 } else {
00620
00621 *upper = (unsigned int) high;
00622 }
00623
00624 #ifdef DD_DEBUG
00625
00626 assert(treenode->size >= *upper - *lower + 1);
00627 #endif
00628
00629 return;
00630
00631 }
00632
00633
00646 static int
00647 ddUniqueCompareGroup(
00648 int * ptrX,
00649 int * ptrY)
00650 {
00651 #if 0
00652 if (entry[*ptrY] == entry[*ptrX]) {
00653 return((*ptrX) - (*ptrY));
00654 }
00655 #endif
00656 return(entry[*ptrY] - entry[*ptrX]);
00657
00658 }
00659
00660
00674 static int
00675 ddGroupSifting(
00676 DdManager * table,
00677 int lower,
00678 int upper,
00679 int (*checkFunction)(DdManager *, int, int),
00680 int lazyFlag)
00681 {
00682 int *var;
00683 int i,j,x,xInit;
00684 int nvars;
00685 int classes;
00686 int result;
00687 int *sifted;
00688 int merged;
00689 int dissolve;
00690 #ifdef DD_STATS
00691 unsigned previousSize;
00692 #endif
00693 int xindex;
00694
00695 nvars = table->size;
00696
00697
00698 entry = NULL;
00699 sifted = NULL;
00700 var = ALLOC(int,nvars);
00701 if (var == NULL) {
00702 table->errorCode = CUDD_MEMORY_OUT;
00703 goto ddGroupSiftingOutOfMem;
00704 }
00705 entry = ALLOC(int,nvars);
00706 if (entry == NULL) {
00707 table->errorCode = CUDD_MEMORY_OUT;
00708 goto ddGroupSiftingOutOfMem;
00709 }
00710 sifted = ALLOC(int,nvars);
00711 if (sifted == NULL) {
00712 table->errorCode = CUDD_MEMORY_OUT;
00713 goto ddGroupSiftingOutOfMem;
00714 }
00715
00716
00717 for (i = 0, classes = 0; i < nvars; i++) {
00718 sifted[i] = 0;
00719 x = table->perm[i];
00720 if ((unsigned) x >= table->subtables[x].next) {
00721 entry[i] = table->subtables[x].keys;
00722 var[classes] = i;
00723 classes++;
00724 }
00725 }
00726
00727 qsort((void *)var,classes,sizeof(int),
00728 (int (*)(const void *, const void *)) ddUniqueCompareGroup);
00729
00730 if (lazyFlag) {
00731 for (i = 0; i < nvars; i ++) {
00732 ddResetVarHandled(table, i);
00733 }
00734 }
00735
00736
00737 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00738 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00739 break;
00740 xindex = var[i];
00741 if (sifted[xindex] == 1)
00742 continue;
00743 x = table->perm[xindex];
00744
00745 if (x < lower || x > upper || table->subtables[x].bindVar == 1)
00746 continue;
00747 #ifdef DD_STATS
00748 previousSize = table->keys - table->isolated;
00749 #endif
00750 #ifdef DD_DEBUG
00751
00752 assert((unsigned) x >= table->subtables[x].next);
00753 #endif
00754 if ((unsigned) x == table->subtables[x].next) {
00755 dissolve = 1;
00756 result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
00757 lazyFlag);
00758 } else {
00759 dissolve = 0;
00760 result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
00761 }
00762 if (!result) goto ddGroupSiftingOutOfMem;
00763
00764
00765 merged = 0;
00766 if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
00767 x = table->perm[xindex];
00768 if ((unsigned) x == table->subtables[x].next) {
00769 if (x != upper && sifted[table->invperm[x+1]] == 0 &&
00770 (unsigned) x+1 == table->subtables[x+1].next) {
00771 if (ddSecDiffCheck(table,x,x+1)) {
00772 merged =1;
00773 ddCreateGroup(table,x,x+1);
00774 }
00775 }
00776 if (x != lower && sifted[table->invperm[x-1]] == 0 &&
00777 (unsigned) x-1 == table->subtables[x-1].next) {
00778 if (ddSecDiffCheck(table,x-1,x)) {
00779 merged =1;
00780 ddCreateGroup(table,x-1,x);
00781 }
00782 }
00783 }
00784 }
00785
00786 if (merged) {
00787
00788 while ((unsigned) x < table->subtables[x].next)
00789 x = table->subtables[x].next;
00790
00791 result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
00792 if (!result) goto ddGroupSiftingOutOfMem;
00793 #ifdef DD_STATS
00794 if (table->keys < previousSize + table->isolated) {
00795 (void) fprintf(table->out,"_");
00796 } else if (table->keys > previousSize + table->isolated) {
00797 (void) fprintf(table->out,"^");
00798 } else {
00799 (void) fprintf(table->out,"*");
00800 }
00801 fflush(table->out);
00802 } else {
00803 if (table->keys < previousSize + table->isolated) {
00804 (void) fprintf(table->out,"-");
00805 } else if (table->keys > previousSize + table->isolated) {
00806 (void) fprintf(table->out,"+");
00807 } else {
00808 (void) fprintf(table->out,"=");
00809 }
00810 fflush(table->out);
00811 #endif
00812 }
00813
00814
00815 x = table->perm[xindex];
00816 if ((unsigned) x != table->subtables[x].next) {
00817 xInit = x;
00818 do {
00819 j = table->invperm[x];
00820 sifted[j] = 1;
00821 x = table->subtables[x].next;
00822 } while (x != xInit);
00823
00824
00825 if (lazyFlag == 0 && dissolve) {
00826 do {
00827 j = table->subtables[x].next;
00828 table->subtables[x].next = x;
00829 x = j;
00830 } while (x != xInit);
00831 }
00832 }
00833
00834 #ifdef DD_DEBUG
00835 if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
00836 #endif
00837
00838 if (lazyFlag) ddSetVarHandled(table, xindex);
00839 }
00840
00841 FREE(sifted);
00842 FREE(var);
00843 FREE(entry);
00844
00845 return(1);
00846
00847 ddGroupSiftingOutOfMem:
00848 if (entry != NULL) FREE(entry);
00849 if (var != NULL) FREE(var);
00850 if (sifted != NULL) FREE(sifted);
00851
00852 return(0);
00853
00854 }
00855
00856
00869 static void
00870 ddCreateGroup(
00871 DdManager * table,
00872 int x,
00873 int y)
00874 {
00875 int gybot;
00876
00877 #ifdef DD_DEBUG
00878 assert(y == x+1);
00879 #endif
00880
00881
00882 gybot = y;
00883 while ((unsigned) gybot < table->subtables[gybot].next)
00884 gybot = table->subtables[gybot].next;
00885
00886
00887 table->subtables[x].next = y;
00888 table->subtables[gybot].next = x;
00889
00890 return;
00891
00892 }
00893
00894
00910 static int
00911 ddGroupSiftingAux(
00912 DdManager * table,
00913 int x,
00914 int xLow,
00915 int xHigh,
00916 int (*checkFunction)(DdManager *, int, int),
00917 int lazyFlag)
00918 {
00919 Move *move;
00920 Move *moves;
00921 int initialSize;
00922 int result;
00923 int y;
00924 int topbot;
00925
00926 #ifdef DD_DEBUG
00927 if (pr > 0) (void) fprintf(table->out,
00928 "ddGroupSiftingAux from %d to %d\n",xLow,xHigh);
00929 assert((unsigned) x >= table->subtables[x].next);
00930 #endif
00931
00932 initialSize = table->keys - table->isolated;
00933 moves = NULL;
00934
00935 originalSize = initialSize;
00936
00937
00938
00939
00940 if ((unsigned) x == table->subtables[x].next) {
00941
00942
00943
00944 for (y = x; y > xLow; y--) {
00945 if (!checkFunction(table,y-1,y))
00946 break;
00947 topbot = table->subtables[y-1].next;
00948 table->subtables[y-1].next = y;
00949 table->subtables[x].next = topbot;
00950
00951 y = topbot + 1;
00952 }
00953
00954
00955
00956 for (y = x; y < xHigh; y++) {
00957 if (!checkFunction(table,y,y+1))
00958 break;
00959
00960 topbot = y + 1;
00961 while ((unsigned) topbot < table->subtables[topbot].next) {
00962 topbot = table->subtables[topbot].next;
00963 }
00964 table->subtables[topbot].next = table->subtables[y].next;
00965 table->subtables[y].next = y + 1;
00966 y = topbot - 1;
00967 }
00968 }
00969
00970
00971
00972
00973 while ((unsigned) x < table->subtables[x].next)
00974 x = table->subtables[x].next;
00975
00976 originalLevel = x;
00977
00978 if (x == xLow) {
00979 #ifdef DD_DEBUG
00980
00981 assert((unsigned) x == table->subtables[x].next);
00982 #endif
00983 if (x == xHigh) return(1);
00984
00985 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
00986 goto ddGroupSiftingAuxOutOfMem;
00987
00988
00989
00990 result = ddGroupSiftingBackward(table,moves,initialSize,
00991 DD_SIFT_DOWN,lazyFlag);
00992 #ifdef DD_DEBUG
00993 assert(table->keys - table->isolated <= (unsigned) initialSize);
00994 #endif
00995 if (!result) goto ddGroupSiftingAuxOutOfMem;
00996
00997 } else if (cuddNextHigh(table,x) > xHigh) {
00998 #ifdef DD_DEBUG
00999
01000 assert((unsigned) x >= table->subtables[x].next);
01001 #endif
01002
01003 x = table->subtables[x].next;
01004
01005 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
01006 goto ddGroupSiftingAuxOutOfMem;
01007
01008
01009
01010 result = ddGroupSiftingBackward(table,moves,initialSize,
01011 DD_SIFT_UP,lazyFlag);
01012 #ifdef DD_DEBUG
01013 assert(table->keys - table->isolated <= (unsigned) initialSize);
01014 #endif
01015 if (!result) goto ddGroupSiftingAuxOutOfMem;
01016
01017 } else if (x - xLow > xHigh - x) {
01018 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
01019 goto ddGroupSiftingAuxOutOfMem;
01020
01021
01022
01023 if (moves) {
01024 x = moves->y;
01025 }
01026 while ((unsigned) x < table->subtables[x].next)
01027 x = table->subtables[x].next;
01028 x = table->subtables[x].next;
01029 #ifdef DD_DEBUG
01030
01031 assert((unsigned) x <= table->subtables[x].next);
01032 #endif
01033
01034 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
01035 goto ddGroupSiftingAuxOutOfMem;
01036
01037
01038 result = ddGroupSiftingBackward(table,moves,initialSize,
01039 DD_SIFT_UP,lazyFlag);
01040 #ifdef DD_DEBUG
01041 assert(table->keys - table->isolated <= (unsigned) initialSize);
01042 #endif
01043 if (!result) goto ddGroupSiftingAuxOutOfMem;
01044
01045 } else {
01046
01047 x = table->subtables[x].next;
01048
01049 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
01050 goto ddGroupSiftingAuxOutOfMem;
01051
01052
01053 if (moves) {
01054 x = moves->x;
01055 }
01056 while ((unsigned) x < table->subtables[x].next)
01057 x = table->subtables[x].next;
01058 #ifdef DD_DEBUG
01059
01060 assert((unsigned) x >= table->subtables[x].next);
01061 #endif
01062
01063 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
01064 goto ddGroupSiftingAuxOutOfMem;
01065
01066
01067 result = ddGroupSiftingBackward(table,moves,initialSize,
01068 DD_SIFT_DOWN,lazyFlag);
01069 #ifdef DD_DEBUG
01070 assert(table->keys - table->isolated <= (unsigned) initialSize);
01071 #endif
01072 if (!result) goto ddGroupSiftingAuxOutOfMem;
01073 }
01074
01075 while (moves != NULL) {
01076 move = moves->next;
01077 cuddDeallocNode(table, (DdNode *) moves);
01078 moves = move;
01079 }
01080
01081 return(1);
01082
01083 ddGroupSiftingAuxOutOfMem:
01084 while (moves != NULL) {
01085 move = moves->next;
01086 cuddDeallocNode(table, (DdNode *) moves);
01087 moves = move;
01088 }
01089
01090 return(0);
01091
01092 }
01093
01094
01110 static int
01111 ddGroupSiftingUp(
01112 DdManager * table,
01113 int y,
01114 int xLow,
01115 int (*checkFunction)(DdManager *, int, int),
01116 Move ** moves)
01117 {
01118 Move *move;
01119 int x;
01120 int size;
01121 int i;
01122 int gxtop,gybot;
01123 int limitSize;
01124 int xindex, yindex;
01125 int zindex;
01126 int z;
01127 int isolated;
01128 int L;
01129 #ifdef DD_DEBUG
01130 int checkL;
01131 #endif
01132
01133 yindex = table->invperm[y];
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 limitSize = L = table->keys - table->isolated;
01145 gybot = y;
01146 while ((unsigned) gybot < table->subtables[gybot].next)
01147 gybot = table->subtables[gybot].next;
01148 for (z = xLow + 1; z <= gybot; z++) {
01149 zindex = table->invperm[z];
01150 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01151 isolated = table->vars[zindex]->ref == 1;
01152 L -= table->subtables[z].keys - isolated;
01153 }
01154 }
01155
01156 originalLevel = y;
01157
01158 x = cuddNextLow(table,y);
01159 while (x >= xLow && L <= limitSize) {
01160 #ifdef DD_DEBUG
01161 gybot = y;
01162 while ((unsigned) gybot < table->subtables[gybot].next)
01163 gybot = table->subtables[gybot].next;
01164 checkL = table->keys - table->isolated;
01165 for (z = xLow + 1; z <= gybot; z++) {
01166 zindex = table->invperm[z];
01167 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01168 isolated = table->vars[zindex]->ref == 1;
01169 checkL -= table->subtables[z].keys - isolated;
01170 }
01171 }
01172 if (pr > 0 && L != checkL) {
01173 (void) fprintf(table->out,
01174 "Inaccurate lower bound: L = %d checkL = %d\n",
01175 L, checkL);
01176 }
01177 #endif
01178 gxtop = table->subtables[x].next;
01179 if (checkFunction(table,x,y)) {
01180
01181 table->subtables[x].next = y;
01182 i = table->subtables[y].next;
01183 while (table->subtables[i].next != (unsigned) y)
01184 i = table->subtables[i].next;
01185 table->subtables[i].next = gxtop;
01186 move = (Move *)cuddDynamicAllocNode(table);
01187 if (move == NULL) goto ddGroupSiftingUpOutOfMem;
01188 move->x = x;
01189 move->y = y;
01190 move->flags = MTR_NEWNODE;
01191 move->size = table->keys - table->isolated;
01192 move->next = *moves;
01193 *moves = move;
01194 } else if (table->subtables[x].next == (unsigned) x &&
01195 table->subtables[y].next == (unsigned) y) {
01196
01197 xindex = table->invperm[x];
01198 size = cuddSwapInPlace(table,x,y);
01199 #ifdef DD_DEBUG
01200 assert(table->subtables[x].next == (unsigned) x);
01201 assert(table->subtables[y].next == (unsigned) y);
01202 #endif
01203 if (size == 0) goto ddGroupSiftingUpOutOfMem;
01204
01205 if (cuddTestInteract(table,xindex,yindex)) {
01206 isolated = table->vars[xindex]->ref == 1;
01207 L += table->subtables[y].keys - isolated;
01208 }
01209 move = (Move *)cuddDynamicAllocNode(table);
01210 if (move == NULL) goto ddGroupSiftingUpOutOfMem;
01211 move->x = x;
01212 move->y = y;
01213 move->flags = MTR_DEFAULT;
01214 move->size = size;
01215 move->next = *moves;
01216 *moves = move;
01217
01218 #ifdef DD_DEBUG
01219 if (pr > 0) (void) fprintf(table->out,
01220 "ddGroupSiftingUp (2 single groups):\n");
01221 #endif
01222 if ((double) size > (double) limitSize * table->maxGrowth)
01223 return(1);
01224 if (size < limitSize) limitSize = size;
01225 } else {
01226 size = ddGroupMove(table,x,y,moves);
01227 if (size == 0) goto ddGroupSiftingUpOutOfMem;
01228
01229 z = (*moves)->y;
01230 do {
01231 zindex = table->invperm[z];
01232 if (cuddTestInteract(table,zindex,yindex)) {
01233 isolated = table->vars[zindex]->ref == 1;
01234 L += table->subtables[z].keys - isolated;
01235 }
01236 z = table->subtables[z].next;
01237 } while (z != (int) (*moves)->y);
01238 if ((double) size > (double) limitSize * table->maxGrowth)
01239 return(1);
01240 if (size < limitSize) limitSize = size;
01241 }
01242 y = gxtop;
01243 x = cuddNextLow(table,y);
01244 }
01245
01246 return(1);
01247
01248 ddGroupSiftingUpOutOfMem:
01249 while (*moves != NULL) {
01250 move = (*moves)->next;
01251 cuddDeallocNode(table, (DdNode *) *moves);
01252 *moves = move;
01253 }
01254 return(0);
01255
01256 }
01257
01258
01270 static int
01271 ddGroupSiftingDown(
01272 DdManager * table,
01273 int x,
01274 int xHigh,
01275 int (*checkFunction)(DdManager *, int, int),
01276 Move ** moves)
01277 {
01278 Move *move;
01279 int y;
01280 int size;
01281 int limitSize;
01282 int gxtop,gybot;
01283 int R;
01284 int xindex, yindex;
01285 int isolated, allVars;
01286 int z;
01287 int zindex;
01288 #ifdef DD_DEBUG
01289 int checkR;
01290 #endif
01291
01292
01293
01294
01295
01296
01297 y = x;
01298 allVars = 1;
01299 do {
01300 if (table->subtables[y].keys != 1) {
01301 allVars = 0;
01302 break;
01303 }
01304 y = table->subtables[y].next;
01305 } while (table->subtables[y].next != (unsigned) x);
01306 if (allVars)
01307 return(1);
01308
01309
01310 xindex = table->invperm[x];
01311 gxtop = table->subtables[x].next;
01312 limitSize = size = table->keys - table->isolated;
01313 R = 0;
01314 for (z = xHigh; z > gxtop; z--) {
01315 zindex = table->invperm[z];
01316 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01317 isolated = table->vars[zindex]->ref == 1;
01318 R += table->subtables[z].keys - isolated;
01319 }
01320 }
01321
01322 originalLevel = x;
01323
01324 y = cuddNextHigh(table,x);
01325 while (y <= xHigh && size - R < limitSize) {
01326 #ifdef DD_DEBUG
01327 gxtop = table->subtables[x].next;
01328 checkR = 0;
01329 for (z = xHigh; z > gxtop; z--) {
01330 zindex = table->invperm[z];
01331 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01332 isolated = table->vars[zindex]->ref == 1;
01333 checkR += table->subtables[z].keys - isolated;
01334 }
01335 }
01336 assert(R >= checkR);
01337 #endif
01338
01339 gybot = table->subtables[y].next;
01340 while (table->subtables[gybot].next != (unsigned) y)
01341 gybot = table->subtables[gybot].next;
01342
01343 if (checkFunction(table,x,y)) {
01344
01345 gxtop = table->subtables[x].next;
01346 table->subtables[x].next = y;
01347 table->subtables[gybot].next = gxtop;
01348 move = (Move *)cuddDynamicAllocNode(table);
01349 if (move == NULL) goto ddGroupSiftingDownOutOfMem;
01350 move->x = x;
01351 move->y = y;
01352 move->flags = MTR_NEWNODE;
01353 move->size = table->keys - table->isolated;
01354 move->next = *moves;
01355 *moves = move;
01356 } else if (table->subtables[x].next == (unsigned) x &&
01357 table->subtables[y].next == (unsigned) y) {
01358
01359
01360 yindex = table->invperm[y];
01361 if (cuddTestInteract(table,xindex,yindex)) {
01362 isolated = table->vars[yindex]->ref == 1;
01363 R -= table->subtables[y].keys - isolated;
01364 }
01365 size = cuddSwapInPlace(table,x,y);
01366 #ifdef DD_DEBUG
01367 assert(table->subtables[x].next == (unsigned) x);
01368 assert(table->subtables[y].next == (unsigned) y);
01369 #endif
01370 if (size == 0) goto ddGroupSiftingDownOutOfMem;
01371
01372
01373 move = (Move *) cuddDynamicAllocNode(table);
01374 if (move == NULL) goto ddGroupSiftingDownOutOfMem;
01375 move->x = x;
01376 move->y = y;
01377 move->flags = MTR_DEFAULT;
01378 move->size = size;
01379 move->next = *moves;
01380 *moves = move;
01381
01382 #ifdef DD_DEBUG
01383 if (pr > 0) (void) fprintf(table->out,
01384 "ddGroupSiftingDown (2 single groups):\n");
01385 #endif
01386 if ((double) size > (double) limitSize * table->maxGrowth)
01387 return(1);
01388 if (size < limitSize) limitSize = size;
01389
01390 x = y;
01391 y = cuddNextHigh(table,x);
01392 } else {
01393
01394 gxtop = table->subtables[x].next;
01395 z = gxtop + 1;
01396 do {
01397 zindex = table->invperm[z];
01398 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01399 isolated = table->vars[zindex]->ref == 1;
01400 R -= table->subtables[z].keys - isolated;
01401 }
01402 z++;
01403 } while (z <= gybot);
01404 size = ddGroupMove(table,x,y,moves);
01405 if (size == 0) goto ddGroupSiftingDownOutOfMem;
01406 if ((double) size > (double) limitSize * table->maxGrowth)
01407 return(1);
01408 if (size < limitSize) limitSize = size;
01409
01410
01411 gxtop = table->subtables[gybot].next;
01412 for (z = gxtop + 1; z <= gybot; z++) {
01413 zindex = table->invperm[z];
01414 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01415 isolated = table->vars[zindex]->ref == 1;
01416 R += table->subtables[z].keys - isolated;
01417 }
01418 }
01419 }
01420 x = gybot;
01421 y = cuddNextHigh(table,x);
01422 }
01423
01424 return(1);
01425
01426 ddGroupSiftingDownOutOfMem:
01427 while (*moves != NULL) {
01428 move = (*moves)->next;
01429 cuddDeallocNode(table, (DdNode *) *moves);
01430 *moves = move;
01431 }
01432
01433 return(0);
01434
01435 }
01436
01437
01448 static int
01449 ddGroupMove(
01450 DdManager * table,
01451 int x,
01452 int y,
01453 Move ** moves)
01454 {
01455 Move *move;
01456 int size;
01457 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01458 int swapx,swapy;
01459 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01460 int initialSize,bestSize;
01461 #endif
01462
01463 #if DD_DEBUG
01464
01465 assert(x < y);
01466 #endif
01467
01468 xbot = x;
01469 xtop = table->subtables[x].next;
01470 xsize = xbot - xtop + 1;
01471 ybot = y;
01472 while ((unsigned) ybot < table->subtables[ybot].next)
01473 ybot = table->subtables[ybot].next;
01474 ytop = y;
01475 ysize = ybot - ytop + 1;
01476
01477 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01478 initialSize = bestSize = table->keys - table->isolated;
01479 #endif
01480
01481 for (i = 1; i <= ysize; i++) {
01482 for (j = 1; j <= xsize; j++) {
01483 size = cuddSwapInPlace(table,x,y);
01484 if (size == 0) goto ddGroupMoveOutOfMem;
01485 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01486 if (size < bestSize)
01487 bestSize = size;
01488 #endif
01489 swapx = x; swapy = y;
01490 y = x;
01491 x = cuddNextLow(table,y);
01492 }
01493 y = ytop + i;
01494 x = cuddNextLow(table,y);
01495 }
01496 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01497 if ((bestSize < initialSize) && (bestSize < size))
01498 (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
01499 #endif
01500
01501
01502 y = xtop;
01503 for (i = 0; i < ysize - 1; i++) {
01504 table->subtables[y].next = cuddNextHigh(table,y);
01505 y = cuddNextHigh(table,y);
01506 }
01507 table->subtables[y].next = xtop;
01508
01509 x = cuddNextHigh(table,y);
01510 newxtop = x;
01511 for (i = 0; i < xsize - 1; i++) {
01512 table->subtables[x].next = cuddNextHigh(table,x);
01513 x = cuddNextHigh(table,x);
01514 }
01515 table->subtables[x].next = newxtop;
01516
01517 #ifdef DD_DEBUG
01518 if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n");
01519 #endif
01520
01521
01522 move = (Move *) cuddDynamicAllocNode(table);
01523 if (move == NULL) goto ddGroupMoveOutOfMem;
01524 move->x = swapx;
01525 move->y = swapy;
01526 move->flags = MTR_DEFAULT;
01527 move->size = table->keys - table->isolated;
01528 move->next = *moves;
01529 *moves = move;
01530
01531 return(table->keys - table->isolated);
01532
01533 ddGroupMoveOutOfMem:
01534 while (*moves != NULL) {
01535 move = (*moves)->next;
01536 cuddDeallocNode(table, (DdNode *) *moves);
01537 *moves = move;
01538 }
01539 return(0);
01540
01541 }
01542
01543
01554 static int
01555 ddGroupMoveBackward(
01556 DdManager * table,
01557 int x,
01558 int y)
01559 {
01560 int size;
01561 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01562
01563
01564 #if DD_DEBUG
01565
01566 assert(x < y);
01567 #endif
01568
01569
01570 xbot = x;
01571 xtop = table->subtables[x].next;
01572 xsize = xbot - xtop + 1;
01573 ybot = y;
01574 while ((unsigned) ybot < table->subtables[ybot].next)
01575 ybot = table->subtables[ybot].next;
01576 ytop = y;
01577 ysize = ybot - ytop + 1;
01578
01579
01580 for (i = 1; i <= ysize; i++) {
01581 for (j = 1; j <= xsize; j++) {
01582 size = cuddSwapInPlace(table,x,y);
01583 if (size == 0)
01584 return(0);
01585 y = x;
01586 x = cuddNextLow(table,y);
01587 }
01588 y = ytop + i;
01589 x = cuddNextLow(table,y);
01590 }
01591
01592
01593 y = xtop;
01594 for (i = 0; i < ysize - 1; i++) {
01595 table->subtables[y].next = cuddNextHigh(table,y);
01596 y = cuddNextHigh(table,y);
01597 }
01598 table->subtables[y].next = xtop;
01599
01600 x = cuddNextHigh(table,y);
01601 newxtop = x;
01602 for (i = 0; i < xsize - 1; i++) {
01603 table->subtables[x].next = cuddNextHigh(table,x);
01604 x = cuddNextHigh(table,x);
01605 }
01606 table->subtables[x].next = newxtop;
01607
01608 #ifdef DD_DEBUG
01609 if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n");
01610 #endif
01611
01612 return(1);
01613
01614 }
01615
01616
01628 static int
01629 ddGroupSiftingBackward(
01630 DdManager * table,
01631 Move * moves,
01632 int size,
01633 int upFlag,
01634 int lazyFlag)
01635 {
01636 Move *move;
01637 int res;
01638 Move *end_move;
01639 int diff, tmp_diff;
01640 int index, pairlev;
01641
01642 if (lazyFlag) {
01643 end_move = NULL;
01644
01645
01646
01647 for (move = moves; move != NULL; move = move->next) {
01648 if (move->size < size) {
01649 size = move->size;
01650 end_move = move;
01651 } else if (move->size == size) {
01652 if (end_move == NULL) end_move = move;
01653 }
01654 }
01655
01656
01657
01658 if (moves != NULL) {
01659 diff = Cudd_ReadSize(table) + 1;
01660 index = (upFlag == 1) ?
01661 table->invperm[moves->x] : table->invperm[moves->y];
01662 pairlev = table->perm[Cudd_bddReadPairIndex(table, index)];
01663
01664 for (move = moves; move != NULL; move = move->next) {
01665 if (move->size == size) {
01666 if (upFlag == 1) {
01667 tmp_diff = (move->x > pairlev) ?
01668 move->x - pairlev : pairlev - move->x;
01669 } else {
01670 tmp_diff = (move->y > pairlev) ?
01671 move->y - pairlev : pairlev - move->y;
01672 }
01673 if (tmp_diff < diff) {
01674 diff = tmp_diff;
01675 end_move = move;
01676 }
01677 }
01678 }
01679 }
01680 } else {
01681
01682 for (move = moves; move != NULL; move = move->next) {
01683 if (move->size < size) {
01684 size = move->size;
01685 }
01686 }
01687 }
01688
01689
01690
01691
01692 for (move = moves; move != NULL; move = move->next) {
01693 if (lazyFlag) {
01694 if (move == end_move) return(1);
01695 } else {
01696 if (move->size == size) return(1);
01697 }
01698 if ((table->subtables[move->x].next == move->x) &&
01699 (table->subtables[move->y].next == move->y)) {
01700 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01701 if (!res) return(0);
01702 #ifdef DD_DEBUG
01703 if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
01704 assert(table->subtables[move->x].next == move->x);
01705 assert(table->subtables[move->y].next == move->y);
01706 #endif
01707 } else {
01708 if (move->flags == MTR_NEWNODE) {
01709 ddDissolveGroup(table,(int)move->x,(int)move->y);
01710 } else {
01711 res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
01712 if (!res) return(0);
01713 }
01714 }
01715
01716 }
01717
01718 return(1);
01719
01720 }
01721
01722
01733 static void
01734 ddMergeGroups(
01735 DdManager * table,
01736 MtrNode * treenode,
01737 int low,
01738 int high)
01739 {
01740 int i;
01741 MtrNode *auxnode;
01742 int saveindex;
01743 int newindex;
01744
01745
01746
01747
01748 if (treenode != table->tree) {
01749 for (i = low; i < high; i++)
01750 table->subtables[i].next = i+1;
01751 table->subtables[high].next = low;
01752 }
01753
01754
01755
01756 saveindex = treenode->index;
01757 newindex = table->invperm[low];
01758 auxnode = treenode;
01759 do {
01760 auxnode->index = newindex;
01761 if (auxnode->parent == NULL ||
01762 (int) auxnode->parent->index != saveindex)
01763 break;
01764 auxnode = auxnode->parent;
01765 } while (1);
01766 return;
01767
01768 }
01769
01770
01781 static void
01782 ddDissolveGroup(
01783 DdManager * table,
01784 int x,
01785 int y)
01786 {
01787 int topx;
01788 int boty;
01789
01790
01791 boty = y;
01792 while ((unsigned) boty < table->subtables[boty].next)
01793 boty = table->subtables[boty].next;
01794
01795 topx = table->subtables[boty].next;
01796
01797 table->subtables[boty].next = y;
01798 table->subtables[x].next = topx;
01799
01800 return;
01801
01802 }
01803
01804
01815 static int
01816 ddNoCheck(
01817 DdManager * table,
01818 int x,
01819 int y)
01820 {
01821 return(0);
01822
01823 }
01824
01825
01839 static int
01840 ddSecDiffCheck(
01841 DdManager * table,
01842 int x,
01843 int y)
01844 {
01845 double Nx,Nx_1;
01846 double Sx;
01847 double threshold;
01848 int xindex,yindex;
01849
01850 if (x==0) return(0);
01851
01852 #ifdef DD_STATS
01853 secdiffcalls++;
01854 #endif
01855 Nx = (double) table->subtables[x].keys;
01856 Nx_1 = (double) table->subtables[x-1].keys;
01857 Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1);
01858
01859 threshold = table->recomb / 100.0;
01860 if (Sx < threshold) {
01861 xindex = table->invperm[x];
01862 yindex = table->invperm[y];
01863 if (cuddTestInteract(table,xindex,yindex)) {
01864 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01865 (void) fprintf(table->out,
01866 "Second difference for %d = %g Pos(%d)\n",
01867 table->invperm[x],Sx,x);
01868 #endif
01869 #ifdef DD_STATS
01870 secdiff++;
01871 #endif
01872 return(1);
01873 } else {
01874 #ifdef DD_STATS
01875 secdiffmisfire++;
01876 #endif
01877 return(0);
01878 }
01879
01880 }
01881 return(0);
01882
01883 }
01884
01885
01896 static int
01897 ddExtSymmCheck(
01898 DdManager * table,
01899 int x,
01900 int y)
01901 {
01902 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
01903 DdNode *one;
01904 int comple;
01905 int notproj;
01906 int arccount;
01907 int TotalRefCount;
01908 int counter;
01909
01910 int arccounter;
01911
01912 int i;
01913 int xindex;
01914 int yindex;
01915 int res;
01916 int slots;
01917 DdNodePtr *list;
01918 DdNode *sentinel = &(table->sentinel);
01919
01920 xindex = table->invperm[x];
01921 yindex = table->invperm[y];
01922
01923
01924 if (!cuddTestInteract(table,xindex,yindex))
01925 return(0);
01926
01927 #ifdef DD_DEBUG
01928
01929
01930
01931
01932
01933 if (table->subtables[x].keys == 1) {
01934 assert(table->vars[xindex]->ref != 1);
01935 }
01936 if (table->subtables[y].keys == 1) {
01937 assert(table->vars[yindex]->ref != 1);
01938 }
01939 #endif
01940
01941 #ifdef DD_STATS
01942 extsymmcalls++;
01943 #endif
01944
01945 arccount = 0;
01946 counter = (int) (table->subtables[x].keys *
01947 (table->symmviolation/100.0) + 0.5);
01948 one = DD_ONE(table);
01949
01950 slots = table->subtables[x].slots;
01951 list = table->subtables[x].nodelist;
01952 for (i = 0; i < slots; i++) {
01953 f = list[i];
01954 while (f != sentinel) {
01955
01956 f1 = cuddT(f);
01957 f0 = Cudd_Regular(cuddE(f));
01958 comple = Cudd_IsComplement(cuddE(f));
01959 notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1;
01960 if (f1->index == yindex) {
01961 arccount++;
01962 f11 = cuddT(f1); f10 = cuddE(f1);
01963 } else {
01964 if ((int) f0->index != yindex) {
01965
01966
01967
01968 if (notproj) {
01969 if (counter == 0)
01970 return(0);
01971 counter--;
01972 }
01973 }
01974 f11 = f10 = f1;
01975 }
01976 if ((int) f0->index == yindex) {
01977 arccount++;
01978 f01 = cuddT(f0); f00 = cuddE(f0);
01979 } else {
01980 f01 = f00 = f0;
01981 }
01982 if (comple) {
01983 f01 = Cudd_Not(f01);
01984 f00 = Cudd_Not(f00);
01985 }
01986
01987
01988
01989
01990
01991 if (notproj) {
01992 if (f01 != f10 && f11 != f00) {
01993 if (counter == 0)
01994 return(0);
01995 counter--;
01996 }
01997 }
01998
01999 f = f->next;
02000 }
02001 }
02002
02003
02004 TotalRefCount = -1;
02005 slots = table->subtables[y].slots;
02006 list = table->subtables[y].nodelist;
02007 for (i = 0; i < slots; i++) {
02008 f = list[i];
02009 while (f != sentinel) {
02010 TotalRefCount += f->ref;
02011 f = f->next;
02012 }
02013 }
02014
02015 arccounter = (int) (table->subtables[y].keys *
02016 (table->arcviolation/100.0) + 0.5);
02017 res = arccount >= TotalRefCount - arccounter;
02018
02019 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
02020 if (res) {
02021 (void) fprintf(table->out,
02022 "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n",
02023 xindex,yindex,x,y);
02024 }
02025 #endif
02026
02027 #ifdef DD_STATS
02028 if (res)
02029 extsymm++;
02030 #endif
02031 return(res);
02032
02033 }
02034
02035
02046 static int
02047 ddVarGroupCheck(
02048 DdManager * table,
02049 int x,
02050 int y)
02051 {
02052 int xindex = table->invperm[x];
02053 int yindex = table->invperm[y];
02054
02055 if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
02056
02057 if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
02058 if (ddIsVarHandled(table, xindex) ||
02059 ddIsVarHandled(table, yindex)) {
02060 if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
02061 Cudd_bddIsVarToBeGrouped(table, yindex) ) {
02062 if (table->keys - table->isolated <= originalSize) {
02063 return(1);
02064 }
02065 }
02066 }
02067 }
02068
02069 return(0);
02070
02071 }
02072
02073
02086 static int
02087 ddSetVarHandled(
02088 DdManager *dd,
02089 int index)
02090 {
02091 if (index >= dd->size || index < 0) return(0);
02092 dd->subtables[dd->perm[index]].varHandled = 1;
02093 return(1);
02094
02095 }
02096
02097
02110 static int
02111 ddResetVarHandled(
02112 DdManager *dd,
02113 int index)
02114 {
02115 if (index >= dd->size || index < 0) return(0);
02116 dd->subtables[dd->perm[index]].varHandled = 0;
02117 return(1);
02118
02119 }
02120
02121
02134 static int
02135 ddIsVarHandled(
02136 DdManager *dd,
02137 int index)
02138 {
02139 if (index >= dd->size || index < 0) return(-1);
02140 return dd->subtables[dd->perm[index]].varHandled;
02141
02142 }