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.

986 lines
24 KiB

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