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.

2177 lines
62 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddDecomp.c]
  3. PackageName [cudd]
  4. Synopsis [Functions for BDD decomposition.]
  5. Description [External procedures included in this file:
  6. <ul>
  7. <li> Cudd_bddApproxConjDecomp()
  8. <li> Cudd_bddApproxDisjDecomp()
  9. <li> Cudd_bddIterConjDecomp()
  10. <li> Cudd_bddIterDisjDecomp()
  11. <li> Cudd_bddGenConjDecomp()
  12. <li> Cudd_bddGenDisjDecomp()
  13. <li> Cudd_bddVarConjDecomp()
  14. <li> Cudd_bddVarDisjDecomp()
  15. </ul>
  16. Static procedures included in this module:
  17. <ul>
  18. <li> cuddConjunctsAux()
  19. <li> CreateBotDist()
  20. <li> BuildConjuncts()
  21. <li> ConjunctsFree()
  22. </ul>]
  23. Author [Kavita Ravi, Fabio Somenzi]
  24. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  25. All rights reserved.
  26. Redistribution and use in source and binary forms, with or without
  27. modification, are permitted provided that the following conditions
  28. are met:
  29. Redistributions of source code must retain the above copyright
  30. notice, this list of conditions and the following disclaimer.
  31. Redistributions in binary form must reproduce the above copyright
  32. notice, this list of conditions and the following disclaimer in the
  33. documentation and/or other materials provided with the distribution.
  34. Neither the name of the University of Colorado nor the names of its
  35. contributors may be used to endorse or promote products derived from
  36. this software without specific prior written permission.
  37. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  38. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  39. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  40. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  41. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  42. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  43. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  44. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  45. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  46. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  47. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  48. POSSIBILITY OF SUCH DAMAGE.]
  49. ******************************************************************************/
  50. #include "util.h"
  51. #include "cuddInt.h"
  52. /*---------------------------------------------------------------------------*/
  53. /* Constant declarations */
  54. /*---------------------------------------------------------------------------*/
  55. #define DEPTH 5
  56. #define THRESHOLD 10
  57. #define NONE 0
  58. #define PAIR_ST 1
  59. #define PAIR_CR 2
  60. #define G_ST 3
  61. #define G_CR 4
  62. #define H_ST 5
  63. #define H_CR 6
  64. #define BOTH_G 7
  65. #define BOTH_H 8
  66. /*---------------------------------------------------------------------------*/
  67. /* Stucture declarations */
  68. /*---------------------------------------------------------------------------*/
  69. /*---------------------------------------------------------------------------*/
  70. /* Type declarations */
  71. /*---------------------------------------------------------------------------*/
  72. typedef struct Conjuncts {
  73. DdNode *g;
  74. DdNode *h;
  75. } Conjuncts;
  76. typedef struct NodeStat {
  77. int distance;
  78. int localRef;
  79. } NodeStat;
  80. /*---------------------------------------------------------------------------*/
  81. /* Variable declarations */
  82. /*---------------------------------------------------------------------------*/
  83. #ifndef lint
  84. static char rcsid[] DD_UNUSED = "$Id: cuddDecomp.c,v 1.45 2012/02/05 01:07:18 fabio Exp $";
  85. #endif
  86. static DdNode *one, *zero;
  87. long lastTimeG;
  88. /*---------------------------------------------------------------------------*/
  89. /* Macro declarations */
  90. /*---------------------------------------------------------------------------*/
  91. #define FactorsNotStored(factors) ((int)((long)(factors) & 01))
  92. #define FactorsComplement(factors) ((Conjuncts *)((long)(factors) | 01))
  93. #define FactorsUncomplement(factors) ((Conjuncts *)((long)(factors) ^ 01))
  94. /**AutomaticStart*************************************************************/
  95. /*---------------------------------------------------------------------------*/
  96. /* Static function prototypes */
  97. /*---------------------------------------------------------------------------*/
  98. static NodeStat * CreateBotDist (DdNode * node, st_table * distanceTable);
  99. static double CountMinterms (DdNode * node, double max, st_table * mintermTable, FILE *fp);
  100. static void ConjunctsFree (DdManager * dd, Conjuncts * factors);
  101. static int PairInTables (DdNode * g, DdNode * h, st_table * ghTable);
  102. static Conjuncts * CheckTablesCacheAndReturn (DdNode * node, DdNode * g, DdNode * h, st_table * ghTable, st_table * cacheTable);
  103. static Conjuncts * PickOnePair (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable);
  104. static Conjuncts * CheckInTables (DdNode * node, DdNode * g1, DdNode * h1, DdNode * g2, DdNode * h2, st_table * ghTable, st_table * cacheTable, int * outOfMem);
  105. static Conjuncts * ZeroCase (DdManager * dd, DdNode * node, Conjuncts * factorsNv, st_table * ghTable, st_table * cacheTable, int switched);
  106. static Conjuncts * BuildConjuncts (DdManager * dd, DdNode * node, st_table * distanceTable, st_table * cacheTable, int approxDistance, int maxLocalRef, st_table * ghTable, st_table * mintermTable);
  107. static int cuddConjunctsAux (DdManager * dd, DdNode * f, DdNode ** c1, DdNode ** c2);
  108. /**AutomaticEnd***************************************************************/
  109. /*---------------------------------------------------------------------------*/
  110. /* Definition of exported functions */
  111. /*---------------------------------------------------------------------------*/
  112. /**Function********************************************************************
  113. Synopsis [Performs two-way conjunctive decomposition of a BDD.]
  114. Description [Performs two-way conjunctive decomposition of a
  115. BDD. This procedure owes its name to the use of supersetting to
  116. obtain an initial factor of the given function. Returns the number
  117. of conjuncts produced, that is, 2 if successful; 1 if no meaningful
  118. decomposition was found; 0 otherwise. The conjuncts produced by this
  119. procedure tend to be imbalanced.]
  120. SideEffects [The factors are returned in an array as side effects.
  121. The array is allocated by this function. It is the caller's responsibility
  122. to free it. On successful completion, the conjuncts are already
  123. referenced. If the function returns 0, the array for the conjuncts is
  124. not allocated. If the function returns 1, the only factor equals the
  125. function to be decomposed.]
  126. SeeAlso [Cudd_bddApproxDisjDecomp Cudd_bddIterConjDecomp
  127. Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox
  128. Cudd_bddSqueeze Cudd_bddLICompaction]
  129. ******************************************************************************/
  130. int
  131. Cudd_bddApproxConjDecomp(
  132. DdManager * dd /* manager */,
  133. DdNode * f /* function to be decomposed */,
  134. DdNode *** conjuncts /* address of the first factor */)
  135. {
  136. DdNode *superset1, *superset2, *glocal, *hlocal;
  137. int nvars = Cudd_SupportSize(dd,f);
  138. /* Find a tentative first factor by overapproximation and minimization. */
  139. superset1 = Cudd_RemapOverApprox(dd,f,nvars,0,1.0);
  140. if (superset1 == NULL) return(0);
  141. cuddRef(superset1);
  142. superset2 = Cudd_bddSqueeze(dd,f,superset1);
  143. if (superset2 == NULL) {
  144. Cudd_RecursiveDeref(dd,superset1);
  145. return(0);
  146. }
  147. cuddRef(superset2);
  148. Cudd_RecursiveDeref(dd,superset1);
  149. /* Compute the second factor by minimization. */
  150. hlocal = Cudd_bddLICompaction(dd,f,superset2);
  151. if (hlocal == NULL) {
  152. Cudd_RecursiveDeref(dd,superset2);
  153. return(0);
  154. }
  155. cuddRef(hlocal);
  156. /* Refine the first factor by minimization. If h turns out to be f, this
  157. ** step guarantees that g will be 1. */
  158. glocal = Cudd_bddLICompaction(dd,superset2,hlocal);
  159. if (glocal == NULL) {
  160. Cudd_RecursiveDeref(dd,superset2);
  161. Cudd_RecursiveDeref(dd,hlocal);
  162. return(0);
  163. }
  164. cuddRef(glocal);
  165. Cudd_RecursiveDeref(dd,superset2);
  166. if (glocal != DD_ONE(dd)) {
  167. if (hlocal != DD_ONE(dd)) {
  168. *conjuncts = ALLOC(DdNode *,2);
  169. if (*conjuncts == NULL) {
  170. Cudd_RecursiveDeref(dd,glocal);
  171. Cudd_RecursiveDeref(dd,hlocal);
  172. dd->errorCode = CUDD_MEMORY_OUT;
  173. return(0);
  174. }
  175. (*conjuncts)[0] = glocal;
  176. (*conjuncts)[1] = hlocal;
  177. return(2);
  178. } else {
  179. Cudd_RecursiveDeref(dd,hlocal);
  180. *conjuncts = ALLOC(DdNode *,1);
  181. if (*conjuncts == NULL) {
  182. Cudd_RecursiveDeref(dd,glocal);
  183. dd->errorCode = CUDD_MEMORY_OUT;
  184. return(0);
  185. }
  186. (*conjuncts)[0] = glocal;
  187. return(1);
  188. }
  189. } else {
  190. Cudd_RecursiveDeref(dd,glocal);
  191. *conjuncts = ALLOC(DdNode *,1);
  192. if (*conjuncts == NULL) {
  193. Cudd_RecursiveDeref(dd,hlocal);
  194. dd->errorCode = CUDD_MEMORY_OUT;
  195. return(0);
  196. }
  197. (*conjuncts)[0] = hlocal;
  198. return(1);
  199. }
  200. } /* end of Cudd_bddApproxConjDecomp */
  201. /**Function********************************************************************
  202. Synopsis [Performs two-way disjunctive decomposition of a BDD.]
  203. Description [Performs two-way disjunctive decomposition of a BDD.
  204. Returns the number of disjuncts produced, that is, 2 if successful;
  205. 1 if no meaningful decomposition was found; 0 otherwise. The
  206. disjuncts produced by this procedure tend to be imbalanced.]
  207. SideEffects [The two disjuncts are returned in an array as side effects.
  208. The array is allocated by this function. It is the caller's responsibility
  209. to free it. On successful completion, the disjuncts are already
  210. referenced. If the function returns 0, the array for the disjuncts is
  211. not allocated. If the function returns 1, the only factor equals the
  212. function to be decomposed.]
  213. SeeAlso [Cudd_bddApproxConjDecomp Cudd_bddIterDisjDecomp
  214. Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp]
  215. ******************************************************************************/
  216. int
  217. Cudd_bddApproxDisjDecomp(
  218. DdManager * dd /* manager */,
  219. DdNode * f /* function to be decomposed */,
  220. DdNode *** disjuncts /* address of the array of the disjuncts */)
  221. {
  222. int result, i;
  223. result = Cudd_bddApproxConjDecomp(dd,Cudd_Not(f),disjuncts);
  224. for (i = 0; i < result; i++) {
  225. (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
  226. }
  227. return(result);
  228. } /* end of Cudd_bddApproxDisjDecomp */
  229. /**Function********************************************************************
  230. Synopsis [Performs two-way conjunctive decomposition of a BDD.]
  231. Description [Performs two-way conjunctive decomposition of a
  232. BDD. This procedure owes its name to the iterated use of
  233. supersetting to obtain a factor of the given function. Returns the
  234. number of conjuncts produced, that is, 2 if successful; 1 if no
  235. meaningful decomposition was found; 0 otherwise. The conjuncts
  236. produced by this procedure tend to be imbalanced.]
  237. SideEffects [The factors are returned in an array as side effects.
  238. The array is allocated by this function. It is the caller's responsibility
  239. to free it. On successful completion, the conjuncts are already
  240. referenced. If the function returns 0, the array for the conjuncts is
  241. not allocated. If the function returns 1, the only factor equals the
  242. function to be decomposed.]
  243. SeeAlso [Cudd_bddIterDisjDecomp Cudd_bddApproxConjDecomp
  244. Cudd_bddGenConjDecomp Cudd_bddVarConjDecomp Cudd_RemapOverApprox
  245. Cudd_bddSqueeze Cudd_bddLICompaction]
  246. ******************************************************************************/
  247. int
  248. Cudd_bddIterConjDecomp(
  249. DdManager * dd /* manager */,
  250. DdNode * f /* function to be decomposed */,
  251. DdNode *** conjuncts /* address of the array of conjuncts */)
  252. {
  253. DdNode *superset1, *superset2, *old[2], *res[2];
  254. int sizeOld, sizeNew;
  255. int nvars = Cudd_SupportSize(dd,f);
  256. old[0] = DD_ONE(dd);
  257. cuddRef(old[0]);
  258. old[1] = f;
  259. cuddRef(old[1]);
  260. sizeOld = Cudd_SharingSize(old,2);
  261. do {
  262. /* Find a tentative first factor by overapproximation and
  263. ** minimization. */
  264. superset1 = Cudd_RemapOverApprox(dd,old[1],nvars,0,1.0);
  265. if (superset1 == NULL) {
  266. Cudd_RecursiveDeref(dd,old[0]);
  267. Cudd_RecursiveDeref(dd,old[1]);
  268. return(0);
  269. }
  270. cuddRef(superset1);
  271. superset2 = Cudd_bddSqueeze(dd,old[1],superset1);
  272. if (superset2 == NULL) {
  273. Cudd_RecursiveDeref(dd,old[0]);
  274. Cudd_RecursiveDeref(dd,old[1]);
  275. Cudd_RecursiveDeref(dd,superset1);
  276. return(0);
  277. }
  278. cuddRef(superset2);
  279. Cudd_RecursiveDeref(dd,superset1);
  280. res[0] = Cudd_bddAnd(dd,old[0],superset2);
  281. if (res[0] == NULL) {
  282. Cudd_RecursiveDeref(dd,superset2);
  283. Cudd_RecursiveDeref(dd,old[0]);
  284. Cudd_RecursiveDeref(dd,old[1]);
  285. return(0);
  286. }
  287. cuddRef(res[0]);
  288. Cudd_RecursiveDeref(dd,superset2);
  289. if (res[0] == old[0]) {
  290. Cudd_RecursiveDeref(dd,res[0]);
  291. break; /* avoid infinite loop */
  292. }
  293. /* Compute the second factor by minimization. */
  294. res[1] = Cudd_bddLICompaction(dd,old[1],res[0]);
  295. if (res[1] == NULL) {
  296. Cudd_RecursiveDeref(dd,old[0]);
  297. Cudd_RecursiveDeref(dd,old[1]);
  298. return(0);
  299. }
  300. cuddRef(res[1]);
  301. sizeNew = Cudd_SharingSize(res,2);
  302. if (sizeNew <= sizeOld) {
  303. Cudd_RecursiveDeref(dd,old[0]);
  304. old[0] = res[0];
  305. Cudd_RecursiveDeref(dd,old[1]);
  306. old[1] = res[1];
  307. sizeOld = sizeNew;
  308. } else {
  309. Cudd_RecursiveDeref(dd,res[0]);
  310. Cudd_RecursiveDeref(dd,res[1]);
  311. break;
  312. }
  313. } while (1);
  314. /* Refine the first factor by minimization. If h turns out to
  315. ** be f, this step guarantees that g will be 1. */
  316. superset1 = Cudd_bddLICompaction(dd,old[0],old[1]);
  317. if (superset1 == NULL) {
  318. Cudd_RecursiveDeref(dd,old[0]);
  319. Cudd_RecursiveDeref(dd,old[1]);
  320. return(0);
  321. }
  322. cuddRef(superset1);
  323. Cudd_RecursiveDeref(dd,old[0]);
  324. old[0] = superset1;
  325. if (old[0] != DD_ONE(dd)) {
  326. if (old[1] != DD_ONE(dd)) {
  327. *conjuncts = ALLOC(DdNode *,2);
  328. if (*conjuncts == NULL) {
  329. Cudd_RecursiveDeref(dd,old[0]);
  330. Cudd_RecursiveDeref(dd,old[1]);
  331. dd->errorCode = CUDD_MEMORY_OUT;
  332. return(0);
  333. }
  334. (*conjuncts)[0] = old[0];
  335. (*conjuncts)[1] = old[1];
  336. return(2);
  337. } else {
  338. Cudd_RecursiveDeref(dd,old[1]);
  339. *conjuncts = ALLOC(DdNode *,1);
  340. if (*conjuncts == NULL) {
  341. Cudd_RecursiveDeref(dd,old[0]);
  342. dd->errorCode = CUDD_MEMORY_OUT;
  343. return(0);
  344. }
  345. (*conjuncts)[0] = old[0];
  346. return(1);
  347. }
  348. } else {
  349. Cudd_RecursiveDeref(dd,old[0]);
  350. *conjuncts = ALLOC(DdNode *,1);
  351. if (*conjuncts == NULL) {
  352. Cudd_RecursiveDeref(dd,old[1]);
  353. dd->errorCode = CUDD_MEMORY_OUT;
  354. return(0);
  355. }
  356. (*conjuncts)[0] = old[1];
  357. return(1);
  358. }
  359. } /* end of Cudd_bddIterConjDecomp */
  360. /**Function********************************************************************
  361. Synopsis [Performs two-way disjunctive decomposition of a BDD.]
  362. Description [Performs two-way disjunctive decomposition of a BDD.
  363. Returns the number of disjuncts produced, that is, 2 if successful;
  364. 1 if no meaningful decomposition was found; 0 otherwise. The
  365. disjuncts produced by this procedure tend to be imbalanced.]
  366. SideEffects [The two disjuncts are returned in an array as side effects.
  367. The array is allocated by this function. It is the caller's responsibility
  368. to free it. On successful completion, the disjuncts are already
  369. referenced. If the function returns 0, the array for the disjuncts is
  370. not allocated. If the function returns 1, the only factor equals the
  371. function to be decomposed.]
  372. SeeAlso [Cudd_bddIterConjDecomp Cudd_bddApproxDisjDecomp
  373. Cudd_bddGenDisjDecomp Cudd_bddVarDisjDecomp]
  374. ******************************************************************************/
  375. int
  376. Cudd_bddIterDisjDecomp(
  377. DdManager * dd /* manager */,
  378. DdNode * f /* function to be decomposed */,
  379. DdNode *** disjuncts /* address of the array of the disjuncts */)
  380. {
  381. int result, i;
  382. result = Cudd_bddIterConjDecomp(dd,Cudd_Not(f),disjuncts);
  383. for (i = 0; i < result; i++) {
  384. (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
  385. }
  386. return(result);
  387. } /* end of Cudd_bddIterDisjDecomp */
  388. /**Function********************************************************************
  389. Synopsis [Performs two-way conjunctive decomposition of a BDD.]
  390. Description [Performs two-way conjunctive decomposition of a
  391. BDD. This procedure owes its name to the fact tht it generalizes the
  392. decomposition based on the cofactors with respect to one
  393. variable. Returns the number of conjuncts produced, that is, 2 if
  394. successful; 1 if no meaningful decomposition was found; 0
  395. otherwise. The conjuncts produced by this procedure tend to be
  396. balanced.]
  397. SideEffects [The two factors are returned in an array as side effects.
  398. The array is allocated by this function. It is the caller's responsibility
  399. to free it. On successful completion, the conjuncts are already
  400. referenced. If the function returns 0, the array for the conjuncts is
  401. not allocated. If the function returns 1, the only factor equals the
  402. function to be decomposed.]
  403. SeeAlso [Cudd_bddGenDisjDecomp Cudd_bddApproxConjDecomp
  404. Cudd_bddIterConjDecomp Cudd_bddVarConjDecomp]
  405. ******************************************************************************/
  406. int
  407. Cudd_bddGenConjDecomp(
  408. DdManager * dd /* manager */,
  409. DdNode * f /* function to be decomposed */,
  410. DdNode *** conjuncts /* address of the array of conjuncts */)
  411. {
  412. int result;
  413. DdNode *glocal, *hlocal;
  414. one = DD_ONE(dd);
  415. zero = Cudd_Not(one);
  416. do {
  417. dd->reordered = 0;
  418. result = cuddConjunctsAux(dd, f, &glocal, &hlocal);
  419. } while (dd->reordered == 1);
  420. if (result == 0) {
  421. return(0);
  422. }
  423. if (glocal != one) {
  424. if (hlocal != one) {
  425. *conjuncts = ALLOC(DdNode *,2);
  426. if (*conjuncts == NULL) {
  427. Cudd_RecursiveDeref(dd,glocal);
  428. Cudd_RecursiveDeref(dd,hlocal);
  429. dd->errorCode = CUDD_MEMORY_OUT;
  430. return(0);
  431. }
  432. (*conjuncts)[0] = glocal;
  433. (*conjuncts)[1] = hlocal;
  434. return(2);
  435. } else {
  436. Cudd_RecursiveDeref(dd,hlocal);
  437. *conjuncts = ALLOC(DdNode *,1);
  438. if (*conjuncts == NULL) {
  439. Cudd_RecursiveDeref(dd,glocal);
  440. dd->errorCode = CUDD_MEMORY_OUT;
  441. return(0);
  442. }
  443. (*conjuncts)[0] = glocal;
  444. return(1);
  445. }
  446. } else {
  447. Cudd_RecursiveDeref(dd,glocal);
  448. *conjuncts = ALLOC(DdNode *,1);
  449. if (*conjuncts == NULL) {
  450. Cudd_RecursiveDeref(dd,hlocal);
  451. dd->errorCode = CUDD_MEMORY_OUT;
  452. return(0);
  453. }
  454. (*conjuncts)[0] = hlocal;
  455. return(1);
  456. }
  457. } /* end of Cudd_bddGenConjDecomp */
  458. /**Function********************************************************************
  459. Synopsis [Performs two-way disjunctive decomposition of a BDD.]
  460. Description [Performs two-way disjunctive decomposition of a BDD.
  461. Returns the number of disjuncts produced, that is, 2 if successful;
  462. 1 if no meaningful decomposition was found; 0 otherwise. The
  463. disjuncts produced by this procedure tend to be balanced.]
  464. SideEffects [The two disjuncts are returned in an array as side effects.
  465. The array is allocated by this function. It is the caller's responsibility
  466. to free it. On successful completion, the disjuncts are already
  467. referenced. If the function returns 0, the array for the disjuncts is
  468. not allocated. If the function returns 1, the only factor equals the
  469. function to be decomposed.]
  470. SeeAlso [Cudd_bddGenConjDecomp Cudd_bddApproxDisjDecomp
  471. Cudd_bddIterDisjDecomp Cudd_bddVarDisjDecomp]
  472. ******************************************************************************/
  473. int
  474. Cudd_bddGenDisjDecomp(
  475. DdManager * dd /* manager */,
  476. DdNode * f /* function to be decomposed */,
  477. DdNode *** disjuncts /* address of the array of the disjuncts */)
  478. {
  479. int result, i;
  480. result = Cudd_bddGenConjDecomp(dd,Cudd_Not(f),disjuncts);
  481. for (i = 0; i < result; i++) {
  482. (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
  483. }
  484. return(result);
  485. } /* end of Cudd_bddGenDisjDecomp */
  486. /**Function********************************************************************
  487. Synopsis [Performs two-way conjunctive decomposition of a BDD.]
  488. Description [Conjunctively decomposes one BDD according to a
  489. variable. If <code>f</code> is the function of the BDD and
  490. <code>x</code> is the variable, the decomposition is
  491. <code>(f+x)(f+x')</code>. The variable is chosen so as to balance
  492. the sizes of the two conjuncts and to keep them small. Returns the
  493. number of conjuncts produced, that is, 2 if successful; 1 if no
  494. meaningful decomposition was found; 0 otherwise.]
  495. SideEffects [The two factors are returned in an array as side effects.
  496. The array is allocated by this function. It is the caller's responsibility
  497. to free it. On successful completion, the conjuncts are already
  498. referenced. If the function returns 0, the array for the conjuncts is
  499. not allocated. If the function returns 1, the only factor equals the
  500. function to be decomposed.]
  501. SeeAlso [Cudd_bddVarDisjDecomp Cudd_bddGenConjDecomp
  502. Cudd_bddApproxConjDecomp Cudd_bddIterConjDecomp]
  503. *****************************************************************************/
  504. int
  505. Cudd_bddVarConjDecomp(
  506. DdManager * dd /* manager */,
  507. DdNode * f /* function to be decomposed */,
  508. DdNode *** conjuncts /* address of the array of conjuncts */)
  509. {
  510. int best;
  511. int min;
  512. DdNode *support, *scan, *var, *glocal, *hlocal;
  513. /* Find best cofactoring variable. */
  514. support = Cudd_Support(dd,f);
  515. if (support == NULL) return(0);
  516. if (Cudd_IsConstant(support)) {
  517. *conjuncts = ALLOC(DdNode *,1);
  518. if (*conjuncts == NULL) {
  519. dd->errorCode = CUDD_MEMORY_OUT;
  520. return(0);
  521. }
  522. (*conjuncts)[0] = f;
  523. cuddRef((*conjuncts)[0]);
  524. return(1);
  525. }
  526. cuddRef(support);
  527. min = 1000000000;
  528. best = -1;
  529. scan = support;
  530. while (!Cudd_IsConstant(scan)) {
  531. int i = scan->index;
  532. int est1 = Cudd_EstimateCofactor(dd,f,i,1);
  533. int est0 = Cudd_EstimateCofactor(dd,f,i,0);
  534. /* Minimize the size of the larger of the two cofactors. */
  535. int est = (est1 > est0) ? est1 : est0;
  536. if (est < min) {
  537. min = est;
  538. best = i;
  539. }
  540. scan = cuddT(scan);
  541. }
  542. #ifdef DD_DEBUG
  543. assert(best >= 0 && best < dd->size);
  544. #endif
  545. Cudd_RecursiveDeref(dd,support);
  546. var = Cudd_bddIthVar(dd,best);
  547. glocal = Cudd_bddOr(dd,f,var);
  548. if (glocal == NULL) {
  549. return(0);
  550. }
  551. cuddRef(glocal);
  552. hlocal = Cudd_bddOr(dd,f,Cudd_Not(var));
  553. if (hlocal == NULL) {
  554. Cudd_RecursiveDeref(dd,glocal);
  555. return(0);
  556. }
  557. cuddRef(hlocal);
  558. if (glocal != DD_ONE(dd)) {
  559. if (hlocal != DD_ONE(dd)) {
  560. *conjuncts = ALLOC(DdNode *,2);
  561. if (*conjuncts == NULL) {
  562. Cudd_RecursiveDeref(dd,glocal);
  563. Cudd_RecursiveDeref(dd,hlocal);
  564. dd->errorCode = CUDD_MEMORY_OUT;
  565. return(0);
  566. }
  567. (*conjuncts)[0] = glocal;
  568. (*conjuncts)[1] = hlocal;
  569. return(2);
  570. } else {
  571. Cudd_RecursiveDeref(dd,hlocal);
  572. *conjuncts = ALLOC(DdNode *,1);
  573. if (*conjuncts == NULL) {
  574. Cudd_RecursiveDeref(dd,glocal);
  575. dd->errorCode = CUDD_MEMORY_OUT;
  576. return(0);
  577. }
  578. (*conjuncts)[0] = glocal;
  579. return(1);
  580. }
  581. } else {
  582. Cudd_RecursiveDeref(dd,glocal);
  583. *conjuncts = ALLOC(DdNode *,1);
  584. if (*conjuncts == NULL) {
  585. Cudd_RecursiveDeref(dd,hlocal);
  586. dd->errorCode = CUDD_MEMORY_OUT;
  587. return(0);
  588. }
  589. (*conjuncts)[0] = hlocal;
  590. return(1);
  591. }
  592. } /* end of Cudd_bddVarConjDecomp */
  593. /**Function********************************************************************
  594. Synopsis [Performs two-way disjunctive decomposition of a BDD.]
  595. Description [Performs two-way disjunctive decomposition of a BDD
  596. according to a variable. If <code>f</code> is the function of the
  597. BDD and <code>x</code> is the variable, the decomposition is
  598. <code>f*x + f*x'</code>. The variable is chosen so as to balance
  599. the sizes of the two disjuncts and to keep them small. Returns the
  600. number of disjuncts produced, that is, 2 if successful; 1 if no
  601. meaningful decomposition was found; 0 otherwise.]
  602. SideEffects [The two disjuncts are returned in an array as side effects.
  603. The array is allocated by this function. It is the caller's responsibility
  604. to free it. On successful completion, the disjuncts are already
  605. referenced. If the function returns 0, the array for the disjuncts is
  606. not allocated. If the function returns 1, the only factor equals the
  607. function to be decomposed.]
  608. SeeAlso [Cudd_bddVarConjDecomp Cudd_bddApproxDisjDecomp
  609. Cudd_bddIterDisjDecomp Cudd_bddGenDisjDecomp]
  610. ******************************************************************************/
  611. int
  612. Cudd_bddVarDisjDecomp(
  613. DdManager * dd /* manager */,
  614. DdNode * f /* function to be decomposed */,
  615. DdNode *** disjuncts /* address of the array of the disjuncts */)
  616. {
  617. int result, i;
  618. result = Cudd_bddVarConjDecomp(dd,Cudd_Not(f),disjuncts);
  619. for (i = 0; i < result; i++) {
  620. (*disjuncts)[i] = Cudd_Not((*disjuncts)[i]);
  621. }
  622. return(result);
  623. } /* end of Cudd_bddVarDisjDecomp */
  624. /*---------------------------------------------------------------------------*/
  625. /* Definition of internal functions */
  626. /*---------------------------------------------------------------------------*/
  627. /*---------------------------------------------------------------------------*/
  628. /* Definition of static functions */
  629. /*---------------------------------------------------------------------------*/
  630. /**Function********************************************************************
  631. Synopsis [Get longest distance of node from constant.]
  632. Description [Get longest distance of node from constant. Returns the
  633. distance of the root from the constant if successful; CUDD_OUT_OF_MEM
  634. otherwise.]
  635. SideEffects [None]
  636. SeeAlso []
  637. ******************************************************************************/
  638. static NodeStat *
  639. CreateBotDist(
  640. DdNode * node,
  641. st_table * distanceTable)
  642. {
  643. DdNode *N, *Nv, *Nnv;
  644. int distance, distanceNv, distanceNnv;
  645. NodeStat *nodeStat, *nodeStatNv, *nodeStatNnv;
  646. #if 0
  647. if (Cudd_IsConstant(node)) {
  648. return(0);
  649. }
  650. #endif
  651. /* Return the entry in the table if found. */
  652. N = Cudd_Regular(node);
  653. if (st_lookup(distanceTable, N, &nodeStat)) {
  654. nodeStat->localRef++;
  655. return(nodeStat);
  656. }
  657. Nv = cuddT(N);
  658. Nnv = cuddE(N);
  659. Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
  660. Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
  661. /* Recur on the children. */
  662. nodeStatNv = CreateBotDist(Nv, distanceTable);
  663. if (nodeStatNv == NULL) return(NULL);
  664. distanceNv = nodeStatNv->distance;
  665. nodeStatNnv = CreateBotDist(Nnv, distanceTable);
  666. if (nodeStatNnv == NULL) return(NULL);
  667. distanceNnv = nodeStatNnv->distance;
  668. /* Store max distance from constant; note sometimes this distance
  669. ** may be to 0.
  670. */
  671. distance = (distanceNv > distanceNnv) ? (distanceNv+1) : (distanceNnv + 1);
  672. nodeStat = ALLOC(NodeStat, 1);
  673. if (nodeStat == NULL) {
  674. return(0);
  675. }
  676. nodeStat->distance = distance;
  677. nodeStat->localRef = 1;
  678. if (st_insert(distanceTable, (char *)N, (char *)nodeStat) ==
  679. ST_OUT_OF_MEM) {
  680. return(0);
  681. }
  682. return(nodeStat);
  683. } /* end of CreateBotDist */
  684. /**Function********************************************************************
  685. Synopsis [Count the number of minterms of each node ina a BDD and
  686. store it in a hash table.]
  687. Description []
  688. SideEffects [None]
  689. SeeAlso []
  690. ******************************************************************************/
  691. static double
  692. CountMinterms(
  693. DdNode * node,
  694. double max,
  695. st_table * mintermTable,
  696. FILE *fp)
  697. {
  698. DdNode *N, *Nv, *Nnv;
  699. double min, minNv, minNnv;
  700. double *dummy;
  701. N = Cudd_Regular(node);
  702. if (cuddIsConstant(N)) {
  703. if (node == zero) {
  704. return(0);
  705. } else {
  706. return(max);
  707. }
  708. }
  709. /* Return the entry in the table if found. */
  710. if (st_lookup(mintermTable, node, &dummy)) {
  711. min = *dummy;
  712. return(min);
  713. }
  714. Nv = cuddT(N);
  715. Nnv = cuddE(N);
  716. Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
  717. Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
  718. /* Recur on the children. */
  719. minNv = CountMinterms(Nv, max, mintermTable, fp);
  720. if (minNv == -1.0) return(-1.0);
  721. minNnv = CountMinterms(Nnv, max, mintermTable, fp);
  722. if (minNnv == -1.0) return(-1.0);
  723. min = minNv / 2.0 + minNnv / 2.0;
  724. /* store
  725. */
  726. dummy = ALLOC(double, 1);
  727. if (dummy == NULL) return(-1.0);
  728. *dummy = min;
  729. if (st_insert(mintermTable, (char *)node, (char *)dummy) == ST_OUT_OF_MEM) {
  730. (void) fprintf(fp, "st table insert failed\n");
  731. }
  732. return(min);
  733. } /* end of CountMinterms */
  734. /**Function********************************************************************
  735. Synopsis [Free factors structure]
  736. Description []
  737. SideEffects [None]
  738. SeeAlso []
  739. ******************************************************************************/
  740. static void
  741. ConjunctsFree(
  742. DdManager * dd,
  743. Conjuncts * factors)
  744. {
  745. Cudd_RecursiveDeref(dd, factors->g);
  746. Cudd_RecursiveDeref(dd, factors->h);
  747. FREE(factors);
  748. return;
  749. } /* end of ConjunctsFree */
  750. /**Function********************************************************************
  751. Synopsis [Check whether the given pair is in the tables.]
  752. Description [.Check whether the given pair is in the tables. gTable
  753. and hTable are combined.
  754. absence in both is indicated by 0,
  755. presence in gTable is indicated by 1,
  756. presence in hTable by 2 and
  757. presence in both by 3.
  758. The values returned by this function are PAIR_ST,
  759. PAIR_CR, G_ST, G_CR, H_ST, H_CR, BOTH_G, BOTH_H, NONE.
  760. PAIR_ST implies g in gTable and h in hTable
  761. PAIR_CR implies g in hTable and h in gTable
  762. G_ST implies g in gTable and h not in any table
  763. G_CR implies g in hTable and h not in any table
  764. H_ST implies h in hTable and g not in any table
  765. H_CR implies h in gTable and g not in any table
  766. BOTH_G implies both in gTable
  767. BOTH_H implies both in hTable
  768. NONE implies none in table; ]
  769. SideEffects []
  770. SeeAlso [CheckTablesCacheAndReturn CheckInTables]
  771. ******************************************************************************/
  772. static int
  773. PairInTables(
  774. DdNode * g,
  775. DdNode * h,
  776. st_table * ghTable)
  777. {
  778. int valueG, valueH, gPresent, hPresent;
  779. valueG = valueH = gPresent = hPresent = 0;
  780. gPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(g), &valueG);
  781. hPresent = st_lookup_int(ghTable, (char *)Cudd_Regular(h), &valueH);
  782. if (!gPresent && !hPresent) return(NONE);
  783. if (!hPresent) {
  784. if (valueG & 1) return(G_ST);
  785. if (valueG & 2) return(G_CR);
  786. }
  787. if (!gPresent) {
  788. if (valueH & 1) return(H_CR);
  789. if (valueH & 2) return(H_ST);
  790. }
  791. /* both in tables */
  792. if ((valueG & 1) && (valueH & 2)) return(PAIR_ST);
  793. if ((valueG & 2) && (valueH & 1)) return(PAIR_CR);
  794. if (valueG & 1) {
  795. return(BOTH_G);
  796. } else {
  797. return(BOTH_H);
  798. }
  799. } /* end of PairInTables */
  800. /**Function********************************************************************
  801. Synopsis [Check the tables for the existence of pair and return one
  802. combination, cache the result.]
  803. Description [Check the tables for the existence of pair and return
  804. one combination, cache the result. The assumption is that one of the
  805. conjuncts is already in the tables.]
  806. SideEffects [g and h referenced for the cache]
  807. SeeAlso [ZeroCase]
  808. ******************************************************************************/
  809. static Conjuncts *
  810. CheckTablesCacheAndReturn(
  811. DdNode * node,
  812. DdNode * g,
  813. DdNode * h,
  814. st_table * ghTable,
  815. st_table * cacheTable)
  816. {
  817. int pairValue;
  818. int value;
  819. Conjuncts *factors;
  820. value = 0;
  821. /* check tables */
  822. pairValue = PairInTables(g, h, ghTable);
  823. assert(pairValue != NONE);
  824. /* if both dont exist in table, we know one exists(either g or h).
  825. * Therefore store the other and proceed
  826. */
  827. factors = ALLOC(Conjuncts, 1);
  828. if (factors == NULL) return(NULL);
  829. if ((pairValue == BOTH_H) || (pairValue == H_ST)) {
  830. if (g != one) {
  831. value = 0;
  832. if (st_lookup_int(ghTable, (char *)Cudd_Regular(g), &value)) {
  833. value |= 1;
  834. } else {
  835. value = 1;
  836. }
  837. if (st_insert(ghTable, (char *)Cudd_Regular(g),
  838. (char *)(long)value) == ST_OUT_OF_MEM) {
  839. return(NULL);
  840. }
  841. }
  842. factors->g = g;
  843. factors->h = h;
  844. } else if ((pairValue == BOTH_G) || (pairValue == G_ST)) {
  845. if (h != one) {
  846. value = 0;
  847. if (st_lookup_int(ghTable, (char *)Cudd_Regular(h), &value)) {
  848. value |= 2;
  849. } else {
  850. value = 2;
  851. }
  852. if (st_insert(ghTable, (char *)Cudd_Regular(h),
  853. (char *)(long)value) == ST_OUT_OF_MEM) {
  854. return(NULL);
  855. }
  856. }
  857. factors->g = g;
  858. factors->h = h;
  859. } else if (pairValue == H_CR) {
  860. if (g != one) {
  861. value = 2;
  862. if (st_insert(ghTable, (char *)Cudd_Regular(g),
  863. (char *)(long)value) == ST_OUT_OF_MEM) {
  864. return(NULL);
  865. }
  866. }
  867. factors->g = h;
  868. factors->h = g;
  869. } else if (pairValue == G_CR) {
  870. if (h != one) {
  871. value = 1;
  872. if (st_insert(ghTable, (char *)Cudd_Regular(h),
  873. (char *)(long)value) == ST_OUT_OF_MEM) {
  874. return(NULL);
  875. }
  876. }
  877. factors->g = h;
  878. factors->h = g;
  879. } else if (pairValue == PAIR_CR) {
  880. /* pair exists in table */
  881. factors->g = h;
  882. factors->h = g;
  883. } else if (pairValue == PAIR_ST) {
  884. factors->g = g;
  885. factors->h = h;
  886. }
  887. /* cache the result for this node */
  888. if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) {
  889. FREE(factors);
  890. return(NULL);
  891. }
  892. return(factors);
  893. } /* end of CheckTablesCacheAndReturn */
  894. /**Function********************************************************************
  895. Synopsis [Check the tables for the existence of pair and return one
  896. combination, store in cache.]
  897. Description [Check the tables for the existence of pair and return
  898. one combination, store in cache. The pair that has more pointers to
  899. it is picked. An approximation of the number of local pointers is
  900. made by taking the reference count of the pairs sent. ]
  901. SideEffects []
  902. SeeAlso [ZeroCase BuildConjuncts]
  903. ******************************************************************************/
  904. static Conjuncts *
  905. PickOnePair(
  906. DdNode * node,
  907. DdNode * g1,
  908. DdNode * h1,
  909. DdNode * g2,
  910. DdNode * h2,
  911. st_table * ghTable,
  912. st_table * cacheTable)
  913. {
  914. int value;
  915. Conjuncts *factors;
  916. int oneRef, twoRef;
  917. factors = ALLOC(Conjuncts, 1);
  918. if (factors == NULL) return(NULL);
  919. /* count the number of pointers to pair 2 */
  920. if (h2 == one) {
  921. twoRef = (Cudd_Regular(g2))->ref;
  922. } else if (g2 == one) {
  923. twoRef = (Cudd_Regular(h2))->ref;
  924. } else {
  925. twoRef = ((Cudd_Regular(g2))->ref + (Cudd_Regular(h2))->ref)/2;
  926. }
  927. /* count the number of pointers to pair 1 */
  928. if (h1 == one) {
  929. oneRef = (Cudd_Regular(g1))->ref;
  930. } else if (g1 == one) {
  931. oneRef = (Cudd_Regular(h1))->ref;
  932. } else {
  933. oneRef = ((Cudd_Regular(g1))->ref + (Cudd_Regular(h1))->ref)/2;
  934. }
  935. /* pick the pair with higher reference count */
  936. if (oneRef >= twoRef) {
  937. factors->g = g1;
  938. factors->h = h1;
  939. } else {
  940. factors->g = g2;
  941. factors->h = h2;
  942. }
  943. /*
  944. * Store computed factors in respective tables to encourage
  945. * recombination.
  946. */
  947. if (factors->g != one) {
  948. /* insert g in htable */
  949. value = 0;
  950. if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->g), &value)) {
  951. if (value == 2) {
  952. value |= 1;
  953. if (st_insert(ghTable, (char *)Cudd_Regular(factors->g),
  954. (char *)(long)value) == ST_OUT_OF_MEM) {
  955. FREE(factors);
  956. return(NULL);
  957. }
  958. }
  959. } else {
  960. value = 1;
  961. if (st_insert(ghTable, (char *)Cudd_Regular(factors->g),
  962. (char *)(long)value) == ST_OUT_OF_MEM) {
  963. FREE(factors);
  964. return(NULL);
  965. }
  966. }
  967. }
  968. if (factors->h != one) {
  969. /* insert h in htable */
  970. value = 0;
  971. if (st_lookup_int(ghTable, (char *)Cudd_Regular(factors->h), &value)) {
  972. if (value == 1) {
  973. value |= 2;
  974. if (st_insert(ghTable, (char *)Cudd_Regular(factors->h),
  975. (char *)(long)value) == ST_OUT_OF_MEM) {
  976. FREE(factors);
  977. return(NULL);
  978. }
  979. }
  980. } else {
  981. value = 2;
  982. if (st_insert(ghTable, (char *)Cudd_Regular(factors->h),
  983. (char *)(long)value) == ST_OUT_OF_MEM) {
  984. FREE(factors);
  985. return(NULL);
  986. }
  987. }
  988. }
  989. /* Store factors in cache table for later use. */
  990. if (st_insert(cacheTable, (char *)node, (char *)factors) ==
  991. ST_OUT_OF_MEM) {
  992. FREE(factors);
  993. return(NULL);
  994. }
  995. return(factors);
  996. } /* end of PickOnePair */
  997. /**Function********************************************************************
  998. Synopsis [Check if the two pairs exist in the table, If any of the
  999. conjuncts do exist, store in the cache and return the corresponding pair.]
  1000. Description [Check if the two pairs exist in the table. If any of
  1001. the conjuncts do exist, store in the cache and return the
  1002. corresponding pair.]
  1003. SideEffects []
  1004. SeeAlso [ZeroCase BuildConjuncts]
  1005. ******************************************************************************/
  1006. static Conjuncts *
  1007. CheckInTables(
  1008. DdNode * node,
  1009. DdNode * g1,
  1010. DdNode * h1,
  1011. DdNode * g2,
  1012. DdNode * h2,
  1013. st_table * ghTable,
  1014. st_table * cacheTable,
  1015. int * outOfMem)
  1016. {
  1017. int pairValue1, pairValue2;
  1018. Conjuncts *factors;
  1019. int value;
  1020. *outOfMem = 0;
  1021. /* check existence of pair in table */
  1022. pairValue1 = PairInTables(g1, h1, ghTable);
  1023. pairValue2 = PairInTables(g2, h2, ghTable);
  1024. /* if none of the 4 exist in the gh tables, return NULL */
  1025. if ((pairValue1 == NONE) && (pairValue2 == NONE)) {
  1026. return NULL;
  1027. }
  1028. factors = ALLOC(Conjuncts, 1);
  1029. if (factors == NULL) {
  1030. *outOfMem = 1;
  1031. return NULL;
  1032. }
  1033. /* pairs that already exist in the table get preference. */
  1034. if (pairValue1 == PAIR_ST) {
  1035. factors->g = g1;
  1036. factors->h = h1;
  1037. } else if (pairValue2 == PAIR_ST) {
  1038. factors->g = g2;
  1039. factors->h = h2;
  1040. } else if (pairValue1 == PAIR_CR) {
  1041. factors->g = h1;
  1042. factors->h = g1;
  1043. } else if (pairValue2 == PAIR_CR) {
  1044. factors->g = h2;
  1045. factors->h = g2;
  1046. } else if (pairValue1 == G_ST) {
  1047. /* g exists in the table, h is not found in either table */
  1048. factors->g = g1;
  1049. factors->h = h1;
  1050. if (h1 != one) {
  1051. value = 2;
  1052. if (st_insert(ghTable, (char *)Cudd_Regular(h1),
  1053. (char *)(long)value) == ST_OUT_OF_MEM) {
  1054. *outOfMem = 1;
  1055. FREE(factors);
  1056. return(NULL);
  1057. }
  1058. }
  1059. } else if (pairValue1 == BOTH_G) {
  1060. /* g and h are found in the g table */
  1061. factors->g = g1;
  1062. factors->h = h1;
  1063. if (h1 != one) {
  1064. value = 3;
  1065. if (st_insert(ghTable, (char *)Cudd_Regular(h1),
  1066. (char *)(long)value) == ST_OUT_OF_MEM) {
  1067. *outOfMem = 1;
  1068. FREE(factors);
  1069. return(NULL);
  1070. }
  1071. }
  1072. } else if (pairValue1 == H_ST) {
  1073. /* h exists in the table, g is not found in either table */
  1074. factors->g = g1;
  1075. factors->h = h1;
  1076. if (g1 != one) {
  1077. value = 1;
  1078. if (st_insert(ghTable, (char *)Cudd_Regular(g1),
  1079. (char *)(long)value) == ST_OUT_OF_MEM) {
  1080. *outOfMem = 1;
  1081. FREE(factors);
  1082. return(NULL);
  1083. }
  1084. }
  1085. } else if (pairValue1 == BOTH_H) {
  1086. /* g and h are found in the h table */
  1087. factors->g = g1;
  1088. factors->h = h1;
  1089. if (g1 != one) {
  1090. value = 3;
  1091. if (st_insert(ghTable, (char *)Cudd_Regular(g1),
  1092. (char *)(long)value) == ST_OUT_OF_MEM) {
  1093. *outOfMem = 1;
  1094. FREE(factors);
  1095. return(NULL);
  1096. }
  1097. }
  1098. } else if (pairValue2 == G_ST) {
  1099. /* g exists in the table, h is not found in either table */
  1100. factors->g = g2;
  1101. factors->h = h2;
  1102. if (h2 != one) {
  1103. value = 2;
  1104. if (st_insert(ghTable, (char *)Cudd_Regular(h2),
  1105. (char *)(long)value) == ST_OUT_OF_MEM) {
  1106. *outOfMem = 1;
  1107. FREE(factors);
  1108. return(NULL);
  1109. }
  1110. }
  1111. } else if (pairValue2 == BOTH_G) {
  1112. /* g and h are found in the g table */
  1113. factors->g = g2;
  1114. factors->h = h2;
  1115. if (h2 != one) {
  1116. value = 3;
  1117. if (st_insert(ghTable, (char *)Cudd_Regular(h2),
  1118. (char *)(long)value) == ST_OUT_OF_MEM) {
  1119. *outOfMem = 1;
  1120. FREE(factors);
  1121. return(NULL);
  1122. }
  1123. }
  1124. } else if (pairValue2 == H_ST) {
  1125. /* h exists in the table, g is not found in either table */
  1126. factors->g = g2;
  1127. factors->h = h2;
  1128. if (g2 != one) {
  1129. value = 1;
  1130. if (st_insert(ghTable, (char *)Cudd_Regular(g2),
  1131. (char *)(long)value) == ST_OUT_OF_MEM) {
  1132. *outOfMem = 1;
  1133. FREE(factors);
  1134. return(NULL);
  1135. }
  1136. }
  1137. } else if (pairValue2 == BOTH_H) {
  1138. /* g and h are found in the h table */
  1139. factors->g = g2;
  1140. factors->h = h2;
  1141. if (g2 != one) {
  1142. value = 3;
  1143. if (st_insert(ghTable, (char *)Cudd_Regular(g2),
  1144. (char *)(long)value) == ST_OUT_OF_MEM) {
  1145. *outOfMem = 1;
  1146. FREE(factors);
  1147. return(NULL);
  1148. }
  1149. }
  1150. } else if (pairValue1 == G_CR) {
  1151. /* g found in h table and h in none */
  1152. factors->g = h1;
  1153. factors->h = g1;
  1154. if (h1 != one) {
  1155. value = 1;
  1156. if (st_insert(ghTable, (char *)Cudd_Regular(h1),
  1157. (char *)(long)value) == ST_OUT_OF_MEM) {
  1158. *outOfMem = 1;
  1159. FREE(factors);
  1160. return(NULL);
  1161. }
  1162. }
  1163. } else if (pairValue1 == H_CR) {
  1164. /* h found in g table and g in none */
  1165. factors->g = h1;
  1166. factors->h = g1;
  1167. if (g1 != one) {
  1168. value = 2;
  1169. if (st_insert(ghTable, (char *)Cudd_Regular(g1),
  1170. (char *)(long)value) == ST_OUT_OF_MEM) {
  1171. *outOfMem = 1;
  1172. FREE(factors);
  1173. return(NULL);
  1174. }
  1175. }
  1176. } else if (pairValue2 == G_CR) {
  1177. /* g found in h table and h in none */
  1178. factors->g = h2;
  1179. factors->h = g2;
  1180. if (h2 != one) {
  1181. value = 1;
  1182. if (st_insert(ghTable, (char *)Cudd_Regular(h2),
  1183. (char *)(long)value) == ST_OUT_OF_MEM) {
  1184. *outOfMem = 1;
  1185. FREE(factors);
  1186. return(NULL);
  1187. }
  1188. }
  1189. } else if (pairValue2 == H_CR) {
  1190. /* h found in g table and g in none */
  1191. factors->g = h2;
  1192. factors->h = g2;
  1193. if (g2 != one) {
  1194. value = 2;
  1195. if (st_insert(ghTable, (char *)Cudd_Regular(g2),
  1196. (char *)(long)value) == ST_OUT_OF_MEM) {
  1197. *outOfMem = 1;
  1198. FREE(factors);
  1199. return(NULL);
  1200. }
  1201. }
  1202. }
  1203. /* Store factors in cache table for later use. */
  1204. if (st_insert(cacheTable, (char *)node, (char *)factors) ==
  1205. ST_OUT_OF_MEM) {
  1206. *outOfMem = 1;
  1207. FREE(factors);
  1208. return(NULL);
  1209. }
  1210. return factors;
  1211. } /* end of CheckInTables */
  1212. /**Function********************************************************************
  1213. Synopsis [If one child is zero, do explicitly what Restrict does or better]
  1214. Description [If one child is zero, do explicitly what Restrict does or better.
  1215. First separate a variable and its child in the base case. In case of a cube
  1216. times a function, separate the cube and function. As a last resort, look in
  1217. tables.]
  1218. SideEffects [Frees the BDDs in factorsNv. factorsNv itself is not freed
  1219. because it is freed above.]
  1220. SeeAlso [BuildConjuncts]
  1221. ******************************************************************************/
  1222. static Conjuncts *
  1223. ZeroCase(
  1224. DdManager * dd,
  1225. DdNode * node,
  1226. Conjuncts * factorsNv,
  1227. st_table * ghTable,
  1228. st_table * cacheTable,
  1229. int switched)
  1230. {
  1231. int topid;
  1232. DdNode *g, *h, *g1, *g2, *h1, *h2, *x, *N, *G, *H, *Gv, *Gnv;
  1233. DdNode *Hv, *Hnv;
  1234. int value;
  1235. int outOfMem;
  1236. Conjuncts *factors;
  1237. /* get var at this node */
  1238. N = Cudd_Regular(node);
  1239. topid = N->index;
  1240. x = dd->vars[topid];
  1241. x = (switched) ? Cudd_Not(x): x;
  1242. cuddRef(x);
  1243. /* Seprate variable and child */
  1244. if (factorsNv->g == one) {
  1245. Cudd_RecursiveDeref(dd, factorsNv->g);
  1246. factors = ALLOC(Conjuncts, 1);
  1247. if (factors == NULL) {
  1248. dd->errorCode = CUDD_MEMORY_OUT;
  1249. Cudd_RecursiveDeref(dd, factorsNv->h);
  1250. Cudd_RecursiveDeref(dd, x);
  1251. return(NULL);
  1252. }
  1253. factors->g = x;
  1254. factors->h = factorsNv->h;
  1255. /* cache the result*/
  1256. if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) {
  1257. dd->errorCode = CUDD_MEMORY_OUT;
  1258. Cudd_RecursiveDeref(dd, factorsNv->h);
  1259. Cudd_RecursiveDeref(dd, x);
  1260. FREE(factors);
  1261. return NULL;
  1262. }
  1263. /* store x in g table, the other node is already in the table */
  1264. if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) {
  1265. value |= 1;
  1266. } else {
  1267. value = 1;
  1268. }
  1269. if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) {
  1270. dd->errorCode = CUDD_MEMORY_OUT;
  1271. return NULL;
  1272. }
  1273. return(factors);
  1274. }
  1275. /* Seprate variable and child */
  1276. if (factorsNv->h == one) {
  1277. Cudd_RecursiveDeref(dd, factorsNv->h);
  1278. factors = ALLOC(Conjuncts, 1);
  1279. if (factors == NULL) {
  1280. dd->errorCode = CUDD_MEMORY_OUT;
  1281. Cudd_RecursiveDeref(dd, factorsNv->g);
  1282. Cudd_RecursiveDeref(dd, x);
  1283. return(NULL);
  1284. }
  1285. factors->g = factorsNv->g;
  1286. factors->h = x;
  1287. /* cache the result. */
  1288. if (st_insert(cacheTable, (char *)node, (char *)factors) == ST_OUT_OF_MEM) {
  1289. dd->errorCode = CUDD_MEMORY_OUT;
  1290. Cudd_RecursiveDeref(dd, factorsNv->g);
  1291. Cudd_RecursiveDeref(dd, x);
  1292. FREE(factors);
  1293. return(NULL);
  1294. }
  1295. /* store x in h table, the other node is already in the table */
  1296. if (st_lookup_int(ghTable, (char *)Cudd_Regular(x), &value)) {
  1297. value |= 2;
  1298. } else {
  1299. value = 2;
  1300. }
  1301. if (st_insert(ghTable, (char *)Cudd_Regular(x), (char *)(long)value) == ST_OUT_OF_MEM) {
  1302. dd->errorCode = CUDD_MEMORY_OUT;
  1303. return NULL;
  1304. }
  1305. return(factors);
  1306. }
  1307. G = Cudd_Regular(factorsNv->g);
  1308. Gv = cuddT(G);
  1309. Gnv = cuddE(G);
  1310. Gv = Cudd_NotCond(Gv, Cudd_IsComplement(node));
  1311. Gnv = Cudd_NotCond(Gnv, Cudd_IsComplement(node));
  1312. /* if the child below is a variable */
  1313. if ((Gv == zero) || (Gnv == zero)) {
  1314. h = factorsNv->h;
  1315. g = cuddBddAndRecur(dd, x, factorsNv->g);
  1316. if (g != NULL) cuddRef(g);
  1317. Cudd_RecursiveDeref(dd, factorsNv->g);
  1318. Cudd_RecursiveDeref(dd, x);
  1319. if (g == NULL) {
  1320. Cudd_RecursiveDeref(dd, factorsNv->h);
  1321. return NULL;
  1322. }
  1323. /* CheckTablesCacheAndReturn responsible for allocating
  1324. * factors structure., g,h referenced for cache store the
  1325. */
  1326. factors = CheckTablesCacheAndReturn(node,
  1327. g,
  1328. h,
  1329. ghTable,
  1330. cacheTable);
  1331. if (factors == NULL) {
  1332. dd->errorCode = CUDD_MEMORY_OUT;
  1333. Cudd_RecursiveDeref(dd, g);
  1334. Cudd_RecursiveDeref(dd, h);
  1335. }
  1336. return(factors);
  1337. }
  1338. H = Cudd_Regular(factorsNv->h);
  1339. Hv = cuddT(H);
  1340. Hnv = cuddE(H);
  1341. Hv = Cudd_NotCond(Hv, Cudd_IsComplement(node));
  1342. Hnv = Cudd_NotCond(Hnv, Cudd_IsComplement(node));
  1343. /* if the child below is a variable */
  1344. if ((Hv == zero) || (Hnv == zero)) {
  1345. g = factorsNv->g;
  1346. h = cuddBddAndRecur(dd, x, factorsNv->h);
  1347. if (h!= NULL) cuddRef(h);
  1348. Cudd_RecursiveDeref(dd, factorsNv->h);
  1349. Cudd_RecursiveDeref(dd, x);
  1350. if (h == NULL) {
  1351. Cudd_RecursiveDeref(dd, factorsNv->g);
  1352. return NULL;
  1353. }
  1354. /* CheckTablesCacheAndReturn responsible for allocating
  1355. * factors structure.g,h referenced for table store
  1356. */
  1357. factors = CheckTablesCacheAndReturn(node,
  1358. g,
  1359. h,
  1360. ghTable,
  1361. cacheTable);
  1362. if (factors == NULL) {
  1363. dd->errorCode = CUDD_MEMORY_OUT;
  1364. Cudd_RecursiveDeref(dd, g);
  1365. Cudd_RecursiveDeref(dd, h);
  1366. }
  1367. return(factors);
  1368. }
  1369. /* build g1 = x*g; h1 = h */
  1370. /* build g2 = g; h2 = x*h */
  1371. Cudd_RecursiveDeref(dd, x);
  1372. h1 = factorsNv->h;
  1373. g1 = cuddBddAndRecur(dd, x, factorsNv->g);
  1374. if (g1 != NULL) cuddRef(g1);
  1375. if (g1 == NULL) {
  1376. Cudd_RecursiveDeref(dd, factorsNv->g);
  1377. Cudd_RecursiveDeref(dd, factorsNv->h);
  1378. return NULL;
  1379. }
  1380. g2 = factorsNv->g;
  1381. h2 = cuddBddAndRecur(dd, x, factorsNv->h);
  1382. if (h2 != NULL) cuddRef(h2);
  1383. if (h2 == NULL) {
  1384. Cudd_RecursiveDeref(dd, factorsNv->h);
  1385. Cudd_RecursiveDeref(dd, factorsNv->g);
  1386. return NULL;
  1387. }
  1388. /* check whether any pair is in tables */
  1389. factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem);
  1390. if (outOfMem) {
  1391. dd->errorCode = CUDD_MEMORY_OUT;
  1392. Cudd_RecursiveDeref(dd, g1);
  1393. Cudd_RecursiveDeref(dd, h1);
  1394. Cudd_RecursiveDeref(dd, g2);
  1395. Cudd_RecursiveDeref(dd, h2);
  1396. return NULL;
  1397. }
  1398. if (factors != NULL) {
  1399. if ((factors->g == g1) || (factors->g == h1)) {
  1400. Cudd_RecursiveDeref(dd, g2);
  1401. Cudd_RecursiveDeref(dd, h2);
  1402. } else {
  1403. Cudd_RecursiveDeref(dd, g1);
  1404. Cudd_RecursiveDeref(dd, h1);
  1405. }
  1406. return factors;
  1407. }
  1408. /* check for each pair in tables and choose one */
  1409. factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable);
  1410. if (factors == NULL) {
  1411. dd->errorCode = CUDD_MEMORY_OUT;
  1412. Cudd_RecursiveDeref(dd, g1);
  1413. Cudd_RecursiveDeref(dd, h1);
  1414. Cudd_RecursiveDeref(dd, g2);
  1415. Cudd_RecursiveDeref(dd, h2);
  1416. } else {
  1417. /* now free what was created and not used */
  1418. if ((factors->g == g1) || (factors->g == h1)) {
  1419. Cudd_RecursiveDeref(dd, g2);
  1420. Cudd_RecursiveDeref(dd, h2);
  1421. } else {
  1422. Cudd_RecursiveDeref(dd, g1);
  1423. Cudd_RecursiveDeref(dd, h1);
  1424. }
  1425. }
  1426. return(factors);
  1427. } /* end of ZeroCase */
  1428. /**Function********************************************************************
  1429. Synopsis [Builds the conjuncts recursively, bottom up.]
  1430. Description [Builds the conjuncts recursively, bottom up. Constants
  1431. are returned as (f, f). The cache is checked for previously computed
  1432. result. The decomposition points are determined by the local
  1433. reference count of this node and the longest distance from the
  1434. constant. At the decomposition point, the factors returned are (f,
  1435. 1). Recur on the two children. The order is determined by the
  1436. heavier branch. Combine the factors of the two children and pick the
  1437. one that already occurs in the gh table. Occurence in g is indicated
  1438. by value 1, occurence in h by 2, occurence in both 3.]
  1439. SideEffects []
  1440. SeeAlso [cuddConjunctsAux]
  1441. ******************************************************************************/
  1442. static Conjuncts *
  1443. BuildConjuncts(
  1444. DdManager * dd,
  1445. DdNode * node,
  1446. st_table * distanceTable,
  1447. st_table * cacheTable,
  1448. int approxDistance,
  1449. int maxLocalRef,
  1450. st_table * ghTable,
  1451. st_table * mintermTable)
  1452. {
  1453. int topid, distance;
  1454. Conjuncts *factorsNv, *factorsNnv, *factors;
  1455. Conjuncts *dummy;
  1456. DdNode *N, *Nv, *Nnv, *temp, *g1, *g2, *h1, *h2, *topv;
  1457. double minNv = 0.0, minNnv = 0.0;
  1458. double *doubleDummy;
  1459. int switched =0;
  1460. int outOfMem;
  1461. int freeNv = 0, freeNnv = 0, freeTemp;
  1462. NodeStat *nodeStat;
  1463. int value;
  1464. /* if f is constant, return (f,f) */
  1465. if (Cudd_IsConstant(node)) {
  1466. factors = ALLOC(Conjuncts, 1);
  1467. if (factors == NULL) {
  1468. dd->errorCode = CUDD_MEMORY_OUT;
  1469. return(NULL);
  1470. }
  1471. factors->g = node;
  1472. factors->h = node;
  1473. return(FactorsComplement(factors));
  1474. }
  1475. /* If result (a pair of conjuncts) in cache, return the factors. */
  1476. if (st_lookup(cacheTable, node, &dummy)) {
  1477. factors = dummy;
  1478. return(factors);
  1479. }
  1480. /* check distance and local reference count of this node */
  1481. N = Cudd_Regular(node);
  1482. if (!st_lookup(distanceTable, N, &nodeStat)) {
  1483. (void) fprintf(dd->err, "Not in table, Something wrong\n");
  1484. dd->errorCode = CUDD_INTERNAL_ERROR;
  1485. return(NULL);
  1486. }
  1487. distance = nodeStat->distance;
  1488. /* at or below decomposition point, return (f, 1) */
  1489. if (((nodeStat->localRef > maxLocalRef*2/3) &&
  1490. (distance < approxDistance*2/3)) ||
  1491. (distance <= approxDistance/4)) {
  1492. factors = ALLOC(Conjuncts, 1);
  1493. if (factors == NULL) {
  1494. dd->errorCode = CUDD_MEMORY_OUT;
  1495. return(NULL);
  1496. }
  1497. /* alternate assigning (f,1) */
  1498. value = 0;
  1499. if (st_lookup_int(ghTable, (char *)Cudd_Regular(node), &value)) {
  1500. if (value == 3) {
  1501. if (!lastTimeG) {
  1502. factors->g = node;
  1503. factors->h = one;
  1504. lastTimeG = 1;
  1505. } else {
  1506. factors->g = one;
  1507. factors->h = node;
  1508. lastTimeG = 0;
  1509. }
  1510. } else if (value == 1) {
  1511. factors->g = node;
  1512. factors->h = one;
  1513. } else {
  1514. factors->g = one;
  1515. factors->h = node;
  1516. }
  1517. } else if (!lastTimeG) {
  1518. factors->g = node;
  1519. factors->h = one;
  1520. lastTimeG = 1;
  1521. value = 1;
  1522. if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) {
  1523. dd->errorCode = CUDD_MEMORY_OUT;
  1524. FREE(factors);
  1525. return NULL;
  1526. }
  1527. } else {
  1528. factors->g = one;
  1529. factors->h = node;
  1530. lastTimeG = 0;
  1531. value = 2;
  1532. if (st_insert(ghTable, (char *)Cudd_Regular(node), (char *)(long)value) == ST_OUT_OF_MEM) {
  1533. dd->errorCode = CUDD_MEMORY_OUT;
  1534. FREE(factors);
  1535. return NULL;
  1536. }
  1537. }
  1538. return(FactorsComplement(factors));
  1539. }
  1540. /* get the children and recur */
  1541. Nv = cuddT(N);
  1542. Nnv = cuddE(N);
  1543. Nv = Cudd_NotCond(Nv, Cudd_IsComplement(node));
  1544. Nnv = Cudd_NotCond(Nnv, Cudd_IsComplement(node));
  1545. /* Choose which subproblem to solve first based on the number of
  1546. * minterms. We go first where there are more minterms.
  1547. */
  1548. if (!Cudd_IsConstant(Nv)) {
  1549. if (!st_lookup(mintermTable, Nv, &doubleDummy)) {
  1550. (void) fprintf(dd->err, "Not in table: Something wrong\n");
  1551. dd->errorCode = CUDD_INTERNAL_ERROR;
  1552. return(NULL);
  1553. }
  1554. minNv = *doubleDummy;
  1555. }
  1556. if (!Cudd_IsConstant(Nnv)) {
  1557. if (!st_lookup(mintermTable, Nnv, &doubleDummy)) {
  1558. (void) fprintf(dd->err, "Not in table: Something wrong\n");
  1559. dd->errorCode = CUDD_INTERNAL_ERROR;
  1560. return(NULL);
  1561. }
  1562. minNnv = *doubleDummy;
  1563. }
  1564. if (minNv < minNnv) {
  1565. temp = Nv;
  1566. Nv = Nnv;
  1567. Nnv = temp;
  1568. switched = 1;
  1569. }
  1570. /* build gt, ht recursively */
  1571. if (Nv != zero) {
  1572. factorsNv = BuildConjuncts(dd, Nv, distanceTable,
  1573. cacheTable, approxDistance, maxLocalRef,
  1574. ghTable, mintermTable);
  1575. if (factorsNv == NULL) return(NULL);
  1576. freeNv = FactorsNotStored(factorsNv);
  1577. factorsNv = (freeNv) ? FactorsUncomplement(factorsNv) : factorsNv;
  1578. cuddRef(factorsNv->g);
  1579. cuddRef(factorsNv->h);
  1580. /* Deal with the zero case */
  1581. if (Nnv == zero) {
  1582. /* is responsible for freeing factorsNv */
  1583. factors = ZeroCase(dd, node, factorsNv, ghTable,
  1584. cacheTable, switched);
  1585. if (freeNv) FREE(factorsNv);
  1586. return(factors);
  1587. }
  1588. }
  1589. /* build ge, he recursively */
  1590. if (Nnv != zero) {
  1591. factorsNnv = BuildConjuncts(dd, Nnv, distanceTable,
  1592. cacheTable, approxDistance, maxLocalRef,
  1593. ghTable, mintermTable);
  1594. if (factorsNnv == NULL) {
  1595. Cudd_RecursiveDeref(dd, factorsNv->g);
  1596. Cudd_RecursiveDeref(dd, factorsNv->h);
  1597. if (freeNv) FREE(factorsNv);
  1598. return(NULL);
  1599. }
  1600. freeNnv = FactorsNotStored(factorsNnv);
  1601. factorsNnv = (freeNnv) ? FactorsUncomplement(factorsNnv) : factorsNnv;
  1602. cuddRef(factorsNnv->g);
  1603. cuddRef(factorsNnv->h);
  1604. /* Deal with the zero case */
  1605. if (Nv == zero) {
  1606. /* is responsible for freeing factorsNv */
  1607. factors = ZeroCase(dd, node, factorsNnv, ghTable,
  1608. cacheTable, switched);
  1609. if (freeNnv) FREE(factorsNnv);
  1610. return(factors);
  1611. }
  1612. }
  1613. /* construct the 2 pairs */
  1614. /* g1 = x*gt + x'*ge; h1 = x*ht + x'*he; */
  1615. /* g2 = x*gt + x'*he; h2 = x*ht + x'*ge */
  1616. if (switched) {
  1617. factors = factorsNnv;
  1618. factorsNnv = factorsNv;
  1619. factorsNv = factors;
  1620. freeTemp = freeNv;
  1621. freeNv = freeNnv;
  1622. freeNnv = freeTemp;
  1623. }
  1624. /* Build the factors for this node. */
  1625. topid = N->index;
  1626. topv = dd->vars[topid];
  1627. g1 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->g);
  1628. if (g1 == NULL) {
  1629. Cudd_RecursiveDeref(dd, factorsNv->g);
  1630. Cudd_RecursiveDeref(dd, factorsNv->h);
  1631. Cudd_RecursiveDeref(dd, factorsNnv->g);
  1632. Cudd_RecursiveDeref(dd, factorsNnv->h);
  1633. if (freeNv) FREE(factorsNv);
  1634. if (freeNnv) FREE(factorsNnv);
  1635. return(NULL);
  1636. }
  1637. cuddRef(g1);
  1638. h1 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->h);
  1639. if (h1 == NULL) {
  1640. Cudd_RecursiveDeref(dd, factorsNv->g);
  1641. Cudd_RecursiveDeref(dd, factorsNv->h);
  1642. Cudd_RecursiveDeref(dd, factorsNnv->g);
  1643. Cudd_RecursiveDeref(dd, factorsNnv->h);
  1644. Cudd_RecursiveDeref(dd, g1);
  1645. if (freeNv) FREE(factorsNv);
  1646. if (freeNnv) FREE(factorsNnv);
  1647. return(NULL);
  1648. }
  1649. cuddRef(h1);
  1650. g2 = cuddBddIteRecur(dd, topv, factorsNv->g, factorsNnv->h);
  1651. if (g2 == NULL) {
  1652. Cudd_RecursiveDeref(dd, factorsNv->h);
  1653. Cudd_RecursiveDeref(dd, factorsNv->g);
  1654. Cudd_RecursiveDeref(dd, factorsNnv->g);
  1655. Cudd_RecursiveDeref(dd, factorsNnv->h);
  1656. Cudd_RecursiveDeref(dd, g1);
  1657. Cudd_RecursiveDeref(dd, h1);
  1658. if (freeNv) FREE(factorsNv);
  1659. if (freeNnv) FREE(factorsNnv);
  1660. return(NULL);
  1661. }
  1662. cuddRef(g2);
  1663. Cudd_RecursiveDeref(dd, factorsNv->g);
  1664. Cudd_RecursiveDeref(dd, factorsNnv->h);
  1665. h2 = cuddBddIteRecur(dd, topv, factorsNv->h, factorsNnv->g);
  1666. if (h2 == NULL) {
  1667. Cudd_RecursiveDeref(dd, factorsNv->g);
  1668. Cudd_RecursiveDeref(dd, factorsNv->h);
  1669. Cudd_RecursiveDeref(dd, factorsNnv->g);
  1670. Cudd_RecursiveDeref(dd, factorsNnv->h);
  1671. Cudd_RecursiveDeref(dd, g1);
  1672. Cudd_RecursiveDeref(dd, h1);
  1673. Cudd_RecursiveDeref(dd, g2);
  1674. if (freeNv) FREE(factorsNv);
  1675. if (freeNnv) FREE(factorsNnv);
  1676. return(NULL);
  1677. }
  1678. cuddRef(h2);
  1679. Cudd_RecursiveDeref(dd, factorsNv->h);
  1680. Cudd_RecursiveDeref(dd, factorsNnv->g);
  1681. if (freeNv) FREE(factorsNv);
  1682. if (freeNnv) FREE(factorsNnv);
  1683. /* check for each pair in tables and choose one */
  1684. factors = CheckInTables(node, g1, h1, g2, h2, ghTable, cacheTable, &outOfMem);
  1685. if (outOfMem) {
  1686. dd->errorCode = CUDD_MEMORY_OUT;
  1687. Cudd_RecursiveDeref(dd, g1);
  1688. Cudd_RecursiveDeref(dd, h1);
  1689. Cudd_RecursiveDeref(dd, g2);
  1690. Cudd_RecursiveDeref(dd, h2);
  1691. return(NULL);
  1692. }
  1693. if (factors != NULL) {
  1694. if ((factors->g == g1) || (factors->g == h1)) {
  1695. Cudd_RecursiveDeref(dd, g2);
  1696. Cudd_RecursiveDeref(dd, h2);
  1697. } else {
  1698. Cudd_RecursiveDeref(dd, g1);
  1699. Cudd_RecursiveDeref(dd, h1);
  1700. }
  1701. return(factors);
  1702. }
  1703. /* if not in tables, pick one pair */
  1704. factors = PickOnePair(node,g1, h1, g2, h2, ghTable, cacheTable);
  1705. if (factors == NULL) {
  1706. dd->errorCode = CUDD_MEMORY_OUT;
  1707. Cudd_RecursiveDeref(dd, g1);
  1708. Cudd_RecursiveDeref(dd, h1);
  1709. Cudd_RecursiveDeref(dd, g2);
  1710. Cudd_RecursiveDeref(dd, h2);
  1711. } else {
  1712. /* now free what was created and not used */
  1713. if ((factors->g == g1) || (factors->g == h1)) {
  1714. Cudd_RecursiveDeref(dd, g2);
  1715. Cudd_RecursiveDeref(dd, h2);
  1716. } else {
  1717. Cudd_RecursiveDeref(dd, g1);
  1718. Cudd_RecursiveDeref(dd, h1);
  1719. }
  1720. }
  1721. return(factors);
  1722. } /* end of BuildConjuncts */
  1723. /**Function********************************************************************
  1724. Synopsis [Procedure to compute two conjunctive factors of f and place in *c1 and *c2.]
  1725. Description [Procedure to compute two conjunctive factors of f and
  1726. place in *c1 and *c2. Sets up the required data - table of distances
  1727. from the constant and local reference count. Also minterm table. ]
  1728. SideEffects []
  1729. SeeAlso []
  1730. ******************************************************************************/
  1731. static int
  1732. cuddConjunctsAux(
  1733. DdManager * dd,
  1734. DdNode * f,
  1735. DdNode ** c1,
  1736. DdNode ** c2)
  1737. {
  1738. st_table *distanceTable = NULL;
  1739. st_table *cacheTable = NULL;
  1740. st_table *mintermTable = NULL;
  1741. st_table *ghTable = NULL;
  1742. st_generator *stGen;
  1743. char *key, *value;
  1744. Conjuncts *factors;
  1745. int distance, approxDistance;
  1746. double max, minterms;
  1747. int freeFactors;
  1748. NodeStat *nodeStat;
  1749. int maxLocalRef;
  1750. /* initialize */
  1751. *c1 = NULL;
  1752. *c2 = NULL;
  1753. /* initialize distances table */
  1754. distanceTable = st_init_table(st_ptrcmp,st_ptrhash);
  1755. if (distanceTable == NULL) goto outOfMem;
  1756. /* make the entry for the constant */
  1757. nodeStat = ALLOC(NodeStat, 1);
  1758. if (nodeStat == NULL) goto outOfMem;
  1759. nodeStat->distance = 0;
  1760. nodeStat->localRef = 1;
  1761. if (st_insert(distanceTable, (char *)one, (char *)nodeStat) == ST_OUT_OF_MEM) {
  1762. goto outOfMem;
  1763. }
  1764. /* Count node distances from constant. */
  1765. nodeStat = CreateBotDist(f, distanceTable);
  1766. if (nodeStat == NULL) goto outOfMem;
  1767. /* set the distance for the decomposition points */
  1768. approxDistance = (DEPTH < nodeStat->distance) ? nodeStat->distance : DEPTH;
  1769. distance = nodeStat->distance;
  1770. if (distance < approxDistance) {
  1771. /* Too small to bother. */
  1772. *c1 = f;
  1773. *c2 = DD_ONE(dd);
  1774. cuddRef(*c1); cuddRef(*c2);
  1775. stGen = st_init_gen(distanceTable);
  1776. if (stGen == NULL) goto outOfMem;
  1777. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1778. FREE(value);
  1779. }
  1780. st_free_gen(stGen); stGen = NULL;
  1781. st_free_table(distanceTable);
  1782. return(1);
  1783. }
  1784. /* record the maximum local reference count */
  1785. maxLocalRef = 0;
  1786. stGen = st_init_gen(distanceTable);
  1787. if (stGen == NULL) goto outOfMem;
  1788. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1789. nodeStat = (NodeStat *)value;
  1790. maxLocalRef = (nodeStat->localRef > maxLocalRef) ?
  1791. nodeStat->localRef : maxLocalRef;
  1792. }
  1793. st_free_gen(stGen); stGen = NULL;
  1794. /* Count minterms for each node. */
  1795. max = pow(2.0, (double)Cudd_SupportSize(dd,f)); /* potential overflow */
  1796. mintermTable = st_init_table(st_ptrcmp,st_ptrhash);
  1797. if (mintermTable == NULL) goto outOfMem;
  1798. minterms = CountMinterms(f, max, mintermTable, dd->err);
  1799. if (minterms == -1.0) goto outOfMem;
  1800. lastTimeG = Cudd_Random() & 1;
  1801. cacheTable = st_init_table(st_ptrcmp, st_ptrhash);
  1802. if (cacheTable == NULL) goto outOfMem;
  1803. ghTable = st_init_table(st_ptrcmp, st_ptrhash);
  1804. if (ghTable == NULL) goto outOfMem;
  1805. /* Build conjuncts. */
  1806. factors = BuildConjuncts(dd, f, distanceTable, cacheTable,
  1807. approxDistance, maxLocalRef, ghTable, mintermTable);
  1808. if (factors == NULL) goto outOfMem;
  1809. /* free up tables */
  1810. stGen = st_init_gen(distanceTable);
  1811. if (stGen == NULL) goto outOfMem;
  1812. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1813. FREE(value);
  1814. }
  1815. st_free_gen(stGen); stGen = NULL;
  1816. st_free_table(distanceTable); distanceTable = NULL;
  1817. st_free_table(ghTable); ghTable = NULL;
  1818. stGen = st_init_gen(mintermTable);
  1819. if (stGen == NULL) goto outOfMem;
  1820. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1821. FREE(value);
  1822. }
  1823. st_free_gen(stGen); stGen = NULL;
  1824. st_free_table(mintermTable); mintermTable = NULL;
  1825. freeFactors = FactorsNotStored(factors);
  1826. factors = (freeFactors) ? FactorsUncomplement(factors) : factors;
  1827. if (factors != NULL) {
  1828. *c1 = factors->g;
  1829. *c2 = factors->h;
  1830. cuddRef(*c1);
  1831. cuddRef(*c2);
  1832. if (freeFactors) FREE(factors);
  1833. #if 0
  1834. if ((*c1 == f) && (!Cudd_IsConstant(f))) {
  1835. assert(*c2 == one);
  1836. }
  1837. if ((*c2 == f) && (!Cudd_IsConstant(f))) {
  1838. assert(*c1 == one);
  1839. }
  1840. if ((*c1 != one) && (!Cudd_IsConstant(f))) {
  1841. assert(!Cudd_bddLeq(dd, *c2, *c1));
  1842. }
  1843. if ((*c2 != one) && (!Cudd_IsConstant(f))) {
  1844. assert(!Cudd_bddLeq(dd, *c1, *c2));
  1845. }
  1846. #endif
  1847. }
  1848. stGen = st_init_gen(cacheTable);
  1849. if (stGen == NULL) goto outOfMem;
  1850. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1851. ConjunctsFree(dd, (Conjuncts *)value);
  1852. }
  1853. st_free_gen(stGen); stGen = NULL;
  1854. st_free_table(cacheTable); cacheTable = NULL;
  1855. return(1);
  1856. outOfMem:
  1857. if (distanceTable != NULL) {
  1858. stGen = st_init_gen(distanceTable);
  1859. if (stGen == NULL) goto outOfMem;
  1860. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1861. FREE(value);
  1862. }
  1863. st_free_gen(stGen); stGen = NULL;
  1864. st_free_table(distanceTable); distanceTable = NULL;
  1865. }
  1866. if (mintermTable != NULL) {
  1867. stGen = st_init_gen(mintermTable);
  1868. if (stGen == NULL) goto outOfMem;
  1869. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1870. FREE(value);
  1871. }
  1872. st_free_gen(stGen); stGen = NULL;
  1873. st_free_table(mintermTable); mintermTable = NULL;
  1874. }
  1875. if (ghTable != NULL) st_free_table(ghTable);
  1876. if (cacheTable != NULL) {
  1877. stGen = st_init_gen(cacheTable);
  1878. if (stGen == NULL) goto outOfMem;
  1879. while(st_gen(stGen, (char **)&key, (char **)&value)) {
  1880. ConjunctsFree(dd, (Conjuncts *)value);
  1881. }
  1882. st_free_gen(stGen); stGen = NULL;
  1883. st_free_table(cacheTable); cacheTable = NULL;
  1884. }
  1885. dd->errorCode = CUDD_MEMORY_OUT;
  1886. return(0);
  1887. } /* end of cuddConjunctsAux */