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.

1023 lines
27 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddWindow.c]
  3. PackageName [cudd]
  4. Synopsis [Functions for variable reordering by window permutation.]
  5. Description [Internal procedures included in this module:
  6. <ul>
  7. <li> cuddWindowReorder()
  8. </ul>
  9. Static procedures included in this module:
  10. <ul>
  11. <li> ddWindow2()
  12. <li> ddWindowConv2()
  13. <li> ddPermuteWindow3()
  14. <li> ddWindow3()
  15. <li> ddWindowConv3()
  16. <li> ddPermuteWindow4()
  17. <li> ddWindow4()
  18. <li> ddWindowConv4()
  19. </ul>]
  20. Author [Fabio Somenzi]
  21. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  22. All rights reserved.
  23. Redistribution and use in source and binary forms, with or without
  24. modification, are permitted provided that the following conditions
  25. are met:
  26. Redistributions of source code must retain the above copyright
  27. notice, this list of conditions and the following disclaimer.
  28. Redistributions in binary form must reproduce the above copyright
  29. notice, this list of conditions and the following disclaimer in the
  30. documentation and/or other materials provided with the distribution.
  31. Neither the name of the University of Colorado nor the names of its
  32. contributors may be used to endorse or promote products derived from
  33. this software without specific prior written permission.
  34. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  35. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  36. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  37. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  38. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  39. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  40. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  41. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  42. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  43. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  44. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  45. POSSIBILITY OF SUCH DAMAGE.]
  46. ******************************************************************************/
  47. #include "util.h"
  48. #include "cuddInt.h"
  49. /*---------------------------------------------------------------------------*/
  50. /* Constant declarations */
  51. /*---------------------------------------------------------------------------*/
  52. /*---------------------------------------------------------------------------*/
  53. /* Stucture declarations */
  54. /*---------------------------------------------------------------------------*/
  55. /*---------------------------------------------------------------------------*/
  56. /* Type declarations */
  57. /*---------------------------------------------------------------------------*/
  58. /*---------------------------------------------------------------------------*/
  59. /* Variable declarations */
  60. /*---------------------------------------------------------------------------*/
  61. #ifndef lint
  62. static char rcsid[] DD_UNUSED = "$Id: cuddWindow.c,v 1.15 2012/02/05 01:07:19 fabio Exp $";
  63. #endif
  64. #ifdef DD_STATS
  65. extern int ddTotalNumberSwapping;
  66. extern int ddTotalNISwaps;
  67. #endif
  68. /*---------------------------------------------------------------------------*/
  69. /* Macro declarations */
  70. /*---------------------------------------------------------------------------*/
  71. /**AutomaticStart*************************************************************/
  72. /*---------------------------------------------------------------------------*/
  73. /* Static function prototypes */
  74. /*---------------------------------------------------------------------------*/
  75. static int ddWindow2 (DdManager *table, int low, int high);
  76. static int ddWindowConv2 (DdManager *table, int low, int high);
  77. static int ddPermuteWindow3 (DdManager *table, int x);
  78. static int ddWindow3 (DdManager *table, int low, int high);
  79. static int ddWindowConv3 (DdManager *table, int low, int high);
  80. static int ddPermuteWindow4 (DdManager *table, int w);
  81. static int ddWindow4 (DdManager *table, int low, int high);
  82. static int ddWindowConv4 (DdManager *table, int low, int high);
  83. /**AutomaticEnd***************************************************************/
  84. /*---------------------------------------------------------------------------*/
  85. /* Definition of exported functions */
  86. /*---------------------------------------------------------------------------*/
  87. /*---------------------------------------------------------------------------*/
  88. /* Definition of internal functions */
  89. /*---------------------------------------------------------------------------*/
  90. /**Function********************************************************************
  91. Synopsis [Reorders by applying the method of the sliding window.]
  92. Description [Reorders by applying the method of the sliding window.
  93. Tries all possible permutations to the variables in a window that
  94. slides from low to high. The size of the window is determined by
  95. submethod. Assumes that no dead nodes are present. Returns 1 in
  96. case of success; 0 otherwise.]
  97. SideEffects [None]
  98. ******************************************************************************/
  99. int
  100. cuddWindowReorder(
  101. DdManager * table /* DD table */,
  102. int low /* lowest index to reorder */,
  103. int high /* highest index to reorder */,
  104. Cudd_ReorderingType submethod /* window reordering option */)
  105. {
  106. int res;
  107. #ifdef DD_DEBUG
  108. int supposedOpt;
  109. #endif
  110. switch (submethod) {
  111. case CUDD_REORDER_WINDOW2:
  112. res = ddWindow2(table,low,high);
  113. break;
  114. case CUDD_REORDER_WINDOW3:
  115. res = ddWindow3(table,low,high);
  116. break;
  117. case CUDD_REORDER_WINDOW4:
  118. res = ddWindow4(table,low,high);
  119. break;
  120. case CUDD_REORDER_WINDOW2_CONV:
  121. res = ddWindowConv2(table,low,high);
  122. break;
  123. case CUDD_REORDER_WINDOW3_CONV:
  124. res = ddWindowConv3(table,low,high);
  125. #ifdef DD_DEBUG
  126. supposedOpt = table->keys - table->isolated;
  127. res = ddWindow3(table,low,high);
  128. if (table->keys - table->isolated != (unsigned) supposedOpt) {
  129. (void) fprintf(table->err, "Convergence failed! (%d != %d)\n",
  130. table->keys - table->isolated, supposedOpt);
  131. }
  132. #endif
  133. break;
  134. case CUDD_REORDER_WINDOW4_CONV:
  135. res = ddWindowConv4(table,low,high);
  136. #ifdef DD_DEBUG
  137. supposedOpt = table->keys - table->isolated;
  138. res = ddWindow4(table,low,high);
  139. if (table->keys - table->isolated != (unsigned) supposedOpt) {
  140. (void) fprintf(table->err,"Convergence failed! (%d != %d)\n",
  141. table->keys - table->isolated, supposedOpt);
  142. }
  143. #endif
  144. break;
  145. default: return(0);
  146. }
  147. return(res);
  148. } /* end of cuddWindowReorder */
  149. /*---------------------------------------------------------------------------*/
  150. /* Definition of static functions */
  151. /*---------------------------------------------------------------------------*/
  152. /**Function********************************************************************
  153. Synopsis [Reorders by applying a sliding window of width 2.]
  154. Description [Reorders by applying a sliding window of width 2.
  155. Tries both permutations of the variables in a window
  156. that slides from low to high. Assumes that no dead nodes are
  157. present. Returns 1 in case of success; 0 otherwise.]
  158. SideEffects [None]
  159. ******************************************************************************/
  160. static int
  161. ddWindow2(
  162. DdManager * table,
  163. int low,
  164. int high)
  165. {
  166. int x;
  167. int res;
  168. int size;
  169. #ifdef DD_DEBUG
  170. assert(low >= 0 && high < table->size);
  171. #endif
  172. if (high-low < 1) return(0);
  173. res = table->keys - table->isolated;
  174. for (x = low; x < high; x++) {
  175. size = res;
  176. res = cuddSwapInPlace(table,x,x+1);
  177. if (res == 0) return(0);
  178. if (res >= size) { /* no improvement: undo permutation */
  179. res = cuddSwapInPlace(table,x,x+1);
  180. if (res == 0) return(0);
  181. }
  182. #ifdef DD_STATS
  183. if (res < size) {
  184. (void) fprintf(table->out,"-");
  185. } else {
  186. (void) fprintf(table->out,"=");
  187. }
  188. fflush(table->out);
  189. #endif
  190. }
  191. return(1);
  192. } /* end of ddWindow2 */
  193. /**Function********************************************************************
  194. Synopsis [Reorders by repeatedly applying a sliding window of width 2.]
  195. Description [Reorders by repeatedly applying a sliding window of width
  196. 2. Tries both permutations of the variables in a window
  197. that slides from low to high. Assumes that no dead nodes are
  198. present. Uses an event-driven approach to determine convergence.
  199. Returns 1 in case of success; 0 otherwise.]
  200. SideEffects [None]
  201. ******************************************************************************/
  202. static int
  203. ddWindowConv2(
  204. DdManager * table,
  205. int low,
  206. int high)
  207. {
  208. int x;
  209. int res;
  210. int nwin;
  211. int newevent;
  212. int *events;
  213. int size;
  214. #ifdef DD_DEBUG
  215. assert(low >= 0 && high < table->size);
  216. #endif
  217. if (high-low < 1) return(ddWindowConv2(table,low,high));
  218. nwin = high-low;
  219. events = ALLOC(int,nwin);
  220. if (events == NULL) {
  221. table->errorCode = CUDD_MEMORY_OUT;
  222. return(0);
  223. }
  224. for (x=0; x<nwin; x++) {
  225. events[x] = 1;
  226. }
  227. res = table->keys - table->isolated;
  228. do {
  229. newevent = 0;
  230. for (x=0; x<nwin; x++) {
  231. if (events[x]) {
  232. size = res;
  233. res = cuddSwapInPlace(table,x+low,x+low+1);
  234. if (res == 0) {
  235. FREE(events);
  236. return(0);
  237. }
  238. if (res >= size) { /* no improvement: undo permutation */
  239. res = cuddSwapInPlace(table,x+low,x+low+1);
  240. if (res == 0) {
  241. FREE(events);
  242. return(0);
  243. }
  244. }
  245. if (res < size) {
  246. if (x < nwin-1) events[x+1] = 1;
  247. if (x > 0) events[x-1] = 1;
  248. newevent = 1;
  249. }
  250. events[x] = 0;
  251. #ifdef DD_STATS
  252. if (res < size) {
  253. (void) fprintf(table->out,"-");
  254. } else {
  255. (void) fprintf(table->out,"=");
  256. }
  257. fflush(table->out);
  258. #endif
  259. }
  260. }
  261. #ifdef DD_STATS
  262. if (newevent) {
  263. (void) fprintf(table->out,"|");
  264. fflush(table->out);
  265. }
  266. #endif
  267. } while (newevent);
  268. FREE(events);
  269. return(1);
  270. } /* end of ddWindowConv3 */
  271. /**Function********************************************************************
  272. Synopsis [Tries all the permutations of the three variables between
  273. x and x+2 and retains the best.]
  274. Description [Tries all the permutations of the three variables between
  275. x and x+2 and retains the best. Assumes that no dead nodes are
  276. present. Returns the index of the best permutation (1-6) in case of
  277. success; 0 otherwise.Assumes that no dead nodes are present. Returns
  278. the index of the best permutation (1-6) in case of success; 0
  279. otherwise.]
  280. SideEffects [None]
  281. ******************************************************************************/
  282. static int
  283. ddPermuteWindow3(
  284. DdManager * table,
  285. int x)
  286. {
  287. int y,z;
  288. int size,sizeNew;
  289. int best;
  290. #ifdef DD_DEBUG
  291. assert(table->dead == 0);
  292. assert(x+2 < table->size);
  293. #endif
  294. size = table->keys - table->isolated;
  295. y = x+1; z = y+1;
  296. /* The permutation pattern is:
  297. ** (x,y)(y,z)
  298. ** repeated three times to get all 3! = 6 permutations.
  299. */
  300. #define ABC 1
  301. best = ABC;
  302. #define BAC 2
  303. sizeNew = cuddSwapInPlace(table,x,y);
  304. if (sizeNew < size) {
  305. if (sizeNew == 0) return(0);
  306. best = BAC;
  307. size = sizeNew;
  308. }
  309. #define BCA 3
  310. sizeNew = cuddSwapInPlace(table,y,z);
  311. if (sizeNew < size) {
  312. if (sizeNew == 0) return(0);
  313. best = BCA;
  314. size = sizeNew;
  315. }
  316. #define CBA 4
  317. sizeNew = cuddSwapInPlace(table,x,y);
  318. if (sizeNew < size) {
  319. if (sizeNew == 0) return(0);
  320. best = CBA;
  321. size = sizeNew;
  322. }
  323. #define CAB 5
  324. sizeNew = cuddSwapInPlace(table,y,z);
  325. if (sizeNew < size) {
  326. if (sizeNew == 0) return(0);
  327. best = CAB;
  328. size = sizeNew;
  329. }
  330. #define ACB 6
  331. sizeNew = cuddSwapInPlace(table,x,y);
  332. if (sizeNew < size) {
  333. if (sizeNew == 0) return(0);
  334. best = ACB;
  335. size = sizeNew;
  336. }
  337. /* Now take the shortest route to the best permuytation.
  338. ** The initial permutation is ACB.
  339. */
  340. switch(best) {
  341. case BCA: if (!cuddSwapInPlace(table,y,z)) return(0);
  342. case CBA: if (!cuddSwapInPlace(table,x,y)) return(0);
  343. case ABC: if (!cuddSwapInPlace(table,y,z)) return(0);
  344. case ACB: break;
  345. case BAC: if (!cuddSwapInPlace(table,y,z)) return(0);
  346. case CAB: if (!cuddSwapInPlace(table,x,y)) return(0);
  347. break;
  348. default: return(0);
  349. }
  350. #ifdef DD_DEBUG
  351. assert(table->keys - table->isolated == (unsigned) size);
  352. #endif
  353. return(best);
  354. } /* end of ddPermuteWindow3 */
  355. /**Function********************************************************************
  356. Synopsis [Reorders by applying a sliding window of width 3.]
  357. Description [Reorders by applying a sliding window of width 3.
  358. Tries all possible permutations to the variables in a
  359. window that slides from low to high. Assumes that no dead nodes are
  360. present. Returns 1 in case of success; 0 otherwise.]
  361. SideEffects [None]
  362. ******************************************************************************/
  363. static int
  364. ddWindow3(
  365. DdManager * table,
  366. int low,
  367. int high)
  368. {
  369. int x;
  370. int res;
  371. #ifdef DD_DEBUG
  372. assert(low >= 0 && high < table->size);
  373. #endif
  374. if (high-low < 2) return(ddWindow2(table,low,high));
  375. for (x = low; x+1 < high; x++) {
  376. res = ddPermuteWindow3(table,x);
  377. if (res == 0) return(0);
  378. #ifdef DD_STATS
  379. if (res == ABC) {
  380. (void) fprintf(table->out,"=");
  381. } else {
  382. (void) fprintf(table->out,"-");
  383. }
  384. fflush(table->out);
  385. #endif
  386. }
  387. return(1);
  388. } /* end of ddWindow3 */
  389. /**Function********************************************************************
  390. Synopsis [Reorders by repeatedly applying a sliding window of width 3.]
  391. Description [Reorders by repeatedly applying a sliding window of width
  392. 3. Tries all possible permutations to the variables in a
  393. window that slides from low to high. Assumes that no dead nodes are
  394. present. Uses an event-driven approach to determine convergence.
  395. Returns 1 in case of success; 0 otherwise.]
  396. SideEffects [None]
  397. ******************************************************************************/
  398. static int
  399. ddWindowConv3(
  400. DdManager * table,
  401. int low,
  402. int high)
  403. {
  404. int x;
  405. int res;
  406. int nwin;
  407. int newevent;
  408. int *events;
  409. #ifdef DD_DEBUG
  410. assert(low >= 0 && high < table->size);
  411. #endif
  412. if (high-low < 2) return(ddWindowConv2(table,low,high));
  413. nwin = high-low-1;
  414. events = ALLOC(int,nwin);
  415. if (events == NULL) {
  416. table->errorCode = CUDD_MEMORY_OUT;
  417. return(0);
  418. }
  419. for (x=0; x<nwin; x++) {
  420. events[x] = 1;
  421. }
  422. do {
  423. newevent = 0;
  424. for (x=0; x<nwin; x++) {
  425. if (events[x]) {
  426. res = ddPermuteWindow3(table,x+low);
  427. switch (res) {
  428. case ABC:
  429. break;
  430. case BAC:
  431. if (x < nwin-1) events[x+1] = 1;
  432. if (x > 1) events[x-2] = 1;
  433. newevent = 1;
  434. break;
  435. case BCA:
  436. case CBA:
  437. case CAB:
  438. if (x < nwin-2) events[x+2] = 1;
  439. if (x < nwin-1) events[x+1] = 1;
  440. if (x > 0) events[x-1] = 1;
  441. if (x > 1) events[x-2] = 1;
  442. newevent = 1;
  443. break;
  444. case ACB:
  445. if (x < nwin-2) events[x+2] = 1;
  446. if (x > 0) events[x-1] = 1;
  447. newevent = 1;
  448. break;
  449. default:
  450. FREE(events);
  451. return(0);
  452. }
  453. events[x] = 0;
  454. #ifdef DD_STATS
  455. if (res == ABC) {
  456. (void) fprintf(table->out,"=");
  457. } else {
  458. (void) fprintf(table->out,"-");
  459. }
  460. fflush(table->out);
  461. #endif
  462. }
  463. }
  464. #ifdef DD_STATS
  465. if (newevent) {
  466. (void) fprintf(table->out,"|");
  467. fflush(table->out);
  468. }
  469. #endif
  470. } while (newevent);
  471. FREE(events);
  472. return(1);
  473. } /* end of ddWindowConv3 */
  474. /**Function********************************************************************
  475. Synopsis [Tries all the permutations of the four variables between w
  476. and w+3 and retains the best.]
  477. Description [Tries all the permutations of the four variables between
  478. w and w+3 and retains the best. Assumes that no dead nodes are
  479. present. Returns the index of the best permutation (1-24) in case of
  480. success; 0 otherwise.]
  481. SideEffects [None]
  482. ******************************************************************************/
  483. static int
  484. ddPermuteWindow4(
  485. DdManager * table,
  486. int w)
  487. {
  488. int x,y,z;
  489. int size,sizeNew;
  490. int best;
  491. #ifdef DD_DEBUG
  492. assert(table->dead == 0);
  493. assert(w+3 < table->size);
  494. #endif
  495. size = table->keys - table->isolated;
  496. x = w+1; y = x+1; z = y+1;
  497. /* The permutation pattern is:
  498. * (w,x)(y,z)(w,x)(x,y)
  499. * (y,z)(w,x)(y,z)(x,y)
  500. * repeated three times to get all 4! = 24 permutations.
  501. * This gives a hamiltonian circuit of Cayley's graph.
  502. * The codes to the permutation are assigned in topological order.
  503. * The permutations at lower distance from the final permutation are
  504. * assigned lower codes. This way we can choose, between
  505. * permutations that give the same size, one that requires the minimum
  506. * number of swaps from the final permutation of the hamiltonian circuit.
  507. * There is an exception to this rule: ABCD is given Code 1, to
  508. * avoid oscillation when convergence is sought.
  509. */
  510. #define ABCD 1
  511. best = ABCD;
  512. #define BACD 7
  513. sizeNew = cuddSwapInPlace(table,w,x);
  514. if (sizeNew < size) {
  515. if (sizeNew == 0) return(0);
  516. best = BACD;
  517. size = sizeNew;
  518. }
  519. #define BADC 13
  520. sizeNew = cuddSwapInPlace(table,y,z);
  521. if (sizeNew < size) {
  522. if (sizeNew == 0) return(0);
  523. best = BADC;
  524. size = sizeNew;
  525. }
  526. #define ABDC 8
  527. sizeNew = cuddSwapInPlace(table,w,x);
  528. if (sizeNew < size || (sizeNew == size && ABDC < best)) {
  529. if (sizeNew == 0) return(0);
  530. best = ABDC;
  531. size = sizeNew;
  532. }
  533. #define ADBC 14
  534. sizeNew = cuddSwapInPlace(table,x,y);
  535. if (sizeNew < size) {
  536. if (sizeNew == 0) return(0);
  537. best = ADBC;
  538. size = sizeNew;
  539. }
  540. #define ADCB 9
  541. sizeNew = cuddSwapInPlace(table,y,z);
  542. if (sizeNew < size || (sizeNew == size && ADCB < best)) {
  543. if (sizeNew == 0) return(0);
  544. best = ADCB;
  545. size = sizeNew;
  546. }
  547. #define DACB 15
  548. sizeNew = cuddSwapInPlace(table,w,x);
  549. if (sizeNew < size) {
  550. if (sizeNew == 0) return(0);
  551. best = DACB;
  552. size = sizeNew;
  553. }
  554. #define DABC 20
  555. sizeNew = cuddSwapInPlace(table,y,z);
  556. if (sizeNew < size) {
  557. if (sizeNew == 0) return(0);
  558. best = DABC;
  559. size = sizeNew;
  560. }
  561. #define DBAC 23
  562. sizeNew = cuddSwapInPlace(table,x,y);
  563. if (sizeNew < size) {
  564. if (sizeNew == 0) return(0);
  565. best = DBAC;
  566. size = sizeNew;
  567. }
  568. #define BDAC 19
  569. sizeNew = cuddSwapInPlace(table,w,x);
  570. if (sizeNew < size || (sizeNew == size && BDAC < best)) {
  571. if (sizeNew == 0) return(0);
  572. best = BDAC;
  573. size = sizeNew;
  574. }
  575. #define BDCA 21
  576. sizeNew = cuddSwapInPlace(table,y,z);
  577. if (sizeNew < size || (sizeNew == size && BDCA < best)) {
  578. if (sizeNew == 0) return(0);
  579. best = BDCA;
  580. size = sizeNew;
  581. }
  582. #define DBCA 24
  583. sizeNew = cuddSwapInPlace(table,w,x);
  584. if (sizeNew < size) {
  585. if (sizeNew == 0) return(0);
  586. best = DBCA;
  587. size = sizeNew;
  588. }
  589. #define DCBA 22
  590. sizeNew = cuddSwapInPlace(table,x,y);
  591. if (sizeNew < size || (sizeNew == size && DCBA < best)) {
  592. if (sizeNew == 0) return(0);
  593. best = DCBA;
  594. size = sizeNew;
  595. }
  596. #define DCAB 18
  597. sizeNew = cuddSwapInPlace(table,y,z);
  598. if (sizeNew < size || (sizeNew == size && DCAB < best)) {
  599. if (sizeNew == 0) return(0);
  600. best = DCAB;
  601. size = sizeNew;
  602. }
  603. #define CDAB 12
  604. sizeNew = cuddSwapInPlace(table,w,x);
  605. if (sizeNew < size || (sizeNew == size && CDAB < best)) {
  606. if (sizeNew == 0) return(0);
  607. best = CDAB;
  608. size = sizeNew;
  609. }
  610. #define CDBA 17
  611. sizeNew = cuddSwapInPlace(table,y,z);
  612. if (sizeNew < size || (sizeNew == size && CDBA < best)) {
  613. if (sizeNew == 0) return(0);
  614. best = CDBA;
  615. size = sizeNew;
  616. }
  617. #define CBDA 11
  618. sizeNew = cuddSwapInPlace(table,x,y);
  619. if (sizeNew < size || (sizeNew == size && CBDA < best)) {
  620. if (sizeNew == 0) return(0);
  621. best = CBDA;
  622. size = sizeNew;
  623. }
  624. #define BCDA 16
  625. sizeNew = cuddSwapInPlace(table,w,x);
  626. if (sizeNew < size || (sizeNew == size && BCDA < best)) {
  627. if (sizeNew == 0) return(0);
  628. best = BCDA;
  629. size = sizeNew;
  630. }
  631. #define BCAD 10
  632. sizeNew = cuddSwapInPlace(table,y,z);
  633. if (sizeNew < size || (sizeNew == size && BCAD < best)) {
  634. if (sizeNew == 0) return(0);
  635. best = BCAD;
  636. size = sizeNew;
  637. }
  638. #define CBAD 5
  639. sizeNew = cuddSwapInPlace(table,w,x);
  640. if (sizeNew < size || (sizeNew == size && CBAD < best)) {
  641. if (sizeNew == 0) return(0);
  642. best = CBAD;
  643. size = sizeNew;
  644. }
  645. #define CABD 3
  646. sizeNew = cuddSwapInPlace(table,x,y);
  647. if (sizeNew < size || (sizeNew == size && CABD < best)) {
  648. if (sizeNew == 0) return(0);
  649. best = CABD;
  650. size = sizeNew;
  651. }
  652. #define CADB 6
  653. sizeNew = cuddSwapInPlace(table,y,z);
  654. if (sizeNew < size || (sizeNew == size && CADB < best)) {
  655. if (sizeNew == 0) return(0);
  656. best = CADB;
  657. size = sizeNew;
  658. }
  659. #define ACDB 4
  660. sizeNew = cuddSwapInPlace(table,w,x);
  661. if (sizeNew < size || (sizeNew == size && ACDB < best)) {
  662. if (sizeNew == 0) return(0);
  663. best = ACDB;
  664. size = sizeNew;
  665. }
  666. #define ACBD 2
  667. sizeNew = cuddSwapInPlace(table,y,z);
  668. if (sizeNew < size || (sizeNew == size && ACBD < best)) {
  669. if (sizeNew == 0) return(0);
  670. best = ACBD;
  671. size = sizeNew;
  672. }
  673. /* Now take the shortest route to the best permutation.
  674. ** The initial permutation is ACBD.
  675. */
  676. switch(best) {
  677. case DBCA: if (!cuddSwapInPlace(table,y,z)) return(0);
  678. case BDCA: if (!cuddSwapInPlace(table,x,y)) return(0);
  679. case CDBA: if (!cuddSwapInPlace(table,w,x)) return(0);
  680. case ADBC: if (!cuddSwapInPlace(table,y,z)) return(0);
  681. case ABDC: if (!cuddSwapInPlace(table,x,y)) return(0);
  682. case ACDB: if (!cuddSwapInPlace(table,y,z)) return(0);
  683. case ACBD: break;
  684. case DCBA: if (!cuddSwapInPlace(table,y,z)) return(0);
  685. case BCDA: if (!cuddSwapInPlace(table,x,y)) return(0);
  686. case CBDA: if (!cuddSwapInPlace(table,w,x)) return(0);
  687. if (!cuddSwapInPlace(table,x,y)) return(0);
  688. if (!cuddSwapInPlace(table,y,z)) return(0);
  689. break;
  690. case DBAC: if (!cuddSwapInPlace(table,x,y)) return(0);
  691. case DCAB: if (!cuddSwapInPlace(table,w,x)) return(0);
  692. case DACB: if (!cuddSwapInPlace(table,y,z)) return(0);
  693. case BACD: if (!cuddSwapInPlace(table,x,y)) return(0);
  694. case CABD: if (!cuddSwapInPlace(table,w,x)) return(0);
  695. break;
  696. case DABC: if (!cuddSwapInPlace(table,y,z)) return(0);
  697. case BADC: if (!cuddSwapInPlace(table,x,y)) return(0);
  698. case CADB: if (!cuddSwapInPlace(table,w,x)) return(0);
  699. if (!cuddSwapInPlace(table,y,z)) return(0);
  700. break;
  701. case BDAC: if (!cuddSwapInPlace(table,x,y)) return(0);
  702. case CDAB: if (!cuddSwapInPlace(table,w,x)) return(0);
  703. case ADCB: if (!cuddSwapInPlace(table,y,z)) return(0);
  704. case ABCD: if (!cuddSwapInPlace(table,x,y)) return(0);
  705. break;
  706. case BCAD: if (!cuddSwapInPlace(table,x,y)) return(0);
  707. case CBAD: if (!cuddSwapInPlace(table,w,x)) return(0);
  708. if (!cuddSwapInPlace(table,x,y)) return(0);
  709. break;
  710. default: return(0);
  711. }
  712. #ifdef DD_DEBUG
  713. assert(table->keys - table->isolated == (unsigned) size);
  714. #endif
  715. return(best);
  716. } /* end of ddPermuteWindow4 */
  717. /**Function********************************************************************
  718. Synopsis [Reorders by applying a sliding window of width 4.]
  719. Description [Reorders by applying a sliding window of width 4.
  720. Tries all possible permutations to the variables in a
  721. window that slides from low to high. Assumes that no dead nodes are
  722. present. Returns 1 in case of success; 0 otherwise.]
  723. SideEffects [None]
  724. ******************************************************************************/
  725. static int
  726. ddWindow4(
  727. DdManager * table,
  728. int low,
  729. int high)
  730. {
  731. int w;
  732. int res;
  733. #ifdef DD_DEBUG
  734. assert(low >= 0 && high < table->size);
  735. #endif
  736. if (high-low < 3) return(ddWindow3(table,low,high));
  737. for (w = low; w+2 < high; w++) {
  738. res = ddPermuteWindow4(table,w);
  739. if (res == 0) return(0);
  740. #ifdef DD_STATS
  741. if (res == ABCD) {
  742. (void) fprintf(table->out,"=");
  743. } else {
  744. (void) fprintf(table->out,"-");
  745. }
  746. fflush(table->out);
  747. #endif
  748. }
  749. return(1);
  750. } /* end of ddWindow4 */
  751. /**Function********************************************************************
  752. Synopsis [Reorders by repeatedly applying a sliding window of width 4.]
  753. Description [Reorders by repeatedly applying a sliding window of width
  754. 4. Tries all possible permutations to the variables in a
  755. window that slides from low to high. Assumes that no dead nodes are
  756. present. Uses an event-driven approach to determine convergence.
  757. Returns 1 in case of success; 0 otherwise.]
  758. SideEffects [None]
  759. ******************************************************************************/
  760. static int
  761. ddWindowConv4(
  762. DdManager * table,
  763. int low,
  764. int high)
  765. {
  766. int x;
  767. int res;
  768. int nwin;
  769. int newevent;
  770. int *events;
  771. #ifdef DD_DEBUG
  772. assert(low >= 0 && high < table->size);
  773. #endif
  774. if (high-low < 3) return(ddWindowConv3(table,low,high));
  775. nwin = high-low-2;
  776. events = ALLOC(int,nwin);
  777. if (events == NULL) {
  778. table->errorCode = CUDD_MEMORY_OUT;
  779. return(0);
  780. }
  781. for (x=0; x<nwin; x++) {
  782. events[x] = 1;
  783. }
  784. do {
  785. newevent = 0;
  786. for (x=0; x<nwin; x++) {
  787. if (events[x]) {
  788. res = ddPermuteWindow4(table,x+low);
  789. switch (res) {
  790. case ABCD:
  791. break;
  792. case BACD:
  793. if (x < nwin-1) events[x+1] = 1;
  794. if (x > 2) events[x-3] = 1;
  795. newevent = 1;
  796. break;
  797. case BADC:
  798. if (x < nwin-3) events[x+3] = 1;
  799. if (x < nwin-1) events[x+1] = 1;
  800. if (x > 0) events[x-1] = 1;
  801. if (x > 2) events[x-3] = 1;
  802. newevent = 1;
  803. break;
  804. case ABDC:
  805. if (x < nwin-3) events[x+3] = 1;
  806. if (x > 0) events[x-1] = 1;
  807. newevent = 1;
  808. break;
  809. case ADBC:
  810. case ADCB:
  811. case ACDB:
  812. if (x < nwin-3) events[x+3] = 1;
  813. if (x < nwin-2) events[x+2] = 1;
  814. if (x > 0) events[x-1] = 1;
  815. if (x > 1) events[x-2] = 1;
  816. newevent = 1;
  817. break;
  818. case DACB:
  819. case DABC:
  820. case DBAC:
  821. case BDAC:
  822. case BDCA:
  823. case DBCA:
  824. case DCBA:
  825. case DCAB:
  826. case CDAB:
  827. case CDBA:
  828. case CBDA:
  829. case BCDA:
  830. case CADB:
  831. if (x < nwin-3) events[x+3] = 1;
  832. if (x < nwin-2) events[x+2] = 1;
  833. if (x < nwin-1) events[x+1] = 1;
  834. if (x > 0) events[x-1] = 1;
  835. if (x > 1) events[x-2] = 1;
  836. if (x > 2) events[x-3] = 1;
  837. newevent = 1;
  838. break;
  839. case BCAD:
  840. case CBAD:
  841. case CABD:
  842. if (x < nwin-2) events[x+2] = 1;
  843. if (x < nwin-1) events[x+1] = 1;
  844. if (x > 1) events[x-2] = 1;
  845. if (x > 2) events[x-3] = 1;
  846. newevent = 1;
  847. break;
  848. case ACBD:
  849. if (x < nwin-2) events[x+2] = 1;
  850. if (x > 1) events[x-2] = 1;
  851. newevent = 1;
  852. break;
  853. default:
  854. FREE(events);
  855. return(0);
  856. }
  857. events[x] = 0;
  858. #ifdef DD_STATS
  859. if (res == ABCD) {
  860. (void) fprintf(table->out,"=");
  861. } else {
  862. (void) fprintf(table->out,"-");
  863. }
  864. fflush(table->out);
  865. #endif
  866. }
  867. }
  868. #ifdef DD_STATS
  869. if (newevent) {
  870. (void) fprintf(table->out,"|");
  871. fflush(table->out);
  872. }
  873. #endif
  874. } while (newevent);
  875. FREE(events);
  876. return(1);
  877. } /* end of ddWindowConv4 */