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.

1430 lines
36 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddBddIte.c]
  3. PackageName [cudd]
  4. Synopsis [BDD ITE function and satellites.]
  5. Description [External procedures included in this module:
  6. <ul>
  7. <li> Cudd_bddIte()
  8. <li> Cudd_bddIteLimit()
  9. <li> Cudd_bddIteConstant()
  10. <li> Cudd_bddIntersect()
  11. <li> Cudd_bddAnd()
  12. <li> Cudd_bddAndLimit()
  13. <li> Cudd_bddOr()
  14. <li> Cudd_bddOrLimit()
  15. <li> Cudd_bddNand()
  16. <li> Cudd_bddNor()
  17. <li> Cudd_bddXor()
  18. <li> Cudd_bddXnor()
  19. <li> Cudd_bddXnorLimit()
  20. <li> Cudd_bddLeq()
  21. </ul>
  22. Internal procedures included in this module:
  23. <ul>
  24. <li> cuddBddIteRecur()
  25. <li> cuddBddIntersectRecur()
  26. <li> cuddBddAndRecur()
  27. <li> cuddBddXorRecur()
  28. </ul>
  29. Static procedures included in this module:
  30. <ul>
  31. <li> bddVarToConst()
  32. <li> bddVarToCanonical()
  33. <li> bddVarToCanonicalSimple()
  34. </ul>]
  35. SeeAlso []
  36. Author [Fabio Somenzi]
  37. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  38. All rights reserved.
  39. Redistribution and use in source and binary forms, with or without
  40. modification, are permitted provided that the following conditions
  41. are met:
  42. Redistributions of source code must retain the above copyright
  43. notice, this list of conditions and the following disclaimer.
  44. Redistributions in binary form must reproduce the above copyright
  45. notice, this list of conditions and the following disclaimer in the
  46. documentation and/or other materials provided with the distribution.
  47. Neither the name of the University of Colorado nor the names of its
  48. contributors may be used to endorse or promote products derived from
  49. this software without specific prior written permission.
  50. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  53. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  54. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  55. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  56. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  57. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  58. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  59. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  60. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  61. POSSIBILITY OF SUCH DAMAGE.]
  62. ******************************************************************************/
  63. #include "util.h"
  64. #include "cuddInt.h"
  65. /*---------------------------------------------------------------------------*/
  66. /* Constant declarations */
  67. /*---------------------------------------------------------------------------*/
  68. /*---------------------------------------------------------------------------*/
  69. /* Stucture declarations */
  70. /*---------------------------------------------------------------------------*/
  71. /*---------------------------------------------------------------------------*/
  72. /* Type declarations */
  73. /*---------------------------------------------------------------------------*/
  74. /*---------------------------------------------------------------------------*/
  75. /* Variable declarations */
  76. /*---------------------------------------------------------------------------*/
  77. #ifndef lint
  78. static char rcsid[] DD_UNUSED = "$Id: cuddBddIte.c,v 1.26 2012/02/05 01:07:18 fabio Exp $";
  79. #endif
  80. /*---------------------------------------------------------------------------*/
  81. /* Macro declarations */
  82. /*---------------------------------------------------------------------------*/
  83. /**AutomaticStart*************************************************************/
  84. /*---------------------------------------------------------------------------*/
  85. /* Static function prototypes */
  86. /*---------------------------------------------------------------------------*/
  87. static void bddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one);
  88. static int bddVarToCanonical (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
  89. static int bddVarToCanonicalSimple (DdManager *dd, DdNode **fp, DdNode **gp, DdNode **hp, unsigned int *topfp, unsigned int *topgp, unsigned int *tophp);
  90. /**AutomaticEnd***************************************************************/
  91. /*---------------------------------------------------------------------------*/
  92. /* Definition of exported functions */
  93. /*---------------------------------------------------------------------------*/
  94. /**Function********************************************************************
  95. Synopsis [Implements ITE(f,g,h).]
  96. Description [Implements ITE(f,g,h). Returns a pointer to the
  97. resulting BDD if successful; NULL if the intermediate result blows
  98. up.]
  99. SideEffects [None]
  100. SeeAlso [Cudd_addIte Cudd_bddIteConstant Cudd_bddIntersect]
  101. ******************************************************************************/
  102. DdNode *
  103. Cudd_bddIte(
  104. DdManager * dd,
  105. DdNode * f,
  106. DdNode * g,
  107. DdNode * h)
  108. {
  109. DdNode *res;
  110. do {
  111. dd->reordered = 0;
  112. res = cuddBddIteRecur(dd,f,g,h);
  113. } while (dd->reordered == 1);
  114. return(res);
  115. } /* end of Cudd_bddIte */
  116. /**Function********************************************************************
  117. Synopsis [Implements ITE(f,g,h). Returns
  118. NULL if too many nodes are required.]
  119. Description [Implements ITE(f,g,h). Returns a
  120. pointer to the resulting BDD if successful; NULL if the intermediate
  121. result blows up or more new nodes than <code>limit</code> are
  122. required.]
  123. SideEffects [None]
  124. SeeAlso [Cudd_bddIte]
  125. ******************************************************************************/
  126. DdNode *
  127. Cudd_bddIteLimit(
  128. DdManager * dd,
  129. DdNode * f,
  130. DdNode * g,
  131. DdNode * h,
  132. unsigned int limit)
  133. {
  134. DdNode *res;
  135. unsigned int saveLimit = dd->maxLive;
  136. dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
  137. do {
  138. dd->reordered = 0;
  139. res = cuddBddIteRecur(dd,f,g,h);
  140. } while (dd->reordered == 1);
  141. dd->maxLive = saveLimit;
  142. return(res);
  143. } /* end of Cudd_bddIteLimit */
  144. /**Function********************************************************************
  145. Synopsis [Implements ITEconstant(f,g,h).]
  146. Description [Implements ITEconstant(f,g,h). Returns a pointer to the
  147. resulting BDD (which may or may not be constant) or DD_NON_CONSTANT.
  148. No new nodes are created.]
  149. SideEffects [None]
  150. SeeAlso [Cudd_bddIte Cudd_bddIntersect Cudd_bddLeq Cudd_addIteConstant]
  151. ******************************************************************************/
  152. DdNode *
  153. Cudd_bddIteConstant(
  154. DdManager * dd,
  155. DdNode * f,
  156. DdNode * g,
  157. DdNode * h)
  158. {
  159. DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
  160. DdNode *one = DD_ONE(dd);
  161. DdNode *zero = Cudd_Not(one);
  162. int comple;
  163. unsigned int topf, topg, toph, v;
  164. statLine(dd);
  165. /* Trivial cases. */
  166. if (f == one) /* ITE(1,G,H) => G */
  167. return(g);
  168. if (f == zero) /* ITE(0,G,H) => H */
  169. return(h);
  170. /* f now not a constant. */
  171. bddVarToConst(f, &g, &h, one); /* possibly convert g or h */
  172. /* to constants */
  173. if (g == h) /* ITE(F,G,G) => G */
  174. return(g);
  175. if (Cudd_IsConstant(g) && Cudd_IsConstant(h))
  176. return(DD_NON_CONSTANT); /* ITE(F,1,0) or ITE(F,0,1) */
  177. /* => DD_NON_CONSTANT */
  178. if (g == Cudd_Not(h))
  179. return(DD_NON_CONSTANT); /* ITE(F,G,G') => DD_NON_CONSTANT */
  180. /* if F != G and F != G' */
  181. comple = bddVarToCanonical(dd, &f, &g, &h, &topf, &topg, &toph);
  182. /* Cache lookup. */
  183. r = cuddConstantLookup(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h);
  184. if (r != NULL) {
  185. return(Cudd_NotCond(r,comple && r != DD_NON_CONSTANT));
  186. }
  187. v = ddMin(topg, toph);
  188. /* ITE(F,G,H) = (v,G,H) (non constant) if F = (v,1,0), v < top(G,H). */
  189. if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
  190. return(DD_NON_CONSTANT);
  191. }
  192. /* Compute cofactors. */
  193. if (topf <= v) {
  194. v = ddMin(topf, v); /* v = top_var(F,G,H) */
  195. Fv = cuddT(f); Fnv = cuddE(f);
  196. } else {
  197. Fv = Fnv = f;
  198. }
  199. if (topg == v) {
  200. Gv = cuddT(g); Gnv = cuddE(g);
  201. } else {
  202. Gv = Gnv = g;
  203. }
  204. if (toph == v) {
  205. H = Cudd_Regular(h);
  206. Hv = cuddT(H); Hnv = cuddE(H);
  207. if (Cudd_IsComplement(h)) {
  208. Hv = Cudd_Not(Hv);
  209. Hnv = Cudd_Not(Hnv);
  210. }
  211. } else {
  212. Hv = Hnv = h;
  213. }
  214. /* Recursion. */
  215. t = Cudd_bddIteConstant(dd, Fv, Gv, Hv);
  216. if (t == DD_NON_CONSTANT || !Cudd_IsConstant(t)) {
  217. cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
  218. return(DD_NON_CONSTANT);
  219. }
  220. e = Cudd_bddIteConstant(dd, Fnv, Gnv, Hnv);
  221. if (e == DD_NON_CONSTANT || !Cudd_IsConstant(e) || t != e) {
  222. cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
  223. return(DD_NON_CONSTANT);
  224. }
  225. cuddCacheInsert(dd, DD_BDD_ITE_CONSTANT_TAG, f, g, h, t);
  226. return(Cudd_NotCond(t,comple));
  227. } /* end of Cudd_bddIteConstant */
  228. /**Function********************************************************************
  229. Synopsis [Returns a function included in the intersection of f and g.]
  230. Description [Computes a function included in the intersection of f and
  231. g. (That is, a witness that the intersection is not empty.)
  232. Cudd_bddIntersect tries to build as few new nodes as possible. If the
  233. only result of interest is whether f and g intersect,
  234. Cudd_bddLeq should be used instead.]
  235. SideEffects [None]
  236. SeeAlso [Cudd_bddLeq Cudd_bddIteConstant]
  237. ******************************************************************************/
  238. DdNode *
  239. Cudd_bddIntersect(
  240. DdManager * dd /* manager */,
  241. DdNode * f /* first operand */,
  242. DdNode * g /* second operand */)
  243. {
  244. DdNode *res;
  245. do {
  246. dd->reordered = 0;
  247. res = cuddBddIntersectRecur(dd,f,g);
  248. } while (dd->reordered == 1);
  249. return(res);
  250. } /* end of Cudd_bddIntersect */
  251. /**Function********************************************************************
  252. Synopsis [Computes the conjunction of two BDDs f and g.]
  253. Description [Computes the conjunction of two BDDs f and g. Returns a
  254. pointer to the resulting BDD if successful; NULL if the intermediate
  255. result blows up.]
  256. SideEffects [None]
  257. SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAndAbstract Cudd_bddIntersect
  258. Cudd_bddOr Cudd_bddNand Cudd_bddNor Cudd_bddXor Cudd_bddXnor]
  259. ******************************************************************************/
  260. DdNode *
  261. Cudd_bddAnd(
  262. DdManager * dd,
  263. DdNode * f,
  264. DdNode * g)
  265. {
  266. DdNode *res;
  267. do {
  268. dd->reordered = 0;
  269. res = cuddBddAndRecur(dd,f,g);
  270. } while (dd->reordered == 1);
  271. return(res);
  272. } /* end of Cudd_bddAnd */
  273. /**Function********************************************************************
  274. Synopsis [Computes the conjunction of two BDDs f and g. Returns
  275. NULL if too many nodes are required.]
  276. Description [Computes the conjunction of two BDDs f and g. Returns a
  277. pointer to the resulting BDD if successful; NULL if the intermediate
  278. result blows up or more new nodes than <code>limit</code> are
  279. required.]
  280. SideEffects [None]
  281. SeeAlso [Cudd_bddAnd]
  282. ******************************************************************************/
  283. DdNode *
  284. Cudd_bddAndLimit(
  285. DdManager * dd,
  286. DdNode * f,
  287. DdNode * g,
  288. unsigned int limit)
  289. {
  290. DdNode *res;
  291. unsigned int saveLimit = dd->maxLive;
  292. dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
  293. do {
  294. dd->reordered = 0;
  295. res = cuddBddAndRecur(dd,f,g);
  296. } while (dd->reordered == 1);
  297. dd->maxLive = saveLimit;
  298. return(res);
  299. } /* end of Cudd_bddAndLimit */
  300. /**Function********************************************************************
  301. Synopsis [Computes the disjunction of two BDDs f and g.]
  302. Description [Computes the disjunction of two BDDs f and g. Returns a
  303. pointer to the resulting BDD if successful; NULL if the intermediate
  304. result blows up.]
  305. SideEffects [None]
  306. SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddNand Cudd_bddNor
  307. Cudd_bddXor Cudd_bddXnor]
  308. ******************************************************************************/
  309. DdNode *
  310. Cudd_bddOr(
  311. DdManager * dd,
  312. DdNode * f,
  313. DdNode * g)
  314. {
  315. DdNode *res;
  316. do {
  317. dd->reordered = 0;
  318. res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
  319. } while (dd->reordered == 1);
  320. res = Cudd_NotCond(res,res != NULL);
  321. return(res);
  322. } /* end of Cudd_bddOr */
  323. /**Function********************************************************************
  324. Synopsis [Computes the disjunction of two BDDs f and g. Returns
  325. NULL if too many nodes are required.]
  326. Description [Computes the disjunction of two BDDs f and g. Returns a
  327. pointer to the resulting BDD if successful; NULL if the intermediate
  328. result blows up or more new nodes than <code>limit</code> are
  329. required.]
  330. SideEffects [None]
  331. SeeAlso [Cudd_bddOr]
  332. ******************************************************************************/
  333. DdNode *
  334. Cudd_bddOrLimit(
  335. DdManager * dd,
  336. DdNode * f,
  337. DdNode * g,
  338. unsigned int limit)
  339. {
  340. DdNode *res;
  341. unsigned int saveLimit = dd->maxLive;
  342. dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
  343. do {
  344. dd->reordered = 0;
  345. res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
  346. } while (dd->reordered == 1);
  347. dd->maxLive = saveLimit;
  348. res = Cudd_NotCond(res,res != NULL);
  349. return(res);
  350. } /* end of Cudd_bddOrLimit */
  351. /**Function********************************************************************
  352. Synopsis [Computes the NAND of two BDDs f and g.]
  353. Description [Computes the NAND of two BDDs f and g. Returns a
  354. pointer to the resulting BDD if successful; NULL if the intermediate
  355. result blows up.]
  356. SideEffects [None]
  357. SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNor
  358. Cudd_bddXor Cudd_bddXnor]
  359. ******************************************************************************/
  360. DdNode *
  361. Cudd_bddNand(
  362. DdManager * dd,
  363. DdNode * f,
  364. DdNode * g)
  365. {
  366. DdNode *res;
  367. do {
  368. dd->reordered = 0;
  369. res = cuddBddAndRecur(dd,f,g);
  370. } while (dd->reordered == 1);
  371. res = Cudd_NotCond(res,res != NULL);
  372. return(res);
  373. } /* end of Cudd_bddNand */
  374. /**Function********************************************************************
  375. Synopsis [Computes the NOR of two BDDs f and g.]
  376. Description [Computes the NOR of two BDDs f and g. Returns a
  377. pointer to the resulting BDD if successful; NULL if the intermediate
  378. result blows up.]
  379. SideEffects [None]
  380. SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr Cudd_bddNand
  381. Cudd_bddXor Cudd_bddXnor]
  382. ******************************************************************************/
  383. DdNode *
  384. Cudd_bddNor(
  385. DdManager * dd,
  386. DdNode * f,
  387. DdNode * g)
  388. {
  389. DdNode *res;
  390. do {
  391. dd->reordered = 0;
  392. res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(g));
  393. } while (dd->reordered == 1);
  394. return(res);
  395. } /* end of Cudd_bddNor */
  396. /**Function********************************************************************
  397. Synopsis [Computes the exclusive OR of two BDDs f and g.]
  398. Description [Computes the exclusive OR of two BDDs f and g. Returns a
  399. pointer to the resulting BDD if successful; NULL if the intermediate
  400. result blows up.]
  401. SideEffects [None]
  402. SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
  403. Cudd_bddNand Cudd_bddNor Cudd_bddXnor]
  404. ******************************************************************************/
  405. DdNode *
  406. Cudd_bddXor(
  407. DdManager * dd,
  408. DdNode * f,
  409. DdNode * g)
  410. {
  411. DdNode *res;
  412. do {
  413. dd->reordered = 0;
  414. res = cuddBddXorRecur(dd,f,g);
  415. } while (dd->reordered == 1);
  416. return(res);
  417. } /* end of Cudd_bddXor */
  418. /**Function********************************************************************
  419. Synopsis [Computes the exclusive NOR of two BDDs f and g.]
  420. Description [Computes the exclusive NOR of two BDDs f and g. Returns a
  421. pointer to the resulting BDD if successful; NULL if the intermediate
  422. result blows up.]
  423. SideEffects [None]
  424. SeeAlso [Cudd_bddIte Cudd_addApply Cudd_bddAnd Cudd_bddOr
  425. Cudd_bddNand Cudd_bddNor Cudd_bddXor]
  426. ******************************************************************************/
  427. DdNode *
  428. Cudd_bddXnor(
  429. DdManager * dd,
  430. DdNode * f,
  431. DdNode * g)
  432. {
  433. DdNode *res;
  434. do {
  435. dd->reordered = 0;
  436. res = cuddBddXorRecur(dd,f,Cudd_Not(g));
  437. } while (dd->reordered == 1);
  438. return(res);
  439. } /* end of Cudd_bddXnor */
  440. /**Function********************************************************************
  441. Synopsis [Computes the exclusive NOR of two BDDs f and g. Returns
  442. NULL if too many nodes are required.]
  443. Description [Computes the exclusive NOR of two BDDs f and g. Returns a
  444. pointer to the resulting BDD if successful; NULL if the intermediate
  445. result blows up or more new nodes than <code>limit</code> are
  446. required.]
  447. SideEffects [None]
  448. SeeAlso [Cudd_bddXnor]
  449. ******************************************************************************/
  450. DdNode *
  451. Cudd_bddXnorLimit(
  452. DdManager * dd,
  453. DdNode * f,
  454. DdNode * g,
  455. unsigned int limit)
  456. {
  457. DdNode *res;
  458. unsigned int saveLimit = dd->maxLive;
  459. dd->maxLive = (dd->keys - dd->dead) + (dd->keysZ - dd->deadZ) + limit;
  460. do {
  461. dd->reordered = 0;
  462. res = cuddBddXorRecur(dd,f,Cudd_Not(g));
  463. } while (dd->reordered == 1);
  464. dd->maxLive = saveLimit;
  465. return(res);
  466. } /* end of Cudd_bddXnorLimit */
  467. /**Function********************************************************************
  468. Synopsis [Determines whether f is less than or equal to g.]
  469. Description [Returns 1 if f is less than or equal to g; 0 otherwise.
  470. No new nodes are created.]
  471. SideEffects [None]
  472. SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst]
  473. ******************************************************************************/
  474. int
  475. Cudd_bddLeq(
  476. DdManager * dd,
  477. DdNode * f,
  478. DdNode * g)
  479. {
  480. DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn;
  481. unsigned int topf, topg, res;
  482. statLine(dd);
  483. /* Terminal cases and normalization. */
  484. if (f == g) return(1);
  485. if (Cudd_IsComplement(g)) {
  486. /* Special case: if f is regular and g is complemented,
  487. ** f(1,...,1) = 1 > 0 = g(1,...,1).
  488. */
  489. if (!Cudd_IsComplement(f)) return(0);
  490. /* Both are complemented: Swap and complement because
  491. ** f <= g <=> g' <= f' and we want the second argument to be regular.
  492. */
  493. tmp = g;
  494. g = Cudd_Not(f);
  495. f = Cudd_Not(tmp);
  496. } else if (Cudd_IsComplement(f) && g < f) {
  497. tmp = g;
  498. g = Cudd_Not(f);
  499. f = Cudd_Not(tmp);
  500. }
  501. /* Now g is regular and, if f is not regular, f < g. */
  502. one = DD_ONE(dd);
  503. if (g == one) return(1); /* no need to test against zero */
  504. if (f == one) return(0); /* since at this point g != one */
  505. if (Cudd_Not(f) == g) return(0); /* because neither is constant */
  506. zero = Cudd_Not(one);
  507. if (f == zero) return(1);
  508. /* Here neither f nor g is constant. */
  509. /* Check cache. */
  510. tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g);
  511. if (tmp != NULL) {
  512. return(tmp == one);
  513. }
  514. /* Compute cofactors. */
  515. F = Cudd_Regular(f);
  516. topf = dd->perm[F->index];
  517. topg = dd->perm[g->index];
  518. if (topf <= topg) {
  519. fv = cuddT(F); fvn = cuddE(F);
  520. if (f != F) {
  521. fv = Cudd_Not(fv);
  522. fvn = Cudd_Not(fvn);
  523. }
  524. } else {
  525. fv = fvn = f;
  526. }
  527. if (topg <= topf) {
  528. gv = cuddT(g); gvn = cuddE(g);
  529. } else {
  530. gv = gvn = g;
  531. }
  532. /* Recursive calls. Since we want to maximize the probability of
  533. ** the special case f(1,...,1) > g(1,...,1), we consider the negative
  534. ** cofactors first. Indeed, the complementation parity of the positive
  535. ** cofactors is the same as the one of the parent functions.
  536. */
  537. res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv);
  538. /* Store result in cache and return. */
  539. cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero));
  540. return(res);
  541. } /* end of Cudd_bddLeq */
  542. /*---------------------------------------------------------------------------*/
  543. /* Definition of internal functions */
  544. /*---------------------------------------------------------------------------*/
  545. /**Function********************************************************************
  546. Synopsis [Implements the recursive step of Cudd_bddIte.]
  547. Description [Implements the recursive step of Cudd_bddIte. Returns a
  548. pointer to the resulting BDD. NULL if the intermediate result blows
  549. up or if reordering occurs.]
  550. SideEffects [None]
  551. SeeAlso []
  552. ******************************************************************************/
  553. DdNode *
  554. cuddBddIteRecur(
  555. DdManager * dd,
  556. DdNode * f,
  557. DdNode * g,
  558. DdNode * h)
  559. {
  560. DdNode *one, *zero, *res;
  561. DdNode *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
  562. unsigned int topf, topg, toph, v;
  563. int index;
  564. int comple;
  565. statLine(dd);
  566. /* Terminal cases. */
  567. /* One variable cases. */
  568. if (f == (one = DD_ONE(dd))) /* ITE(1,G,H) = G */
  569. return(g);
  570. if (f == (zero = Cudd_Not(one))) /* ITE(0,G,H) = H */
  571. return(h);
  572. /* From now on, f is known not to be a constant. */
  573. if (g == one || f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
  574. if (h == zero) { /* ITE(F,1,0) = F */
  575. return(f);
  576. } else {
  577. res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
  578. return(Cudd_NotCond(res,res != NULL));
  579. }
  580. } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
  581. if (h == one) { /* ITE(F,0,1) = !F */
  582. return(Cudd_Not(f));
  583. } else {
  584. res = cuddBddAndRecur(dd,Cudd_Not(f),h);
  585. return(res);
  586. }
  587. }
  588. if (h == zero || f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
  589. res = cuddBddAndRecur(dd,f,g);
  590. return(res);
  591. } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
  592. res = cuddBddAndRecur(dd,f,Cudd_Not(g));
  593. return(Cudd_NotCond(res,res != NULL));
  594. }
  595. /* Check remaining one variable case. */
  596. if (g == h) { /* ITE(F,G,G) = G */
  597. return(g);
  598. } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
  599. res = cuddBddXorRecur(dd,f,h);
  600. return(res);
  601. }
  602. /* From here, there are no constants. */
  603. comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);
  604. /* f & g are now regular pointers */
  605. v = ddMin(topg, toph);
  606. /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
  607. if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
  608. r = cuddUniqueInter(dd, (int) f->index, g, h);
  609. return(Cudd_NotCond(r,comple && r != NULL));
  610. }
  611. /* Check cache. */
  612. r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
  613. if (r != NULL) {
  614. return(Cudd_NotCond(r,comple));
  615. }
  616. /* Compute cofactors. */
  617. if (topf <= v) {
  618. v = ddMin(topf, v); /* v = top_var(F,G,H) */
  619. index = f->index;
  620. Fv = cuddT(f); Fnv = cuddE(f);
  621. } else {
  622. Fv = Fnv = f;
  623. }
  624. if (topg == v) {
  625. index = g->index;
  626. Gv = cuddT(g); Gnv = cuddE(g);
  627. } else {
  628. Gv = Gnv = g;
  629. }
  630. if (toph == v) {
  631. H = Cudd_Regular(h);
  632. index = H->index;
  633. Hv = cuddT(H); Hnv = cuddE(H);
  634. if (Cudd_IsComplement(h)) {
  635. Hv = Cudd_Not(Hv);
  636. Hnv = Cudd_Not(Hnv);
  637. }
  638. } else {
  639. Hv = Hnv = h;
  640. }
  641. /* Recursive step. */
  642. t = cuddBddIteRecur(dd,Fv,Gv,Hv);
  643. if (t == NULL) return(NULL);
  644. cuddRef(t);
  645. e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
  646. if (e == NULL) {
  647. Cudd_IterDerefBdd(dd,t);
  648. return(NULL);
  649. }
  650. cuddRef(e);
  651. r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
  652. if (r == NULL) {
  653. Cudd_IterDerefBdd(dd,t);
  654. Cudd_IterDerefBdd(dd,e);
  655. return(NULL);
  656. }
  657. cuddDeref(t);
  658. cuddDeref(e);
  659. cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
  660. return(Cudd_NotCond(r,comple));
  661. } /* end of cuddBddIteRecur */
  662. /**Function********************************************************************
  663. Synopsis [Implements the recursive step of Cudd_bddIntersect.]
  664. Description []
  665. SideEffects [None]
  666. SeeAlso [Cudd_bddIntersect]
  667. ******************************************************************************/
  668. DdNode *
  669. cuddBddIntersectRecur(
  670. DdManager * dd,
  671. DdNode * f,
  672. DdNode * g)
  673. {
  674. DdNode *res;
  675. DdNode *F, *G, *t, *e;
  676. DdNode *fv, *fnv, *gv, *gnv;
  677. DdNode *one, *zero;
  678. unsigned int index, topf, topg;
  679. statLine(dd);
  680. one = DD_ONE(dd);
  681. zero = Cudd_Not(one);
  682. /* Terminal cases. */
  683. if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
  684. if (f == g || g == one) return(f);
  685. if (f == one) return(g);
  686. /* At this point f and g are not constant. */
  687. if (f > g) { DdNode *tmp = f; f = g; g = tmp; }
  688. res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g);
  689. if (res != NULL) return(res);
  690. /* Find splitting variable. Here we can skip the use of cuddI,
  691. ** because the operands are known to be non-constant.
  692. */
  693. F = Cudd_Regular(f);
  694. topf = dd->perm[F->index];
  695. G = Cudd_Regular(g);
  696. topg = dd->perm[G->index];
  697. /* Compute cofactors. */
  698. if (topf <= topg) {
  699. index = F->index;
  700. fv = cuddT(F);
  701. fnv = cuddE(F);
  702. if (Cudd_IsComplement(f)) {
  703. fv = Cudd_Not(fv);
  704. fnv = Cudd_Not(fnv);
  705. }
  706. } else {
  707. index = G->index;
  708. fv = fnv = f;
  709. }
  710. if (topg <= topf) {
  711. gv = cuddT(G);
  712. gnv = cuddE(G);
  713. if (Cudd_IsComplement(g)) {
  714. gv = Cudd_Not(gv);
  715. gnv = Cudd_Not(gnv);
  716. }
  717. } else {
  718. gv = gnv = g;
  719. }
  720. /* Compute partial results. */
  721. t = cuddBddIntersectRecur(dd,fv,gv);
  722. if (t == NULL) return(NULL);
  723. cuddRef(t);
  724. if (t != zero) {
  725. e = zero;
  726. } else {
  727. e = cuddBddIntersectRecur(dd,fnv,gnv);
  728. if (e == NULL) {
  729. Cudd_IterDerefBdd(dd, t);
  730. return(NULL);
  731. }
  732. }
  733. cuddRef(e);
  734. if (t == e) { /* both equal zero */
  735. res = t;
  736. } else if (Cudd_IsComplement(t)) {
  737. res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e));
  738. if (res == NULL) {
  739. Cudd_IterDerefBdd(dd, t);
  740. Cudd_IterDerefBdd(dd, e);
  741. return(NULL);
  742. }
  743. res = Cudd_Not(res);
  744. } else {
  745. res = cuddUniqueInter(dd,(int)index,t,e);
  746. if (res == NULL) {
  747. Cudd_IterDerefBdd(dd, t);
  748. Cudd_IterDerefBdd(dd, e);
  749. return(NULL);
  750. }
  751. }
  752. cuddDeref(e);
  753. cuddDeref(t);
  754. cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res);
  755. return(res);
  756. } /* end of cuddBddIntersectRecur */
  757. /**Function********************************************************************
  758. Synopsis [Implements the recursive step of Cudd_bddAnd.]
  759. Description [Implements the recursive step of Cudd_bddAnd by taking
  760. the conjunction of two BDDs. Returns a pointer to the result is
  761. successful; NULL otherwise.]
  762. SideEffects [None]
  763. SeeAlso [Cudd_bddAnd]
  764. ******************************************************************************/
  765. DdNode *
  766. cuddBddAndRecur(
  767. DdManager * manager,
  768. DdNode * f,
  769. DdNode * g)
  770. {
  771. DdNode *F, *fv, *fnv, *G, *gv, *gnv;
  772. DdNode *one, *r, *t, *e;
  773. unsigned int topf, topg, index;
  774. statLine(manager);
  775. one = DD_ONE(manager);
  776. /* Terminal cases. */
  777. F = Cudd_Regular(f);
  778. G = Cudd_Regular(g);
  779. if (F == G) {
  780. if (f == g) return(f);
  781. else return(Cudd_Not(one));
  782. }
  783. if (F == one) {
  784. if (f == one) return(g);
  785. else return(f);
  786. }
  787. if (G == one) {
  788. if (g == one) return(f);
  789. else return(g);
  790. }
  791. /* At this point f and g are not constant. */
  792. if (f > g) { /* Try to increase cache efficiency. */
  793. DdNode *tmp = f;
  794. f = g;
  795. g = tmp;
  796. F = Cudd_Regular(f);
  797. G = Cudd_Regular(g);
  798. }
  799. /* Check cache. */
  800. if (F->ref != 1 || G->ref != 1) {
  801. r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g);
  802. if (r != NULL) return(r);
  803. }
  804. /* Here we can skip the use of cuddI, because the operands are known
  805. ** to be non-constant.
  806. */
  807. topf = manager->perm[F->index];
  808. topg = manager->perm[G->index];
  809. /* Compute cofactors. */
  810. if (topf <= topg) {
  811. index = F->index;
  812. fv = cuddT(F);
  813. fnv = cuddE(F);
  814. if (Cudd_IsComplement(f)) {
  815. fv = Cudd_Not(fv);
  816. fnv = Cudd_Not(fnv);
  817. }
  818. } else {
  819. index = G->index;
  820. fv = fnv = f;
  821. }
  822. if (topg <= topf) {
  823. gv = cuddT(G);
  824. gnv = cuddE(G);
  825. if (Cudd_IsComplement(g)) {
  826. gv = Cudd_Not(gv);
  827. gnv = Cudd_Not(gnv);
  828. }
  829. } else {
  830. gv = gnv = g;
  831. }
  832. t = cuddBddAndRecur(manager, fv, gv);
  833. if (t == NULL) return(NULL);
  834. cuddRef(t);
  835. e = cuddBddAndRecur(manager, fnv, gnv);
  836. if (e == NULL) {
  837. Cudd_IterDerefBdd(manager, t);
  838. return(NULL);
  839. }
  840. cuddRef(e);
  841. if (t == e) {
  842. r = t;
  843. } else {
  844. if (Cudd_IsComplement(t)) {
  845. r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
  846. if (r == NULL) {
  847. Cudd_IterDerefBdd(manager, t);
  848. Cudd_IterDerefBdd(manager, e);
  849. return(NULL);
  850. }
  851. r = Cudd_Not(r);
  852. } else {
  853. r = cuddUniqueInter(manager,(int)index,t,e);
  854. if (r == NULL) {
  855. Cudd_IterDerefBdd(manager, t);
  856. Cudd_IterDerefBdd(manager, e);
  857. return(NULL);
  858. }
  859. }
  860. }
  861. cuddDeref(e);
  862. cuddDeref(t);
  863. if (F->ref != 1 || G->ref != 1)
  864. cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r);
  865. return(r);
  866. } /* end of cuddBddAndRecur */
  867. /**Function********************************************************************
  868. Synopsis [Implements the recursive step of Cudd_bddXor.]
  869. Description [Implements the recursive step of Cudd_bddXor by taking
  870. the exclusive OR of two BDDs. Returns a pointer to the result is
  871. successful; NULL otherwise.]
  872. SideEffects [None]
  873. SeeAlso [Cudd_bddXor]
  874. ******************************************************************************/
  875. DdNode *
  876. cuddBddXorRecur(
  877. DdManager * manager,
  878. DdNode * f,
  879. DdNode * g)
  880. {
  881. DdNode *fv, *fnv, *G, *gv, *gnv;
  882. DdNode *one, *zero, *r, *t, *e;
  883. unsigned int topf, topg, index;
  884. statLine(manager);
  885. one = DD_ONE(manager);
  886. zero = Cudd_Not(one);
  887. /* Terminal cases. */
  888. if (f == g) return(zero);
  889. if (f == Cudd_Not(g)) return(one);
  890. if (f > g) { /* Try to increase cache efficiency and simplify tests. */
  891. DdNode *tmp = f;
  892. f = g;
  893. g = tmp;
  894. }
  895. if (g == zero) return(f);
  896. if (g == one) return(Cudd_Not(f));
  897. if (Cudd_IsComplement(f)) {
  898. f = Cudd_Not(f);
  899. g = Cudd_Not(g);
  900. }
  901. /* Now the first argument is regular. */
  902. if (f == one) return(Cudd_Not(g));
  903. /* At this point f and g are not constant. */
  904. /* Check cache. */
  905. r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
  906. if (r != NULL) return(r);
  907. /* Here we can skip the use of cuddI, because the operands are known
  908. ** to be non-constant.
  909. */
  910. topf = manager->perm[f->index];
  911. G = Cudd_Regular(g);
  912. topg = manager->perm[G->index];
  913. /* Compute cofactors. */
  914. if (topf <= topg) {
  915. index = f->index;
  916. fv = cuddT(f);
  917. fnv = cuddE(f);
  918. } else {
  919. index = G->index;
  920. fv = fnv = f;
  921. }
  922. if (topg <= topf) {
  923. gv = cuddT(G);
  924. gnv = cuddE(G);
  925. if (Cudd_IsComplement(g)) {
  926. gv = Cudd_Not(gv);
  927. gnv = Cudd_Not(gnv);
  928. }
  929. } else {
  930. gv = gnv = g;
  931. }
  932. t = cuddBddXorRecur(manager, fv, gv);
  933. if (t == NULL) return(NULL);
  934. cuddRef(t);
  935. e = cuddBddXorRecur(manager, fnv, gnv);
  936. if (e == NULL) {
  937. Cudd_IterDerefBdd(manager, t);
  938. return(NULL);
  939. }
  940. cuddRef(e);
  941. if (t == e) {
  942. r = t;
  943. } else {
  944. if (Cudd_IsComplement(t)) {
  945. r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
  946. if (r == NULL) {
  947. Cudd_IterDerefBdd(manager, t);
  948. Cudd_IterDerefBdd(manager, e);
  949. return(NULL);
  950. }
  951. r = Cudd_Not(r);
  952. } else {
  953. r = cuddUniqueInter(manager,(int)index,t,e);
  954. if (r == NULL) {
  955. Cudd_IterDerefBdd(manager, t);
  956. Cudd_IterDerefBdd(manager, e);
  957. return(NULL);
  958. }
  959. }
  960. }
  961. cuddDeref(e);
  962. cuddDeref(t);
  963. cuddCacheInsert2(manager, Cudd_bddXor, f, g, r);
  964. return(r);
  965. } /* end of cuddBddXorRecur */
  966. /*---------------------------------------------------------------------------*/
  967. /* Definition of static functions */
  968. /*---------------------------------------------------------------------------*/
  969. /**Function********************************************************************
  970. Synopsis [Replaces variables with constants if possible.]
  971. Description [This function performs part of the transformation to
  972. standard form by replacing variables with constants if possible.]
  973. SideEffects [None]
  974. SeeAlso [bddVarToCanonical bddVarToCanonicalSimple]
  975. ******************************************************************************/
  976. static void
  977. bddVarToConst(
  978. DdNode * f,
  979. DdNode ** gp,
  980. DdNode ** hp,
  981. DdNode * one)
  982. {
  983. DdNode *g = *gp;
  984. DdNode *h = *hp;
  985. if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
  986. *gp = one;
  987. } else if (f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
  988. *gp = Cudd_Not(one);
  989. }
  990. if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
  991. *hp = Cudd_Not(one);
  992. } else if (f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
  993. *hp = one;
  994. }
  995. } /* end of bddVarToConst */
  996. /**Function********************************************************************
  997. Synopsis [Picks unique member from equiv expressions.]
  998. Description [Reduces 2 variable expressions to canonical form.]
  999. SideEffects [None]
  1000. SeeAlso [bddVarToConst bddVarToCanonicalSimple]
  1001. ******************************************************************************/
  1002. static int
  1003. bddVarToCanonical(
  1004. DdManager * dd,
  1005. DdNode ** fp,
  1006. DdNode ** gp,
  1007. DdNode ** hp,
  1008. unsigned int * topfp,
  1009. unsigned int * topgp,
  1010. unsigned int * tophp)
  1011. {
  1012. register DdNode *F, *G, *H, *r, *f, *g, *h;
  1013. register unsigned int topf, topg, toph;
  1014. DdNode *one = dd->one;
  1015. int comple, change;
  1016. f = *fp;
  1017. g = *gp;
  1018. h = *hp;
  1019. F = Cudd_Regular(f);
  1020. G = Cudd_Regular(g);
  1021. H = Cudd_Regular(h);
  1022. topf = cuddI(dd,F->index);
  1023. topg = cuddI(dd,G->index);
  1024. toph = cuddI(dd,H->index);
  1025. change = 0;
  1026. if (G == one) { /* ITE(F,c,H) */
  1027. if ((topf > toph) || (topf == toph && f > h)) {
  1028. r = h;
  1029. h = f;
  1030. f = r; /* ITE(F,1,H) = ITE(H,1,F) */
  1031. if (g != one) { /* g == zero */
  1032. f = Cudd_Not(f); /* ITE(F,0,H) = ITE(!H,0,!F) */
  1033. h = Cudd_Not(h);
  1034. }
  1035. change = 1;
  1036. }
  1037. } else if (H == one) { /* ITE(F,G,c) */
  1038. if ((topf > topg) || (topf == topg && f > g)) {
  1039. r = g;
  1040. g = f;
  1041. f = r; /* ITE(F,G,0) = ITE(G,F,0) */
  1042. if (h == one) {
  1043. f = Cudd_Not(f); /* ITE(F,G,1) = ITE(!G,!F,1) */
  1044. g = Cudd_Not(g);
  1045. }
  1046. change = 1;
  1047. }
  1048. } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = ITE(G,F,!F) */
  1049. if ((topf > topg) || (topf == topg && f > g)) {
  1050. r = f;
  1051. f = g;
  1052. g = r;
  1053. h = Cudd_Not(r);
  1054. change = 1;
  1055. }
  1056. }
  1057. /* adjust pointers so that the first 2 arguments to ITE are regular */
  1058. if (Cudd_IsComplement(f) != 0) { /* ITE(!F,G,H) = ITE(F,H,G) */
  1059. f = Cudd_Not(f);
  1060. r = g;
  1061. g = h;
  1062. h = r;
  1063. change = 1;
  1064. }
  1065. comple = 0;
  1066. if (Cudd_IsComplement(g) != 0) { /* ITE(F,!G,H) = !ITE(F,G,!H) */
  1067. g = Cudd_Not(g);
  1068. h = Cudd_Not(h);
  1069. change = 1;
  1070. comple = 1;
  1071. }
  1072. if (change != 0) {
  1073. *fp = f;
  1074. *gp = g;
  1075. *hp = h;
  1076. }
  1077. *topfp = cuddI(dd,f->index);
  1078. *topgp = cuddI(dd,g->index);
  1079. *tophp = cuddI(dd,Cudd_Regular(h)->index);
  1080. return(comple);
  1081. } /* end of bddVarToCanonical */
  1082. /**Function********************************************************************
  1083. Synopsis [Picks unique member from equiv expressions.]
  1084. Description [Makes sure the first two pointers are regular. This
  1085. mat require the complementation of the result, which is signaled by
  1086. returning 1 instead of 0. This function is simpler than the general
  1087. case because it assumes that no two arguments are the same or
  1088. complementary, and no argument is constant.]
  1089. SideEffects [None]
  1090. SeeAlso [bddVarToConst bddVarToCanonical]
  1091. ******************************************************************************/
  1092. static int
  1093. bddVarToCanonicalSimple(
  1094. DdManager * dd,
  1095. DdNode ** fp,
  1096. DdNode ** gp,
  1097. DdNode ** hp,
  1098. unsigned int * topfp,
  1099. unsigned int * topgp,
  1100. unsigned int * tophp)
  1101. {
  1102. register DdNode *r, *f, *g, *h;
  1103. int comple, change;
  1104. f = *fp;
  1105. g = *gp;
  1106. h = *hp;
  1107. change = 0;
  1108. /* adjust pointers so that the first 2 arguments to ITE are regular */
  1109. if (Cudd_IsComplement(f)) { /* ITE(!F,G,H) = ITE(F,H,G) */
  1110. f = Cudd_Not(f);
  1111. r = g;
  1112. g = h;
  1113. h = r;
  1114. change = 1;
  1115. }
  1116. comple = 0;
  1117. if (Cudd_IsComplement(g)) { /* ITE(F,!G,H) = !ITE(F,G,!H) */
  1118. g = Cudd_Not(g);
  1119. h = Cudd_Not(h);
  1120. change = 1;
  1121. comple = 1;
  1122. }
  1123. if (change) {
  1124. *fp = f;
  1125. *gp = g;
  1126. *hp = h;
  1127. }
  1128. /* Here we can skip the use of cuddI, because the operands are known
  1129. ** to be non-constant.
  1130. */
  1131. *topfp = dd->perm[f->index];
  1132. *topgp = dd->perm[g->index];
  1133. *tophp = dd->perm[Cudd_Regular(h)->index];
  1134. return(comple);
  1135. } /* end of bddVarToCanonicalSimple */