00001
00079 #include "util.h"
00080 #include "cuddInt.h"
00081
00082
00083
00084
00085
00086
00087 #define DD_NORMAL_SIFT 0
00088 #define DD_LAZY_SIFT 1
00089
00090
00091 #define DD_SIFT_DOWN 0
00092 #define DD_SIFT_UP 1
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 #ifdef __cplusplus
00103 extern "C" {
00104 #endif
00105 typedef int (*DD_CHKFP)(DdManager *, int, int);
00106 #ifdef __cplusplus
00107 }
00108 #endif
00109
00110
00111
00112
00113
00114 #ifndef lint
00115 static char rcsid[] DD_UNUSED = "$Id: cuddGroup.c,v 1.44 2009/02/21 18:24:10 fabio Exp $";
00116 #endif
00117
00118 static int *entry;
00119 extern int ddTotalNumberSwapping;
00120 #ifdef DD_STATS
00121 extern int ddTotalNISwaps;
00122 static int extsymmcalls;
00123 static int extsymm;
00124 static int secdiffcalls;
00125 static int secdiff;
00126 static int secdiffmisfire;
00127 #endif
00128 #ifdef DD_DEBUG
00129 static int pr = 0;
00130
00131 #endif
00132 static unsigned int originalSize;
00133
00134
00135
00136
00137
00138 #ifdef __cplusplus
00139 extern "C" {
00140 #endif
00141
00144
00145
00146
00147
00148 static int ddTreeSiftingAux (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
00149 #ifdef DD_STATS
00150 static int ddCountInternalMtrNodes (DdManager *table, MtrNode *treenode);
00151 #endif
00152 static int ddReorderChildren (DdManager *table, MtrNode *treenode, Cudd_ReorderingType method);
00153 static void ddFindNodeHiLo (DdManager *table, MtrNode *treenode, int *lower, int *upper);
00154 static int ddUniqueCompareGroup (int *ptrX, int *ptrY);
00155 static int ddGroupSifting (DdManager *table, int lower, int upper, DD_CHKFP checkFunction, int lazyFlag);
00156 static void ddCreateGroup (DdManager *table, int x, int y);
00157 static int ddGroupSiftingAux (DdManager *table, int x, int xLow, int xHigh, DD_CHKFP checkFunction, int lazyFlag);
00158 static int ddGroupSiftingUp (DdManager *table, int y, int xLow, DD_CHKFP checkFunction, Move **moves);
00159 static int ddGroupSiftingDown (DdManager *table, int x, int xHigh, DD_CHKFP checkFunction, Move **moves);
00160 static int ddGroupMove (DdManager *table, int x, int y, Move **moves);
00161 static int ddGroupMoveBackward (DdManager *table, int x, int y);
00162 static int ddGroupSiftingBackward (DdManager *table, Move *moves, int size, int upFlag, int lazyFlag);
00163 static void ddMergeGroups (DdManager *table, MtrNode *treenode, int low, int high);
00164 static void ddDissolveGroup (DdManager *table, int x, int y);
00165 static int ddNoCheck (DdManager *table, int x, int y);
00166 static int ddSecDiffCheck (DdManager *table, int x, int y);
00167 static int ddExtSymmCheck (DdManager *table, int x, int y);
00168 static int ddVarGroupCheck (DdManager * table, int x, int y);
00169 static int ddSetVarHandled (DdManager *dd, int index);
00170 static int ddResetVarHandled (DdManager *dd, int index);
00171 static int ddIsVarHandled (DdManager *dd, int index);
00172
00175 #ifdef __cplusplus
00176 }
00177 #endif
00178
00179
00180
00181
00182
00183
00201 MtrNode *
00202 Cudd_MakeTreeNode(
00203 DdManager * dd ,
00204 unsigned int low ,
00205 unsigned int size ,
00206 unsigned int type )
00207 {
00208 MtrNode *group;
00209 MtrNode *tree;
00210 unsigned int level;
00211
00212
00213
00214
00215
00216
00217 level = (low < (unsigned int) dd->size) ? dd->perm[low] : low;
00218
00219 if (level + size - 1> (int) MTR_MAXHIGH)
00220 return(NULL);
00221
00222
00223 tree = dd->tree;
00224 if (tree == NULL) {
00225 dd->tree = tree = Mtr_InitGroupTree(0, dd->size);
00226 if (tree == NULL)
00227 return(NULL);
00228 tree->index = dd->invperm[0];
00229 }
00230
00231
00232
00233
00234 tree->size = ddMax(tree->size, ddMax(level + size, (unsigned) dd->size));
00235
00236
00237 group = Mtr_MakeGroup(tree, level, size, type);
00238 if (group == NULL)
00239 return(NULL);
00240
00241
00242
00243
00244
00245 group->index = (MtrHalfWord) low;
00246
00247 return(group);
00248
00249 }
00250
00251
00252
00253
00254
00255
00256
00269 int
00270 cuddTreeSifting(
00271 DdManager * table ,
00272 Cudd_ReorderingType method )
00273 {
00274 int i;
00275 int nvars;
00276 int result;
00277 int tempTree;
00278
00279
00280
00281
00282
00283 tempTree = table->tree == NULL;
00284 if (tempTree) {
00285 table->tree = Mtr_InitGroupTree(0,table->size);
00286 table->tree->index = table->invperm[0];
00287 }
00288 nvars = table->size;
00289
00290 #ifdef DD_DEBUG
00291 if (pr > 0 && !tempTree) (void) fprintf(table->out,"cuddTreeSifting:");
00292 Mtr_PrintGroups(table->tree,pr <= 0);
00293 #endif
00294
00295 #ifdef DD_STATS
00296 extsymmcalls = 0;
00297 extsymm = 0;
00298 secdiffcalls = 0;
00299 secdiff = 0;
00300 secdiffmisfire = 0;
00301
00302 (void) fprintf(table->out,"\n");
00303 if (!tempTree)
00304 (void) fprintf(table->out,"#:IM_NODES %8d: group tree nodes\n",
00305 ddCountInternalMtrNodes(table,table->tree));
00306 #endif
00307
00308
00309
00310
00311
00312 for (i = 0; i < nvars; i++)
00313 table->subtables[i].next = i;
00314
00315
00316
00317 result = ddTreeSiftingAux(table, table->tree, method);
00318
00319 #ifdef DD_STATS
00320 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00321 (table->groupcheck == CUDD_GROUP_CHECK7 ||
00322 table->groupcheck == CUDD_GROUP_CHECK5)) {
00323 (void) fprintf(table->out,"\nextsymmcalls = %d\n",extsymmcalls);
00324 (void) fprintf(table->out,"extsymm = %d",extsymm);
00325 }
00326 if (!tempTree && method == CUDD_REORDER_GROUP_SIFT &&
00327 table->groupcheck == CUDD_GROUP_CHECK7) {
00328 (void) fprintf(table->out,"\nsecdiffcalls = %d\n",secdiffcalls);
00329 (void) fprintf(table->out,"secdiff = %d\n",secdiff);
00330 (void) fprintf(table->out,"secdiffmisfire = %d",secdiffmisfire);
00331 }
00332 #endif
00333
00334 if (tempTree)
00335 Cudd_FreeTree(table);
00336 return(result);
00337
00338 }
00339
00340
00341
00342
00343
00344
00345
00356 static int
00357 ddTreeSiftingAux(
00358 DdManager * table,
00359 MtrNode * treenode,
00360 Cudd_ReorderingType method)
00361 {
00362 MtrNode *auxnode;
00363 int res;
00364 Cudd_AggregationType saveCheck;
00365
00366 #ifdef DD_DEBUG
00367 Mtr_PrintGroups(treenode,1);
00368 #endif
00369
00370 auxnode = treenode;
00371 while (auxnode != NULL) {
00372 if (auxnode->child != NULL) {
00373 if (!ddTreeSiftingAux(table, auxnode->child, method))
00374 return(0);
00375 saveCheck = table->groupcheck;
00376 table->groupcheck = CUDD_NO_CHECK;
00377 if (method != CUDD_REORDER_LAZY_SIFT)
00378 res = ddReorderChildren(table, auxnode, CUDD_REORDER_GROUP_SIFT);
00379 else
00380 res = ddReorderChildren(table, auxnode, CUDD_REORDER_LAZY_SIFT);
00381 table->groupcheck = saveCheck;
00382
00383 if (res == 0)
00384 return(0);
00385 } else if (auxnode->size > 1) {
00386 if (!ddReorderChildren(table, auxnode, method))
00387 return(0);
00388 }
00389 auxnode = auxnode->younger;
00390 }
00391
00392 return(1);
00393
00394 }
00395
00396
00397 #ifdef DD_STATS
00398
00408 static int
00409 ddCountInternalMtrNodes(
00410 DdManager * table,
00411 MtrNode * treenode)
00412 {
00413 MtrNode *auxnode;
00414 int count,nodeCount;
00415
00416
00417 nodeCount = 0;
00418 auxnode = treenode;
00419 while (auxnode != NULL) {
00420 if (!(MTR_TEST(auxnode,MTR_TERMINAL))) {
00421 nodeCount++;
00422 count = ddCountInternalMtrNodes(table,auxnode->child);
00423 nodeCount += count;
00424 }
00425 auxnode = auxnode->younger;
00426 }
00427
00428 return(nodeCount);
00429
00430 }
00431 #endif
00432
00433
00448 static int
00449 ddReorderChildren(
00450 DdManager * table,
00451 MtrNode * treenode,
00452 Cudd_ReorderingType method)
00453 {
00454 int lower;
00455 int upper;
00456 int result;
00457 unsigned int initialSize;
00458
00459 ddFindNodeHiLo(table,treenode,&lower,&upper);
00460
00461 if (upper == -1)
00462 return(1);
00463
00464 if (treenode->flags == MTR_FIXED) {
00465 result = 1;
00466 } else {
00467 #ifdef DD_STATS
00468 (void) fprintf(table->out," ");
00469 #endif
00470 switch (method) {
00471 case CUDD_REORDER_RANDOM:
00472 case CUDD_REORDER_RANDOM_PIVOT:
00473 result = cuddSwapping(table,lower,upper,method);
00474 break;
00475 case CUDD_REORDER_SIFT:
00476 result = cuddSifting(table,lower,upper);
00477 break;
00478 case CUDD_REORDER_SIFT_CONVERGE:
00479 do {
00480 initialSize = table->keys - table->isolated;
00481 result = cuddSifting(table,lower,upper);
00482 if (initialSize <= table->keys - table->isolated)
00483 break;
00484 #ifdef DD_STATS
00485 else
00486 (void) fprintf(table->out,"\n");
00487 #endif
00488 } while (result != 0);
00489 break;
00490 case CUDD_REORDER_SYMM_SIFT:
00491 result = cuddSymmSifting(table,lower,upper);
00492 break;
00493 case CUDD_REORDER_SYMM_SIFT_CONV:
00494 result = cuddSymmSiftingConv(table,lower,upper);
00495 break;
00496 case CUDD_REORDER_GROUP_SIFT:
00497 if (table->groupcheck == CUDD_NO_CHECK) {
00498 result = ddGroupSifting(table,lower,upper,ddNoCheck,
00499 DD_NORMAL_SIFT);
00500 } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
00501 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00502 DD_NORMAL_SIFT);
00503 } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
00504 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00505 DD_NORMAL_SIFT);
00506 } else {
00507 (void) fprintf(table->err,
00508 "Unknown group ckecking method\n");
00509 result = 0;
00510 }
00511 break;
00512 case CUDD_REORDER_GROUP_SIFT_CONV:
00513 do {
00514 initialSize = table->keys - table->isolated;
00515 if (table->groupcheck == CUDD_NO_CHECK) {
00516 result = ddGroupSifting(table,lower,upper,ddNoCheck,
00517 DD_NORMAL_SIFT);
00518 } else if (table->groupcheck == CUDD_GROUP_CHECK5) {
00519 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00520 DD_NORMAL_SIFT);
00521 } else if (table->groupcheck == CUDD_GROUP_CHECK7) {
00522 result = ddGroupSifting(table,lower,upper,ddExtSymmCheck,
00523 DD_NORMAL_SIFT);
00524 } else {
00525 (void) fprintf(table->err,
00526 "Unknown group ckecking method\n");
00527 result = 0;
00528 }
00529 #ifdef DD_STATS
00530 (void) fprintf(table->out,"\n");
00531 #endif
00532 result = cuddWindowReorder(table,lower,upper,
00533 CUDD_REORDER_WINDOW4);
00534 if (initialSize <= table->keys - table->isolated)
00535 break;
00536 #ifdef DD_STATS
00537 else
00538 (void) fprintf(table->out,"\n");
00539 #endif
00540 } while (result != 0);
00541 break;
00542 case CUDD_REORDER_WINDOW2:
00543 case CUDD_REORDER_WINDOW3:
00544 case CUDD_REORDER_WINDOW4:
00545 case CUDD_REORDER_WINDOW2_CONV:
00546 case CUDD_REORDER_WINDOW3_CONV:
00547 case CUDD_REORDER_WINDOW4_CONV:
00548 result = cuddWindowReorder(table,lower,upper,method);
00549 break;
00550 case CUDD_REORDER_ANNEALING:
00551 result = cuddAnnealing(table,lower,upper);
00552 break;
00553 case CUDD_REORDER_GENETIC:
00554 result = cuddGa(table,lower,upper);
00555 break;
00556 case CUDD_REORDER_LINEAR:
00557 result = cuddLinearAndSifting(table,lower,upper);
00558 break;
00559 case CUDD_REORDER_LINEAR_CONVERGE:
00560 do {
00561 initialSize = table->keys - table->isolated;
00562 result = cuddLinearAndSifting(table,lower,upper);
00563 if (initialSize <= table->keys - table->isolated)
00564 break;
00565 #ifdef DD_STATS
00566 else
00567 (void) fprintf(table->out,"\n");
00568 #endif
00569 } while (result != 0);
00570 break;
00571 case CUDD_REORDER_EXACT:
00572 result = cuddExact(table,lower,upper);
00573 break;
00574 case CUDD_REORDER_LAZY_SIFT:
00575 result = ddGroupSifting(table,lower,upper,ddVarGroupCheck,
00576 DD_LAZY_SIFT);
00577 break;
00578 default:
00579 return(0);
00580 }
00581 }
00582
00583
00584
00585
00586
00587 ddMergeGroups(table,treenode,lower,upper);
00588
00589 #ifdef DD_DEBUG
00590 if (pr > 0) (void) fprintf(table->out,"ddReorderChildren:");
00591 #endif
00592
00593 return(result);
00594
00595 }
00596
00597
00612 static void
00613 ddFindNodeHiLo(
00614 DdManager * table,
00615 MtrNode * treenode,
00616 int * lower,
00617 int * upper)
00618 {
00619 int low;
00620 int high;
00621
00622
00623
00624
00625
00626 if ((int) treenode->low >= table->size) {
00627 *lower = table->size;
00628 *upper = -1;
00629 return;
00630 }
00631
00632 *lower = low = (unsigned int) table->perm[treenode->index];
00633 high = (int) (low + treenode->size - 1);
00634
00635 if (high >= table->size) {
00636
00637
00638
00639
00640
00641
00642
00643 MtrNode *auxnode = treenode->child;
00644 if (auxnode == NULL) {
00645 *upper = (unsigned int) table->size - 1;
00646 } else {
00647
00648
00649
00650
00651
00652 while (auxnode != NULL) {
00653 int thisLower = table->perm[auxnode->low];
00654 int thisUpper = thisLower + auxnode->size - 1;
00655 if (thisUpper >= table->size && thisLower < table->size)
00656 *upper = (unsigned int) thisLower - 1;
00657 auxnode = auxnode->younger;
00658 }
00659 }
00660 } else {
00661
00662 *upper = (unsigned int) high;
00663 }
00664
00665 #ifdef DD_DEBUG
00666
00667 assert(treenode->size >= *upper - *lower + 1);
00668 #endif
00669
00670 return;
00671
00672 }
00673
00674
00687 static int
00688 ddUniqueCompareGroup(
00689 int * ptrX,
00690 int * ptrY)
00691 {
00692 #if 0
00693 if (entry[*ptrY] == entry[*ptrX]) {
00694 return((*ptrX) - (*ptrY));
00695 }
00696 #endif
00697 return(entry[*ptrY] - entry[*ptrX]);
00698
00699 }
00700
00701
00715 static int
00716 ddGroupSifting(
00717 DdManager * table,
00718 int lower,
00719 int upper,
00720 DD_CHKFP checkFunction,
00721 int lazyFlag)
00722 {
00723 int *var;
00724 int i,j,x,xInit;
00725 int nvars;
00726 int classes;
00727 int result;
00728 int *sifted;
00729 int merged;
00730 int dissolve;
00731 #ifdef DD_STATS
00732 unsigned previousSize;
00733 #endif
00734 int xindex;
00735
00736 nvars = table->size;
00737
00738
00739 entry = NULL;
00740 sifted = NULL;
00741 var = ALLOC(int,nvars);
00742 if (var == NULL) {
00743 table->errorCode = CUDD_MEMORY_OUT;
00744 goto ddGroupSiftingOutOfMem;
00745 }
00746 entry = ALLOC(int,nvars);
00747 if (entry == NULL) {
00748 table->errorCode = CUDD_MEMORY_OUT;
00749 goto ddGroupSiftingOutOfMem;
00750 }
00751 sifted = ALLOC(int,nvars);
00752 if (sifted == NULL) {
00753 table->errorCode = CUDD_MEMORY_OUT;
00754 goto ddGroupSiftingOutOfMem;
00755 }
00756
00757
00758 for (i = 0, classes = 0; i < nvars; i++) {
00759 sifted[i] = 0;
00760 x = table->perm[i];
00761 if ((unsigned) x >= table->subtables[x].next) {
00762 entry[i] = table->subtables[x].keys;
00763 var[classes] = i;
00764 classes++;
00765 }
00766 }
00767
00768 qsort((void *)var,classes,sizeof(int),
00769 (DD_QSFP) ddUniqueCompareGroup);
00770
00771 if (lazyFlag) {
00772 for (i = 0; i < nvars; i ++) {
00773 ddResetVarHandled(table, i);
00774 }
00775 }
00776
00777
00778 for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
00779 if (ddTotalNumberSwapping >= table->siftMaxSwap)
00780 break;
00781 xindex = var[i];
00782 if (sifted[xindex] == 1)
00783 continue;
00784 x = table->perm[xindex];
00785
00786 if (x < lower || x > upper || table->subtables[x].bindVar == 1)
00787 continue;
00788 #ifdef DD_STATS
00789 previousSize = table->keys - table->isolated;
00790 #endif
00791 #ifdef DD_DEBUG
00792
00793 assert((unsigned) x >= table->subtables[x].next);
00794 #endif
00795 if ((unsigned) x == table->subtables[x].next) {
00796 dissolve = 1;
00797 result = ddGroupSiftingAux(table,x,lower,upper,checkFunction,
00798 lazyFlag);
00799 } else {
00800 dissolve = 0;
00801 result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
00802 }
00803 if (!result) goto ddGroupSiftingOutOfMem;
00804
00805
00806 merged = 0;
00807 if (lazyFlag == 0 && table->groupcheck == CUDD_GROUP_CHECK7) {
00808 x = table->perm[xindex];
00809 if ((unsigned) x == table->subtables[x].next) {
00810 if (x != upper && sifted[table->invperm[x+1]] == 0 &&
00811 (unsigned) x+1 == table->subtables[x+1].next) {
00812 if (ddSecDiffCheck(table,x,x+1)) {
00813 merged =1;
00814 ddCreateGroup(table,x,x+1);
00815 }
00816 }
00817 if (x != lower && sifted[table->invperm[x-1]] == 0 &&
00818 (unsigned) x-1 == table->subtables[x-1].next) {
00819 if (ddSecDiffCheck(table,x-1,x)) {
00820 merged =1;
00821 ddCreateGroup(table,x-1,x);
00822 }
00823 }
00824 }
00825 }
00826
00827 if (merged) {
00828
00829 while ((unsigned) x < table->subtables[x].next)
00830 x = table->subtables[x].next;
00831
00832 result = ddGroupSiftingAux(table,x,lower,upper,ddNoCheck,lazyFlag);
00833 if (!result) goto ddGroupSiftingOutOfMem;
00834 #ifdef DD_STATS
00835 if (table->keys < previousSize + table->isolated) {
00836 (void) fprintf(table->out,"_");
00837 } else if (table->keys > previousSize + table->isolated) {
00838 (void) fprintf(table->out,"^");
00839 } else {
00840 (void) fprintf(table->out,"*");
00841 }
00842 fflush(table->out);
00843 } else {
00844 if (table->keys < previousSize + table->isolated) {
00845 (void) fprintf(table->out,"-");
00846 } else if (table->keys > previousSize + table->isolated) {
00847 (void) fprintf(table->out,"+");
00848 } else {
00849 (void) fprintf(table->out,"=");
00850 }
00851 fflush(table->out);
00852 #endif
00853 }
00854
00855
00856 x = table->perm[xindex];
00857 if ((unsigned) x != table->subtables[x].next) {
00858 xInit = x;
00859 do {
00860 j = table->invperm[x];
00861 sifted[j] = 1;
00862 x = table->subtables[x].next;
00863 } while (x != xInit);
00864
00865
00866 if (lazyFlag == 0 && dissolve) {
00867 do {
00868 j = table->subtables[x].next;
00869 table->subtables[x].next = x;
00870 x = j;
00871 } while (x != xInit);
00872 }
00873 }
00874
00875 #ifdef DD_DEBUG
00876 if (pr > 0) (void) fprintf(table->out,"ddGroupSifting:");
00877 #endif
00878
00879 if (lazyFlag) ddSetVarHandled(table, xindex);
00880 }
00881
00882 FREE(sifted);
00883 FREE(var);
00884 FREE(entry);
00885
00886 return(1);
00887
00888 ddGroupSiftingOutOfMem:
00889 if (entry != NULL) FREE(entry);
00890 if (var != NULL) FREE(var);
00891 if (sifted != NULL) FREE(sifted);
00892
00893 return(0);
00894
00895 }
00896
00897
00910 static void
00911 ddCreateGroup(
00912 DdManager * table,
00913 int x,
00914 int y)
00915 {
00916 int gybot;
00917
00918 #ifdef DD_DEBUG
00919 assert(y == x+1);
00920 #endif
00921
00922
00923 gybot = y;
00924 while ((unsigned) gybot < table->subtables[gybot].next)
00925 gybot = table->subtables[gybot].next;
00926
00927
00928 table->subtables[x].next = y;
00929 table->subtables[gybot].next = x;
00930
00931 return;
00932
00933 }
00934
00935
00951 static int
00952 ddGroupSiftingAux(
00953 DdManager * table,
00954 int x,
00955 int xLow,
00956 int xHigh,
00957 DD_CHKFP checkFunction,
00958 int lazyFlag)
00959 {
00960 Move *move;
00961 Move *moves;
00962 int initialSize;
00963 int result;
00964 int y;
00965 int topbot;
00966
00967 #ifdef DD_DEBUG
00968 if (pr > 0) (void) fprintf(table->out,
00969 "ddGroupSiftingAux from %d to %d\n",xLow,xHigh);
00970 assert((unsigned) x >= table->subtables[x].next);
00971 #endif
00972
00973 initialSize = table->keys - table->isolated;
00974 moves = NULL;
00975
00976 originalSize = initialSize;
00977
00978
00979
00980
00981 if ((unsigned) x == table->subtables[x].next) {
00982
00983
00984
00985 for (y = x; y > xLow; y--) {
00986 if (!checkFunction(table,y-1,y))
00987 break;
00988 topbot = table->subtables[y-1].next;
00989 table->subtables[y-1].next = y;
00990 table->subtables[x].next = topbot;
00991
00992 y = topbot + 1;
00993 }
00994
00995
00996
00997 for (y = x; y < xHigh; y++) {
00998 if (!checkFunction(table,y,y+1))
00999 break;
01000
01001 topbot = y + 1;
01002 while ((unsigned) topbot < table->subtables[topbot].next) {
01003 topbot = table->subtables[topbot].next;
01004 }
01005 table->subtables[topbot].next = table->subtables[y].next;
01006 table->subtables[y].next = y + 1;
01007 y = topbot - 1;
01008 }
01009 }
01010
01011
01012
01013
01014 while ((unsigned) x < table->subtables[x].next)
01015 x = table->subtables[x].next;
01016
01017 if (x == xLow) {
01018 #ifdef DD_DEBUG
01019
01020 assert((unsigned) x == table->subtables[x].next);
01021 #endif
01022 if (x == xHigh) return(1);
01023
01024 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
01025 goto ddGroupSiftingAuxOutOfMem;
01026
01027
01028
01029 result = ddGroupSiftingBackward(table,moves,initialSize,
01030 DD_SIFT_DOWN,lazyFlag);
01031 #ifdef DD_DEBUG
01032 assert(table->keys - table->isolated <= (unsigned) initialSize);
01033 #endif
01034 if (!result) goto ddGroupSiftingAuxOutOfMem;
01035
01036 } else if (cuddNextHigh(table,x) > xHigh) {
01037 #ifdef DD_DEBUG
01038
01039 assert((unsigned) x >= table->subtables[x].next);
01040 #endif
01041
01042 x = table->subtables[x].next;
01043
01044 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
01045 goto ddGroupSiftingAuxOutOfMem;
01046
01047
01048
01049 result = ddGroupSiftingBackward(table,moves,initialSize,
01050 DD_SIFT_UP,lazyFlag);
01051 #ifdef DD_DEBUG
01052 assert(table->keys - table->isolated <= (unsigned) initialSize);
01053 #endif
01054 if (!result) goto ddGroupSiftingAuxOutOfMem;
01055
01056 } else if (x - xLow > xHigh - x) {
01057 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
01058 goto ddGroupSiftingAuxOutOfMem;
01059
01060
01061
01062 if (moves) {
01063 x = moves->y;
01064 }
01065 while ((unsigned) x < table->subtables[x].next)
01066 x = table->subtables[x].next;
01067 x = table->subtables[x].next;
01068 #ifdef DD_DEBUG
01069
01070 assert((unsigned) x <= table->subtables[x].next);
01071 #endif
01072
01073 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
01074 goto ddGroupSiftingAuxOutOfMem;
01075
01076
01077 result = ddGroupSiftingBackward(table,moves,initialSize,
01078 DD_SIFT_UP,lazyFlag);
01079 #ifdef DD_DEBUG
01080 assert(table->keys - table->isolated <= (unsigned) initialSize);
01081 #endif
01082 if (!result) goto ddGroupSiftingAuxOutOfMem;
01083
01084 } else {
01085
01086 x = table->subtables[x].next;
01087
01088 if (!ddGroupSiftingUp(table,x,xLow,checkFunction,&moves))
01089 goto ddGroupSiftingAuxOutOfMem;
01090
01091
01092 if (moves) {
01093 x = moves->x;
01094 }
01095 while ((unsigned) x < table->subtables[x].next)
01096 x = table->subtables[x].next;
01097 #ifdef DD_DEBUG
01098
01099 assert((unsigned) x >= table->subtables[x].next);
01100 #endif
01101
01102 if (!ddGroupSiftingDown(table,x,xHigh,checkFunction,&moves))
01103 goto ddGroupSiftingAuxOutOfMem;
01104
01105
01106 result = ddGroupSiftingBackward(table,moves,initialSize,
01107 DD_SIFT_DOWN,lazyFlag);
01108 #ifdef DD_DEBUG
01109 assert(table->keys - table->isolated <= (unsigned) initialSize);
01110 #endif
01111 if (!result) goto ddGroupSiftingAuxOutOfMem;
01112 }
01113
01114 while (moves != NULL) {
01115 move = moves->next;
01116 cuddDeallocMove(table, moves);
01117 moves = move;
01118 }
01119
01120 return(1);
01121
01122 ddGroupSiftingAuxOutOfMem:
01123 while (moves != NULL) {
01124 move = moves->next;
01125 cuddDeallocMove(table, moves);
01126 moves = move;
01127 }
01128
01129 return(0);
01130
01131 }
01132
01133
01149 static int
01150 ddGroupSiftingUp(
01151 DdManager * table,
01152 int y,
01153 int xLow,
01154 DD_CHKFP checkFunction,
01155 Move ** moves)
01156 {
01157 Move *move;
01158 int x;
01159 int size;
01160 int i;
01161 int gxtop,gybot;
01162 int limitSize;
01163 int xindex, yindex;
01164 int zindex;
01165 int z;
01166 int isolated;
01167 int L;
01168 #ifdef DD_DEBUG
01169 int checkL;
01170 #endif
01171
01172 yindex = table->invperm[y];
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183 limitSize = L = table->keys - table->isolated;
01184 gybot = y;
01185 while ((unsigned) gybot < table->subtables[gybot].next)
01186 gybot = table->subtables[gybot].next;
01187 for (z = xLow + 1; z <= gybot; z++) {
01188 zindex = table->invperm[z];
01189 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01190 isolated = table->vars[zindex]->ref == 1;
01191 L -= table->subtables[z].keys - isolated;
01192 }
01193 }
01194
01195 x = cuddNextLow(table,y);
01196 while (x >= xLow && L <= limitSize) {
01197 #ifdef DD_DEBUG
01198 gybot = y;
01199 while ((unsigned) gybot < table->subtables[gybot].next)
01200 gybot = table->subtables[gybot].next;
01201 checkL = table->keys - table->isolated;
01202 for (z = xLow + 1; z <= gybot; z++) {
01203 zindex = table->invperm[z];
01204 if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
01205 isolated = table->vars[zindex]->ref == 1;
01206 checkL -= table->subtables[z].keys - isolated;
01207 }
01208 }
01209 if (pr > 0 && L != checkL) {
01210 (void) fprintf(table->out,
01211 "Inaccurate lower bound: L = %d checkL = %d\n",
01212 L, checkL);
01213 }
01214 #endif
01215 gxtop = table->subtables[x].next;
01216 if (checkFunction(table,x,y)) {
01217
01218 table->subtables[x].next = y;
01219 i = table->subtables[y].next;
01220 while (table->subtables[i].next != (unsigned) y)
01221 i = table->subtables[i].next;
01222 table->subtables[i].next = gxtop;
01223 move = (Move *)cuddDynamicAllocNode(table);
01224 if (move == NULL) goto ddGroupSiftingUpOutOfMem;
01225 move->x = x;
01226 move->y = y;
01227 move->flags = MTR_NEWNODE;
01228 move->size = table->keys - table->isolated;
01229 move->next = *moves;
01230 *moves = move;
01231 } else if (table->subtables[x].next == (unsigned) x &&
01232 table->subtables[y].next == (unsigned) y) {
01233
01234 xindex = table->invperm[x];
01235 size = cuddSwapInPlace(table,x,y);
01236 #ifdef DD_DEBUG
01237 assert(table->subtables[x].next == (unsigned) x);
01238 assert(table->subtables[y].next == (unsigned) y);
01239 #endif
01240 if (size == 0) goto ddGroupSiftingUpOutOfMem;
01241
01242 if (cuddTestInteract(table,xindex,yindex)) {
01243 isolated = table->vars[xindex]->ref == 1;
01244 L += table->subtables[y].keys - isolated;
01245 }
01246 move = (Move *)cuddDynamicAllocNode(table);
01247 if (move == NULL) goto ddGroupSiftingUpOutOfMem;
01248 move->x = x;
01249 move->y = y;
01250 move->flags = MTR_DEFAULT;
01251 move->size = size;
01252 move->next = *moves;
01253 *moves = move;
01254
01255 #ifdef DD_DEBUG
01256 if (pr > 0) (void) fprintf(table->out,
01257 "ddGroupSiftingUp (2 single groups):\n");
01258 #endif
01259 if ((double) size > (double) limitSize * table->maxGrowth)
01260 return(1);
01261 if (size < limitSize) limitSize = size;
01262 } else {
01263 size = ddGroupMove(table,x,y,moves);
01264 if (size == 0) goto ddGroupSiftingUpOutOfMem;
01265
01266 z = (*moves)->y;
01267 do {
01268 zindex = table->invperm[z];
01269 if (cuddTestInteract(table,zindex,yindex)) {
01270 isolated = table->vars[zindex]->ref == 1;
01271 L += table->subtables[z].keys - isolated;
01272 }
01273 z = table->subtables[z].next;
01274 } while (z != (int) (*moves)->y);
01275 if ((double) size > (double) limitSize * table->maxGrowth)
01276 return(1);
01277 if (size < limitSize) limitSize = size;
01278 }
01279 y = gxtop;
01280 x = cuddNextLow(table,y);
01281 }
01282
01283 return(1);
01284
01285 ddGroupSiftingUpOutOfMem:
01286 while (*moves != NULL) {
01287 move = (*moves)->next;
01288 cuddDeallocMove(table, *moves);
01289 *moves = move;
01290 }
01291 return(0);
01292
01293 }
01294
01295
01307 static int
01308 ddGroupSiftingDown(
01309 DdManager * table,
01310 int x,
01311 int xHigh,
01312 DD_CHKFP checkFunction,
01313 Move ** moves)
01314 {
01315 Move *move;
01316 int y;
01317 int size;
01318 int limitSize;
01319 int gxtop,gybot;
01320 int R;
01321 int xindex, yindex;
01322 int isolated, allVars;
01323 int z;
01324 int zindex;
01325 #ifdef DD_DEBUG
01326 int checkR;
01327 #endif
01328
01329
01330
01331
01332
01333
01334 y = x;
01335 allVars = 1;
01336 do {
01337 if (table->subtables[y].keys != 1) {
01338 allVars = 0;
01339 break;
01340 }
01341 y = table->subtables[y].next;
01342 } while (table->subtables[y].next != (unsigned) x);
01343 if (allVars)
01344 return(1);
01345
01346
01347 xindex = table->invperm[x];
01348 gxtop = table->subtables[x].next;
01349 limitSize = size = table->keys - table->isolated;
01350 R = 0;
01351 for (z = xHigh; z > gxtop; z--) {
01352 zindex = table->invperm[z];
01353 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01354 isolated = table->vars[zindex]->ref == 1;
01355 R += table->subtables[z].keys - isolated;
01356 }
01357 }
01358
01359 y = cuddNextHigh(table,x);
01360 while (y <= xHigh && size - R < limitSize) {
01361 #ifdef DD_DEBUG
01362 gxtop = table->subtables[x].next;
01363 checkR = 0;
01364 for (z = xHigh; z > gxtop; z--) {
01365 zindex = table->invperm[z];
01366 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01367 isolated = table->vars[zindex]->ref == 1;
01368 checkR += table->subtables[z].keys - isolated;
01369 }
01370 }
01371 assert(R >= checkR);
01372 #endif
01373
01374 gybot = table->subtables[y].next;
01375 while (table->subtables[gybot].next != (unsigned) y)
01376 gybot = table->subtables[gybot].next;
01377
01378 if (checkFunction(table,x,y)) {
01379
01380 gxtop = table->subtables[x].next;
01381 table->subtables[x].next = y;
01382 table->subtables[gybot].next = gxtop;
01383 move = (Move *)cuddDynamicAllocNode(table);
01384 if (move == NULL) goto ddGroupSiftingDownOutOfMem;
01385 move->x = x;
01386 move->y = y;
01387 move->flags = MTR_NEWNODE;
01388 move->size = table->keys - table->isolated;
01389 move->next = *moves;
01390 *moves = move;
01391 } else if (table->subtables[x].next == (unsigned) x &&
01392 table->subtables[y].next == (unsigned) y) {
01393
01394
01395 yindex = table->invperm[y];
01396 if (cuddTestInteract(table,xindex,yindex)) {
01397 isolated = table->vars[yindex]->ref == 1;
01398 R -= table->subtables[y].keys - isolated;
01399 }
01400 size = cuddSwapInPlace(table,x,y);
01401 #ifdef DD_DEBUG
01402 assert(table->subtables[x].next == (unsigned) x);
01403 assert(table->subtables[y].next == (unsigned) y);
01404 #endif
01405 if (size == 0) goto ddGroupSiftingDownOutOfMem;
01406
01407
01408 move = (Move *) cuddDynamicAllocNode(table);
01409 if (move == NULL) goto ddGroupSiftingDownOutOfMem;
01410 move->x = x;
01411 move->y = y;
01412 move->flags = MTR_DEFAULT;
01413 move->size = size;
01414 move->next = *moves;
01415 *moves = move;
01416
01417 #ifdef DD_DEBUG
01418 if (pr > 0) (void) fprintf(table->out,
01419 "ddGroupSiftingDown (2 single groups):\n");
01420 #endif
01421 if ((double) size > (double) limitSize * table->maxGrowth)
01422 return(1);
01423 if (size < limitSize) limitSize = size;
01424
01425 x = y;
01426 y = cuddNextHigh(table,x);
01427 } else {
01428
01429 gxtop = table->subtables[x].next;
01430 z = gxtop + 1;
01431 do {
01432 zindex = table->invperm[z];
01433 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01434 isolated = table->vars[zindex]->ref == 1;
01435 R -= table->subtables[z].keys - isolated;
01436 }
01437 z++;
01438 } while (z <= gybot);
01439 size = ddGroupMove(table,x,y,moves);
01440 if (size == 0) goto ddGroupSiftingDownOutOfMem;
01441 if ((double) size > (double) limitSize * table->maxGrowth)
01442 return(1);
01443 if (size < limitSize) limitSize = size;
01444
01445
01446 gxtop = table->subtables[gybot].next;
01447 for (z = gxtop + 1; z <= gybot; z++) {
01448 zindex = table->invperm[z];
01449 if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
01450 isolated = table->vars[zindex]->ref == 1;
01451 R += table->subtables[z].keys - isolated;
01452 }
01453 }
01454 }
01455 x = gybot;
01456 y = cuddNextHigh(table,x);
01457 }
01458
01459 return(1);
01460
01461 ddGroupSiftingDownOutOfMem:
01462 while (*moves != NULL) {
01463 move = (*moves)->next;
01464 cuddDeallocMove(table, *moves);
01465 *moves = move;
01466 }
01467
01468 return(0);
01469
01470 }
01471
01472
01483 static int
01484 ddGroupMove(
01485 DdManager * table,
01486 int x,
01487 int y,
01488 Move ** moves)
01489 {
01490 Move *move;
01491 int size;
01492 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01493 int swapx,swapy;
01494 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01495 int initialSize,bestSize;
01496 #endif
01497
01498 #ifdef DD_DEBUG
01499
01500 assert(x < y);
01501 #endif
01502
01503 xbot = x;
01504 xtop = table->subtables[x].next;
01505 xsize = xbot - xtop + 1;
01506 ybot = y;
01507 while ((unsigned) ybot < table->subtables[ybot].next)
01508 ybot = table->subtables[ybot].next;
01509 ytop = y;
01510 ysize = ybot - ytop + 1;
01511
01512 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01513 initialSize = bestSize = table->keys - table->isolated;
01514 #endif
01515
01516 for (i = 1; i <= ysize; i++) {
01517 for (j = 1; j <= xsize; j++) {
01518 size = cuddSwapInPlace(table,x,y);
01519 if (size == 0) goto ddGroupMoveOutOfMem;
01520 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01521 if (size < bestSize)
01522 bestSize = size;
01523 #endif
01524 swapx = x; swapy = y;
01525 y = x;
01526 x = cuddNextLow(table,y);
01527 }
01528 y = ytop + i;
01529 x = cuddNextLow(table,y);
01530 }
01531 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01532 if ((bestSize < initialSize) && (bestSize < size))
01533 (void) fprintf(table->out,"Missed local minimum: initialSize:%d bestSize:%d finalSize:%d\n",initialSize,bestSize,size);
01534 #endif
01535
01536
01537 y = xtop;
01538 for (i = 0; i < ysize - 1; i++) {
01539 table->subtables[y].next = cuddNextHigh(table,y);
01540 y = cuddNextHigh(table,y);
01541 }
01542 table->subtables[y].next = xtop;
01543
01544 x = cuddNextHigh(table,y);
01545 newxtop = x;
01546 for (i = 0; i < xsize - 1; i++) {
01547 table->subtables[x].next = cuddNextHigh(table,x);
01548 x = cuddNextHigh(table,x);
01549 }
01550 table->subtables[x].next = newxtop;
01551
01552 #ifdef DD_DEBUG
01553 if (pr > 0) (void) fprintf(table->out,"ddGroupMove:\n");
01554 #endif
01555
01556
01557 move = (Move *) cuddDynamicAllocNode(table);
01558 if (move == NULL) goto ddGroupMoveOutOfMem;
01559 move->x = swapx;
01560 move->y = swapy;
01561 move->flags = MTR_DEFAULT;
01562 move->size = table->keys - table->isolated;
01563 move->next = *moves;
01564 *moves = move;
01565
01566 return(table->keys - table->isolated);
01567
01568 ddGroupMoveOutOfMem:
01569 while (*moves != NULL) {
01570 move = (*moves)->next;
01571 cuddDeallocMove(table, *moves);
01572 *moves = move;
01573 }
01574 return(0);
01575
01576 }
01577
01578
01589 static int
01590 ddGroupMoveBackward(
01591 DdManager * table,
01592 int x,
01593 int y)
01594 {
01595 int size;
01596 int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
01597
01598
01599 #ifdef DD_DEBUG
01600
01601 assert(x < y);
01602 #endif
01603
01604
01605 xbot = x;
01606 xtop = table->subtables[x].next;
01607 xsize = xbot - xtop + 1;
01608 ybot = y;
01609 while ((unsigned) ybot < table->subtables[ybot].next)
01610 ybot = table->subtables[ybot].next;
01611 ytop = y;
01612 ysize = ybot - ytop + 1;
01613
01614
01615 for (i = 1; i <= ysize; i++) {
01616 for (j = 1; j <= xsize; j++) {
01617 size = cuddSwapInPlace(table,x,y);
01618 if (size == 0)
01619 return(0);
01620 y = x;
01621 x = cuddNextLow(table,y);
01622 }
01623 y = ytop + i;
01624 x = cuddNextLow(table,y);
01625 }
01626
01627
01628 y = xtop;
01629 for (i = 0; i < ysize - 1; i++) {
01630 table->subtables[y].next = cuddNextHigh(table,y);
01631 y = cuddNextHigh(table,y);
01632 }
01633 table->subtables[y].next = xtop;
01634
01635 x = cuddNextHigh(table,y);
01636 newxtop = x;
01637 for (i = 0; i < xsize - 1; i++) {
01638 table->subtables[x].next = cuddNextHigh(table,x);
01639 x = cuddNextHigh(table,x);
01640 }
01641 table->subtables[x].next = newxtop;
01642
01643 #ifdef DD_DEBUG
01644 if (pr > 0) (void) fprintf(table->out,"ddGroupMoveBackward:\n");
01645 #endif
01646
01647 return(1);
01648
01649 }
01650
01651
01663 static int
01664 ddGroupSiftingBackward(
01665 DdManager * table,
01666 Move * moves,
01667 int size,
01668 int upFlag,
01669 int lazyFlag)
01670 {
01671 Move *move;
01672 int res;
01673 Move *end_move;
01674 int diff, tmp_diff;
01675 int index;
01676 unsigned int pairlev;
01677
01678 if (lazyFlag) {
01679 end_move = NULL;
01680
01681
01682
01683 for (move = moves; move != NULL; move = move->next) {
01684 if (move->size < size) {
01685 size = move->size;
01686 end_move = move;
01687 } else if (move->size == size) {
01688 if (end_move == NULL) end_move = move;
01689 }
01690 }
01691
01692
01693
01694 if (moves != NULL) {
01695 diff = Cudd_ReadSize(table) + 1;
01696 index = (upFlag == 1) ?
01697 table->invperm[moves->x] : table->invperm[moves->y];
01698 pairlev =
01699 (unsigned) table->perm[Cudd_bddReadPairIndex(table, index)];
01700
01701 for (move = moves; move != NULL; move = move->next) {
01702 if (move->size == size) {
01703 if (upFlag == 1) {
01704 tmp_diff = (move->x > pairlev) ?
01705 move->x - pairlev : pairlev - move->x;
01706 } else {
01707 tmp_diff = (move->y > pairlev) ?
01708 move->y - pairlev : pairlev - move->y;
01709 }
01710 if (tmp_diff < diff) {
01711 diff = tmp_diff;
01712 end_move = move;
01713 }
01714 }
01715 }
01716 }
01717 } else {
01718
01719 for (move = moves; move != NULL; move = move->next) {
01720 if (move->size < size) {
01721 size = move->size;
01722 }
01723 }
01724 }
01725
01726
01727
01728
01729 for (move = moves; move != NULL; move = move->next) {
01730 if (lazyFlag) {
01731 if (move == end_move) return(1);
01732 } else {
01733 if (move->size == size) return(1);
01734 }
01735 if ((table->subtables[move->x].next == move->x) &&
01736 (table->subtables[move->y].next == move->y)) {
01737 res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
01738 if (!res) return(0);
01739 #ifdef DD_DEBUG
01740 if (pr > 0) (void) fprintf(table->out,"ddGroupSiftingBackward:\n");
01741 assert(table->subtables[move->x].next == move->x);
01742 assert(table->subtables[move->y].next == move->y);
01743 #endif
01744 } else {
01745 if (move->flags == MTR_NEWNODE) {
01746 ddDissolveGroup(table,(int)move->x,(int)move->y);
01747 } else {
01748 res = ddGroupMoveBackward(table,(int)move->x,(int)move->y);
01749 if (!res) return(0);
01750 }
01751 }
01752
01753 }
01754
01755 return(1);
01756
01757 }
01758
01759
01770 static void
01771 ddMergeGroups(
01772 DdManager * table,
01773 MtrNode * treenode,
01774 int low,
01775 int high)
01776 {
01777 int i;
01778 MtrNode *auxnode;
01779 int saveindex;
01780 int newindex;
01781
01782
01783
01784
01785 if (treenode != table->tree) {
01786 for (i = low; i < high; i++)
01787 table->subtables[i].next = i+1;
01788 table->subtables[high].next = low;
01789 }
01790
01791
01792
01793 saveindex = treenode->index;
01794 newindex = table->invperm[low];
01795 auxnode = treenode;
01796 do {
01797 auxnode->index = newindex;
01798 if (auxnode->parent == NULL ||
01799 (int) auxnode->parent->index != saveindex)
01800 break;
01801 auxnode = auxnode->parent;
01802 } while (1);
01803 return;
01804
01805 }
01806
01807
01818 static void
01819 ddDissolveGroup(
01820 DdManager * table,
01821 int x,
01822 int y)
01823 {
01824 int topx;
01825 int boty;
01826
01827
01828 boty = y;
01829 while ((unsigned) boty < table->subtables[boty].next)
01830 boty = table->subtables[boty].next;
01831
01832 topx = table->subtables[boty].next;
01833
01834 table->subtables[boty].next = y;
01835 table->subtables[x].next = topx;
01836
01837 return;
01838
01839 }
01840
01841
01852 static int
01853 ddNoCheck(
01854 DdManager * table,
01855 int x,
01856 int y)
01857 {
01858 return(0);
01859
01860 }
01861
01862
01876 static int
01877 ddSecDiffCheck(
01878 DdManager * table,
01879 int x,
01880 int y)
01881 {
01882 double Nx,Nx_1;
01883 double Sx;
01884 double threshold;
01885 int xindex,yindex;
01886
01887 if (x==0) return(0);
01888
01889 #ifdef DD_STATS
01890 secdiffcalls++;
01891 #endif
01892 Nx = (double) table->subtables[x].keys;
01893 Nx_1 = (double) table->subtables[x-1].keys;
01894 Sx = (table->subtables[y].keys/Nx) - (Nx/Nx_1);
01895
01896 threshold = table->recomb / 100.0;
01897 if (Sx < threshold) {
01898 xindex = table->invperm[x];
01899 yindex = table->invperm[y];
01900 if (cuddTestInteract(table,xindex,yindex)) {
01901 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
01902 (void) fprintf(table->out,
01903 "Second difference for %d = %g Pos(%d)\n",
01904 table->invperm[x],Sx,x);
01905 #endif
01906 #ifdef DD_STATS
01907 secdiff++;
01908 #endif
01909 return(1);
01910 } else {
01911 #ifdef DD_STATS
01912 secdiffmisfire++;
01913 #endif
01914 return(0);
01915 }
01916
01917 }
01918 return(0);
01919
01920 }
01921
01922
01933 static int
01934 ddExtSymmCheck(
01935 DdManager * table,
01936 int x,
01937 int y)
01938 {
01939 DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
01940 DdNode *one;
01941 unsigned comple;
01942 int notproj;
01943 int arccount;
01944 int TotalRefCount;
01945 int counter;
01946
01947 int arccounter;
01948
01949 int i;
01950 int xindex;
01951 int yindex;
01952 int res;
01953 int slots;
01954 DdNodePtr *list;
01955 DdNode *sentinel = &(table->sentinel);
01956
01957 xindex = table->invperm[x];
01958 yindex = table->invperm[y];
01959
01960
01961 if (!cuddTestInteract(table,xindex,yindex))
01962 return(0);
01963
01964 #ifdef DD_DEBUG
01965
01966
01967
01968
01969
01970 if (table->subtables[x].keys == 1) {
01971 assert(table->vars[xindex]->ref != 1);
01972 }
01973 if (table->subtables[y].keys == 1) {
01974 assert(table->vars[yindex]->ref != 1);
01975 }
01976 #endif
01977
01978 #ifdef DD_STATS
01979 extsymmcalls++;
01980 #endif
01981
01982 arccount = 0;
01983 counter = (int) (table->subtables[x].keys *
01984 (table->symmviolation/100.0) + 0.5);
01985 one = DD_ONE(table);
01986
01987 slots = table->subtables[x].slots;
01988 list = table->subtables[x].nodelist;
01989 for (i = 0; i < slots; i++) {
01990 f = list[i];
01991 while (f != sentinel) {
01992
01993 f1 = cuddT(f);
01994 f0 = Cudd_Regular(cuddE(f));
01995 comple = Cudd_IsComplement(cuddE(f));
01996 notproj = f1 != one || f0 != one || f->ref != (DdHalfWord) 1;
01997 if (f1->index == (unsigned) yindex) {
01998 arccount++;
01999 f11 = cuddT(f1); f10 = cuddE(f1);
02000 } else {
02001 if ((int) f0->index != yindex) {
02002
02003
02004
02005 if (notproj) {
02006 if (counter == 0)
02007 return(0);
02008 counter--;
02009 }
02010 }
02011 f11 = f10 = f1;
02012 }
02013 if ((int) f0->index == yindex) {
02014 arccount++;
02015 f01 = cuddT(f0); f00 = cuddE(f0);
02016 } else {
02017 f01 = f00 = f0;
02018 }
02019 if (comple) {
02020 f01 = Cudd_Not(f01);
02021 f00 = Cudd_Not(f00);
02022 }
02023
02024
02025
02026
02027
02028 if (notproj) {
02029 if (f01 != f10 && f11 != f00) {
02030 if (counter == 0)
02031 return(0);
02032 counter--;
02033 }
02034 }
02035
02036 f = f->next;
02037 }
02038 }
02039
02040
02041 TotalRefCount = -1;
02042 slots = table->subtables[y].slots;
02043 list = table->subtables[y].nodelist;
02044 for (i = 0; i < slots; i++) {
02045 f = list[i];
02046 while (f != sentinel) {
02047 TotalRefCount += f->ref;
02048 f = f->next;
02049 }
02050 }
02051
02052 arccounter = (int) (table->subtables[y].keys *
02053 (table->arcviolation/100.0) + 0.5);
02054 res = arccount >= TotalRefCount - arccounter;
02055
02056 #if defined(DD_DEBUG) && defined(DD_VERBOSE)
02057 if (res) {
02058 (void) fprintf(table->out,
02059 "Found extended symmetry! x = %d\ty = %d\tPos(%d,%d)\n",
02060 xindex,yindex,x,y);
02061 }
02062 #endif
02063
02064 #ifdef DD_STATS
02065 if (res)
02066 extsymm++;
02067 #endif
02068 return(res);
02069
02070 }
02071
02072
02083 static int
02084 ddVarGroupCheck(
02085 DdManager * table,
02086 int x,
02087 int y)
02088 {
02089 int xindex = table->invperm[x];
02090 int yindex = table->invperm[y];
02091
02092 if (Cudd_bddIsVarToBeUngrouped(table, xindex)) return(0);
02093
02094 if (Cudd_bddReadPairIndex(table, xindex) == yindex) {
02095 if (ddIsVarHandled(table, xindex) ||
02096 ddIsVarHandled(table, yindex)) {
02097 if (Cudd_bddIsVarToBeGrouped(table, xindex) ||
02098 Cudd_bddIsVarToBeGrouped(table, yindex) ) {
02099 if (table->keys - table->isolated <= originalSize) {
02100 return(1);
02101 }
02102 }
02103 }
02104 }
02105
02106 return(0);
02107
02108 }
02109
02110
02123 static int
02124 ddSetVarHandled(
02125 DdManager *dd,
02126 int index)
02127 {
02128 if (index >= dd->size || index < 0) return(0);
02129 dd->subtables[dd->perm[index]].varHandled = 1;
02130 return(1);
02131
02132 }
02133
02134
02147 static int
02148 ddResetVarHandled(
02149 DdManager *dd,
02150 int index)
02151 {
02152 if (index >= dd->size || index < 0) return(0);
02153 dd->subtables[dd->perm[index]].varHandled = 0;
02154 return(1);
02155
02156 }
02157
02158
02171 static int
02172 ddIsVarHandled(
02173 DdManager *dd,
02174 int index)
02175 {
02176 if (index >= dd->size || index < 0) return(-1);
02177 return dd->subtables[dd->perm[index]].varHandled;
02178
02179 }