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.

2178 lines
57 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddGenCof.c]
  3. PackageName [cudd]
  4. Synopsis [Generalized cofactors for BDDs and ADDs.]
  5. Description [External procedures included in this module:
  6. <ul>
  7. <li> Cudd_bddConstrain()
  8. <li> Cudd_bddRestrict()
  9. <li> Cudd_bddNPAnd()
  10. <li> Cudd_addConstrain()
  11. <li> Cudd_bddConstrainDecomp()
  12. <li> Cudd_addRestrict()
  13. <li> Cudd_bddCharToVect()
  14. <li> Cudd_bddLICompaction()
  15. <li> Cudd_bddSqueeze()
  16. <li> Cudd_bddMinimize()
  17. <li> Cudd_SubsetCompress()
  18. <li> Cudd_SupersetCompress()
  19. </ul>
  20. Internal procedures included in this module:
  21. <ul>
  22. <li> cuddBddConstrainRecur()
  23. <li> cuddBddRestrictRecur()
  24. <li> cuddBddNPAndRecur()
  25. <li> cuddAddConstrainRecur()
  26. <li> cuddAddRestrictRecur()
  27. <li> cuddBddLICompaction()
  28. </ul>
  29. Static procedures included in this module:
  30. <ul>
  31. <li> cuddBddConstrainDecomp()
  32. <li> cuddBddCharToVect()
  33. <li> cuddBddLICMarkEdges()
  34. <li> cuddBddLICBuildResult()
  35. <li> MarkCacheHash()
  36. <li> MarkCacheCompare()
  37. <li> MarkCacheCleanUp()
  38. <li> cuddBddSqueeze()
  39. </ul>
  40. ]
  41. Author [Fabio Somenzi]
  42. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  43. All rights reserved.
  44. Redistribution and use in source and binary forms, with or without
  45. modification, are permitted provided that the following conditions
  46. are met:
  47. Redistributions of source code must retain the above copyright
  48. notice, this list of conditions and the following disclaimer.
  49. Redistributions in binary form must reproduce the above copyright
  50. notice, this list of conditions and the following disclaimer in the
  51. documentation and/or other materials provided with the distribution.
  52. Neither the name of the University of Colorado nor the names of its
  53. contributors may be used to endorse or promote products derived from
  54. this software without specific prior written permission.
  55. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  56. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  57. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  58. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  59. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  60. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  61. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  62. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  63. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  64. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  65. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  66. POSSIBILITY OF SUCH DAMAGE.]
  67. ******************************************************************************/
  68. #include "util.h"
  69. #include "cuddInt.h"
  70. /*---------------------------------------------------------------------------*/
  71. /* Constant declarations */
  72. /*---------------------------------------------------------------------------*/
  73. /* Codes for edge markings in Cudd_bddLICompaction. The codes are defined
  74. ** so that they can be bitwise ORed to implement the code priority scheme.
  75. */
  76. #define DD_LIC_DC 0
  77. #define DD_LIC_1 1
  78. #define DD_LIC_0 2
  79. #define DD_LIC_NL 3
  80. /*---------------------------------------------------------------------------*/
  81. /* Stucture declarations */
  82. /*---------------------------------------------------------------------------*/
  83. /*---------------------------------------------------------------------------*/
  84. /* Type declarations */
  85. /*---------------------------------------------------------------------------*/
  86. /* Key for the cache used in the edge marking phase. */
  87. typedef struct MarkCacheKey {
  88. DdNode *f;
  89. DdNode *c;
  90. } MarkCacheKey;
  91. /*---------------------------------------------------------------------------*/
  92. /* Variable declarations */
  93. /*---------------------------------------------------------------------------*/
  94. #ifndef lint
  95. static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.40 2012/02/05 01:07:18 fabio Exp $";
  96. #endif
  97. /*---------------------------------------------------------------------------*/
  98. /* Macro declarations */
  99. /*---------------------------------------------------------------------------*/
  100. #ifdef __cplusplus
  101. extern "C" {
  102. #endif
  103. /**AutomaticStart*************************************************************/
  104. /*---------------------------------------------------------------------------*/
  105. /* Static function prototypes */
  106. /*---------------------------------------------------------------------------*/
  107. static int cuddBddConstrainDecomp (DdManager *dd, DdNode *f, DdNode **decomp);
  108. static DdNode * cuddBddCharToVect (DdManager *dd, DdNode *f, DdNode *x);
  109. static int cuddBddLICMarkEdges (DdManager *dd, DdNode *f, DdNode *c, st_table *table, st_table *cache);
  110. static DdNode * cuddBddLICBuildResult (DdManager *dd, DdNode *f, st_table *cache, st_table *table);
  111. static int MarkCacheHash (char *ptr, int modulus);
  112. static int MarkCacheCompare (const char *ptr1, const char *ptr2);
  113. static enum st_retval MarkCacheCleanUp (char *key, char *value, char *arg);
  114. static DdNode * cuddBddSqueeze (DdManager *dd, DdNode *l, DdNode *u);
  115. /**AutomaticEnd***************************************************************/
  116. #ifdef __cplusplus
  117. }
  118. #endif
  119. /*---------------------------------------------------------------------------*/
  120. /* Definition of exported functions */
  121. /*---------------------------------------------------------------------------*/
  122. /**Function********************************************************************
  123. Synopsis [Computes f constrain c.]
  124. Description [Computes f constrain c (f @ c).
  125. Uses a canonical form: (f' @ c) = (f @ c)'. (Note: this is not true
  126. for c.) List of special cases:
  127. <ul>
  128. <li> f @ 0 = 0
  129. <li> f @ 1 = f
  130. <li> 0 @ c = 0
  131. <li> 1 @ c = 1
  132. <li> f @ f = 1
  133. <li> f @ f'= 0
  134. </ul>
  135. Returns a pointer to the result if successful; NULL otherwise. Note that if
  136. F=(f1,...,fn) and reordering takes place while computing F @ c, then the
  137. image restriction property (Img(F,c) = Img(F @ c)) is lost.]
  138. SideEffects [None]
  139. SeeAlso [Cudd_bddRestrict Cudd_addConstrain]
  140. ******************************************************************************/
  141. DdNode *
  142. Cudd_bddConstrain(
  143. DdManager * dd,
  144. DdNode * f,
  145. DdNode * c)
  146. {
  147. DdNode *res;
  148. do {
  149. dd->reordered = 0;
  150. res = cuddBddConstrainRecur(dd,f,c);
  151. } while (dd->reordered == 1);
  152. return(res);
  153. } /* end of Cudd_bddConstrain */
  154. /**Function********************************************************************
  155. Synopsis [BDD restrict according to Coudert and Madre's algorithm
  156. (ICCAD90).]
  157. Description [BDD restrict according to Coudert and Madre's algorithm
  158. (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.
  159. If application of restrict results in a BDD larger than the input
  160. BDD, the input BDD is returned.]
  161. SideEffects [None]
  162. SeeAlso [Cudd_bddConstrain Cudd_addRestrict]
  163. ******************************************************************************/
  164. DdNode *
  165. Cudd_bddRestrict(
  166. DdManager * dd,
  167. DdNode * f,
  168. DdNode * c)
  169. {
  170. DdNode *suppF, *suppC, *commonSupport;
  171. DdNode *cplus, *res;
  172. int retval;
  173. int sizeF, sizeRes;
  174. /* Check terminal cases here to avoid computing supports in trivial cases.
  175. ** This also allows us notto check later for the case c == 0, in which
  176. ** there is no common support. */
  177. if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd)));
  178. if (Cudd_IsConstant(f)) return(f);
  179. if (f == c) return(DD_ONE(dd));
  180. if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
  181. /* Check if supports intersect. */
  182. retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC);
  183. if (retval == 0) {
  184. return(NULL);
  185. }
  186. cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC);
  187. Cudd_IterDerefBdd(dd,suppF);
  188. if (commonSupport == DD_ONE(dd)) {
  189. Cudd_IterDerefBdd(dd,commonSupport);
  190. Cudd_IterDerefBdd(dd,suppC);
  191. return(f);
  192. }
  193. Cudd_IterDerefBdd(dd,commonSupport);
  194. /* Abstract from c the variables that do not appear in f. */
  195. cplus = Cudd_bddExistAbstract(dd, c, suppC);
  196. if (cplus == NULL) {
  197. Cudd_IterDerefBdd(dd,suppC);
  198. return(NULL);
  199. }
  200. cuddRef(cplus);
  201. Cudd_IterDerefBdd(dd,suppC);
  202. do {
  203. dd->reordered = 0;
  204. res = cuddBddRestrictRecur(dd, f, cplus);
  205. } while (dd->reordered == 1);
  206. if (res == NULL) {
  207. Cudd_IterDerefBdd(dd,cplus);
  208. return(NULL);
  209. }
  210. cuddRef(res);
  211. Cudd_IterDerefBdd(dd,cplus);
  212. /* Make restric safe by returning the smaller of the input and the
  213. ** result. */
  214. sizeF = Cudd_DagSize(f);
  215. sizeRes = Cudd_DagSize(res);
  216. if (sizeF <= sizeRes) {
  217. Cudd_IterDerefBdd(dd, res);
  218. return(f);
  219. } else {
  220. cuddDeref(res);
  221. return(res);
  222. }
  223. } /* end of Cudd_bddRestrict */
  224. /**Function********************************************************************
  225. Synopsis [Computes f non-polluting-and g.]
  226. Description [Computes f non-polluting-and g. The non-polluting AND
  227. of f and g is a hybrid of AND and Restrict. From Restrict, this
  228. operation takes the idea of existentially quantifying the top
  229. variable of the second operand if it does not appear in the first.
  230. Therefore, the variables that appear in the result also appear in f.
  231. For the rest, the function behaves like AND. Since the two operands
  232. play different roles, non-polluting AND is not commutative.
  233. Returns a pointer to the result if successful; NULL otherwise.]
  234. SideEffects [None]
  235. SeeAlso [Cudd_bddConstrain Cudd_bddRestrict]
  236. ******************************************************************************/
  237. DdNode *
  238. Cudd_bddNPAnd(
  239. DdManager * dd,
  240. DdNode * f,
  241. DdNode * g)
  242. {
  243. DdNode *res;
  244. do {
  245. dd->reordered = 0;
  246. res = cuddBddNPAndRecur(dd,f,g);
  247. } while (dd->reordered == 1);
  248. return(res);
  249. } /* end of Cudd_bddNPAnd */
  250. /**Function********************************************************************
  251. Synopsis [Computes f constrain c for ADDs.]
  252. Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1
  253. ADD. List of special cases:
  254. <ul>
  255. <li> F @ 0 = 0
  256. <li> F @ 1 = F
  257. <li> 0 @ c = 0
  258. <li> 1 @ c = 1
  259. <li> F @ F = 1
  260. </ul>
  261. Returns a pointer to the result if successful; NULL otherwise.]
  262. SideEffects [None]
  263. SeeAlso [Cudd_bddConstrain]
  264. ******************************************************************************/
  265. DdNode *
  266. Cudd_addConstrain(
  267. DdManager * dd,
  268. DdNode * f,
  269. DdNode * c)
  270. {
  271. DdNode *res;
  272. do {
  273. dd->reordered = 0;
  274. res = cuddAddConstrainRecur(dd,f,c);
  275. } while (dd->reordered == 1);
  276. return(res);
  277. } /* end of Cudd_addConstrain */
  278. /**Function********************************************************************
  279. Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.]
  280. Description [BDD conjunctive decomposition as in McMillan's CAV96
  281. paper. The decomposition is canonical only for a given variable
  282. order. If canonicity is required, variable ordering must be disabled
  283. after the decomposition has been computed. Returns an array with one
  284. entry for each BDD variable in the manager if successful; otherwise
  285. NULL. The components of the solution have their reference counts
  286. already incremented (unlike the results of most other functions in
  287. the package).]
  288. SideEffects [None]
  289. SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract]
  290. ******************************************************************************/
  291. DdNode **
  292. Cudd_bddConstrainDecomp(
  293. DdManager * dd,
  294. DdNode * f)
  295. {
  296. DdNode **decomp;
  297. int res;
  298. int i;
  299. /* Create an initialize decomposition array. */
  300. decomp = ALLOC(DdNode *,dd->size);
  301. if (decomp == NULL) {
  302. dd->errorCode = CUDD_MEMORY_OUT;
  303. return(NULL);
  304. }
  305. for (i = 0; i < dd->size; i++) {
  306. decomp[i] = NULL;
  307. }
  308. do {
  309. dd->reordered = 0;
  310. /* Clean up the decomposition array in case reordering took place. */
  311. for (i = 0; i < dd->size; i++) {
  312. if (decomp[i] != NULL) {
  313. Cudd_IterDerefBdd(dd, decomp[i]);
  314. decomp[i] = NULL;
  315. }
  316. }
  317. res = cuddBddConstrainDecomp(dd,f,decomp);
  318. } while (dd->reordered == 1);
  319. if (res == 0) {
  320. FREE(decomp);
  321. return(NULL);
  322. }
  323. /* Missing components are constant ones. */
  324. for (i = 0; i < dd->size; i++) {
  325. if (decomp[i] == NULL) {
  326. decomp[i] = DD_ONE(dd);
  327. cuddRef(decomp[i]);
  328. }
  329. }
  330. return(decomp);
  331. } /* end of Cudd_bddConstrainDecomp */
  332. /**Function********************************************************************
  333. Synopsis [ADD restrict according to Coudert and Madre's algorithm
  334. (ICCAD90).]
  335. Description [ADD restrict according to Coudert and Madre's algorithm
  336. (ICCAD90). Returns the restricted ADD if successful; otherwise NULL.
  337. If application of restrict results in an ADD larger than the input
  338. ADD, the input ADD is returned.]
  339. SideEffects [None]
  340. SeeAlso [Cudd_addConstrain Cudd_bddRestrict]
  341. ******************************************************************************/
  342. DdNode *
  343. Cudd_addRestrict(
  344. DdManager * dd,
  345. DdNode * f,
  346. DdNode * c)
  347. {
  348. DdNode *supp_f, *supp_c;
  349. DdNode *res, *commonSupport;
  350. int intersection;
  351. int sizeF, sizeRes;
  352. /* Check if supports intersect. */
  353. supp_f = Cudd_Support(dd, f);
  354. if (supp_f == NULL) {
  355. return(NULL);
  356. }
  357. cuddRef(supp_f);
  358. supp_c = Cudd_Support(dd, c);
  359. if (supp_c == NULL) {
  360. Cudd_RecursiveDeref(dd,supp_f);
  361. return(NULL);
  362. }
  363. cuddRef(supp_c);
  364. commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c);
  365. if (commonSupport == NULL) {
  366. Cudd_RecursiveDeref(dd,supp_f);
  367. Cudd_RecursiveDeref(dd,supp_c);
  368. return(NULL);
  369. }
  370. cuddRef(commonSupport);
  371. Cudd_RecursiveDeref(dd,supp_f);
  372. Cudd_RecursiveDeref(dd,supp_c);
  373. intersection = commonSupport != DD_ONE(dd);
  374. Cudd_RecursiveDeref(dd,commonSupport);
  375. if (intersection) {
  376. do {
  377. dd->reordered = 0;
  378. res = cuddAddRestrictRecur(dd, f, c);
  379. } while (dd->reordered == 1);
  380. sizeF = Cudd_DagSize(f);
  381. sizeRes = Cudd_DagSize(res);
  382. if (sizeF <= sizeRes) {
  383. cuddRef(res);
  384. Cudd_RecursiveDeref(dd, res);
  385. return(f);
  386. } else {
  387. return(res);
  388. }
  389. } else {
  390. return(f);
  391. }
  392. } /* end of Cudd_addRestrict */
  393. /**Function********************************************************************
  394. Synopsis [Computes a vector whose image equals a non-zero function.]
  395. Description [Computes a vector of BDDs whose image equals a non-zero
  396. function.
  397. The result depends on the variable order. The i-th component of the vector
  398. depends only on the first i variables in the order. Each BDD in the vector
  399. is not larger than the BDD of the given characteristic function. This
  400. function is based on the description of char-to-vect in "Verification of
  401. Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C.
  402. Berthet and J. C. Madre.
  403. Returns a pointer to an array containing the result if successful; NULL
  404. otherwise. The size of the array equals the number of variables in the
  405. manager. The components of the solution have their reference counts
  406. already incremented (unlike the results of most other functions in
  407. the package).]
  408. SideEffects [None]
  409. SeeAlso [Cudd_bddConstrain]
  410. ******************************************************************************/
  411. DdNode **
  412. Cudd_bddCharToVect(
  413. DdManager * dd,
  414. DdNode * f)
  415. {
  416. int i, j;
  417. DdNode **vect;
  418. DdNode *res = NULL;
  419. if (f == Cudd_Not(DD_ONE(dd))) return(NULL);
  420. vect = ALLOC(DdNode *, dd->size);
  421. if (vect == NULL) {
  422. dd->errorCode = CUDD_MEMORY_OUT;
  423. return(NULL);
  424. }
  425. do {
  426. dd->reordered = 0;
  427. for (i = 0; i < dd->size; i++) {
  428. res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]);
  429. if (res == NULL) {
  430. /* Clean up the vector array in case reordering took place. */
  431. for (j = 0; j < i; j++) {
  432. Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]);
  433. }
  434. break;
  435. }
  436. cuddRef(res);
  437. vect[dd->invperm[i]] = res;
  438. }
  439. } while (dd->reordered == 1);
  440. if (res == NULL) {
  441. FREE(vect);
  442. return(NULL);
  443. }
  444. return(vect);
  445. } /* end of Cudd_bddCharToVect */
  446. /**Function********************************************************************
  447. Synopsis [Performs safe minimization of a BDD.]
  448. Description [Performs safe minimization of a BDD. Given the BDD
  449. <code>f</code> of a function to be minimized and a BDD
  450. <code>c</code> representing the care set, Cudd_bddLICompaction
  451. produces the BDD of a function that agrees with <code>f</code>
  452. wherever <code>c</code> is 1. Safe minimization means that the size
  453. of the result is guaranteed not to exceed the size of
  454. <code>f</code>. This function is based on the DAC97 paper by Hong et
  455. al.. Returns a pointer to the result if successful; NULL
  456. otherwise.]
  457. SideEffects [None]
  458. SeeAlso [Cudd_bddRestrict]
  459. ******************************************************************************/
  460. DdNode *
  461. Cudd_bddLICompaction(
  462. DdManager * dd /* manager */,
  463. DdNode * f /* function to be minimized */,
  464. DdNode * c /* constraint (care set) */)
  465. {
  466. DdNode *res;
  467. do {
  468. dd->reordered = 0;
  469. res = cuddBddLICompaction(dd,f,c);
  470. } while (dd->reordered == 1);
  471. return(res);
  472. } /* end of Cudd_bddLICompaction */
  473. /**Function********************************************************************
  474. Synopsis [Finds a small BDD in a function interval.]
  475. Description [Finds a small BDD in a function interval. Given BDDs
  476. <code>l</code> and <code>u</code>, representing the lower bound and
  477. upper bound of a function interval, Cudd_bddSqueeze produces the BDD
  478. of a function within the interval with a small BDD. Returns a
  479. pointer to the result if successful; NULL otherwise.]
  480. SideEffects [None]
  481. SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction]
  482. ******************************************************************************/
  483. DdNode *
  484. Cudd_bddSqueeze(
  485. DdManager * dd /* manager */,
  486. DdNode * l /* lower bound */,
  487. DdNode * u /* upper bound */)
  488. {
  489. DdNode *res;
  490. int sizeRes, sizeL, sizeU;
  491. do {
  492. dd->reordered = 0;
  493. res = cuddBddSqueeze(dd,l,u);
  494. } while (dd->reordered == 1);
  495. if (res == NULL) return(NULL);
  496. /* We now compare the result with the bounds and return the smallest.
  497. ** We first compare to u, so that in case l == 0 and u == 1, we return
  498. ** 0 as in other minimization algorithms. */
  499. sizeRes = Cudd_DagSize(res);
  500. sizeU = Cudd_DagSize(u);
  501. if (sizeU <= sizeRes) {
  502. cuddRef(res);
  503. Cudd_IterDerefBdd(dd,res);
  504. res = u;
  505. sizeRes = sizeU;
  506. }
  507. sizeL = Cudd_DagSize(l);
  508. if (sizeL <= sizeRes) {
  509. cuddRef(res);
  510. Cudd_IterDerefBdd(dd,res);
  511. res = l;
  512. sizeRes = sizeL;
  513. }
  514. return(res);
  515. } /* end of Cudd_bddSqueeze */
  516. /**Function********************************************************************
  517. Synopsis [Finds a small BDD that agrees with <code>f</code> over
  518. <code>c</code>.]
  519. Description [Finds a small BDD that agrees with <code>f</code> over
  520. <code>c</code>. Returns a pointer to the result if successful; NULL
  521. otherwise.]
  522. SideEffects [None]
  523. SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze]
  524. ******************************************************************************/
  525. DdNode *
  526. Cudd_bddMinimize(
  527. DdManager * dd,
  528. DdNode * f,
  529. DdNode * c)
  530. {
  531. DdNode *cplus, *res;
  532. if (c == Cudd_Not(DD_ONE(dd))) return(c);
  533. if (Cudd_IsConstant(f)) return(f);
  534. if (f == c) return(DD_ONE(dd));
  535. if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
  536. cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0);
  537. if (cplus == NULL) return(NULL);
  538. cuddRef(cplus);
  539. res = Cudd_bddLICompaction(dd,f,cplus);
  540. if (res == NULL) {
  541. Cudd_IterDerefBdd(dd,cplus);
  542. return(NULL);
  543. }
  544. cuddRef(res);
  545. Cudd_IterDerefBdd(dd,cplus);
  546. cuddDeref(res);
  547. return(res);
  548. } /* end of Cudd_bddMinimize */
  549. /**Function********************************************************************
  550. Synopsis [Find a dense subset of BDD <code>f</code>.]
  551. Description [Finds a dense subset of BDD <code>f</code>. Density is
  552. the ratio of number of minterms to number of nodes. Uses several
  553. techniques in series. It is more expensive than other subsetting
  554. procedures, but often produces better results. See
  555. Cudd_SubsetShortPaths for a description of the threshold and nvars
  556. parameters. Returns a pointer to the result if successful; NULL
  557. otherwise.]
  558. SideEffects [None]
  559. SeeAlso [Cudd_RemapUnderApprox Cudd_SubsetShortPaths
  560. Cudd_SubsetHeavyBranch Cudd_bddSqueeze]
  561. ******************************************************************************/
  562. DdNode *
  563. Cudd_SubsetCompress(
  564. DdManager * dd /* manager */,
  565. DdNode * f /* BDD whose subset is sought */,
  566. int nvars /* number of variables in the support of f */,
  567. int threshold /* maximum number of nodes in the subset */)
  568. {
  569. DdNode *res, *tmp1, *tmp2;
  570. tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0);
  571. if (tmp1 == NULL) return(NULL);
  572. cuddRef(tmp1);
  573. tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,0.95);
  574. if (tmp2 == NULL) {
  575. Cudd_IterDerefBdd(dd,tmp1);
  576. return(NULL);
  577. }
  578. cuddRef(tmp2);
  579. Cudd_IterDerefBdd(dd,tmp1);
  580. res = Cudd_bddSqueeze(dd,tmp2,f);
  581. if (res == NULL) {
  582. Cudd_IterDerefBdd(dd,tmp2);
  583. return(NULL);
  584. }
  585. cuddRef(res);
  586. Cudd_IterDerefBdd(dd,tmp2);
  587. cuddDeref(res);
  588. return(res);
  589. } /* end of Cudd_SubsetCompress */
  590. /**Function********************************************************************
  591. Synopsis [Find a dense superset of BDD <code>f</code>.]
  592. Description [Finds a dense superset of BDD <code>f</code>. Density is
  593. the ratio of number of minterms to number of nodes. Uses several
  594. techniques in series. It is more expensive than other supersetting
  595. procedures, but often produces better results. See
  596. Cudd_SupersetShortPaths for a description of the threshold and nvars
  597. parameters. Returns a pointer to the result if successful; NULL
  598. otherwise.]
  599. SideEffects [None]
  600. SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths
  601. Cudd_SupersetHeavyBranch Cudd_bddSqueeze]
  602. ******************************************************************************/
  603. DdNode *
  604. Cudd_SupersetCompress(
  605. DdManager * dd /* manager */,
  606. DdNode * f /* BDD whose superset is sought */,
  607. int nvars /* number of variables in the support of f */,
  608. int threshold /* maximum number of nodes in the superset */)
  609. {
  610. DdNode *subset;
  611. subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold);
  612. return(Cudd_NotCond(subset, (subset != NULL)));
  613. } /* end of Cudd_SupersetCompress */
  614. /*---------------------------------------------------------------------------*/
  615. /* Definition of internal functions */
  616. /*---------------------------------------------------------------------------*/
  617. /**Function********************************************************************
  618. Synopsis [Performs the recursive step of Cudd_bddConstrain.]
  619. Description [Performs the recursive step of Cudd_bddConstrain.
  620. Returns a pointer to the result if successful; NULL otherwise.]
  621. SideEffects [None]
  622. SeeAlso [Cudd_bddConstrain]
  623. ******************************************************************************/
  624. DdNode *
  625. cuddBddConstrainRecur(
  626. DdManager * dd,
  627. DdNode * f,
  628. DdNode * c)
  629. {
  630. DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
  631. DdNode *one, *zero;
  632. unsigned int topf, topc;
  633. int index;
  634. int comple = 0;
  635. statLine(dd);
  636. one = DD_ONE(dd);
  637. zero = Cudd_Not(one);
  638. /* Trivial cases. */
  639. if (c == one) return(f);
  640. if (c == zero) return(zero);
  641. if (Cudd_IsConstant(f)) return(f);
  642. if (f == c) return(one);
  643. if (f == Cudd_Not(c)) return(zero);
  644. /* Make canonical to increase the utilization of the cache. */
  645. if (Cudd_IsComplement(f)) {
  646. f = Cudd_Not(f);
  647. comple = 1;
  648. }
  649. /* Now f is a regular pointer to a non-constant node; c is also
  650. ** non-constant, but may be complemented.
  651. */
  652. /* Check the cache. */
  653. r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c);
  654. if (r != NULL) {
  655. return(Cudd_NotCond(r,comple));
  656. }
  657. /* Recursive step. */
  658. topf = dd->perm[f->index];
  659. topc = dd->perm[Cudd_Regular(c)->index];
  660. if (topf <= topc) {
  661. index = f->index;
  662. Fv = cuddT(f); Fnv = cuddE(f);
  663. } else {
  664. index = Cudd_Regular(c)->index;
  665. Fv = Fnv = f;
  666. }
  667. if (topc <= topf) {
  668. Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
  669. if (Cudd_IsComplement(c)) {
  670. Cv = Cudd_Not(Cv);
  671. Cnv = Cudd_Not(Cnv);
  672. }
  673. } else {
  674. Cv = Cnv = c;
  675. }
  676. if (!Cudd_IsConstant(Cv)) {
  677. t = cuddBddConstrainRecur(dd, Fv, Cv);
  678. if (t == NULL)
  679. return(NULL);
  680. } else if (Cv == one) {
  681. t = Fv;
  682. } else { /* Cv == zero: return Fnv @ Cnv */
  683. if (Cnv == one) {
  684. r = Fnv;
  685. } else {
  686. r = cuddBddConstrainRecur(dd, Fnv, Cnv);
  687. if (r == NULL)
  688. return(NULL);
  689. }
  690. return(Cudd_NotCond(r,comple));
  691. }
  692. cuddRef(t);
  693. if (!Cudd_IsConstant(Cnv)) {
  694. e = cuddBddConstrainRecur(dd, Fnv, Cnv);
  695. if (e == NULL) {
  696. Cudd_IterDerefBdd(dd, t);
  697. return(NULL);
  698. }
  699. } else if (Cnv == one) {
  700. e = Fnv;
  701. } else { /* Cnv == zero: return Fv @ Cv previously computed */
  702. cuddDeref(t);
  703. return(Cudd_NotCond(t,comple));
  704. }
  705. cuddRef(e);
  706. if (Cudd_IsComplement(t)) {
  707. t = Cudd_Not(t);
  708. e = Cudd_Not(e);
  709. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  710. if (r == NULL) {
  711. Cudd_IterDerefBdd(dd, e);
  712. Cudd_IterDerefBdd(dd, t);
  713. return(NULL);
  714. }
  715. r = Cudd_Not(r);
  716. } else {
  717. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  718. if (r == NULL) {
  719. Cudd_IterDerefBdd(dd, e);
  720. Cudd_IterDerefBdd(dd, t);
  721. return(NULL);
  722. }
  723. }
  724. cuddDeref(t);
  725. cuddDeref(e);
  726. cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r);
  727. return(Cudd_NotCond(r,comple));
  728. } /* end of cuddBddConstrainRecur */
  729. /**Function********************************************************************
  730. Synopsis [Performs the recursive step of Cudd_bddRestrict.]
  731. Description [Performs the recursive step of Cudd_bddRestrict.
  732. Returns the restricted BDD if successful; otherwise NULL.]
  733. SideEffects [None]
  734. SeeAlso [Cudd_bddRestrict]
  735. ******************************************************************************/
  736. DdNode *
  737. cuddBddRestrictRecur(
  738. DdManager * dd,
  739. DdNode * f,
  740. DdNode * c)
  741. {
  742. DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
  743. unsigned int topf, topc;
  744. int index;
  745. int comple = 0;
  746. statLine(dd);
  747. one = DD_ONE(dd);
  748. zero = Cudd_Not(one);
  749. /* Trivial cases */
  750. if (c == one) return(f);
  751. if (c == zero) return(zero);
  752. if (Cudd_IsConstant(f)) return(f);
  753. if (f == c) return(one);
  754. if (f == Cudd_Not(c)) return(zero);
  755. /* Make canonical to increase the utilization of the cache. */
  756. if (Cudd_IsComplement(f)) {
  757. f = Cudd_Not(f);
  758. comple = 1;
  759. }
  760. /* Now f is a regular pointer to a non-constant node; c is also
  761. ** non-constant, but may be complemented.
  762. */
  763. /* Check the cache. */
  764. r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c);
  765. if (r != NULL) {
  766. return(Cudd_NotCond(r,comple));
  767. }
  768. topf = dd->perm[f->index];
  769. topc = dd->perm[Cudd_Regular(c)->index];
  770. if (topc < topf) { /* abstract top variable from c */
  771. DdNode *d, *s1, *s2;
  772. /* Find complements of cofactors of c. */
  773. if (Cudd_IsComplement(c)) {
  774. s1 = cuddT(Cudd_Regular(c));
  775. s2 = cuddE(Cudd_Regular(c));
  776. } else {
  777. s1 = Cudd_Not(cuddT(c));
  778. s2 = Cudd_Not(cuddE(c));
  779. }
  780. /* Take the OR by applying DeMorgan. */
  781. d = cuddBddAndRecur(dd, s1, s2);
  782. if (d == NULL) return(NULL);
  783. d = Cudd_Not(d);
  784. cuddRef(d);
  785. r = cuddBddRestrictRecur(dd, f, d);
  786. if (r == NULL) {
  787. Cudd_IterDerefBdd(dd, d);
  788. return(NULL);
  789. }
  790. cuddRef(r);
  791. Cudd_IterDerefBdd(dd, d);
  792. cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
  793. cuddDeref(r);
  794. return(Cudd_NotCond(r,comple));
  795. }
  796. /* Recursive step. Here topf <= topc. */
  797. index = f->index;
  798. Fv = cuddT(f); Fnv = cuddE(f);
  799. if (topc == topf) {
  800. Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
  801. if (Cudd_IsComplement(c)) {
  802. Cv = Cudd_Not(Cv);
  803. Cnv = Cudd_Not(Cnv);
  804. }
  805. } else {
  806. Cv = Cnv = c;
  807. }
  808. if (!Cudd_IsConstant(Cv)) {
  809. t = cuddBddRestrictRecur(dd, Fv, Cv);
  810. if (t == NULL) return(NULL);
  811. } else if (Cv == one) {
  812. t = Fv;
  813. } else { /* Cv == zero: return(Fnv @ Cnv) */
  814. if (Cnv == one) {
  815. r = Fnv;
  816. } else {
  817. r = cuddBddRestrictRecur(dd, Fnv, Cnv);
  818. if (r == NULL) return(NULL);
  819. }
  820. return(Cudd_NotCond(r,comple));
  821. }
  822. cuddRef(t);
  823. if (!Cudd_IsConstant(Cnv)) {
  824. e = cuddBddRestrictRecur(dd, Fnv, Cnv);
  825. if (e == NULL) {
  826. Cudd_IterDerefBdd(dd, t);
  827. return(NULL);
  828. }
  829. } else if (Cnv == one) {
  830. e = Fnv;
  831. } else { /* Cnv == zero: return (Fv @ Cv) previously computed */
  832. cuddDeref(t);
  833. return(Cudd_NotCond(t,comple));
  834. }
  835. cuddRef(e);
  836. if (Cudd_IsComplement(t)) {
  837. t = Cudd_Not(t);
  838. e = Cudd_Not(e);
  839. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  840. if (r == NULL) {
  841. Cudd_IterDerefBdd(dd, e);
  842. Cudd_IterDerefBdd(dd, t);
  843. return(NULL);
  844. }
  845. r = Cudd_Not(r);
  846. } else {
  847. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  848. if (r == NULL) {
  849. Cudd_IterDerefBdd(dd, e);
  850. Cudd_IterDerefBdd(dd, t);
  851. return(NULL);
  852. }
  853. }
  854. cuddDeref(t);
  855. cuddDeref(e);
  856. cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
  857. return(Cudd_NotCond(r,comple));
  858. } /* end of cuddBddRestrictRecur */
  859. /**Function********************************************************************
  860. Synopsis [Implements the recursive step of Cudd_bddAnd.]
  861. Description [Implements the recursive step of Cudd_bddNPAnd.
  862. Returns a pointer to the result is successful; NULL otherwise.]
  863. SideEffects [None]
  864. SeeAlso [Cudd_bddNPAnd]
  865. ******************************************************************************/
  866. DdNode *
  867. cuddBddNPAndRecur(
  868. DdManager * manager,
  869. DdNode * f,
  870. DdNode * g)
  871. {
  872. DdNode *F, *ft, *fe, *G, *gt, *ge;
  873. DdNode *one, *r, *t, *e;
  874. unsigned int topf, topg, index;
  875. statLine(manager);
  876. one = DD_ONE(manager);
  877. /* Terminal cases. */
  878. F = Cudd_Regular(f);
  879. G = Cudd_Regular(g);
  880. if (F == G) {
  881. if (f == g) return(one);
  882. else return(Cudd_Not(one));
  883. }
  884. if (G == one) {
  885. if (g == one) return(f);
  886. else return(g);
  887. }
  888. if (F == one) {
  889. return(f);
  890. }
  891. /* At this point f and g are not constant. */
  892. /* Check cache. */
  893. if (F->ref != 1 || G->ref != 1) {
  894. r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g);
  895. if (r != NULL) return(r);
  896. }
  897. /* Here we can skip the use of cuddI, because the operands are known
  898. ** to be non-constant.
  899. */
  900. topf = manager->perm[F->index];
  901. topg = manager->perm[G->index];
  902. if (topg < topf) { /* abstract top variable from g */
  903. DdNode *d;
  904. /* Find complements of cofactors of g. */
  905. if (Cudd_IsComplement(g)) {
  906. gt = cuddT(G);
  907. ge = cuddE(G);
  908. } else {
  909. gt = Cudd_Not(cuddT(g));
  910. ge = Cudd_Not(cuddE(g));
  911. }
  912. /* Take the OR by applying DeMorgan. */
  913. d = cuddBddAndRecur(manager, gt, ge);
  914. if (d == NULL) return(NULL);
  915. d = Cudd_Not(d);
  916. cuddRef(d);
  917. r = cuddBddNPAndRecur(manager, f, d);
  918. if (r == NULL) {
  919. Cudd_IterDerefBdd(manager, d);
  920. return(NULL);
  921. }
  922. cuddRef(r);
  923. Cudd_IterDerefBdd(manager, d);
  924. cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
  925. cuddDeref(r);
  926. return(r);
  927. }
  928. /* Compute cofactors. */
  929. index = F->index;
  930. ft = cuddT(F);
  931. fe = cuddE(F);
  932. if (Cudd_IsComplement(f)) {
  933. ft = Cudd_Not(ft);
  934. fe = Cudd_Not(fe);
  935. }
  936. if (topg == topf) {
  937. gt = cuddT(G);
  938. ge = cuddE(G);
  939. if (Cudd_IsComplement(g)) {
  940. gt = Cudd_Not(gt);
  941. ge = Cudd_Not(ge);
  942. }
  943. } else {
  944. gt = ge = g;
  945. }
  946. t = cuddBddAndRecur(manager, ft, gt);
  947. if (t == NULL) return(NULL);
  948. cuddRef(t);
  949. e = cuddBddAndRecur(manager, fe, ge);
  950. if (e == NULL) {
  951. Cudd_IterDerefBdd(manager, t);
  952. return(NULL);
  953. }
  954. cuddRef(e);
  955. if (t == e) {
  956. r = t;
  957. } else {
  958. if (Cudd_IsComplement(t)) {
  959. r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
  960. if (r == NULL) {
  961. Cudd_IterDerefBdd(manager, t);
  962. Cudd_IterDerefBdd(manager, e);
  963. return(NULL);
  964. }
  965. r = Cudd_Not(r);
  966. } else {
  967. r = cuddUniqueInter(manager,(int)index,t,e);
  968. if (r == NULL) {
  969. Cudd_IterDerefBdd(manager, t);
  970. Cudd_IterDerefBdd(manager, e);
  971. return(NULL);
  972. }
  973. }
  974. }
  975. cuddDeref(e);
  976. cuddDeref(t);
  977. if (F->ref != 1 || G->ref != 1)
  978. cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
  979. return(r);
  980. } /* end of cuddBddNPAndRecur */
  981. /**Function********************************************************************
  982. Synopsis [Performs the recursive step of Cudd_addConstrain.]
  983. Description [Performs the recursive step of Cudd_addConstrain.
  984. Returns a pointer to the result if successful; NULL otherwise.]
  985. SideEffects [None]
  986. SeeAlso [Cudd_addConstrain]
  987. ******************************************************************************/
  988. DdNode *
  989. cuddAddConstrainRecur(
  990. DdManager * dd,
  991. DdNode * f,
  992. DdNode * c)
  993. {
  994. DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
  995. DdNode *one, *zero;
  996. unsigned int topf, topc;
  997. int index;
  998. statLine(dd);
  999. one = DD_ONE(dd);
  1000. zero = DD_ZERO(dd);
  1001. /* Trivial cases. */
  1002. if (c == one) return(f);
  1003. if (c == zero) return(zero);
  1004. if (Cudd_IsConstant(f)) return(f);
  1005. if (f == c) return(one);
  1006. /* Now f and c are non-constant. */
  1007. /* Check the cache. */
  1008. r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c);
  1009. if (r != NULL) {
  1010. return(r);
  1011. }
  1012. /* Recursive step. */
  1013. topf = dd->perm[f->index];
  1014. topc = dd->perm[c->index];
  1015. if (topf <= topc) {
  1016. index = f->index;
  1017. Fv = cuddT(f); Fnv = cuddE(f);
  1018. } else {
  1019. index = c->index;
  1020. Fv = Fnv = f;
  1021. }
  1022. if (topc <= topf) {
  1023. Cv = cuddT(c); Cnv = cuddE(c);
  1024. } else {
  1025. Cv = Cnv = c;
  1026. }
  1027. if (!Cudd_IsConstant(Cv)) {
  1028. t = cuddAddConstrainRecur(dd, Fv, Cv);
  1029. if (t == NULL)
  1030. return(NULL);
  1031. } else if (Cv == one) {
  1032. t = Fv;
  1033. } else { /* Cv == zero: return Fnv @ Cnv */
  1034. if (Cnv == one) {
  1035. r = Fnv;
  1036. } else {
  1037. r = cuddAddConstrainRecur(dd, Fnv, Cnv);
  1038. if (r == NULL)
  1039. return(NULL);
  1040. }
  1041. return(r);
  1042. }
  1043. cuddRef(t);
  1044. if (!Cudd_IsConstant(Cnv)) {
  1045. e = cuddAddConstrainRecur(dd, Fnv, Cnv);
  1046. if (e == NULL) {
  1047. Cudd_RecursiveDeref(dd, t);
  1048. return(NULL);
  1049. }
  1050. } else if (Cnv == one) {
  1051. e = Fnv;
  1052. } else { /* Cnv == zero: return Fv @ Cv previously computed */
  1053. cuddDeref(t);
  1054. return(t);
  1055. }
  1056. cuddRef(e);
  1057. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  1058. if (r == NULL) {
  1059. Cudd_RecursiveDeref(dd, e);
  1060. Cudd_RecursiveDeref(dd, t);
  1061. return(NULL);
  1062. }
  1063. cuddDeref(t);
  1064. cuddDeref(e);
  1065. cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r);
  1066. return(r);
  1067. } /* end of cuddAddConstrainRecur */
  1068. /**Function********************************************************************
  1069. Synopsis [Performs the recursive step of Cudd_addRestrict.]
  1070. Description [Performs the recursive step of Cudd_addRestrict.
  1071. Returns the restricted ADD if successful; otherwise NULL.]
  1072. SideEffects [None]
  1073. SeeAlso [Cudd_addRestrict]
  1074. ******************************************************************************/
  1075. DdNode *
  1076. cuddAddRestrictRecur(
  1077. DdManager * dd,
  1078. DdNode * f,
  1079. DdNode * c)
  1080. {
  1081. DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
  1082. unsigned int topf, topc;
  1083. int index;
  1084. statLine(dd);
  1085. one = DD_ONE(dd);
  1086. zero = DD_ZERO(dd);
  1087. /* Trivial cases */
  1088. if (c == one) return(f);
  1089. if (c == zero) return(zero);
  1090. if (Cudd_IsConstant(f)) return(f);
  1091. if (f == c) return(one);
  1092. /* Now f and c are non-constant. */
  1093. /* Check the cache. */
  1094. r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c);
  1095. if (r != NULL) {
  1096. return(r);
  1097. }
  1098. topf = dd->perm[f->index];
  1099. topc = dd->perm[c->index];
  1100. if (topc < topf) { /* abstract top variable from c */
  1101. DdNode *d, *s1, *s2;
  1102. /* Find cofactors of c. */
  1103. s1 = cuddT(c);
  1104. s2 = cuddE(c);
  1105. /* Take the OR by applying DeMorgan. */
  1106. d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2);
  1107. if (d == NULL) return(NULL);
  1108. cuddRef(d);
  1109. r = cuddAddRestrictRecur(dd, f, d);
  1110. if (r == NULL) {
  1111. Cudd_RecursiveDeref(dd, d);
  1112. return(NULL);
  1113. }
  1114. cuddRef(r);
  1115. Cudd_RecursiveDeref(dd, d);
  1116. cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
  1117. cuddDeref(r);
  1118. return(r);
  1119. }
  1120. /* Recursive step. Here topf <= topc. */
  1121. index = f->index;
  1122. Fv = cuddT(f); Fnv = cuddE(f);
  1123. if (topc == topf) {
  1124. Cv = cuddT(c); Cnv = cuddE(c);
  1125. } else {
  1126. Cv = Cnv = c;
  1127. }
  1128. if (!Cudd_IsConstant(Cv)) {
  1129. t = cuddAddRestrictRecur(dd, Fv, Cv);
  1130. if (t == NULL) return(NULL);
  1131. } else if (Cv == one) {
  1132. t = Fv;
  1133. } else { /* Cv == zero: return(Fnv @ Cnv) */
  1134. if (Cnv == one) {
  1135. r = Fnv;
  1136. } else {
  1137. r = cuddAddRestrictRecur(dd, Fnv, Cnv);
  1138. if (r == NULL) return(NULL);
  1139. }
  1140. return(r);
  1141. }
  1142. cuddRef(t);
  1143. if (!Cudd_IsConstant(Cnv)) {
  1144. e = cuddAddRestrictRecur(dd, Fnv, Cnv);
  1145. if (e == NULL) {
  1146. Cudd_RecursiveDeref(dd, t);
  1147. return(NULL);
  1148. }
  1149. } else if (Cnv == one) {
  1150. e = Fnv;
  1151. } else { /* Cnv == zero: return (Fv @ Cv) previously computed */
  1152. cuddDeref(t);
  1153. return(t);
  1154. }
  1155. cuddRef(e);
  1156. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  1157. if (r == NULL) {
  1158. Cudd_RecursiveDeref(dd, e);
  1159. Cudd_RecursiveDeref(dd, t);
  1160. return(NULL);
  1161. }
  1162. cuddDeref(t);
  1163. cuddDeref(e);
  1164. cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
  1165. return(r);
  1166. } /* end of cuddAddRestrictRecur */
  1167. /**Function********************************************************************
  1168. Synopsis [Performs safe minimization of a BDD.]
  1169. Description [Performs safe minimization of a BDD. Given the BDD
  1170. <code>f</code> of a function to be minimized and a BDD
  1171. <code>c</code> representing the care set, Cudd_bddLICompaction
  1172. produces the BDD of a function that agrees with <code>f</code>
  1173. wherever <code>c</code> is 1. Safe minimization means that the size
  1174. of the result is guaranteed not to exceed the size of
  1175. <code>f</code>. This function is based on the DAC97 paper by Hong et
  1176. al.. Returns a pointer to the result if successful; NULL
  1177. otherwise.]
  1178. SideEffects [None]
  1179. SeeAlso [Cudd_bddLICompaction]
  1180. ******************************************************************************/
  1181. DdNode *
  1182. cuddBddLICompaction(
  1183. DdManager * dd /* manager */,
  1184. DdNode * f /* function to be minimized */,
  1185. DdNode * c /* constraint (care set) */)
  1186. {
  1187. st_table *marktable, *markcache, *buildcache;
  1188. DdNode *res, *zero;
  1189. zero = Cudd_Not(DD_ONE(dd));
  1190. if (c == zero) return(zero);
  1191. /* We need to use local caches for both steps of this operation.
  1192. ** The results of the edge marking step are only valid as long as the
  1193. ** edge markings themselves are available. However, the edge markings
  1194. ** are lost at the end of one invocation of Cudd_bddLICompaction.
  1195. ** Hence, the cache entries for the edge marking step must be
  1196. ** invalidated at the end of this function.
  1197. ** For the result of the building step we argue as follows. The result
  1198. ** for a node and a given constrain depends on the BDD in which the node
  1199. ** appears. Hence, the same node and constrain may give different results
  1200. ** in successive invocations.
  1201. */
  1202. marktable = st_init_table(st_ptrcmp,st_ptrhash);
  1203. if (marktable == NULL) {
  1204. return(NULL);
  1205. }
  1206. markcache = st_init_table(MarkCacheCompare,MarkCacheHash);
  1207. if (markcache == NULL) {
  1208. st_free_table(marktable);
  1209. return(NULL);
  1210. }
  1211. if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) {
  1212. st_foreach(markcache, MarkCacheCleanUp, NULL);
  1213. st_free_table(marktable);
  1214. st_free_table(markcache);
  1215. return(NULL);
  1216. }
  1217. st_foreach(markcache, MarkCacheCleanUp, NULL);
  1218. st_free_table(markcache);
  1219. buildcache = st_init_table(st_ptrcmp,st_ptrhash);
  1220. if (buildcache == NULL) {
  1221. st_free_table(marktable);
  1222. return(NULL);
  1223. }
  1224. res = cuddBddLICBuildResult(dd,f,buildcache,marktable);
  1225. st_free_table(buildcache);
  1226. st_free_table(marktable);
  1227. return(res);
  1228. } /* end of cuddBddLICompaction */
  1229. /*---------------------------------------------------------------------------*/
  1230. /* Definition of static functions */
  1231. /*---------------------------------------------------------------------------*/
  1232. /**Function********************************************************************
  1233. Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.]
  1234. Description [Performs the recursive step of Cudd_bddConstrainDecomp.
  1235. Returns f super (i) if successful; otherwise NULL.]
  1236. SideEffects [None]
  1237. SeeAlso [Cudd_bddConstrainDecomp]
  1238. ******************************************************************************/
  1239. static int
  1240. cuddBddConstrainDecomp(
  1241. DdManager * dd,
  1242. DdNode * f,
  1243. DdNode ** decomp)
  1244. {
  1245. DdNode *F, *fv, *fvn;
  1246. DdNode *fAbs;
  1247. DdNode *result;
  1248. int ok;
  1249. if (Cudd_IsConstant(f)) return(1);
  1250. /* Compute complements of cofactors. */
  1251. F = Cudd_Regular(f);
  1252. fv = cuddT(F);
  1253. fvn = cuddE(F);
  1254. if (F == f) {
  1255. fv = Cudd_Not(fv);
  1256. fvn = Cudd_Not(fvn);
  1257. }
  1258. /* Compute abstraction of top variable. */
  1259. fAbs = cuddBddAndRecur(dd, fv, fvn);
  1260. if (fAbs == NULL) {
  1261. return(0);
  1262. }
  1263. cuddRef(fAbs);
  1264. fAbs = Cudd_Not(fAbs);
  1265. /* Recursively find the next abstraction and the components of the
  1266. ** decomposition. */
  1267. ok = cuddBddConstrainDecomp(dd, fAbs, decomp);
  1268. if (ok == 0) {
  1269. Cudd_IterDerefBdd(dd,fAbs);
  1270. return(0);
  1271. }
  1272. /* Compute the component of the decomposition corresponding to the
  1273. ** top variable and store it in the decomposition array. */
  1274. result = cuddBddConstrainRecur(dd, f, fAbs);
  1275. if (result == NULL) {
  1276. Cudd_IterDerefBdd(dd,fAbs);
  1277. return(0);
  1278. }
  1279. cuddRef(result);
  1280. decomp[F->index] = result;
  1281. Cudd_IterDerefBdd(dd, fAbs);
  1282. return(1);
  1283. } /* end of cuddBddConstrainDecomp */
  1284. /**Function********************************************************************
  1285. Synopsis [Performs the recursive step of Cudd_bddCharToVect.]
  1286. Description [Performs the recursive step of Cudd_bddCharToVect.
  1287. This function maintains the invariant that f is non-zero.
  1288. Returns the i-th component of the vector if successful; otherwise NULL.]
  1289. SideEffects [None]
  1290. SeeAlso [Cudd_bddCharToVect]
  1291. ******************************************************************************/
  1292. static DdNode *
  1293. cuddBddCharToVect(
  1294. DdManager * dd,
  1295. DdNode * f,
  1296. DdNode * x)
  1297. {
  1298. unsigned int topf;
  1299. unsigned int level;
  1300. int comple;
  1301. DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E;
  1302. statLine(dd);
  1303. /* Check the cache. */
  1304. res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x);
  1305. if (res != NULL) {
  1306. return(res);
  1307. }
  1308. F = Cudd_Regular(f);
  1309. topf = cuddI(dd,F->index);
  1310. level = dd->perm[x->index];
  1311. if (topf > level) return(x);
  1312. one = DD_ONE(dd);
  1313. zero = Cudd_Not(one);
  1314. comple = F != f;
  1315. fT = Cudd_NotCond(cuddT(F),comple);
  1316. fE = Cudd_NotCond(cuddE(F),comple);
  1317. if (topf == level) {
  1318. if (fT == zero) return(zero);
  1319. if (fE == zero) return(one);
  1320. return(x);
  1321. }
  1322. /* Here topf < level. */
  1323. if (fT == zero) return(cuddBddCharToVect(dd, fE, x));
  1324. if (fE == zero) return(cuddBddCharToVect(dd, fT, x));
  1325. T = cuddBddCharToVect(dd, fT, x);
  1326. if (T == NULL) {
  1327. return(NULL);
  1328. }
  1329. cuddRef(T);
  1330. E = cuddBddCharToVect(dd, fE, x);
  1331. if (E == NULL) {
  1332. Cudd_IterDerefBdd(dd,T);
  1333. return(NULL);
  1334. }
  1335. cuddRef(E);
  1336. res = cuddBddIteRecur(dd, dd->vars[F->index], T, E);
  1337. if (res == NULL) {
  1338. Cudd_IterDerefBdd(dd,T);
  1339. Cudd_IterDerefBdd(dd,E);
  1340. return(NULL);
  1341. }
  1342. cuddDeref(T);
  1343. cuddDeref(E);
  1344. cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res);
  1345. return(res);
  1346. } /* end of cuddBddCharToVect */
  1347. /**Function********************************************************************
  1348. Synopsis [Performs the edge marking step of Cudd_bddLICompaction.]
  1349. Description [Performs the edge marking step of Cudd_bddLICompaction.
  1350. Returns the LUB of the markings of the two outgoing edges of <code>f</code>
  1351. if successful; otherwise CUDD_OUT_OF_MEM.]
  1352. SideEffects [None]
  1353. SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult]
  1354. ******************************************************************************/
  1355. static int
  1356. cuddBddLICMarkEdges(
  1357. DdManager * dd,
  1358. DdNode * f,
  1359. DdNode * c,
  1360. st_table * table,
  1361. st_table * cache)
  1362. {
  1363. DdNode *Fv, *Fnv, *Cv, *Cnv;
  1364. DdNode *one, *zero;
  1365. unsigned int topf, topc;
  1366. int comple;
  1367. int resT, resE, res, retval;
  1368. char **slot;
  1369. MarkCacheKey *key;
  1370. one = DD_ONE(dd);
  1371. zero = Cudd_Not(one);
  1372. /* Terminal cases. */
  1373. if (c == zero) return(DD_LIC_DC);
  1374. if (f == one) return(DD_LIC_1);
  1375. if (f == zero) return(DD_LIC_0);
  1376. /* Make canonical to increase the utilization of the cache. */
  1377. comple = Cudd_IsComplement(f);
  1378. f = Cudd_Regular(f);
  1379. /* Now f is a regular pointer to a non-constant node; c may be
  1380. ** constant, or it may be complemented.
  1381. */
  1382. /* Check the cache. */
  1383. key = ALLOC(MarkCacheKey, 1);
  1384. if (key == NULL) {
  1385. dd->errorCode = CUDD_MEMORY_OUT;
  1386. return(CUDD_OUT_OF_MEM);
  1387. }
  1388. key->f = f; key->c = c;
  1389. if (st_lookup_int(cache, (char *)key, &res)) {
  1390. FREE(key);
  1391. if (comple) {
  1392. if (res == DD_LIC_0) res = DD_LIC_1;
  1393. else if (res == DD_LIC_1) res = DD_LIC_0;
  1394. }
  1395. return(res);
  1396. }
  1397. /* Recursive step. */
  1398. topf = dd->perm[f->index];
  1399. topc = cuddI(dd,Cudd_Regular(c)->index);
  1400. if (topf <= topc) {
  1401. Fv = cuddT(f); Fnv = cuddE(f);
  1402. } else {
  1403. Fv = Fnv = f;
  1404. }
  1405. if (topc <= topf) {
  1406. /* We know that c is not constant because f is not. */
  1407. Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
  1408. if (Cudd_IsComplement(c)) {
  1409. Cv = Cudd_Not(Cv);
  1410. Cnv = Cudd_Not(Cnv);
  1411. }
  1412. } else {
  1413. Cv = Cnv = c;
  1414. }
  1415. resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache);
  1416. if (resT == CUDD_OUT_OF_MEM) {
  1417. FREE(key);
  1418. return(CUDD_OUT_OF_MEM);
  1419. }
  1420. resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache);
  1421. if (resE == CUDD_OUT_OF_MEM) {
  1422. FREE(key);
  1423. return(CUDD_OUT_OF_MEM);
  1424. }
  1425. /* Update edge markings. */
  1426. if (topf <= topc) {
  1427. retval = st_find_or_add(table, (char *)f, (char ***)&slot);
  1428. if (retval == 0) {
  1429. *slot = (char *) (ptrint)((resT << 2) | resE);
  1430. } else if (retval == 1) {
  1431. *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE);
  1432. } else {
  1433. FREE(key);
  1434. return(CUDD_OUT_OF_MEM);
  1435. }
  1436. }
  1437. /* Cache result. */
  1438. res = resT | resE;
  1439. if (st_insert(cache, (char *)key, (char *)(ptrint)res) == ST_OUT_OF_MEM) {
  1440. FREE(key);
  1441. return(CUDD_OUT_OF_MEM);
  1442. }
  1443. /* Take into account possible complementation. */
  1444. if (comple) {
  1445. if (res == DD_LIC_0) res = DD_LIC_1;
  1446. else if (res == DD_LIC_1) res = DD_LIC_0;
  1447. }
  1448. return(res);
  1449. } /* end of cuddBddLICMarkEdges */
  1450. /**Function********************************************************************
  1451. Synopsis [Builds the result of Cudd_bddLICompaction.]
  1452. Description [Builds the results of Cudd_bddLICompaction.
  1453. Returns a pointer to the minimized BDD if successful; otherwise NULL.]
  1454. SideEffects [None]
  1455. SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges]
  1456. ******************************************************************************/
  1457. static DdNode *
  1458. cuddBddLICBuildResult(
  1459. DdManager * dd,
  1460. DdNode * f,
  1461. st_table * cache,
  1462. st_table * table)
  1463. {
  1464. DdNode *Fv, *Fnv, *r, *t, *e;
  1465. DdNode *one, *zero;
  1466. int index;
  1467. int comple;
  1468. int markT, markE, markings;
  1469. one = DD_ONE(dd);
  1470. zero = Cudd_Not(one);
  1471. if (Cudd_IsConstant(f)) return(f);
  1472. /* Make canonical to increase the utilization of the cache. */
  1473. comple = Cudd_IsComplement(f);
  1474. f = Cudd_Regular(f);
  1475. /* Check the cache. */
  1476. if (st_lookup(cache, f, &r)) {
  1477. return(Cudd_NotCond(r,comple));
  1478. }
  1479. /* Retrieve the edge markings. */
  1480. if (st_lookup_int(table, (char *)f, &markings) == 0)
  1481. return(NULL);
  1482. markT = markings >> 2;
  1483. markE = markings & 3;
  1484. index = f->index;
  1485. Fv = cuddT(f); Fnv = cuddE(f);
  1486. if (markT == DD_LIC_NL) {
  1487. t = cuddBddLICBuildResult(dd,Fv,cache,table);
  1488. if (t == NULL) {
  1489. return(NULL);
  1490. }
  1491. } else if (markT == DD_LIC_1) {
  1492. t = one;
  1493. } else {
  1494. t = zero;
  1495. }
  1496. cuddRef(t);
  1497. if (markE == DD_LIC_NL) {
  1498. e = cuddBddLICBuildResult(dd,Fnv,cache,table);
  1499. if (e == NULL) {
  1500. Cudd_IterDerefBdd(dd,t);
  1501. return(NULL);
  1502. }
  1503. } else if (markE == DD_LIC_1) {
  1504. e = one;
  1505. } else {
  1506. e = zero;
  1507. }
  1508. cuddRef(e);
  1509. if (markT == DD_LIC_DC && markE != DD_LIC_DC) {
  1510. r = e;
  1511. } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) {
  1512. r = t;
  1513. } else {
  1514. if (Cudd_IsComplement(t)) {
  1515. t = Cudd_Not(t);
  1516. e = Cudd_Not(e);
  1517. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  1518. if (r == NULL) {
  1519. Cudd_IterDerefBdd(dd, e);
  1520. Cudd_IterDerefBdd(dd, t);
  1521. return(NULL);
  1522. }
  1523. r = Cudd_Not(r);
  1524. } else {
  1525. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  1526. if (r == NULL) {
  1527. Cudd_IterDerefBdd(dd, e);
  1528. Cudd_IterDerefBdd(dd, t);
  1529. return(NULL);
  1530. }
  1531. }
  1532. }
  1533. cuddDeref(t);
  1534. cuddDeref(e);
  1535. if (st_insert(cache, (char *)f, (char *)r) == ST_OUT_OF_MEM) {
  1536. cuddRef(r);
  1537. Cudd_IterDerefBdd(dd,r);
  1538. return(NULL);
  1539. }
  1540. return(Cudd_NotCond(r,comple));
  1541. } /* end of cuddBddLICBuildResult */
  1542. /**Function********************************************************************
  1543. Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.]
  1544. Description [Hash function for the computed table of
  1545. cuddBddLICMarkEdges. Returns the bucket number.]
  1546. SideEffects [None]
  1547. SeeAlso [Cudd_bddLICompaction]
  1548. ******************************************************************************/
  1549. static int
  1550. MarkCacheHash(
  1551. char * ptr,
  1552. int modulus)
  1553. {
  1554. int val = 0;
  1555. MarkCacheKey *entry;
  1556. entry = (MarkCacheKey *) ptr;
  1557. val = (int) (ptrint) entry->f;
  1558. val = val * 997 + (int) (ptrint) entry->c;
  1559. return ((val < 0) ? -val : val) % modulus;
  1560. } /* end of MarkCacheHash */
  1561. /**Function********************************************************************
  1562. Synopsis [Comparison function for the computed table of
  1563. cuddBddLICMarkEdges.]
  1564. Description [Comparison function for the computed table of
  1565. cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1
  1566. otherwise.]
  1567. SideEffects [None]
  1568. SeeAlso [Cudd_bddLICompaction]
  1569. ******************************************************************************/
  1570. static int
  1571. MarkCacheCompare(
  1572. const char * ptr1,
  1573. const char * ptr2)
  1574. {
  1575. MarkCacheKey *entry1, *entry2;
  1576. entry1 = (MarkCacheKey *) ptr1;
  1577. entry2 = (MarkCacheKey *) ptr2;
  1578. return((entry1->f != entry2->f) || (entry1->c != entry2->c));
  1579. } /* end of MarkCacheCompare */
  1580. /**Function********************************************************************
  1581. Synopsis [Frees memory associated with computed table of
  1582. cuddBddLICMarkEdges.]
  1583. Description [Frees memory associated with computed table of
  1584. cuddBddLICMarkEdges. Returns ST_CONTINUE.]
  1585. SideEffects [None]
  1586. SeeAlso [Cudd_bddLICompaction]
  1587. ******************************************************************************/
  1588. static enum st_retval
  1589. MarkCacheCleanUp(
  1590. char * key,
  1591. char * value,
  1592. char * arg)
  1593. {
  1594. MarkCacheKey *entry;
  1595. entry = (MarkCacheKey *) key;
  1596. FREE(entry);
  1597. return ST_CONTINUE;
  1598. } /* end of MarkCacheCleanUp */
  1599. /**Function********************************************************************
  1600. Synopsis [Performs the recursive step of Cudd_bddSqueeze.]
  1601. Description [Performs the recursive step of Cudd_bddSqueeze. This
  1602. procedure exploits the fact that if we complement and swap the
  1603. bounds of the interval we obtain a valid solution by taking the
  1604. complement of the solution to the original problem. Therefore, we
  1605. can enforce the condition that the upper bound is always regular.
  1606. Returns a pointer to the result if successful; NULL otherwise.]
  1607. SideEffects [None]
  1608. SeeAlso [Cudd_bddSqueeze]
  1609. ******************************************************************************/
  1610. static DdNode *
  1611. cuddBddSqueeze(
  1612. DdManager * dd,
  1613. DdNode * l,
  1614. DdNode * u)
  1615. {
  1616. DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e;
  1617. #if 0
  1618. DdNode *ar;
  1619. #endif
  1620. int comple = 0;
  1621. unsigned int topu, topl;
  1622. int index;
  1623. statLine(dd);
  1624. if (l == u) {
  1625. return(l);
  1626. }
  1627. one = DD_ONE(dd);
  1628. zero = Cudd_Not(one);
  1629. /* The only case when l == zero && u == one is at the top level,
  1630. ** where returning either one or zero is OK. In all other cases
  1631. ** the procedure will detect such a case and will perform
  1632. ** remapping. Therefore the order in which we test l and u at this
  1633. ** point is immaterial. */
  1634. if (l == zero) return(l);
  1635. if (u == one) return(u);
  1636. /* Make canonical to increase the utilization of the cache. */
  1637. if (Cudd_IsComplement(u)) {
  1638. DdNode *temp;
  1639. temp = Cudd_Not(l);
  1640. l = Cudd_Not(u);
  1641. u = temp;
  1642. comple = 1;
  1643. }
  1644. /* At this point u is regular and non-constant; l is non-constant, but
  1645. ** may be complemented. */
  1646. /* Here we could check the relative sizes. */
  1647. /* Check the cache. */
  1648. r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u);
  1649. if (r != NULL) {
  1650. return(Cudd_NotCond(r,comple));
  1651. }
  1652. /* Recursive step. */
  1653. topu = dd->perm[u->index];
  1654. topl = dd->perm[Cudd_Regular(l)->index];
  1655. if (topu <= topl) {
  1656. index = u->index;
  1657. ut = cuddT(u); ue = cuddE(u);
  1658. } else {
  1659. index = Cudd_Regular(l)->index;
  1660. ut = ue = u;
  1661. }
  1662. if (topl <= topu) {
  1663. lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l));
  1664. if (Cudd_IsComplement(l)) {
  1665. lt = Cudd_Not(lt);
  1666. le = Cudd_Not(le);
  1667. }
  1668. } else {
  1669. lt = le = l;
  1670. }
  1671. /* If one interval is contained in the other, use the smaller
  1672. ** interval. This corresponds to one-sided matching. */
  1673. if ((lt == zero || Cudd_bddLeq(dd,lt,le)) &&
  1674. (ut == one || Cudd_bddLeq(dd,ue,ut))) { /* remap */
  1675. r = cuddBddSqueeze(dd, le, ue);
  1676. if (r == NULL)
  1677. return(NULL);
  1678. return(Cudd_NotCond(r,comple));
  1679. } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) &&
  1680. (ue == one || Cudd_bddLeq(dd,ut,ue))) { /* remap */
  1681. r = cuddBddSqueeze(dd, lt, ut);
  1682. if (r == NULL)
  1683. return(NULL);
  1684. return(Cudd_NotCond(r,comple));
  1685. } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) &&
  1686. (ue == one || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */
  1687. t = cuddBddSqueeze(dd, lt, ut);
  1688. cuddRef(t);
  1689. if (Cudd_IsComplement(t)) {
  1690. r = cuddUniqueInter(dd, index, Cudd_Not(t), t);
  1691. if (r == NULL) {
  1692. Cudd_IterDerefBdd(dd, t);
  1693. return(NULL);
  1694. }
  1695. r = Cudd_Not(r);
  1696. } else {
  1697. r = cuddUniqueInter(dd, index, t, Cudd_Not(t));
  1698. if (r == NULL) {
  1699. Cudd_IterDerefBdd(dd, t);
  1700. return(NULL);
  1701. }
  1702. }
  1703. cuddDeref(t);
  1704. if (r == NULL)
  1705. return(NULL);
  1706. cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
  1707. return(Cudd_NotCond(r,comple));
  1708. } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) &&
  1709. (ut == one || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */
  1710. e = cuddBddSqueeze(dd, le, ue);
  1711. cuddRef(e);
  1712. if (Cudd_IsComplement(e)) {
  1713. r = cuddUniqueInter(dd, index, Cudd_Not(e), e);
  1714. if (r == NULL) {
  1715. Cudd_IterDerefBdd(dd, e);
  1716. return(NULL);
  1717. }
  1718. } else {
  1719. r = cuddUniqueInter(dd, index, e, Cudd_Not(e));
  1720. if (r == NULL) {
  1721. Cudd_IterDerefBdd(dd, e);
  1722. return(NULL);
  1723. }
  1724. r = Cudd_Not(r);
  1725. }
  1726. cuddDeref(e);
  1727. if (r == NULL)
  1728. return(NULL);
  1729. cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
  1730. return(Cudd_NotCond(r,comple));
  1731. }
  1732. #if 0
  1733. /* If the two intervals intersect, take a solution from
  1734. ** the intersection of the intervals. This guarantees that the
  1735. ** splitting variable will not appear in the result.
  1736. ** This approach corresponds to two-sided matching, and is very
  1737. ** expensive. */
  1738. if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) {
  1739. DdNode *au, *al;
  1740. au = cuddBddAndRecur(dd,ut,ue);
  1741. if (au == NULL)
  1742. return(NULL);
  1743. cuddRef(au);
  1744. al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le));
  1745. if (al == NULL) {
  1746. Cudd_IterDerefBdd(dd,au);
  1747. return(NULL);
  1748. }
  1749. cuddRef(al);
  1750. al = Cudd_Not(al);
  1751. ar = cuddBddSqueeze(dd, al, au);
  1752. if (ar == NULL) {
  1753. Cudd_IterDerefBdd(dd,au);
  1754. Cudd_IterDerefBdd(dd,al);
  1755. return(NULL);
  1756. }
  1757. cuddRef(ar);
  1758. Cudd_IterDerefBdd(dd,au);
  1759. Cudd_IterDerefBdd(dd,al);
  1760. } else {
  1761. ar = NULL;
  1762. }
  1763. #endif
  1764. t = cuddBddSqueeze(dd, lt, ut);
  1765. if (t == NULL) {
  1766. return(NULL);
  1767. }
  1768. cuddRef(t);
  1769. e = cuddBddSqueeze(dd, le, ue);
  1770. if (e == NULL) {
  1771. Cudd_IterDerefBdd(dd,t);
  1772. return(NULL);
  1773. }
  1774. cuddRef(e);
  1775. if (Cudd_IsComplement(t)) {
  1776. t = Cudd_Not(t);
  1777. e = Cudd_Not(e);
  1778. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  1779. if (r == NULL) {
  1780. Cudd_IterDerefBdd(dd, e);
  1781. Cudd_IterDerefBdd(dd, t);
  1782. return(NULL);
  1783. }
  1784. r = Cudd_Not(r);
  1785. } else {
  1786. r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
  1787. if (r == NULL) {
  1788. Cudd_IterDerefBdd(dd, e);
  1789. Cudd_IterDerefBdd(dd, t);
  1790. return(NULL);
  1791. }
  1792. }
  1793. cuddDeref(t);
  1794. cuddDeref(e);
  1795. #if 0
  1796. /* Check whether there is a result obtained by abstraction and whether
  1797. ** it is better than the one obtained by recursion. */
  1798. cuddRef(r);
  1799. if (ar != NULL) {
  1800. if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) {
  1801. Cudd_IterDerefBdd(dd, r);
  1802. r = ar;
  1803. } else {
  1804. Cudd_IterDerefBdd(dd, ar);
  1805. }
  1806. }
  1807. cuddDeref(r);
  1808. #endif
  1809. cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
  1810. return(Cudd_NotCond(r,comple));
  1811. } /* end of cuddBddSqueeze */