You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1707 lines
49 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddSymmetry.c]
  3. PackageName [cudd]
  4. Synopsis [Functions for symmetry-based variable reordering.]
  5. Description [External procedures included in this file:
  6. <ul>
  7. <li> Cudd_SymmProfile()
  8. </ul>
  9. Internal procedures included in this module:
  10. <ul>
  11. <li> cuddSymmCheck()
  12. <li> cuddSymmSifting()
  13. <li> cuddSymmSiftingConv()
  14. </ul>
  15. Static procedures included in this module:
  16. <ul>
  17. <li> ddSymmUniqueCompare()
  18. <li> ddSymmSiftingAux()
  19. <li> ddSymmSiftingConvAux()
  20. <li> ddSymmSiftingUp()
  21. <li> ddSymmSiftingDown()
  22. <li> ddSymmGroupMove()
  23. <li> ddSymmGroupMoveBackward()
  24. <li> ddSymmSiftingBackward()
  25. <li> ddSymmSummary()
  26. </ul>]
  27. Author [Shipra Panda, Fabio Somenzi]
  28. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  29. All rights reserved.
  30. Redistribution and use in source and binary forms, with or without
  31. modification, are permitted provided that the following conditions
  32. are met:
  33. Redistributions of source code must retain the above copyright
  34. notice, this list of conditions and the following disclaimer.
  35. Redistributions in binary form must reproduce the above copyright
  36. notice, this list of conditions and the following disclaimer in the
  37. documentation and/or other materials provided with the distribution.
  38. Neither the name of the University of Colorado nor the names of its
  39. contributors may be used to endorse or promote products derived from
  40. this software without specific prior written permission.
  41. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  42. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  43. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  44. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  45. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  46. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  47. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  48. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  49. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  50. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  51. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  52. POSSIBILITY OF SUCH DAMAGE.]
  53. ******************************************************************************/
  54. #include "util.h"
  55. #include "cuddInt.h"
  56. /*---------------------------------------------------------------------------*/
  57. /* Constant declarations */
  58. /*---------------------------------------------------------------------------*/
  59. #define MV_OOM (Move *)1
  60. /*---------------------------------------------------------------------------*/
  61. /* Stucture declarations */
  62. /*---------------------------------------------------------------------------*/
  63. /*---------------------------------------------------------------------------*/
  64. /* Type declarations */
  65. /*---------------------------------------------------------------------------*/
  66. /*---------------------------------------------------------------------------*/
  67. /* Variable declarations */
  68. /*---------------------------------------------------------------------------*/
  69. #ifndef lint
  70. static char rcsid[] DD_UNUSED = "$Id: cuddSymmetry.c,v 1.28 2012/02/05 01:07:19 fabio Exp $";
  71. #endif
  72. static int *entry;
  73. extern int ddTotalNumberSwapping;
  74. #ifdef DD_STATS
  75. extern int ddTotalNISwaps;
  76. #endif
  77. /*---------------------------------------------------------------------------*/
  78. /* Macro declarations */
  79. /*---------------------------------------------------------------------------*/
  80. /**AutomaticStart*************************************************************/
  81. /*---------------------------------------------------------------------------*/
  82. /* Static function prototypes */
  83. /*---------------------------------------------------------------------------*/
  84. static int ddSymmUniqueCompare (int *ptrX, int *ptrY);
  85. static int ddSymmSiftingAux (DdManager *table, int x, int xLow, int xHigh);
  86. static int ddSymmSiftingConvAux (DdManager *table, int x, int xLow, int xHigh);
  87. static Move * ddSymmSiftingUp (DdManager *table, int y, int xLow);
  88. static Move * ddSymmSiftingDown (DdManager *table, int x, int xHigh);
  89. static int ddSymmGroupMove (DdManager *table, int x, int y, Move **moves);
  90. static int ddSymmGroupMoveBackward (DdManager *table, int x, int y);
  91. static int ddSymmSiftingBackward (DdManager *table, Move *moves, int size);
  92. static void ddSymmSummary (DdManager *table, int lower, int upper, int *symvars, int *symgroups);
  93. /**AutomaticEnd***************************************************************/
  94. /*---------------------------------------------------------------------------*/
  95. /* Definition of exported functions */
  96. /*---------------------------------------------------------------------------*/
  97. /**Function********************************************************************
  98. Synopsis [Prints statistics on symmetric variables.]
  99. Description []
  100. SideEffects [None]
  101. ******************************************************************************/
  102. void
  103. Cudd_SymmProfile(
  104. DdManager * table,
  105. int lower,
  106. int upper)
  107. {
  108. int i,x,gbot;
  109. int TotalSymm = 0;
  110. int TotalSymmGroups = 0;
  111. for (i = lower; i <= upper; i++) {
  112. if (table->subtables[i].next != (unsigned) i) {
  113. x = i;
  114. (void) fprintf(table->out,"Group:");
  115. do {
  116. (void) fprintf(table->out," %d",table->invperm[x]);
  117. TotalSymm++;
  118. gbot = x;
  119. x = table->subtables[x].next;
  120. } while (x != i);
  121. TotalSymmGroups++;
  122. #ifdef DD_DEBUG
  123. assert(table->subtables[gbot].next == (unsigned) i);
  124. #endif
  125. i = gbot;
  126. (void) fprintf(table->out,"\n");
  127. }
  128. }
  129. (void) fprintf(table->out,"Total Symmetric = %d\n",TotalSymm);
  130. (void) fprintf(table->out,"Total Groups = %d\n",TotalSymmGroups);
  131. } /* end of Cudd_SymmProfile */
  132. /*---------------------------------------------------------------------------*/
  133. /* Definition of internal functions */
  134. /*---------------------------------------------------------------------------*/
  135. /**Function********************************************************************
  136. Synopsis [Checks for symmetry of x and y.]
  137. Description [Checks for symmetry of x and y. Ignores projection
  138. functions, unless they are isolated. Returns 1 in case of symmetry; 0
  139. otherwise.]
  140. SideEffects [None]
  141. ******************************************************************************/
  142. int
  143. cuddSymmCheck(
  144. DdManager * table,
  145. int x,
  146. int y)
  147. {
  148. DdNode *f,*f0,*f1,*f01,*f00,*f11,*f10;
  149. int comple; /* f0 is complemented */
  150. int xsymmy; /* x and y may be positively symmetric */
  151. int xsymmyp; /* x and y may be negatively symmetric */
  152. int arccount; /* number of arcs from layer x to layer y */
  153. int TotalRefCount; /* total reference count of layer y minus 1 */
  154. int yindex;
  155. int i;
  156. DdNodePtr *list;
  157. int slots;
  158. DdNode *sentinel = &(table->sentinel);
  159. #ifdef DD_DEBUG
  160. int xindex;
  161. #endif
  162. /* Checks that x and y are not the projection functions.
  163. ** For x it is sufficient to check whether there is only one
  164. ** node; indeed, if there is one node, it is the projection function
  165. ** and it cannot point to y. Hence, if y isn't just the projection
  166. ** function, it has one arc coming from a layer different from x.
  167. */
  168. if (table->subtables[x].keys == 1) {
  169. return(0);
  170. }
  171. yindex = table->invperm[y];
  172. if (table->subtables[y].keys == 1) {
  173. if (table->vars[yindex]->ref == 1)
  174. return(0);
  175. }
  176. xsymmy = xsymmyp = 1;
  177. arccount = 0;
  178. slots = table->subtables[x].slots;
  179. list = table->subtables[x].nodelist;
  180. for (i = 0; i < slots; i++) {
  181. f = list[i];
  182. while (f != sentinel) {
  183. /* Find f1, f0, f11, f10, f01, f00. */
  184. f1 = cuddT(f);
  185. f0 = Cudd_Regular(cuddE(f));
  186. comple = Cudd_IsComplement(cuddE(f));
  187. if ((int) f1->index == yindex) {
  188. arccount++;
  189. f11 = cuddT(f1); f10 = cuddE(f1);
  190. } else {
  191. if ((int) f0->index != yindex) {
  192. /* If f is an isolated projection function it is
  193. ** allowed to bypass layer y.
  194. */
  195. if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1)
  196. return(0); /* f bypasses layer y */
  197. }
  198. f11 = f10 = f1;
  199. }
  200. if ((int) f0->index == yindex) {
  201. arccount++;
  202. f01 = cuddT(f0); f00 = cuddE(f0);
  203. } else {
  204. f01 = f00 = f0;
  205. }
  206. if (comple) {
  207. f01 = Cudd_Not(f01);
  208. f00 = Cudd_Not(f00);
  209. }
  210. if (f1 != DD_ONE(table) || f0 != DD_ONE(table) || f->ref != 1) {
  211. xsymmy &= f01 == f10;
  212. xsymmyp &= f11 == f00;
  213. if ((xsymmy == 0) && (xsymmyp == 0))
  214. return(0);
  215. }
  216. f = f->next;
  217. } /* while */
  218. } /* for */
  219. /* Calculate the total reference counts of y */
  220. TotalRefCount = -1; /* -1 for projection function */
  221. slots = table->subtables[y].slots;
  222. list = table->subtables[y].nodelist;
  223. for (i = 0; i < slots; i++) {
  224. f = list[i];
  225. while (f != sentinel) {
  226. TotalRefCount += f->ref;
  227. f = f->next;
  228. }
  229. }
  230. #if defined(DD_DEBUG) && defined(DD_VERBOSE)
  231. if (arccount == TotalRefCount) {
  232. xindex = table->invperm[x];
  233. (void) fprintf(table->out,
  234. "Found symmetry! x =%d\ty = %d\tPos(%d,%d)\n",
  235. xindex,yindex,x,y);
  236. }
  237. #endif
  238. return(arccount == TotalRefCount);
  239. } /* end of cuddSymmCheck */
  240. /**Function********************************************************************
  241. Synopsis [Symmetric sifting algorithm.]
  242. Description [Symmetric sifting algorithm.
  243. Assumes that no dead nodes are present.
  244. <ol>
  245. <li> Order all the variables according to the number of entries in
  246. each unique subtable.
  247. <li> Sift the variable up and down, remembering each time the total
  248. size of the DD heap and grouping variables that are symmetric.
  249. <li> Select the best permutation.
  250. <li> Repeat 3 and 4 for all variables.
  251. </ol>
  252. Returns 1 plus the number of symmetric variables if successful; 0
  253. otherwise.]
  254. SideEffects [None]
  255. SeeAlso [cuddSymmSiftingConv]
  256. ******************************************************************************/
  257. int
  258. cuddSymmSifting(
  259. DdManager * table,
  260. int lower,
  261. int upper)
  262. {
  263. int i;
  264. int *var;
  265. int size;
  266. int x;
  267. int result;
  268. int symvars;
  269. int symgroups;
  270. #ifdef DD_STATS
  271. int previousSize;
  272. #endif
  273. size = table->size;
  274. /* Find order in which to sift variables. */
  275. var = NULL;
  276. entry = ALLOC(int,size);
  277. if (entry == NULL) {
  278. table->errorCode = CUDD_MEMORY_OUT;
  279. goto ddSymmSiftingOutOfMem;
  280. }
  281. var = ALLOC(int,size);
  282. if (var == NULL) {
  283. table->errorCode = CUDD_MEMORY_OUT;
  284. goto ddSymmSiftingOutOfMem;
  285. }
  286. for (i = 0; i < size; i++) {
  287. x = table->perm[i];
  288. entry[i] = table->subtables[x].keys;
  289. var[i] = i;
  290. }
  291. qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
  292. /* Initialize the symmetry of each subtable to itself. */
  293. for (i = lower; i <= upper; i++) {
  294. table->subtables[i].next = i;
  295. }
  296. for (i = 0; i < ddMin(table->siftMaxVar,size); i++) {
  297. if (ddTotalNumberSwapping >= table->siftMaxSwap)
  298. break;
  299. if (util_cpu_time() - table->startTime > table->timeLimit) {
  300. table->autoDyn = 0; /* prevent further reordering */
  301. break;
  302. }
  303. x = table->perm[var[i]];
  304. #ifdef DD_STATS
  305. previousSize = table->keys - table->isolated;
  306. #endif
  307. if (x < lower || x > upper) continue;
  308. if (table->subtables[x].next == (unsigned) x) {
  309. result = ddSymmSiftingAux(table,x,lower,upper);
  310. if (!result) goto ddSymmSiftingOutOfMem;
  311. #ifdef DD_STATS
  312. if (table->keys < (unsigned) previousSize + table->isolated) {
  313. (void) fprintf(table->out,"-");
  314. } else if (table->keys > (unsigned) previousSize +
  315. table->isolated) {
  316. (void) fprintf(table->out,"+"); /* should never happen */
  317. } else {
  318. (void) fprintf(table->out,"=");
  319. }
  320. fflush(table->out);
  321. #endif
  322. }
  323. }
  324. FREE(var);
  325. FREE(entry);
  326. ddSymmSummary(table, lower, upper, &symvars, &symgroups);
  327. #ifdef DD_STATS
  328. (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
  329. symvars);
  330. (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
  331. symgroups);
  332. #endif
  333. return(1+symvars);
  334. ddSymmSiftingOutOfMem:
  335. if (entry != NULL) FREE(entry);
  336. if (var != NULL) FREE(var);
  337. return(0);
  338. } /* end of cuddSymmSifting */
  339. /**Function********************************************************************
  340. Synopsis [Symmetric sifting to convergence algorithm.]
  341. Description [Symmetric sifting to convergence algorithm.
  342. Assumes that no dead nodes are present.
  343. <ol>
  344. <li> Order all the variables according to the number of entries in
  345. each unique subtable.
  346. <li> Sift the variable up and down, remembering each time the total
  347. size of the DD heap and grouping variables that are symmetric.
  348. <li> Select the best permutation.
  349. <li> Repeat 3 and 4 for all variables.
  350. <li> Repeat 1-4 until no further improvement.
  351. </ol>
  352. Returns 1 plus the number of symmetric variables if successful; 0
  353. otherwise.]
  354. SideEffects [None]
  355. SeeAlso [cuddSymmSifting]
  356. ******************************************************************************/
  357. int
  358. cuddSymmSiftingConv(
  359. DdManager * table,
  360. int lower,
  361. int upper)
  362. {
  363. int i;
  364. int *var;
  365. int size;
  366. int x;
  367. int result;
  368. int symvars;
  369. int symgroups;
  370. int classes;
  371. int initialSize;
  372. #ifdef DD_STATS
  373. int previousSize;
  374. #endif
  375. initialSize = table->keys - table->isolated;
  376. size = table->size;
  377. /* Find order in which to sift variables. */
  378. var = NULL;
  379. entry = ALLOC(int,size);
  380. if (entry == NULL) {
  381. table->errorCode = CUDD_MEMORY_OUT;
  382. goto ddSymmSiftingConvOutOfMem;
  383. }
  384. var = ALLOC(int,size);
  385. if (var == NULL) {
  386. table->errorCode = CUDD_MEMORY_OUT;
  387. goto ddSymmSiftingConvOutOfMem;
  388. }
  389. for (i = 0; i < size; i++) {
  390. x = table->perm[i];
  391. entry[i] = table->subtables[x].keys;
  392. var[i] = i;
  393. }
  394. qsort((void *)var,size,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
  395. /* Initialize the symmetry of each subtable to itself
  396. ** for first pass of converging symmetric sifting.
  397. */
  398. for (i = lower; i <= upper; i++) {
  399. table->subtables[i].next = i;
  400. }
  401. for (i = 0; i < ddMin(table->siftMaxVar, table->size); i++) {
  402. if (ddTotalNumberSwapping >= table->siftMaxSwap)
  403. break;
  404. if (util_cpu_time() - table->startTime > table->timeLimit) {
  405. table->autoDyn = 0; /* prevent further reordering */
  406. break;
  407. }
  408. x = table->perm[var[i]];
  409. if (x < lower || x > upper) continue;
  410. /* Only sift if not in symmetry group already. */
  411. if (table->subtables[x].next == (unsigned) x) {
  412. #ifdef DD_STATS
  413. previousSize = table->keys - table->isolated;
  414. #endif
  415. result = ddSymmSiftingAux(table,x,lower,upper);
  416. if (!result) goto ddSymmSiftingConvOutOfMem;
  417. #ifdef DD_STATS
  418. if (table->keys < (unsigned) previousSize + table->isolated) {
  419. (void) fprintf(table->out,"-");
  420. } else if (table->keys > (unsigned) previousSize +
  421. table->isolated) {
  422. (void) fprintf(table->out,"+");
  423. } else {
  424. (void) fprintf(table->out,"=");
  425. }
  426. fflush(table->out);
  427. #endif
  428. }
  429. }
  430. /* Sifting now until convergence. */
  431. while ((unsigned) initialSize > table->keys - table->isolated) {
  432. initialSize = table->keys - table->isolated;
  433. #ifdef DD_STATS
  434. (void) fprintf(table->out,"\n");
  435. #endif
  436. /* Here we consider only one representative for each symmetry class. */
  437. for (x = lower, classes = 0; x <= upper; x++, classes++) {
  438. while ((unsigned) x < table->subtables[x].next) {
  439. x = table->subtables[x].next;
  440. }
  441. /* Here x is the largest index in a group.
  442. ** Groups consist of adjacent variables.
  443. ** Hence, the next increment of x will move it to a new group.
  444. */
  445. i = table->invperm[x];
  446. entry[i] = table->subtables[x].keys;
  447. var[classes] = i;
  448. }
  449. qsort((void *)var,classes,sizeof(int),(DD_QSFP)ddSymmUniqueCompare);
  450. /* Now sift. */
  451. for (i = 0; i < ddMin(table->siftMaxVar,classes); i++) {
  452. if (ddTotalNumberSwapping >= table->siftMaxSwap)
  453. break;
  454. if (util_cpu_time() - table->startTime > table->timeLimit) {
  455. table->autoDyn = 0; /* prevent further reordering */
  456. break;
  457. }
  458. x = table->perm[var[i]];
  459. if ((unsigned) x >= table->subtables[x].next) {
  460. #ifdef DD_STATS
  461. previousSize = table->keys - table->isolated;
  462. #endif
  463. result = ddSymmSiftingConvAux(table,x,lower,upper);
  464. if (!result ) goto ddSymmSiftingConvOutOfMem;
  465. #ifdef DD_STATS
  466. if (table->keys < (unsigned) previousSize + table->isolated) {
  467. (void) fprintf(table->out,"-");
  468. } else if (table->keys > (unsigned) previousSize +
  469. table->isolated) {
  470. (void) fprintf(table->out,"+");
  471. } else {
  472. (void) fprintf(table->out,"=");
  473. }
  474. fflush(table->out);
  475. #endif
  476. }
  477. } /* for */
  478. }
  479. ddSymmSummary(table, lower, upper, &symvars, &symgroups);
  480. #ifdef DD_STATS
  481. (void) fprintf(table->out, "\n#:S_SIFTING %8d: symmetric variables\n",
  482. symvars);
  483. (void) fprintf(table->out, "#:G_SIFTING %8d: symmetric groups",
  484. symgroups);
  485. #endif
  486. FREE(var);
  487. FREE(entry);
  488. return(1+symvars);
  489. ddSymmSiftingConvOutOfMem:
  490. if (entry != NULL) FREE(entry);
  491. if (var != NULL) FREE(var);
  492. return(0);
  493. } /* end of cuddSymmSiftingConv */
  494. /*---------------------------------------------------------------------------*/
  495. /* Definition of static functions */
  496. /*---------------------------------------------------------------------------*/
  497. /**Function********************************************************************
  498. Synopsis [Comparison function used by qsort.]
  499. Description [Comparison function used by qsort to order the variables
  500. according to the number of keys in the subtables.
  501. Returns the difference in number of keys between the two
  502. variables being compared.]
  503. SideEffects [None]
  504. ******************************************************************************/
  505. static int
  506. ddSymmUniqueCompare(
  507. int * ptrX,
  508. int * ptrY)
  509. {
  510. #if 0
  511. if (entry[*ptrY] == entry[*ptrX]) {
  512. return((*ptrX) - (*ptrY));
  513. }
  514. #endif
  515. return(entry[*ptrY] - entry[*ptrX]);
  516. } /* end of ddSymmUniqueCompare */
  517. /**Function********************************************************************
  518. Synopsis [Given xLow <= x <= xHigh moves x up and down between the
  519. boundaries.]
  520. Description [Given xLow <= x <= xHigh moves x up and down between the
  521. boundaries. Finds the best position and does the required changes.
  522. Assumes that x is not part of a symmetry group. Returns 1 if
  523. successful; 0 otherwise.]
  524. SideEffects [None]
  525. ******************************************************************************/
  526. static int
  527. ddSymmSiftingAux(
  528. DdManager * table,
  529. int x,
  530. int xLow,
  531. int xHigh)
  532. {
  533. Move *move;
  534. Move *moveUp; /* list of up moves */
  535. Move *moveDown; /* list of down moves */
  536. int initialSize;
  537. int result;
  538. int i;
  539. int topbot; /* index to either top or bottom of symmetry group */
  540. int initGroupSize, finalGroupSize;
  541. #ifdef DD_DEBUG
  542. /* check for previously detected symmetry */
  543. assert(table->subtables[x].next == (unsigned) x);
  544. #endif
  545. initialSize = table->keys - table->isolated;
  546. moveDown = NULL;
  547. moveUp = NULL;
  548. if ((x - xLow) > (xHigh - x)) {
  549. /* Will go down first, unless x == xHigh:
  550. ** Look for consecutive symmetries above x.
  551. */
  552. for (i = x; i > xLow; i--) {
  553. if (!cuddSymmCheck(table,i-1,i))
  554. break;
  555. topbot = table->subtables[i-1].next; /* find top of i-1's group */
  556. table->subtables[i-1].next = i;
  557. table->subtables[x].next = topbot; /* x is bottom of group so its */
  558. /* next is top of i-1's group */
  559. i = topbot + 1; /* add 1 for i--; new i is top of symm group */
  560. }
  561. } else {
  562. /* Will go up first unless x == xlow:
  563. ** Look for consecutive symmetries below x.
  564. */
  565. for (i = x; i < xHigh; i++) {
  566. if (!cuddSymmCheck(table,i,i+1))
  567. break;
  568. /* find bottom of i+1's symm group */
  569. topbot = i + 1;
  570. while ((unsigned) topbot < table->subtables[topbot].next) {
  571. topbot = table->subtables[topbot].next;
  572. }
  573. table->subtables[topbot].next = table->subtables[i].next;
  574. table->subtables[i].next = i + 1;
  575. i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
  576. }
  577. }
  578. /* Now x may be in the middle of a symmetry group.
  579. ** Find bottom of x's symm group.
  580. */
  581. while ((unsigned) x < table->subtables[x].next)
  582. x = table->subtables[x].next;
  583. if (x == xLow) { /* Sift down */
  584. #ifdef DD_DEBUG
  585. /* x must be a singleton */
  586. assert((unsigned) x == table->subtables[x].next);
  587. #endif
  588. if (x == xHigh) return(1); /* just one variable */
  589. initGroupSize = 1;
  590. moveDown = ddSymmSiftingDown(table,x,xHigh);
  591. /* after this point x --> xHigh, unless early term */
  592. if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
  593. if (moveDown == NULL) return(1);
  594. x = moveDown->y;
  595. /* Find bottom of x's group */
  596. i = x;
  597. while ((unsigned) i < table->subtables[i].next) {
  598. i = table->subtables[i].next;
  599. }
  600. #ifdef DD_DEBUG
  601. /* x should be the top of the symmetry group and i the bottom */
  602. assert((unsigned) i >= table->subtables[i].next);
  603. assert((unsigned) x == table->subtables[i].next);
  604. #endif
  605. finalGroupSize = i - x + 1;
  606. if (initGroupSize == finalGroupSize) {
  607. /* No new symmetry groups detected, return to best position */
  608. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  609. } else {
  610. initialSize = table->keys - table->isolated;
  611. moveUp = ddSymmSiftingUp(table,x,xLow);
  612. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  613. }
  614. if (!result) goto ddSymmSiftingAuxOutOfMem;
  615. } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
  616. /* Find top of x's symm group */
  617. i = x; /* bottom */
  618. x = table->subtables[x].next; /* top */
  619. if (x == xLow) return(1); /* just one big group */
  620. initGroupSize = i - x + 1;
  621. moveUp = ddSymmSiftingUp(table,x,xLow);
  622. /* after this point x --> xLow, unless early term */
  623. if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
  624. if (moveUp == NULL) return(1);
  625. x = moveUp->x;
  626. /* Find top of x's group */
  627. i = table->subtables[x].next;
  628. #ifdef DD_DEBUG
  629. /* x should be the bottom of the symmetry group and i the top */
  630. assert((unsigned) x >= table->subtables[x].next);
  631. assert((unsigned) i == table->subtables[x].next);
  632. #endif
  633. finalGroupSize = x - i + 1;
  634. if (initGroupSize == finalGroupSize) {
  635. /* No new symmetry groups detected, return to best position */
  636. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  637. } else {
  638. initialSize = table->keys - table->isolated;
  639. moveDown = ddSymmSiftingDown(table,x,xHigh);
  640. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  641. }
  642. if (!result) goto ddSymmSiftingAuxOutOfMem;
  643. } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
  644. moveDown = ddSymmSiftingDown(table,x,xHigh);
  645. /* at this point x == xHigh, unless early term */
  646. if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
  647. if (moveDown != NULL) {
  648. x = moveDown->y; /* x is top here */
  649. i = x;
  650. while ((unsigned) i < table->subtables[i].next) {
  651. i = table->subtables[i].next;
  652. }
  653. } else {
  654. i = x;
  655. while ((unsigned) i < table->subtables[i].next) {
  656. i = table->subtables[i].next;
  657. }
  658. x = table->subtables[i].next;
  659. }
  660. #ifdef DD_DEBUG
  661. /* x should be the top of the symmetry group and i the bottom */
  662. assert((unsigned) i >= table->subtables[i].next);
  663. assert((unsigned) x == table->subtables[i].next);
  664. #endif
  665. initGroupSize = i - x + 1;
  666. moveUp = ddSymmSiftingUp(table,x,xLow);
  667. if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
  668. if (moveUp != NULL) {
  669. x = moveUp->x;
  670. i = table->subtables[x].next;
  671. } else {
  672. i = x;
  673. while ((unsigned) x < table->subtables[x].next)
  674. x = table->subtables[x].next;
  675. }
  676. #ifdef DD_DEBUG
  677. /* x should be the bottom of the symmetry group and i the top */
  678. assert((unsigned) x >= table->subtables[x].next);
  679. assert((unsigned) i == table->subtables[x].next);
  680. #endif
  681. finalGroupSize = x - i + 1;
  682. if (initGroupSize == finalGroupSize) {
  683. /* No new symmetry groups detected, return to best position */
  684. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  685. } else {
  686. while (moveDown != NULL) {
  687. move = moveDown->next;
  688. cuddDeallocMove(table, moveDown);
  689. moveDown = move;
  690. }
  691. initialSize = table->keys - table->isolated;
  692. moveDown = ddSymmSiftingDown(table,x,xHigh);
  693. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  694. }
  695. if (!result) goto ddSymmSiftingAuxOutOfMem;
  696. } else { /* moving up first: shorter */
  697. /* Find top of x's symmetry group */
  698. x = table->subtables[x].next;
  699. moveUp = ddSymmSiftingUp(table,x,xLow);
  700. /* at this point x == xHigh, unless early term */
  701. if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
  702. if (moveUp != NULL) {
  703. x = moveUp->x;
  704. i = table->subtables[x].next;
  705. } else {
  706. while ((unsigned) x < table->subtables[x].next)
  707. x = table->subtables[x].next;
  708. i = table->subtables[x].next;
  709. }
  710. #ifdef DD_DEBUG
  711. /* x is bottom of the symmetry group and i is top */
  712. assert((unsigned) x >= table->subtables[x].next);
  713. assert((unsigned) i == table->subtables[x].next);
  714. #endif
  715. initGroupSize = x - i + 1;
  716. moveDown = ddSymmSiftingDown(table,x,xHigh);
  717. if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
  718. if (moveDown != NULL) {
  719. x = moveDown->y;
  720. i = x;
  721. while ((unsigned) i < table->subtables[i].next) {
  722. i = table->subtables[i].next;
  723. }
  724. } else {
  725. i = x;
  726. x = table->subtables[x].next;
  727. }
  728. #ifdef DD_DEBUG
  729. /* x should be the top of the symmetry group and i the bottom */
  730. assert((unsigned) i >= table->subtables[i].next);
  731. assert((unsigned) x == table->subtables[i].next);
  732. #endif
  733. finalGroupSize = i - x + 1;
  734. if (initGroupSize == finalGroupSize) {
  735. /* No new symmetries detected, go back to best position */
  736. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  737. } else {
  738. while (moveUp != NULL) {
  739. move = moveUp->next;
  740. cuddDeallocMove(table, moveUp);
  741. moveUp = move;
  742. }
  743. initialSize = table->keys - table->isolated;
  744. moveUp = ddSymmSiftingUp(table,x,xLow);
  745. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  746. }
  747. if (!result) goto ddSymmSiftingAuxOutOfMem;
  748. }
  749. while (moveDown != NULL) {
  750. move = moveDown->next;
  751. cuddDeallocMove(table, moveDown);
  752. moveDown = move;
  753. }
  754. while (moveUp != NULL) {
  755. move = moveUp->next;
  756. cuddDeallocMove(table, moveUp);
  757. moveUp = move;
  758. }
  759. return(1);
  760. ddSymmSiftingAuxOutOfMem:
  761. if (moveDown != MV_OOM) {
  762. while (moveDown != NULL) {
  763. move = moveDown->next;
  764. cuddDeallocMove(table, moveDown);
  765. moveDown = move;
  766. }
  767. }
  768. if (moveUp != MV_OOM) {
  769. while (moveUp != NULL) {
  770. move = moveUp->next;
  771. cuddDeallocMove(table, moveUp);
  772. moveUp = move;
  773. }
  774. }
  775. return(0);
  776. } /* end of ddSymmSiftingAux */
  777. /**Function********************************************************************
  778. Synopsis [Given xLow <= x <= xHigh moves x up and down between the
  779. boundaries.]
  780. Description [Given xLow <= x <= xHigh moves x up and down between the
  781. boundaries. Finds the best position and does the required changes.
  782. Assumes that x is either an isolated variable, or it is the bottom of
  783. a symmetry group. All symmetries may not have been found, because of
  784. exceeded growth limit. Returns 1 if successful; 0 otherwise.]
  785. SideEffects [None]
  786. ******************************************************************************/
  787. static int
  788. ddSymmSiftingConvAux(
  789. DdManager * table,
  790. int x,
  791. int xLow,
  792. int xHigh)
  793. {
  794. Move *move;
  795. Move *moveUp; /* list of up moves */
  796. Move *moveDown; /* list of down moves */
  797. int initialSize;
  798. int result;
  799. int i;
  800. int initGroupSize, finalGroupSize;
  801. initialSize = table->keys - table->isolated;
  802. moveDown = NULL;
  803. moveUp = NULL;
  804. if (x == xLow) { /* Sift down */
  805. #ifdef DD_DEBUG
  806. /* x is bottom of symmetry group */
  807. assert((unsigned) x >= table->subtables[x].next);
  808. #endif
  809. i = table->subtables[x].next;
  810. initGroupSize = x - i + 1;
  811. moveDown = ddSymmSiftingDown(table,x,xHigh);
  812. /* at this point x == xHigh, unless early term */
  813. if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
  814. if (moveDown == NULL) return(1);
  815. x = moveDown->y;
  816. i = x;
  817. while ((unsigned) i < table->subtables[i].next) {
  818. i = table->subtables[i].next;
  819. }
  820. #ifdef DD_DEBUG
  821. /* x should be the top of the symmetric group and i the bottom */
  822. assert((unsigned) i >= table->subtables[i].next);
  823. assert((unsigned) x == table->subtables[i].next);
  824. #endif
  825. finalGroupSize = i - x + 1;
  826. if (initGroupSize == finalGroupSize) {
  827. /* No new symmetries detected, go back to best position */
  828. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  829. } else {
  830. initialSize = table->keys - table->isolated;
  831. moveUp = ddSymmSiftingUp(table,x,xLow);
  832. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  833. }
  834. if (!result) goto ddSymmSiftingConvAuxOutOfMem;
  835. } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
  836. /* Find top of x's symm group */
  837. while ((unsigned) x < table->subtables[x].next)
  838. x = table->subtables[x].next;
  839. i = x; /* bottom */
  840. x = table->subtables[x].next; /* top */
  841. if (x == xLow) return(1);
  842. initGroupSize = i - x + 1;
  843. moveUp = ddSymmSiftingUp(table,x,xLow);
  844. /* at this point x == xLow, unless early term */
  845. if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
  846. if (moveUp == NULL) return(1);
  847. x = moveUp->x;
  848. i = table->subtables[x].next;
  849. #ifdef DD_DEBUG
  850. /* x should be the bottom of the symmetry group and i the top */
  851. assert((unsigned) x >= table->subtables[x].next);
  852. assert((unsigned) i == table->subtables[x].next);
  853. #endif
  854. finalGroupSize = x - i + 1;
  855. if (initGroupSize == finalGroupSize) {
  856. /* No new symmetry groups detected, return to best position */
  857. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  858. } else {
  859. initialSize = table->keys - table->isolated;
  860. moveDown = ddSymmSiftingDown(table,x,xHigh);
  861. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  862. }
  863. if (!result)
  864. goto ddSymmSiftingConvAuxOutOfMem;
  865. } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
  866. moveDown = ddSymmSiftingDown(table,x,xHigh);
  867. /* at this point x == xHigh, unless early term */
  868. if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
  869. if (moveDown != NULL) {
  870. x = moveDown->y;
  871. i = x;
  872. while ((unsigned) i < table->subtables[i].next) {
  873. i = table->subtables[i].next;
  874. }
  875. } else {
  876. while ((unsigned) x < table->subtables[x].next)
  877. x = table->subtables[x].next;
  878. i = x;
  879. x = table->subtables[x].next;
  880. }
  881. #ifdef DD_DEBUG
  882. /* x should be the top of the symmetry group and i the bottom */
  883. assert((unsigned) i >= table->subtables[i].next);
  884. assert((unsigned) x == table->subtables[i].next);
  885. #endif
  886. initGroupSize = i - x + 1;
  887. moveUp = ddSymmSiftingUp(table,x,xLow);
  888. if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
  889. if (moveUp != NULL) {
  890. x = moveUp->x;
  891. i = table->subtables[x].next;
  892. } else {
  893. i = x;
  894. while ((unsigned) x < table->subtables[x].next)
  895. x = table->subtables[x].next;
  896. }
  897. #ifdef DD_DEBUG
  898. /* x should be the bottom of the symmetry group and i the top */
  899. assert((unsigned) x >= table->subtables[x].next);
  900. assert((unsigned) i == table->subtables[x].next);
  901. #endif
  902. finalGroupSize = x - i + 1;
  903. if (initGroupSize == finalGroupSize) {
  904. /* No new symmetry groups detected, return to best position */
  905. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  906. } else {
  907. while (moveDown != NULL) {
  908. move = moveDown->next;
  909. cuddDeallocMove(table, moveDown);
  910. moveDown = move;
  911. }
  912. initialSize = table->keys - table->isolated;
  913. moveDown = ddSymmSiftingDown(table,x,xHigh);
  914. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  915. }
  916. if (!result) goto ddSymmSiftingConvAuxOutOfMem;
  917. } else { /* moving up first: shorter */
  918. /* Find top of x's symmetry group */
  919. x = table->subtables[x].next;
  920. moveUp = ddSymmSiftingUp(table,x,xLow);
  921. /* at this point x == xHigh, unless early term */
  922. if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
  923. if (moveUp != NULL) {
  924. x = moveUp->x;
  925. i = table->subtables[x].next;
  926. } else {
  927. i = x;
  928. while ((unsigned) x < table->subtables[x].next)
  929. x = table->subtables[x].next;
  930. }
  931. #ifdef DD_DEBUG
  932. /* x is bottom of the symmetry group and i is top */
  933. assert((unsigned) x >= table->subtables[x].next);
  934. assert((unsigned) i == table->subtables[x].next);
  935. #endif
  936. initGroupSize = x - i + 1;
  937. moveDown = ddSymmSiftingDown(table,x,xHigh);
  938. if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
  939. if (moveDown != NULL) {
  940. x = moveDown->y;
  941. i = x;
  942. while ((unsigned) i < table->subtables[i].next) {
  943. i = table->subtables[i].next;
  944. }
  945. } else {
  946. i = x;
  947. x = table->subtables[x].next;
  948. }
  949. #ifdef DD_DEBUG
  950. /* x should be the top of the symmetry group and i the bottom */
  951. assert((unsigned) i >= table->subtables[i].next);
  952. assert((unsigned) x == table->subtables[i].next);
  953. #endif
  954. finalGroupSize = i - x + 1;
  955. if (initGroupSize == finalGroupSize) {
  956. /* No new symmetries detected, go back to best position */
  957. result = ddSymmSiftingBackward(table,moveDown,initialSize);
  958. } else {
  959. while (moveUp != NULL) {
  960. move = moveUp->next;
  961. cuddDeallocMove(table, moveUp);
  962. moveUp = move;
  963. }
  964. initialSize = table->keys - table->isolated;
  965. moveUp = ddSymmSiftingUp(table,x,xLow);
  966. result = ddSymmSiftingBackward(table,moveUp,initialSize);
  967. }
  968. if (!result) goto ddSymmSiftingConvAuxOutOfMem;
  969. }
  970. while (moveDown != NULL) {
  971. move = moveDown->next;
  972. cuddDeallocMove(table, moveDown);
  973. moveDown = move;
  974. }
  975. while (moveUp != NULL) {
  976. move = moveUp->next;
  977. cuddDeallocMove(table, moveUp);
  978. moveUp = move;
  979. }
  980. return(1);
  981. ddSymmSiftingConvAuxOutOfMem:
  982. if (moveDown != MV_OOM) {
  983. while (moveDown != NULL) {
  984. move = moveDown->next;
  985. cuddDeallocMove(table, moveDown);
  986. moveDown = move;
  987. }
  988. }
  989. if (moveUp != MV_OOM) {
  990. while (moveUp != NULL) {
  991. move = moveUp->next;
  992. cuddDeallocMove(table, moveUp);
  993. moveUp = move;
  994. }
  995. }
  996. return(0);
  997. } /* end of ddSymmSiftingConvAux */
  998. /**Function********************************************************************
  999. Synopsis [Moves x up until either it reaches the bound (xLow) or
  1000. the size of the DD heap increases too much.]
  1001. Description [Moves x up until either it reaches the bound (xLow) or
  1002. the size of the DD heap increases too much. Assumes that x is the top
  1003. of a symmetry group. Checks x for symmetry to the adjacent
  1004. variables. If symmetry is found, the symmetry group of x is merged
  1005. with the symmetry group of the other variable. Returns the set of
  1006. moves in case of success; MV_OOM if memory is full.]
  1007. SideEffects [None]
  1008. ******************************************************************************/
  1009. static Move *
  1010. ddSymmSiftingUp(
  1011. DdManager * table,
  1012. int y,
  1013. int xLow)
  1014. {
  1015. Move *moves;
  1016. Move *move;
  1017. int x;
  1018. int size;
  1019. int i;
  1020. int gxtop,gybot;
  1021. int limitSize;
  1022. int xindex, yindex;
  1023. int zindex;
  1024. int z;
  1025. int isolated;
  1026. int L; /* lower bound on DD size */
  1027. #ifdef DD_DEBUG
  1028. int checkL;
  1029. #endif
  1030. moves = NULL;
  1031. yindex = table->invperm[y];
  1032. /* Initialize the lower bound.
  1033. ** The part of the DD below the bottom of y' group will not change.
  1034. ** The part of the DD above y that does not interact with y will not
  1035. ** change. The rest may vanish in the best case, except for
  1036. ** the nodes at level xLow, which will not vanish, regardless.
  1037. */
  1038. limitSize = L = table->keys - table->isolated;
  1039. gybot = y;
  1040. while ((unsigned) gybot < table->subtables[gybot].next)
  1041. gybot = table->subtables[gybot].next;
  1042. for (z = xLow + 1; z <= gybot; z++) {
  1043. zindex = table->invperm[z];
  1044. if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
  1045. isolated = table->vars[zindex]->ref == 1;
  1046. L -= table->subtables[z].keys - isolated;
  1047. }
  1048. }
  1049. x = cuddNextLow(table,y);
  1050. while (x >= xLow && L <= limitSize) {
  1051. #ifdef DD_DEBUG
  1052. gybot = y;
  1053. while ((unsigned) gybot < table->subtables[gybot].next)
  1054. gybot = table->subtables[gybot].next;
  1055. checkL = table->keys - table->isolated;
  1056. for (z = xLow + 1; z <= gybot; z++) {
  1057. zindex = table->invperm[z];
  1058. if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
  1059. isolated = table->vars[zindex]->ref == 1;
  1060. checkL -= table->subtables[z].keys - isolated;
  1061. }
  1062. }
  1063. assert(L == checkL);
  1064. #endif
  1065. gxtop = table->subtables[x].next;
  1066. if (cuddSymmCheck(table,x,y)) {
  1067. /* Symmetry found, attach symm groups */
  1068. table->subtables[x].next = y;
  1069. i = table->subtables[y].next;
  1070. while (table->subtables[i].next != (unsigned) y)
  1071. i = table->subtables[i].next;
  1072. table->subtables[i].next = gxtop;
  1073. } else if (table->subtables[x].next == (unsigned) x &&
  1074. table->subtables[y].next == (unsigned) y) {
  1075. /* x and y have self symmetry */
  1076. xindex = table->invperm[x];
  1077. size = cuddSwapInPlace(table,x,y);
  1078. #ifdef DD_DEBUG
  1079. assert(table->subtables[x].next == (unsigned) x);
  1080. assert(table->subtables[y].next == (unsigned) y);
  1081. #endif
  1082. if (size == 0) goto ddSymmSiftingUpOutOfMem;
  1083. /* Update the lower bound. */
  1084. if (cuddTestInteract(table,xindex,yindex)) {
  1085. isolated = table->vars[xindex]->ref == 1;
  1086. L += table->subtables[y].keys - isolated;
  1087. }
  1088. move = (Move *) cuddDynamicAllocNode(table);
  1089. if (move == NULL) goto ddSymmSiftingUpOutOfMem;
  1090. move->x = x;
  1091. move->y = y;
  1092. move->size = size;
  1093. move->next = moves;
  1094. moves = move;
  1095. if ((double) size > (double) limitSize * table->maxGrowth)
  1096. return(moves);
  1097. if (size < limitSize) limitSize = size;
  1098. } else { /* Group move */
  1099. size = ddSymmGroupMove(table,x,y,&moves);
  1100. if (size == 0) goto ddSymmSiftingUpOutOfMem;
  1101. /* Update the lower bound. */
  1102. z = moves->y;
  1103. do {
  1104. zindex = table->invperm[z];
  1105. if (cuddTestInteract(table,zindex,yindex)) {
  1106. isolated = table->vars[zindex]->ref == 1;
  1107. L += table->subtables[z].keys - isolated;
  1108. }
  1109. z = table->subtables[z].next;
  1110. } while (z != (int) moves->y);
  1111. if ((double) size > (double) limitSize * table->maxGrowth)
  1112. return(moves);
  1113. if (size < limitSize) limitSize = size;
  1114. }
  1115. y = gxtop;
  1116. x = cuddNextLow(table,y);
  1117. }
  1118. return(moves);
  1119. ddSymmSiftingUpOutOfMem:
  1120. while (moves != NULL) {
  1121. move = moves->next;
  1122. cuddDeallocMove(table, moves);
  1123. moves = move;
  1124. }
  1125. return(MV_OOM);
  1126. } /* end of ddSymmSiftingUp */
  1127. /**Function********************************************************************
  1128. Synopsis [Moves x down until either it reaches the bound (xHigh) or
  1129. the size of the DD heap increases too much.]
  1130. Description [Moves x down until either it reaches the bound (xHigh)
  1131. or the size of the DD heap increases too much. Assumes that x is the
  1132. bottom of a symmetry group. Checks x for symmetry to the adjacent
  1133. variables. If symmetry is found, the symmetry group of x is merged
  1134. with the symmetry group of the other variable. Returns the set of
  1135. moves in case of success; MV_OOM if memory is full.]
  1136. SideEffects [None]
  1137. ******************************************************************************/
  1138. static Move *
  1139. ddSymmSiftingDown(
  1140. DdManager * table,
  1141. int x,
  1142. int xHigh)
  1143. {
  1144. Move *moves;
  1145. Move *move;
  1146. int y;
  1147. int size;
  1148. int limitSize;
  1149. int gxtop,gybot;
  1150. int R; /* upper bound on node decrease */
  1151. int xindex, yindex;
  1152. int isolated;
  1153. int z;
  1154. int zindex;
  1155. #ifdef DD_DEBUG
  1156. int checkR;
  1157. #endif
  1158. moves = NULL;
  1159. /* Initialize R */
  1160. xindex = table->invperm[x];
  1161. gxtop = table->subtables[x].next;
  1162. limitSize = size = table->keys - table->isolated;
  1163. R = 0;
  1164. for (z = xHigh; z > gxtop; z--) {
  1165. zindex = table->invperm[z];
  1166. if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
  1167. isolated = table->vars[zindex]->ref == 1;
  1168. R += table->subtables[z].keys - isolated;
  1169. }
  1170. }
  1171. y = cuddNextHigh(table,x);
  1172. while (y <= xHigh && size - R < limitSize) {
  1173. #ifdef DD_DEBUG
  1174. gxtop = table->subtables[x].next;
  1175. checkR = 0;
  1176. for (z = xHigh; z > gxtop; z--) {
  1177. zindex = table->invperm[z];
  1178. if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
  1179. isolated = table->vars[zindex]->ref == 1;
  1180. checkR += table->subtables[z].keys - isolated;
  1181. }
  1182. }
  1183. assert(R == checkR);
  1184. #endif
  1185. gybot = table->subtables[y].next;
  1186. while (table->subtables[gybot].next != (unsigned) y)
  1187. gybot = table->subtables[gybot].next;
  1188. if (cuddSymmCheck(table,x,y)) {
  1189. /* Symmetry found, attach symm groups */
  1190. gxtop = table->subtables[x].next;
  1191. table->subtables[x].next = y;
  1192. table->subtables[gybot].next = gxtop;
  1193. } else if (table->subtables[x].next == (unsigned) x &&
  1194. table->subtables[y].next == (unsigned) y) {
  1195. /* x and y have self symmetry */
  1196. /* Update upper bound on node decrease. */
  1197. yindex = table->invperm[y];
  1198. if (cuddTestInteract(table,xindex,yindex)) {
  1199. isolated = table->vars[yindex]->ref == 1;
  1200. R -= table->subtables[y].keys - isolated;
  1201. }
  1202. size = cuddSwapInPlace(table,x,y);
  1203. #ifdef DD_DEBUG
  1204. assert(table->subtables[x].next == (unsigned) x);
  1205. assert(table->subtables[y].next == (unsigned) y);
  1206. #endif
  1207. if (size == 0) goto ddSymmSiftingDownOutOfMem;
  1208. move = (Move *) cuddDynamicAllocNode(table);
  1209. if (move == NULL) goto ddSymmSiftingDownOutOfMem;
  1210. move->x = x;
  1211. move->y = y;
  1212. move->size = size;
  1213. move->next = moves;
  1214. moves = move;
  1215. if ((double) size > (double) limitSize * table->maxGrowth)
  1216. return(moves);
  1217. if (size < limitSize) limitSize = size;
  1218. } else { /* Group move */
  1219. /* Update upper bound on node decrease: first phase. */
  1220. gxtop = table->subtables[x].next;
  1221. z = gxtop + 1;
  1222. do {
  1223. zindex = table->invperm[z];
  1224. if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
  1225. isolated = table->vars[zindex]->ref == 1;
  1226. R -= table->subtables[z].keys - isolated;
  1227. }
  1228. z++;
  1229. } while (z <= gybot);
  1230. size = ddSymmGroupMove(table,x,y,&moves);
  1231. if (size == 0) goto ddSymmSiftingDownOutOfMem;
  1232. if ((double) size > (double) limitSize * table->maxGrowth)
  1233. return(moves);
  1234. if (size < limitSize) limitSize = size;
  1235. /* Update upper bound on node decrease: second phase. */
  1236. gxtop = table->subtables[gybot].next;
  1237. for (z = gxtop + 1; z <= gybot; z++) {
  1238. zindex = table->invperm[z];
  1239. if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
  1240. isolated = table->vars[zindex]->ref == 1;
  1241. R += table->subtables[z].keys - isolated;
  1242. }
  1243. }
  1244. }
  1245. x = gybot;
  1246. y = cuddNextHigh(table,x);
  1247. }
  1248. return(moves);
  1249. ddSymmSiftingDownOutOfMem:
  1250. while (moves != NULL) {
  1251. move = moves->next;
  1252. cuddDeallocMove(table, moves);
  1253. moves = move;
  1254. }
  1255. return(MV_OOM);
  1256. } /* end of ddSymmSiftingDown */
  1257. /**Function********************************************************************
  1258. Synopsis [Swaps two groups.]
  1259. Description [Swaps two groups. x is assumed to be the bottom variable
  1260. of the first group. y is assumed to be the top variable of the second
  1261. group. Updates the list of moves. Returns the number of keys in the
  1262. table if successful; 0 otherwise.]
  1263. SideEffects [None]
  1264. ******************************************************************************/
  1265. static int
  1266. ddSymmGroupMove(
  1267. DdManager * table,
  1268. int x,
  1269. int y,
  1270. Move ** moves)
  1271. {
  1272. Move *move;
  1273. int size;
  1274. int i,j;
  1275. int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
  1276. int swapx,swapy;
  1277. #ifdef DD_DEBUG
  1278. assert(x < y); /* we assume that x < y */
  1279. #endif
  1280. /* Find top, bottom, and size for the two groups. */
  1281. xbot = x;
  1282. xtop = table->subtables[x].next;
  1283. xsize = xbot - xtop + 1;
  1284. ybot = y;
  1285. while ((unsigned) ybot < table->subtables[ybot].next)
  1286. ybot = table->subtables[ybot].next;
  1287. ytop = y;
  1288. ysize = ybot - ytop + 1;
  1289. /* Sift the variables of the second group up through the first group. */
  1290. for (i = 1; i <= ysize; i++) {
  1291. for (j = 1; j <= xsize; j++) {
  1292. size = cuddSwapInPlace(table,x,y);
  1293. if (size == 0) return(0);
  1294. swapx = x; swapy = y;
  1295. y = x;
  1296. x = y - 1;
  1297. }
  1298. y = ytop + i;
  1299. x = y - 1;
  1300. }
  1301. /* fix symmetries */
  1302. y = xtop; /* ytop is now where xtop used to be */
  1303. for (i = 0; i < ysize-1 ; i++) {
  1304. table->subtables[y].next = y + 1;
  1305. y = y + 1;
  1306. }
  1307. table->subtables[y].next = xtop; /* y is bottom of its group, join */
  1308. /* its symmetry to top of its group */
  1309. x = y + 1;
  1310. newxtop = x;
  1311. for (i = 0; i < xsize - 1 ; i++) {
  1312. table->subtables[x].next = x + 1;
  1313. x = x + 1;
  1314. }
  1315. table->subtables[x].next = newxtop; /* x is bottom of its group, join */
  1316. /* its symmetry to top of its group */
  1317. /* Store group move */
  1318. move = (Move *) cuddDynamicAllocNode(table);
  1319. if (move == NULL) return(0);
  1320. move->x = swapx;
  1321. move->y = swapy;
  1322. move->size = size;
  1323. move->next = *moves;
  1324. *moves = move;
  1325. return(size);
  1326. } /* end of ddSymmGroupMove */
  1327. /**Function********************************************************************
  1328. Synopsis [Undoes the swap of two groups.]
  1329. Description [Undoes the swap of two groups. x is assumed to be the
  1330. bottom variable of the first group. y is assumed to be the top
  1331. variable of the second group. Returns the number of keys in the table
  1332. if successful; 0 otherwise.]
  1333. SideEffects [None]
  1334. ******************************************************************************/
  1335. static int
  1336. ddSymmGroupMoveBackward(
  1337. DdManager * table,
  1338. int x,
  1339. int y)
  1340. {
  1341. int size;
  1342. int i,j;
  1343. int xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
  1344. #ifdef DD_DEBUG
  1345. assert(x < y); /* We assume that x < y */
  1346. #endif
  1347. /* Find top, bottom, and size for the two groups. */
  1348. xbot = x;
  1349. xtop = table->subtables[x].next;
  1350. xsize = xbot - xtop + 1;
  1351. ybot = y;
  1352. while ((unsigned) ybot < table->subtables[ybot].next)
  1353. ybot = table->subtables[ybot].next;
  1354. ytop = y;
  1355. ysize = ybot - ytop + 1;
  1356. /* Sift the variables of the second group up through the first group. */
  1357. for (i = 1; i <= ysize; i++) {
  1358. for (j = 1; j <= xsize; j++) {
  1359. size = cuddSwapInPlace(table,x,y);
  1360. if (size == 0) return(0);
  1361. y = x;
  1362. x = cuddNextLow(table,y);
  1363. }
  1364. y = ytop + i;
  1365. x = y - 1;
  1366. }
  1367. /* Fix symmetries. */
  1368. y = xtop;
  1369. for (i = 0; i < ysize-1 ; i++) {
  1370. table->subtables[y].next = y + 1;
  1371. y = y + 1;
  1372. }
  1373. table->subtables[y].next = xtop; /* y is bottom of its group, join */
  1374. /* its symmetry to top of its group */
  1375. x = y + 1;
  1376. newxtop = x;
  1377. for (i = 0; i < xsize-1 ; i++) {
  1378. table->subtables[x].next = x + 1;
  1379. x = x + 1;
  1380. }
  1381. table->subtables[x].next = newxtop; /* x is bottom of its group, join */
  1382. /* its symmetry to top of its group */
  1383. return(size);
  1384. } /* end of ddSymmGroupMoveBackward */
  1385. /**Function********************************************************************
  1386. Synopsis [Given a set of moves, returns the DD heap to the position
  1387. giving the minimum size.]
  1388. Description [Given a set of moves, returns the DD heap to the
  1389. position giving the minimum size. In case of ties, returns to the
  1390. closest position giving the minimum size. Returns 1 in case of
  1391. success; 0 otherwise.]
  1392. SideEffects [None]
  1393. ******************************************************************************/
  1394. static int
  1395. ddSymmSiftingBackward(
  1396. DdManager * table,
  1397. Move * moves,
  1398. int size)
  1399. {
  1400. Move *move;
  1401. int res;
  1402. for (move = moves; move != NULL; move = move->next) {
  1403. if (move->size < size) {
  1404. size = move->size;
  1405. }
  1406. }
  1407. for (move = moves; move != NULL; move = move->next) {
  1408. if (move->size == size) return(1);
  1409. if (table->subtables[move->x].next == move->x && table->subtables[move->y].next == move->y) {
  1410. res = cuddSwapInPlace(table,(int)move->x,(int)move->y);
  1411. #ifdef DD_DEBUG
  1412. assert(table->subtables[move->x].next == move->x);
  1413. assert(table->subtables[move->y].next == move->y);
  1414. #endif
  1415. } else { /* Group move necessary */
  1416. res = ddSymmGroupMoveBackward(table,(int)move->x,(int)move->y);
  1417. }
  1418. if (!res) return(0);
  1419. }
  1420. return(1);
  1421. } /* end of ddSymmSiftingBackward */
  1422. /**Function********************************************************************
  1423. Synopsis [Counts numbers of symmetric variables and symmetry
  1424. groups.]
  1425. Description []
  1426. SideEffects [None]
  1427. ******************************************************************************/
  1428. static void
  1429. ddSymmSummary(
  1430. DdManager * table,
  1431. int lower,
  1432. int upper,
  1433. int * symvars,
  1434. int * symgroups)
  1435. {
  1436. int i,x,gbot;
  1437. int TotalSymm = 0;
  1438. int TotalSymmGroups = 0;
  1439. for (i = lower; i <= upper; i++) {
  1440. if (table->subtables[i].next != (unsigned) i) {
  1441. TotalSymmGroups++;
  1442. x = i;
  1443. do {
  1444. TotalSymm++;
  1445. gbot = x;
  1446. x = table->subtables[x].next;
  1447. } while (x != i);
  1448. #ifdef DD_DEBUG
  1449. assert(table->subtables[gbot].next == (unsigned) i);
  1450. #endif
  1451. i = gbot;
  1452. }
  1453. }
  1454. *symvars = TotalSymm;
  1455. *symgroups = TotalSymmGroups;
  1456. return;
  1457. } /* end of ddSymmSummary */