The source code and dockerfile for the GSW2024 AI Lab.
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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

2131 lines
58 KiB

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