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.

1578 lines
47 KiB

2 months ago
  1. /**CFile**********************************************************************
  2. FileName [dddmpStoreCnf.c]
  3. PackageName [dddmp]
  4. Synopsis [Functions to write out BDDs to file in a CNF format]
  5. Description [Functions to write out BDDs to file in a CNF format.]
  6. Author [Gianpiero Cabodi and Stefano Quer]
  7. Copyright [
  8. Copyright (c) 2004 by Politecnico di Torino.
  9. All Rights Reserved. This software is for educational purposes only.
  10. Permission is given to academic institutions to use, copy, and modify
  11. this software and its documentation provided that this introductory
  12. message is not removed, that this software and its documentation is
  13. used for the institutions' internal research and educational purposes,
  14. and that no monies are exchanged. No guarantee is expressed or implied
  15. by the distribution of this code.
  16. Send bug-reports and/or questions to:
  17. {gianpiero.cabodi,stefano.quer}@polito.it.
  18. ]
  19. ******************************************************************************/
  20. #include <limits.h>
  21. #include "dddmpInt.h"
  22. /*-------------------------------1--------------------------------------------*/
  23. /* Stucture declarations */
  24. /*---------------------------------------------------------------------------*/
  25. /*---------------------------------------------------------------------------*/
  26. /* Type declarations */
  27. /*---------------------------------------------------------------------------*/
  28. /*---------------------------------------------------------------------------*/
  29. /* Variable declarations */
  30. /*---------------------------------------------------------------------------*/
  31. #define DDDMP_DEBUG_CNF 0
  32. /*---------------------------------------------------------------------------*/
  33. /* Macro declarations */
  34. /*---------------------------------------------------------------------------*/
  35. #define GET_MAX(x,y) (x>y?x:y)
  36. /**AutomaticStart*************************************************************/
  37. /*---------------------------------------------------------------------------*/
  38. /* Static function prototypes */
  39. /*---------------------------------------------------------------------------*/
  40. static int DddmpCuddBddArrayStoreCnf(DdManager *ddMgr, DdNode **f, int rootN, Dddmp_DecompCnfStoreType mode, int noHeader, char **varNames, int *bddIds, int *bddAuxIds, int *cnfIds, int idInitial, int edgeInTh, int pathLengthTh, char *fname, FILE *fp, int *clauseNPtr, int *varNewNPtr);
  41. static int StoreCnfNodeByNode(DdManager *ddMgr, DdNode **f, int rootN, int *bddIds, int *cnfIds, FILE *fp, int *clauseN, int *varMax, int *rootStartLine);
  42. static int StoreCnfNodeByNodeRecur(DdManager *ddMgr, DdNode *f, int *bddIds, int *cnfIds, FILE *fp, int *clauseN, int *varMax);
  43. static int StoreCnfOneNode(DdNode *f, int idf, int vf, int idT, int idE, FILE *fp, int *clauseN, int *varMax);
  44. static int StoreCnfMaxtermByMaxterm(DdManager *ddMgr, DdNode **f, int rootN, int *bddIds, int *cnfIds, int idInitial, FILE *fp, int *varMax, int *clauseN, int *rootStartLine);
  45. static int StoreCnfBest(DdManager *ddMgr, DdNode **f, int rootN, int *bddIds, int *cnfIds, int idInitial, FILE *fp, int *varMax, int *clauseN, int *rootStartLine);
  46. static void StoreCnfMaxtermByMaxtermRecur(DdManager *ddMgr, DdNode *node, int *bddIds, int *cnfIds, FILE *fp, int *list, int *clauseN, int *varMax);
  47. static int StoreCnfBestNotSharedRecur(DdManager *ddMgr, DdNode *node, int idf, int *bddIds, int *cnfIds, FILE *fp, int *list, int *clauseN, int *varMax);
  48. static int StoreCnfBestSharedRecur(DdManager *ddMgr, DdNode *node, int *bddIds, int *cnfIds, FILE *fp, int *list, int *clauseN, int *varMax);
  49. static int printCubeCnf(DdManager *ddMgr, DdNode *node, int *cnfIds, FILE *fp, int *list, int *varMax);
  50. /**AutomaticEnd***************************************************************/
  51. /*---------------------------------------------------------------------------*/
  52. /* Definition of exported functions */
  53. /*---------------------------------------------------------------------------*/
  54. /**Function********************************************************************
  55. Synopsis [Writes a dump file representing the argument BDD in
  56. a CNF format.
  57. ]
  58. Description [Dumps the argument BDD to file.
  59. This task is performed by calling the function
  60. Dddmp_cuddBddArrayStoreCnf.
  61. ]
  62. SideEffects [Nodes are temporarily removed from unique hash. They are
  63. re-linked after the store operation in a modified order.
  64. ]
  65. SeeAlso [Dddmp_cuddBddArrayStoreCnf]
  66. ******************************************************************************/
  67. int
  68. Dddmp_cuddBddStoreCnf (
  69. DdManager *ddMgr /* IN: DD Manager */,
  70. DdNode *f /* IN: BDD root to be stored */,
  71. Dddmp_DecompCnfStoreType mode /* IN: format selection */,
  72. int noHeader /* IN: do not store header iff 1 */,
  73. char **varNames /* IN: array of variable names (or NULL) */,
  74. int *bddIds /* IN: array of var ids */,
  75. int *bddAuxIds /* IN: array of BDD node Auxiliary Ids */,
  76. int *cnfIds /* IN: array of CNF var ids */,
  77. int idInitial /* IN: starting id for cutting variables */,
  78. int edgeInTh /* IN: Max # Incoming Edges */,
  79. int pathLengthTh /* IN: Max Path Length */,
  80. char *fname /* IN: file name */,
  81. FILE *fp /* IN: pointer to the store file */,
  82. int *clauseNPtr /* OUT: number of clause stored */,
  83. int *varNewNPtr /* OUT: number of new variable created */
  84. )
  85. {
  86. int retValue;
  87. DdNode *tmpArray[1];
  88. tmpArray[0] = f;
  89. retValue = Dddmp_cuddBddArrayStoreCnf (ddMgr, tmpArray, 1, mode,
  90. noHeader, varNames, bddIds, bddAuxIds, cnfIds, idInitial, edgeInTh,
  91. pathLengthTh, fname, fp, clauseNPtr, varNewNPtr);
  92. Dddmp_CheckAndReturn (retValue==DDDMP_FAILURE, "Failure.");
  93. return (DDDMP_SUCCESS);
  94. }
  95. /**Function********************************************************************
  96. Synopsis [Writes a dump file representing the argument array of BDDs
  97. in CNF format.
  98. ]
  99. Description [Dumps the argument array of BDDs to file.]
  100. SideEffects [Nodes are temporarily removed from the unique hash
  101. table. They are re-linked after the store operation in a
  102. modified order.
  103. Three methods are allowed:
  104. * NodeByNode method: Insert a cut-point for each BDD node (but the
  105. terminal nodes)
  106. * MaxtermByMaxterm method: Insert no cut-points, i.e. the off-set of
  107. trhe function is stored
  108. * Best method: Tradeoff between the previous two methods.
  109. Auxiliary variables, i.e., cut points are inserted following these
  110. criterias:
  111. * edgeInTh
  112. indicates the maximum number of incoming edges up to which
  113. no cut point (auxiliary variable) is inserted.
  114. If edgeInTh:
  115. * is equal to -1 no cut point due to incoming edges are inserted
  116. (MaxtermByMaxterm method.)
  117. * is equal to 0 a cut point is inserted for each node with a single
  118. incoming edge, i.e., each node, (NodeByNode method).
  119. * is equal to n a cut point is inserted for each node with (n+1)
  120. incoming edges.
  121. * pathLengthTh
  122. indicates the maximum length path up to which no cut points
  123. (auxiliary variable) is inserted.
  124. If the path length between two nodes exceeds this value, a cut point
  125. is inserted.
  126. If pathLengthTh:
  127. * is equal to -1 no cut point due path length are inserted
  128. (MaxtermByMaxterm method.)
  129. * is equal to 0 a cut point is inserted for each node (NodeByNode
  130. method).
  131. * is equal to n a cut point is inserted on path whose length is
  132. equal to (n+1).
  133. Notice that the maximum number of literals in a clause is equal
  134. to (pathLengthTh + 2), i.e., for each path we have to keep into
  135. account a CNF variable for each node plus 2 added variables for
  136. the bottom and top-path cut points.
  137. The stored file can contain a file header or not depending on the
  138. noHeader parameter (IFF 0, usual setting, the header is usually stored.
  139. This option can be useful in storing multiple BDDs, as separate BDDs,
  140. on the same file leaving the opening of the file to the caller.
  141. ]
  142. SeeAlso []
  143. ******************************************************************************/
  144. int
  145. Dddmp_cuddBddArrayStoreCnf (
  146. DdManager *ddMgr /* IN: DD Manager */,
  147. DdNode **f /* IN: array of BDD roots to be stored */,
  148. int rootN /* IN: # output BDD roots to be stored */,
  149. Dddmp_DecompCnfStoreType mode /* IN: format selection */,
  150. int noHeader /* IN: do not store header iff 1 */,
  151. char **varNames /* IN: array of variable names (or NULL) */,
  152. int *bddIds /* IN: array of converted var IDs */,
  153. int *bddAuxIds /* IN: array of BDD node Auxiliary Ids */,
  154. int *cnfIds /* IN: array of converted var IDs */,
  155. int idInitial /* IN: starting id for cutting variables */,
  156. int edgeInTh /* IN: Max # Incoming Edges */,
  157. int pathLengthTh /* IN: Max Path Length */,
  158. char *fname /* IN: file name */,
  159. FILE *fp /* IN: pointer to the store file */,
  160. int *clauseNPtr /* OUT: number of clause stored */,
  161. int *varNewNPtr /* OUT: number of new variable created */
  162. )
  163. {
  164. int retValue2;
  165. #if 0
  166. #ifdef DDDMP_DEBUG
  167. #ifndef __alpha__
  168. int retValue1;
  169. retValue1 = Cudd_DebugCheck (ddMgr);
  170. Dddmp_CheckAndReturn (retValue1==1,
  171. "Inconsistency Found During CNF Store.");
  172. Dddmp_CheckAndReturn (retValue1==CUDD_OUT_OF_MEM,
  173. "Out of Memory During CNF Store.");
  174. #endif
  175. #endif
  176. #endif
  177. retValue2 = DddmpCuddBddArrayStoreCnf (ddMgr, f, rootN, mode, noHeader,
  178. varNames, bddIds, bddAuxIds, cnfIds, idInitial, edgeInTh, pathLengthTh,
  179. fname, fp, clauseNPtr, varNewNPtr);
  180. #if 0
  181. #ifdef DDDMP_DEBUG
  182. #ifndef __alpha__
  183. retValue1 = Cudd_DebugCheck (ddMgr);
  184. Dddmp_CheckAndReturn (retValue1==1,
  185. "Inconsistency Found During CNF Store.");
  186. Dddmp_CheckAndReturn (retValue1==CUDD_OUT_OF_MEM,
  187. "Out of Memory During CNF Store.");
  188. #endif
  189. #endif
  190. #endif
  191. return (retValue2);
  192. }
  193. /*---------------------------------------------------------------------------*/
  194. /* Definition of internal functions */
  195. /*---------------------------------------------------------------------------*/
  196. /**Function********************************************************************
  197. Synopsis [Writes a dump file representing the argument Array of
  198. BDDs in the CNF standard format.
  199. ]
  200. Description [Dumps the argument array of BDDs/ADDs to file in CNF format.
  201. The following arrays: varNames, bddIds, bddAuxIds, and cnfIds
  202. fix the correspondence among variable names, BDD ids, BDD
  203. auxiliary ids and the ids used to store the CNF problem.
  204. All these arrays are automatically created iff NULL.
  205. Auxiliary variable, iff necessary, are created starting from value
  206. idInitial.
  207. Iff idInitial is <= 0 its value is selected as the number of internal
  208. CUDD variable + 2.
  209. Auxiliary variables, i.e., cut points are inserted following these
  210. criterias:
  211. * edgeInTh
  212. indicates the maximum number of incoming edges up to which
  213. no cut point (auxiliary variable) is inserted.
  214. If edgeInTh:
  215. * is equal to -1 no cut point due to incoming edges are inserted
  216. (MaxtermByMaxterm method.)
  217. * is equal to 0 a cut point is inserted for each node with a single
  218. incoming edge, i.e., each node, (NodeByNode method).
  219. * is equal to n a cut point is inserted for each node with (n+1)
  220. incoming edges.
  221. * pathLengthTh
  222. indicates the maximum length path up to which no cut points
  223. (auxiliary variable) is inserted.
  224. If the path length between two nodes exceeds this value, a cut point
  225. is inserted.
  226. If pathLengthTh:
  227. * is equal to -1 no cut point due path length are inserted
  228. (MaxtermByMaxterm method.)
  229. * is equal to 0 a cut point is inserted for each node (NodeByNode
  230. method).
  231. * is equal to n a cut point is inserted on path whose length is
  232. equal to (n+1).
  233. Notice that the maximum number of literals in a clause is equal
  234. to (pathLengthTh + 2), i.e., for each path we have to keep into
  235. account a CNF variable for each node plus 2 added variables for
  236. the bottom and top-path cut points.
  237. ]
  238. SideEffects [Nodes are temporarily removed from the unique hash table.
  239. They are re-linked after the store operation in a modified
  240. order.
  241. ]
  242. SeeAlso [Dddmp_cuddBddStore]
  243. ******************************************************************************/
  244. static int
  245. DddmpCuddBddArrayStoreCnf (
  246. DdManager *ddMgr /* IN: DD Manager */,
  247. DdNode **f /* IN: array of BDD roots to be stored */,
  248. int rootN /* IN: # of output BDD roots to be stored */,
  249. Dddmp_DecompCnfStoreType mode /* IN: format selection */,
  250. int noHeader /* IN: do not store header iff 1 */,
  251. char **varNames /* IN: array of variable names (or NULL) */,
  252. int *bddIds /* IN: array of BDD node Ids (or NULL) */,
  253. int *bddAuxIds /* IN: array of BDD Aux Ids (or NULL) */,
  254. int *cnfIds /* IN: array of CNF ids (or NULL) */,
  255. int idInitial /* IN: starting id for cutting variables */,
  256. int edgeInTh /* IN: Max # Incoming Edges */,
  257. int pathLengthTh /* IN: Max Path Length */,
  258. char *fname /* IN: file name */,
  259. FILE *fp /* IN: pointer to the store file */,
  260. int *clauseNPtr /* OUT: number of clause stored */,
  261. int *varNewNPtr /* OUT: number of new variable created */
  262. )
  263. {
  264. DdNode *support = NULL;
  265. DdNode *scan = NULL;
  266. int *bddIdsInSupport = NULL;
  267. int *permIdsInSupport = NULL;
  268. int *rootStartLine = NULL;
  269. int nVar, nVarInSupport, retValue, i, j, fileToClose;
  270. int varMax, clauseN, flagVar, intStringLength;
  271. int bddIdsToFree = 0;
  272. int bddAuxIdsToFree = 0;
  273. int cnfIdsToFree = 0;
  274. int varNamesToFree = 0;
  275. char intString[DDDMP_MAXSTRLEN];
  276. char tmpString[DDDMP_MAXSTRLEN];
  277. fpos_t posFile1, posFile2;
  278. /*---------------------------- Set Initial Values -------------------------*/
  279. support = scan = NULL;
  280. bddIdsInSupport = permIdsInSupport = rootStartLine = NULL;
  281. nVar = ddMgr->size;
  282. fileToClose = 0;
  283. sprintf (intString, "%d", INT_MAX);
  284. intStringLength = strlen (intString);
  285. /*---------- Check if File needs to be opened in the proper mode ----------*/
  286. if (fp == NULL) {
  287. fp = fopen (fname, "w");
  288. Dddmp_CheckAndGotoLabel (fp==NULL, "Error opening file.",
  289. failure);
  290. fileToClose = 1;
  291. }
  292. /*--------- Generate Bdd LOCAL IDs and Perm IDs and count them ------------*/
  293. /* BDD Ids */
  294. bddIdsInSupport = DDDMP_ALLOC (int, nVar);
  295. Dddmp_CheckAndGotoLabel (bddIdsInSupport==NULL, "Error allocating memory.",
  296. failure);
  297. /* BDD PermIds */
  298. permIdsInSupport = DDDMP_ALLOC (int, nVar);
  299. Dddmp_CheckAndGotoLabel (permIdsInSupport==NULL, "Error allocating memory.",
  300. failure);
  301. /* Support Size (Number of BDD Ids-PermIds */
  302. nVarInSupport = 0;
  303. for (i=0; i<nVar; i++) {
  304. bddIdsInSupport[i] = permIdsInSupport[i] = (-1);
  305. }
  306. /*
  307. * Take the union of the supports of each output function.
  308. * Skip NULL functions.
  309. */
  310. for (i=0; i<rootN; i++) {
  311. if (f[i] == NULL) {
  312. continue;
  313. }
  314. support = Cudd_Support (ddMgr, f[i]);
  315. Dddmp_CheckAndGotoLabel (support==NULL, "NULL support returned.",
  316. failure);
  317. cuddRef (support);
  318. scan = support;
  319. while (!cuddIsConstant(scan)) {
  320. /* Count Number of Variable in the Support */
  321. nVarInSupport++;
  322. /* Set Ids and Perm-Ids */
  323. bddIdsInSupport[scan->index] = scan->index;
  324. permIdsInSupport[scan->index] = ddMgr->perm[scan->index];
  325. scan = cuddT (scan);
  326. }
  327. Cudd_RecursiveDeref (ddMgr, support);
  328. }
  329. /* so that we do not try to free it in case of failure */
  330. support = NULL;
  331. /*---------------------------- Start HEADER -------------------------------*/
  332. if (noHeader==0) {
  333. retValue = fprintf (fp,
  334. "c # BDD stored by the DDDMP tool in CNF format\n");
  335. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing on file.",
  336. failure);
  337. fprintf (fp, "c #\n");
  338. }
  339. /*-------------------- Generate Bdd IDs IFF necessary ---------------------*/
  340. if (bddIds == NULL) {
  341. if (noHeader==0) {
  342. fprintf (fp, "c # Warning: BDD IDs missing ... evaluating them.\n");
  343. fprintf (fp, "c # \n");
  344. fflush (fp);
  345. }
  346. bddIdsToFree = 1;
  347. bddIds = DDDMP_ALLOC (int, nVar);
  348. Dddmp_CheckAndGotoLabel (bddIds==NULL, "Error allocating memory.",
  349. failure);
  350. /* Get BDD-IDs Directly from Cudd Manager */
  351. for (i=0; i<nVar; i++) {
  352. bddIds[i] = i;
  353. }
  354. } /* end if bddIds == NULL */
  355. /*------------------ Generate AUX BDD IDs IF necessary --------------------*/
  356. if (bddAuxIds == NULL) {
  357. if (noHeader==0) {
  358. fprintf (fp, "c # Warning: AUX IDs missing ... equal to BDD IDs.\n");
  359. fprintf (fp, "c #\n");
  360. fflush (fp);
  361. }
  362. bddAuxIdsToFree = 1;
  363. bddAuxIds = DDDMP_ALLOC (int, nVar);
  364. Dddmp_CheckAndGotoLabel (bddAuxIds==NULL, "Error allocating memory.",
  365. failure);
  366. for (i=0; i<nVar; i++) {
  367. bddAuxIds[i] = bddIds[i];
  368. }
  369. } /* end if cnfIds == NULL */
  370. /*------------------- Generate CNF IDs IF necessary -----------------------*/
  371. if (cnfIds == NULL) {
  372. if (noHeader==0) {
  373. fprintf (fp, "c # Warning: CNF IDs missing ... equal to BDD IDs.\n");
  374. fprintf (fp, "c #\n");
  375. fflush (fp);
  376. }
  377. cnfIdsToFree = 1;
  378. cnfIds = DDDMP_ALLOC (int, nVar);
  379. Dddmp_CheckAndGotoLabel (cnfIds==NULL, "Error allocating memory.",
  380. failure);
  381. for (i=0; i<nVar; i++) {
  382. cnfIds[i] = bddIds[i] + 1;
  383. }
  384. } /* end if cnfIds == NULL */
  385. /*------------------ Generate Var Names IF necessary ----------------------*/
  386. flagVar = 0;
  387. if (varNames == NULL) {
  388. if (noHeader==0) {
  389. fprintf (fp,
  390. "c # Warning: null variable names ... create DUMMY names.\n");
  391. fprintf (fp, "c #\n");
  392. fflush (stderr);
  393. }
  394. varNamesToFree = 1;
  395. varNames = DDDMP_ALLOC (char *, nVar);
  396. for (i=0; i<nVar; i++) {
  397. varNames[i] = NULL;
  398. }
  399. Dddmp_CheckAndGotoLabel (varNames==NULL, "Error allocating memory.",
  400. failure);
  401. flagVar = 1;
  402. } else {
  403. /* Protect the user also from partially loaded varNames array !!! */
  404. for (i=0; i<nVar && flagVar==0; i++) {
  405. if (varNames[i] == NULL) {
  406. flagVar = 1;
  407. }
  408. }
  409. }
  410. if (flagVar == 1) {
  411. for (i=0; i<nVar; i++) {
  412. if (varNames[i] == NULL) {
  413. sprintf (tmpString, "DUMMY%d", bddIds[i]);
  414. varNames[i] = DDDMP_ALLOC (char, (strlen (tmpString)+1));
  415. strcpy (varNames[i], tmpString);
  416. }
  417. }
  418. }
  419. /*----------------------- Set Initial ID IF necessary --------------------*/
  420. if (idInitial <= 0) {
  421. idInitial = nVar + 1;
  422. }
  423. /*--------------------------- Continue HEADER -----------------------------*/
  424. if (noHeader==0) {
  425. fprintf (fp, "c .ver %s\n", DDDMP_VERSION);
  426. fprintf (fp, "c .nnodes %d\n", Cudd_SharingSize (f, rootN));
  427. fprintf (fp, "c .nvars %d\n", nVar);
  428. fprintf (fp, "c .nsuppvars %d\n", nVarInSupport);
  429. /* Support Variable Names */
  430. if (varNames != NULL) {
  431. fprintf (fp, "c .suppvarnames");
  432. for (i=0; i<nVar; i++) {
  433. if (bddIdsInSupport[i] >= 0) {
  434. fprintf (fp, " %s", varNames[i]);
  435. }
  436. }
  437. fprintf (fp, "\n");
  438. }
  439. /* Ordered Variable Names */
  440. if (varNames != NULL) {
  441. fprintf (fp, "c .orderedvarnames");
  442. for (i=0; i<nVar; i++) {
  443. fprintf (fp, " %s", varNames[i]);
  444. }
  445. fprintf (fp, "\n");
  446. }
  447. /* BDD Variable Ids */
  448. fprintf (fp, "c .ids ");
  449. for (i=0; i<nVar; i++) {
  450. if (bddIdsInSupport[i] >= 0) {
  451. fprintf (fp, " %d", bddIdsInSupport[i]);
  452. }
  453. }
  454. fprintf (fp, "\n");
  455. /* BDD Variable Permutation Ids */
  456. fprintf (fp, "c .permids ");
  457. for (i=0; i<nVar; i++) {
  458. if (bddIdsInSupport[i] >= 0) {
  459. fprintf (fp, " %d", permIdsInSupport[i]);
  460. }
  461. }
  462. fprintf (fp, "\n");
  463. /* BDD Variable Auxiliary Ids */
  464. fprintf (fp, "c .auxids ");
  465. for (i=0; i<nVar; i++) {
  466. if (bddIdsInSupport[i] >= 0) {
  467. fprintf (fp, " %d", bddAuxIds[i]);
  468. }
  469. }
  470. fprintf (fp, "\n");
  471. /* CNF Ids */
  472. fprintf (fp, "c .cnfids ");
  473. for (i=0; i<nVar; i++) {
  474. if (bddIdsInSupport[i] >= 0) {
  475. fprintf (fp, " %d", cnfIds[i]);
  476. }
  477. }
  478. fprintf (fp, "\n");
  479. /* Number of Roots */
  480. fprintf (fp, "c .nroots %d", rootN);
  481. fprintf (fp, "\n");
  482. /* Root Starting Line */
  483. fgetpos (fp, &posFile1);
  484. fprintf (fp, "c .rootids");
  485. for (i=0; i<rootN; i++) {
  486. for (j=0; j<intStringLength+1; j++) {
  487. retValue = fprintf (fp, " ");
  488. }
  489. }
  490. retValue = fprintf (fp, "\n");
  491. fflush (fp);
  492. } /* End of noHeader check */
  493. /*------------ Select Mode and Print Number of Tmp Var Created ------------*/
  494. switch (mode) {
  495. case DDDMP_CNF_MODE_NODE:
  496. *varNewNPtr = idInitial;
  497. *varNewNPtr = DddmpNumberDdNodesCnf (ddMgr, f, rootN, cnfIds, idInitial)
  498. - *varNewNPtr;
  499. break;
  500. case DDDMP_CNF_MODE_MAXTERM:
  501. *varNewNPtr = 0;
  502. break;
  503. default:
  504. Dddmp_Warning (1, "Wrong DDDMP Store Mode. Force DDDMP_MODE_BEST.");
  505. case DDDMP_CNF_MODE_BEST:
  506. *varNewNPtr = idInitial;
  507. *varNewNPtr = DddmpDdNodesCountEdgesAndNumber (ddMgr, f, rootN,
  508. edgeInTh, pathLengthTh, cnfIds, idInitial) - *varNewNPtr;
  509. break;
  510. }
  511. /*------------ Print Space for Number of Variable and Clauses -------------*/
  512. if (noHeader==0) {
  513. fprintf (fp, "c .nAddedCnfVar %d\n", *varNewNPtr);
  514. fprintf (fp, "c #\n");
  515. fprintf (fp, "c # Init CNF Clauses\n");
  516. fprintf (fp, "c #\n");
  517. fgetpos (fp, &posFile2);
  518. retValue = fprintf (fp, "p cnf");
  519. for (j=0; j<2*(intStringLength+1); j++) {
  520. retValue = fprintf (fp, " ");
  521. }
  522. retValue = fprintf (fp, "\n");
  523. fflush (fp);
  524. }
  525. /*---------------------- Select Mode and Do the Job -----------------------*/
  526. clauseN = 0;
  527. varMax = -1;
  528. rootStartLine = DDDMP_ALLOC (int, rootN);
  529. Dddmp_CheckAndGotoLabel (rootStartLine==NULL, "Error allocating memory.",
  530. failure);
  531. for (i=0; i<rootN; i++) {
  532. rootStartLine[i] = (-1);
  533. }
  534. switch (mode) {
  535. case DDDMP_CNF_MODE_NODE:
  536. StoreCnfNodeByNode (ddMgr, f, rootN, bddIds, cnfIds, fp, &clauseN,
  537. &varMax, rootStartLine);
  538. DddmpUnnumberDdNodesCnf (ddMgr, f, rootN);
  539. break;
  540. case DDDMP_CNF_MODE_MAXTERM:
  541. StoreCnfMaxtermByMaxterm (ddMgr, f, rootN, bddIds, cnfIds, idInitial,
  542. fp, &varMax, &clauseN, rootStartLine);
  543. break;
  544. default:
  545. Dddmp_Warning (1, "Wrong DDDMP Store Mode. Force DDDMP_MODE_BEST.");
  546. case DDDMP_CNF_MODE_BEST:
  547. StoreCnfBest (ddMgr, f, rootN, bddIds, cnfIds, idInitial,
  548. fp, &varMax, &clauseN, rootStartLine);
  549. DddmpUnnumberDdNodesCnf (ddMgr, f, rootN);
  550. break;
  551. }
  552. /*------------------------------ Write trailer ----------------------------*/
  553. if (noHeader==0) {
  554. retValue = fprintf (fp, "c # End of Cnf From dddmp-2.0\n");
  555. Dddmp_CheckAndGotoLabel (retValue==EOF, "Error writing to file.",
  556. failure);
  557. }
  558. /*
  559. * Write Root Starting Line
  560. */
  561. if (noHeader==0) {
  562. fsetpos (fp, &posFile1);
  563. fprintf (fp, "c .rootids");
  564. for (i=0; i<rootN; i++) {
  565. Dddmp_Warning (rootStartLine[i]==(-1),
  566. "Init Line for CNF file = (-1) {[(Stored one or zero BDD)]}.");
  567. sprintf (tmpString, " %d", rootStartLine[i]);
  568. for (j=strlen(tmpString); j<intStringLength+1; j++) {
  569. strcat (tmpString, " ");
  570. }
  571. retValue = fprintf (fp, "%s", tmpString);
  572. }
  573. retValue = fprintf (fp, "\n");
  574. fflush (fp);
  575. }
  576. /*
  577. * Write Number of clauses and variable in the header
  578. */
  579. *clauseNPtr = clauseN;
  580. if (noHeader==0) {
  581. fsetpos (fp, &posFile2);
  582. retValue = fprintf (fp, "p cnf");
  583. sprintf (tmpString, " %d %d", varMax, clauseN);
  584. for (j=strlen(tmpString); j<2*(intStringLength+1); j++) {
  585. strcat (tmpString, " ");
  586. }
  587. retValue = fprintf (fp, "%s\n", tmpString);
  588. fflush (fp);
  589. }
  590. /*-------------------------- Close file and return ------------------------*/
  591. if (fileToClose) {
  592. fclose (fp);
  593. }
  594. DDDMP_FREE (bddIdsInSupport);
  595. DDDMP_FREE (permIdsInSupport);
  596. DDDMP_FREE (rootStartLine);
  597. if (bddIdsToFree == 1) {
  598. DDDMP_FREE (bddIds);
  599. }
  600. if (bddAuxIdsToFree == 1) {
  601. DDDMP_FREE (bddAuxIds);
  602. }
  603. if (cnfIdsToFree == 1) {
  604. DDDMP_FREE (cnfIds);
  605. }
  606. if (varNamesToFree == 1) {
  607. for (i=0; i<nVar; i++) {
  608. DDDMP_FREE (varNames[i]);
  609. }
  610. DDDMP_FREE (varNames);
  611. }
  612. return (DDDMP_SUCCESS);
  613. failure:
  614. if (support != NULL) {
  615. Cudd_RecursiveDeref (ddMgr, support);
  616. }
  617. DDDMP_FREE (bddIdsInSupport);
  618. DDDMP_FREE (permIdsInSupport);
  619. DDDMP_FREE (rootStartLine);
  620. if (bddIdsToFree == 1) {
  621. DDDMP_FREE (bddIds);
  622. }
  623. if (bddAuxIdsToFree == 1) {
  624. DDDMP_FREE (bddAuxIds);
  625. }
  626. if (cnfIdsToFree == 1) {
  627. DDDMP_FREE (cnfIds);
  628. }
  629. if (varNamesToFree == 1) {
  630. for (i=0; i<nVar; i++) {
  631. DDDMP_FREE (varNames[i]);
  632. }
  633. DDDMP_FREE (varNames);
  634. }
  635. return (DDDMP_FAILURE);
  636. }
  637. /*---------------------------------------------------------------------------*/
  638. /* Definition of static functions */
  639. /*---------------------------------------------------------------------------*/
  640. /**Function********************************************************************
  641. Synopsis [Store the BDD as CNF clauses.]
  642. Description [Store the BDD as CNF clauses.
  643. Use a multiplexer description for each BDD node.
  644. ]
  645. SideEffects [None]
  646. SeeAlso []
  647. ******************************************************************************/
  648. static int
  649. StoreCnfNodeByNode (
  650. DdManager *ddMgr /* IN: DD Manager */,
  651. DdNode **f /* IN: BDD array to be stored */,
  652. int rootN /* IN: number of BDDs in the array */,
  653. int *bddIds /* IN: BDD ids for variables */,
  654. int *cnfIds /* IN: CNF ids for variables */,
  655. FILE *fp /* IN: store file */,
  656. int *clauseN /* IN/OUT: number of clauses written in the CNF file */,
  657. int *varMax /* IN/OUT: maximum value of id written in the CNF file */,
  658. int *rootStartLine /* OUT: CNF line where root starts */
  659. )
  660. {
  661. int retValue = 0;
  662. int i, idf;
  663. for (i=0; i<rootN; i++) {
  664. if (f[i] != NULL) {
  665. if (!cuddIsConstant(Cudd_Regular (f[i]))) {
  666. /*
  667. * Set Starting Line for this Root
  668. */
  669. rootStartLine[i] = *clauseN + 1;
  670. /*
  671. * Store the BDD
  672. */
  673. retValue = StoreCnfNodeByNodeRecur (ddMgr, Cudd_Regular(f[i]),
  674. bddIds, cnfIds, fp, clauseN, varMax);
  675. if (retValue == 0) {
  676. (void) fprintf (stderr,
  677. "DdStoreCnf: Error in recursive node store\n");
  678. fflush (stderr);
  679. }
  680. /*
  681. * Store CNF for the root if necessary
  682. */
  683. idf = DddmpReadNodeIndexCnf (Cudd_Regular (f[i]));
  684. #if DDDMP_DEBUG_CNF
  685. retValue = fprintf (fp, "root %d --> \n", i);
  686. #endif
  687. if (Cudd_IsComplement (f[i])) {
  688. retValue = fprintf (fp, "-%d 0\n", idf);
  689. } else {
  690. retValue = fprintf (fp, "%d 0\n", idf);
  691. }
  692. *varMax = GET_MAX (*varMax, idf);
  693. *clauseN = *clauseN + 1;
  694. if (retValue == EOF) {
  695. (void) fprintf (stderr,
  696. "DdStoreCnf: Error in recursive node store\n");
  697. fflush (stderr);
  698. }
  699. }
  700. }
  701. }
  702. return (retValue);
  703. }
  704. /**Function********************************************************************
  705. Synopsis [Performs the recursive step of Dddmp_bddStore.]
  706. Description [Performs the recursive step of Dddmp_bddStore.
  707. Traverse the BDD and store a CNF formula for each "terminal" node.
  708. ]
  709. SideEffects [None]
  710. SeeAlso []
  711. ******************************************************************************/
  712. static int
  713. StoreCnfNodeByNodeRecur (
  714. DdManager *ddMgr /* IN: DD Manager */,
  715. DdNode *f /* IN: BDD node to be stored */,
  716. int *bddIds /* IN: BDD ids for variables */,
  717. int *cnfIds /* IN: CNF ids for variables */,
  718. FILE *fp /* IN: store file */,
  719. int *clauseN /* OUT: number of clauses written in the CNF file */,
  720. int *varMax /* OUT: maximum value of id written in the CNF file */
  721. )
  722. {
  723. DdNode *T, *E;
  724. int idf, idT, idE, vf;
  725. int retValue;
  726. #ifdef DDDMP_DEBUG
  727. assert(!Cudd_IsComplement(f));
  728. assert(f!=NULL);
  729. #endif
  730. /* If constant, nothing to do. */
  731. if (Cudd_IsConstant(f)) {
  732. return (1);
  733. }
  734. /* If already visited, nothing to do. */
  735. if (DddmpVisitedCnf (f)) {
  736. return (1);
  737. }
  738. /* Mark node as visited. */
  739. DddmpSetVisitedCnf (f);
  740. /*------------------ Non Terminal Node -------------------------------*/
  741. #ifdef DDDMP_DEBUG
  742. /* BDDs! Only one constant supported */
  743. assert (!cuddIsConstant(f));
  744. #endif
  745. /*
  746. * Recursive call for Then edge
  747. */
  748. T = cuddT (f);
  749. #ifdef DDDMP_DEBUG
  750. /* ROBDDs! No complemented Then edge */
  751. assert (!Cudd_IsComplement(T));
  752. #endif
  753. /* recur */
  754. retValue = StoreCnfNodeByNodeRecur (ddMgr, T, bddIds, cnfIds, fp,
  755. clauseN, varMax);
  756. if (retValue != 1) {
  757. return(retValue);
  758. }
  759. /*
  760. * Recursive call for Else edge
  761. */
  762. E = Cudd_Regular (cuddE (f));
  763. retValue = StoreCnfNodeByNodeRecur (ddMgr, E, bddIds, cnfIds, fp,
  764. clauseN, varMax);
  765. if (retValue != 1) {
  766. return (retValue);
  767. }
  768. /*
  769. * Obtain nodeids and variable ids of f, T, E
  770. */
  771. idf = DddmpReadNodeIndexCnf (f);
  772. vf = f->index;
  773. if (bddIds[vf] != vf) {
  774. (void) fprintf (stderr, "DdStoreCnf: Error writing to file\n");
  775. fflush (stderr);
  776. return (0);
  777. }
  778. idT = DddmpReadNodeIndexCnf (T);
  779. idE = DddmpReadNodeIndexCnf (E);
  780. if (Cudd_IsComplement (cuddE (f))) {
  781. idE = -idE;
  782. }
  783. retValue = StoreCnfOneNode (f, idf, cnfIds[vf], idT, idE, fp,
  784. clauseN, varMax);
  785. if (retValue == EOF) {
  786. return (0);
  787. } else {
  788. return (1);
  789. }
  790. }
  791. /**Function********************************************************************
  792. Synopsis [Store One Single BDD Node.]
  793. Description [Store One Single BDD Node translating it as a multiplexer.]
  794. SideEffects [None]
  795. SeeAlso []
  796. ******************************************************************************/
  797. static int
  798. StoreCnfOneNode (
  799. DdNode *f /* IN: node to be stored */,
  800. int idf /* IN: node CNF Index */,
  801. int vf /* IN: node BDD Index */,
  802. int idT /* IN: Then CNF Index with sign = inverted edge */,
  803. int idE /* IN: Else CNF Index with sign = inverted edge */,
  804. FILE *fp /* IN: store file */,
  805. int *clauseN /* OUT: number of clauses */,
  806. int *varMax /* OUT: maximun Index of variable stored */
  807. )
  808. {
  809. int retValue = 0;
  810. int idfAbs, idTAbs, idEAbs;
  811. idfAbs = abs (idf);
  812. idTAbs = abs (idT);
  813. idEAbs = abs (idE);
  814. /*----------------------------- Check for Constant ------------------------*/
  815. assert(!Cudd_IsConstant(f));
  816. /*------------------------- Check for terminal nodes ----------------------*/
  817. if ((idTAbs==1) && (idEAbs==1)) {
  818. return (1);
  819. }
  820. /*------------------------------ Internal Node ----------------------------*/
  821. #if DDDMP_DEBUG_CNF
  822. retValue = fprintf (fp, "id=%d var=%d idT=%d idE=%d\n",
  823. idf, vf, idT, idE);
  824. #endif
  825. /*
  826. * Then to terminal
  827. */
  828. if ((idTAbs==1) && (idEAbs!=1)) {
  829. #if DDDMP_DEBUG_CNF
  830. retValue = fprintf (fp, "CASE 1 -->\n");
  831. #endif
  832. retValue = fprintf (fp, "%d %d 0\n",
  833. idf, -vf);
  834. retValue = fprintf (fp, "%d %d 0\n",
  835. idf, -idE);
  836. retValue = fprintf (fp, "%d %d %d 0\n",
  837. -idf, vf, idE);
  838. *clauseN = *clauseN + 3;
  839. *varMax = GET_MAX (*varMax, idfAbs);
  840. *varMax = GET_MAX (*varMax, vf);
  841. *varMax = GET_MAX (*varMax, idEAbs);
  842. }
  843. /*
  844. * Else to terminal
  845. */
  846. if ((idTAbs!=1) && (idEAbs==1)) {
  847. if (idE == 1) {
  848. #if DDDMP_DEBUG_CNF
  849. retValue = fprintf (fp, "CASE 2 -->\n");
  850. #endif
  851. retValue = fprintf (fp, "%d %d 0\n",
  852. idf, vf);
  853. retValue = fprintf (fp, "%d %d 0\n",
  854. idf, -idT);
  855. retValue = fprintf (fp, "%d %d %d 0\n",
  856. -idf, -vf, idT);
  857. } else {
  858. #if DDDMP_DEBUG_CNF
  859. retValue = fprintf (fp, "CASE 3 -->\n");
  860. #endif
  861. retValue = fprintf (fp, "%d %d 0\n",
  862. -idf, vf);
  863. retValue = fprintf (fp, "%d %d 0\n",
  864. -idf, idT);
  865. retValue = fprintf (fp, "%d %d %d 0\n",
  866. idf, -vf, -idT);
  867. }
  868. *varMax = GET_MAX (*varMax, idfAbs);
  869. *varMax = GET_MAX (*varMax, vf);
  870. *varMax = GET_MAX (*varMax, idTAbs);
  871. *clauseN = *clauseN + 3;
  872. }
  873. /*
  874. * Nor Then or Else to terminal
  875. */
  876. if ((idTAbs!=1) && (idEAbs!=1)) {
  877. #if DDDMP_DEBUG_CNF
  878. retValue = fprintf (fp, "CASE 4 -->\n");
  879. #endif
  880. retValue = fprintf (fp, "%d %d %d 0\n",
  881. idf, vf, -idE);
  882. retValue = fprintf (fp, "%d %d %d 0\n",
  883. -idf, vf, idE);
  884. retValue = fprintf (fp, "%d %d %d 0\n",
  885. idf, -vf, -idT);
  886. retValue = fprintf (fp, "%d %d %d 0\n",
  887. -idf, -vf, idT);
  888. *varMax = GET_MAX (*varMax, idfAbs);
  889. *varMax = GET_MAX (*varMax, vf);
  890. *varMax = GET_MAX (*varMax, idTAbs);
  891. *varMax = GET_MAX (*varMax, idEAbs);
  892. *clauseN = *clauseN + 4;
  893. }
  894. return (retValue);
  895. }
  896. /**Function********************************************************************
  897. Synopsis [Prints a disjoint sum of products.]
  898. Description [Prints a disjoint sum of product cover for the function
  899. rooted at node. Each product corresponds to a path from node a
  900. leaf node different from the logical zero, and different from
  901. the background value. Uses the standard output. Returns 1 if
  902. successful, 0 otherwise.
  903. ]
  904. SideEffects [None]
  905. SeeAlso [StoreCnfBest]
  906. ******************************************************************************/
  907. static int
  908. StoreCnfMaxtermByMaxterm (
  909. DdManager *ddMgr /* IN: DD Manager */,
  910. DdNode **f /* IN: array of BDDs to store */,
  911. int rootN /* IN: number of BDDs in the array */,
  912. int *bddIds /* IN: BDD Identifiers */,
  913. int *cnfIds /* IN: corresponding CNF Identifiers */,
  914. int idInitial /* IN: initial value for numbering new CNF variables */,
  915. FILE *fp /* IN: file pointer */,
  916. int *varMax /* OUT: maximum identifier of the variables created */,
  917. int *clauseN /* OUT: number of stored clauses */,
  918. int *rootStartLine /* OUT: line where root starts */
  919. )
  920. {
  921. int i, j, *list;
  922. (void) idInitial; /* avoid warning */
  923. list = DDDMP_ALLOC (int, ddMgr->size);
  924. if (list == NULL) {
  925. ddMgr->errorCode = CUDD_MEMORY_OUT;
  926. return (DDDMP_FAILURE);
  927. }
  928. for (i=0; i<rootN; i++) {
  929. if (f[i] != NULL) {
  930. if (!cuddIsConstant(Cudd_Regular (f[i]))) {
  931. for (j=0; j<ddMgr->size; j++) {
  932. list[j] = 2;
  933. }
  934. /*
  935. * Set Starting Line for this Root
  936. */
  937. rootStartLine[i] = *clauseN + 1;
  938. StoreCnfMaxtermByMaxtermRecur (ddMgr, f[i], bddIds, cnfIds, fp,
  939. list, clauseN, varMax);
  940. }
  941. }
  942. }
  943. FREE (list);
  944. return (1);
  945. }
  946. /**Function********************************************************************
  947. Synopsis [Prints a disjoint sum of products with intermediate
  948. cutting points.]
  949. Description [Prints a disjoint sum of product cover for the function
  950. rooted at node intorducing cutting points whenever necessary.
  951. Each product corresponds to a path from node a leaf
  952. node different from the logical zero, and different from the
  953. background value. Uses the standard output. Returns 1 if
  954. successful, 0 otherwise.
  955. ]
  956. SideEffects [None]
  957. SeeAlso [StoreCnfMaxtermByMaxterm]
  958. ******************************************************************************/
  959. static int
  960. StoreCnfBest (
  961. DdManager *ddMgr /* IN: DD Manager */,
  962. DdNode **f /* IN: array of BDDs to store */,
  963. int rootN /* IN: number of BDD in the array */,
  964. int *bddIds /* IN: BDD identifiers */,
  965. int *cnfIds /* IN: corresponding CNF identifiers */,
  966. int idInitial /* IN: initial value for numbering new CNF variables */,
  967. FILE *fp /* IN: file pointer */,
  968. int *varMax /* OUT: maximum identifier of the variables created */,
  969. int *clauseN /* OUT: number of stored clauses */,
  970. int *rootStartLine /* OUT: line where root starts */
  971. )
  972. {
  973. int i, j, *list;
  974. (void) idInitial; /* avoid warning */
  975. list = DDDMP_ALLOC (int, ddMgr->size);
  976. if (list == NULL) {
  977. ddMgr->errorCode = CUDD_MEMORY_OUT;
  978. return (DDDMP_FAILURE);
  979. }
  980. for (i=0; i<rootN; i++) {
  981. if (f[i] != NULL) {
  982. if (!cuddIsConstant(Cudd_Regular (f[i]))) {
  983. for (j=0; j<ddMgr->size; j++) {
  984. list[j] = 2;
  985. }
  986. /*
  987. * Set Starting Line for this Root
  988. */
  989. rootStartLine[i] = *clauseN + 1;
  990. #if DDDMP_DEBUG_CNF
  991. fprintf (fp, "root NOT shared BDDs %d --> \n", i);
  992. #endif
  993. StoreCnfBestNotSharedRecur (ddMgr, f[i], 0, bddIds, cnfIds, fp, list,
  994. clauseN, varMax);
  995. #if DDDMP_DEBUG_CNF
  996. fprintf (fp, "root SHARED BDDs %d --> \n", i);
  997. #endif
  998. StoreCnfBestSharedRecur (ddMgr, Cudd_Regular (f[i]), bddIds, cnfIds,
  999. fp, list, clauseN, varMax);
  1000. }
  1001. }
  1002. }
  1003. #if DDDMP_DEBUG_CNF
  1004. fprintf (stdout, "###---> BDDs After the Storing Process:\n");
  1005. DddmpPrintBddAndNext (ddMgr, f, rootN);
  1006. #endif
  1007. FREE (list);
  1008. return (DDDMP_SUCCESS);
  1009. }
  1010. /**Function********************************************************************
  1011. Synopsis [Performs the recursive step of Print Maxterm.]
  1012. Description [Performs the recursive step of Print Maxterm.
  1013. Traverse a BDD a print out a cube in CNF format each time a terminal
  1014. node is reached.
  1015. ]
  1016. SideEffects [None]
  1017. SeeAlso []
  1018. ******************************************************************************/
  1019. static void
  1020. StoreCnfMaxtermByMaxtermRecur (
  1021. DdManager *ddMgr /* IN: DD Manager */,
  1022. DdNode *node /* IN: BDD to store */,
  1023. int *bddIds /* IN: BDD identifiers */,
  1024. int *cnfIds /* IN: corresponding CNF identifiers */,
  1025. FILE *fp /* IN: file pointer */,
  1026. int *list /* IN: temporary array to store cubes */,
  1027. int *clauseN /* OUT: number of stored clauses */,
  1028. int *varMax /* OUT: maximum identifier of the variables created */
  1029. )
  1030. {
  1031. DdNode *N, *Nv, *Nnv;
  1032. int retValue, index;
  1033. N = Cudd_Regular (node);
  1034. /*
  1035. * Terminal case: Print one cube based on the current recursion
  1036. */
  1037. if (cuddIsConstant (N)) {
  1038. retValue = printCubeCnf (ddMgr, node, cnfIds, fp, list, varMax);
  1039. if (retValue == DDDMP_SUCCESS) {
  1040. fprintf (fp, "0\n");
  1041. *clauseN = *clauseN + 1;
  1042. }
  1043. return;
  1044. }
  1045. /*
  1046. * NON Terminal case: Recur
  1047. */
  1048. Nv = cuddT (N);
  1049. Nnv = cuddE (N);
  1050. if (Cudd_IsComplement (node)) {
  1051. Nv = Cudd_Not (Nv);
  1052. Nnv = Cudd_Not (Nnv);
  1053. }
  1054. index = N->index;
  1055. /*
  1056. * StQ 06.05.2003
  1057. * Perform the optimization:
  1058. * f = (a + b)' = (a') ^ (a + b') = (a') ^ (b')
  1059. * i.e., if the THEN node is the constant ZERO then that variable
  1060. * can be forgotten (list[index] = 2) for subsequent ELSE cubes
  1061. */
  1062. if (cuddIsConstant (Cudd_Regular (Nv)) && Nv != ddMgr->one) {
  1063. list[index] = 2;
  1064. } else {
  1065. list[index] = 0;
  1066. }
  1067. StoreCnfMaxtermByMaxtermRecur (ddMgr, Nnv, bddIds, cnfIds, fp, list,
  1068. clauseN, varMax);
  1069. /*
  1070. * StQ 06.05.2003
  1071. * Perform the optimization:
  1072. * f = a ^ b = (a) ^ (a' + b) = (a) ^ (b)
  1073. * i.e., if the ELSE node is the constant ZERO then that variable
  1074. * can be forgotten (list[index] = 2) for subsequent THEN cubes
  1075. */
  1076. if (cuddIsConstant (Cudd_Regular (Nnv)) && Nnv != ddMgr->one) {
  1077. list[index] = 2;
  1078. } else {
  1079. list[index] = 1;
  1080. }
  1081. StoreCnfMaxtermByMaxtermRecur (ddMgr, Nv, bddIds, cnfIds, fp, list,
  1082. clauseN, varMax);
  1083. list[index] = 2;
  1084. return;
  1085. }
  1086. /**Function********************************************************************
  1087. Synopsis [Performs the recursive step of Print Best on Not Shared
  1088. sub-BDDs.]
  1089. Description [Performs the recursive step of Print Best on Not Shared
  1090. sub-BDDs, i.e., print out information for the nodes belonging to
  1091. BDDs not shared (whose root has just one incoming edge).
  1092. ]
  1093. SideEffects [None]
  1094. SeeAlso []
  1095. ******************************************************************************/
  1096. static int
  1097. StoreCnfBestNotSharedRecur (
  1098. DdManager *ddMgr /* IN: DD Manager */,
  1099. DdNode *node /* IN: BDD to store */,
  1100. int idf /* IN: Id to store */,
  1101. int *bddIds /* IN: BDD identifiers */,
  1102. int *cnfIds /* IN: corresponding CNF identifiers */,
  1103. FILE *fp /* IN: file pointer */,
  1104. int *list /* IN: temporary array to store cubes */,
  1105. int *clauseN /* OUT: number of stored clauses */,
  1106. int *varMax /* OUT: maximum identifier of the variables created */
  1107. )
  1108. {
  1109. DdNode *N, *Nv, *Nnv;
  1110. int index, retValue;
  1111. N = Cudd_Regular (node);
  1112. /*
  1113. * Terminal case or Already Visited:
  1114. * Print one cube based on the current recursion
  1115. */
  1116. if (cuddIsConstant (N)) {
  1117. retValue = printCubeCnf (ddMgr, node, cnfIds, fp, list, varMax);
  1118. if (retValue == DDDMP_SUCCESS) {
  1119. if (idf != 0) {
  1120. fprintf (fp, "%d ", idf);
  1121. }
  1122. fprintf (fp, "0\n");
  1123. *varMax = GET_MAX (*varMax, abs(idf));
  1124. *clauseN = *clauseN + 1;
  1125. }
  1126. return (DDDMP_SUCCESS);
  1127. }
  1128. /*
  1129. * Shared Sub-Tree: Print Cube
  1130. */
  1131. index = DddmpReadNodeIndexCnf (N);
  1132. if (index > 0) {
  1133. if (idf != 0) {
  1134. fprintf (fp, "%d ", idf);
  1135. }
  1136. if (Cudd_IsComplement (node)) {
  1137. retValue = fprintf (fp, "-%d ", index);
  1138. } else {
  1139. retValue = fprintf (fp, "%d ", index);
  1140. }
  1141. retValue = printCubeCnf (ddMgr, node, cnfIds, fp, list, varMax);
  1142. fprintf (fp, "0\n");
  1143. *varMax = GET_MAX (*varMax, abs(index));
  1144. *clauseN = *clauseN + 1;
  1145. return (DDDMP_SUCCESS);
  1146. }
  1147. /*
  1148. * NON Terminal case: Recur
  1149. */
  1150. Nv = cuddT (N);
  1151. Nnv = cuddE (N);
  1152. if (Cudd_IsComplement (node)) {
  1153. Nv = Cudd_Not (Nv);
  1154. Nnv = Cudd_Not (Nnv);
  1155. }
  1156. index = N->index;
  1157. /*
  1158. * StQ 06.05.2003
  1159. * Perform the optimization:
  1160. * f = (a + b)' = (a') ^ (a + b') = (a') ^ (b')
  1161. * i.e., if the THEN node is the constant ZERO then that variable
  1162. * can be forgotten (list[index] = 2) for subsequent ELSE cubes
  1163. */
  1164. if (cuddIsConstant (Cudd_Regular (Nv)) && Nv != ddMgr->one) {
  1165. list[index] = 2;
  1166. } else {
  1167. list[index] = 0;
  1168. }
  1169. StoreCnfBestNotSharedRecur (ddMgr, Nnv, idf, bddIds, cnfIds, fp, list,
  1170. clauseN, varMax);
  1171. /*
  1172. * StQ 06.05.2003
  1173. * Perform the optimization:
  1174. * f = a ^ b = (a) ^ (a' + b) = (a) ^ (b)
  1175. * i.e., if the ELSE node is the constant ZERO then that variable
  1176. * can be forgotten (list[index] = 2) for subsequent THEN cubes
  1177. */
  1178. if (cuddIsConstant (Cudd_Regular (Nnv)) && Nnv != ddMgr->one) {
  1179. list[index] = 2;
  1180. } else {
  1181. list[index] = 1;
  1182. }
  1183. StoreCnfBestNotSharedRecur (ddMgr, Nv, idf, bddIds, cnfIds, fp, list,
  1184. clauseN, varMax);
  1185. list[index] = 2;
  1186. return (DDDMP_SUCCESS);
  1187. }
  1188. /**Function********************************************************************
  1189. Synopsis [Performs the recursive step of Print Best on Shared
  1190. sub-BDDs.
  1191. ]
  1192. Description [Performs the recursive step of Print Best on Not Shared
  1193. sub-BDDs, i.e., print out information for the nodes belonging to
  1194. BDDs not shared (whose root has just one incoming edge).
  1195. ]
  1196. SideEffects [None]
  1197. SeeAlso []
  1198. ******************************************************************************/
  1199. static int
  1200. StoreCnfBestSharedRecur (
  1201. DdManager *ddMgr /* IN: DD Manager */,
  1202. DdNode *node /* IN: BDD to store */,
  1203. int *bddIds /* IN: BDD identifiers */,
  1204. int *cnfIds /* IN: corresponding CNF identifiers */,
  1205. FILE *fp /* IN: file pointer */,
  1206. int *list /* IN: temporary array to store cubes */,
  1207. int *clauseN /* OUT: number of stored clauses */,
  1208. int *varMax /* OUT: maximum identifier of the variables created */
  1209. )
  1210. {
  1211. DdNode *nodeThen, *nodeElse;
  1212. int i, idf;
  1213. Dddmp_Assert (node==Cudd_Regular(node),
  1214. "Inverted Edge during Shared Printing.");
  1215. /* If constant, nothing to do. */
  1216. if (cuddIsConstant (node)) {
  1217. return (DDDMP_SUCCESS);
  1218. }
  1219. /* If already visited, nothing to do. */
  1220. if (DddmpVisitedCnf (node)) {
  1221. return (DDDMP_SUCCESS);
  1222. }
  1223. /*
  1224. * Shared Sub-Tree: Print Cube
  1225. */
  1226. idf = DddmpReadNodeIndexCnf (node);
  1227. if (idf > 0) {
  1228. /* Cheat the Recur Function about the Index of the Current Node */
  1229. DddmpWriteNodeIndexCnf (node, 0);
  1230. #if DDDMP_DEBUG_CNF
  1231. fprintf (fp, "Else of XNOR\n");
  1232. #endif
  1233. for (i=0; i<ddMgr->size; i++) {
  1234. list[i] = 2;
  1235. }
  1236. StoreCnfBestNotSharedRecur (ddMgr, Cudd_Not (node), idf, bddIds, cnfIds,
  1237. fp, list, clauseN, varMax);
  1238. #if DDDMP_DEBUG_CNF
  1239. fprintf (fp, "Then of XNOR\n");
  1240. #endif
  1241. for (i=0; i<ddMgr->size; i++) {
  1242. list[i] = 2;
  1243. }
  1244. StoreCnfBestNotSharedRecur (ddMgr, node, -idf, bddIds, cnfIds,
  1245. fp, list, clauseN, varMax);
  1246. /* Set Back Index of Current Node */
  1247. DddmpWriteNodeIndexCnf (node, idf);
  1248. }
  1249. /* Mark node as visited. */
  1250. DddmpSetVisitedCnf (node);
  1251. /*
  1252. * Recur
  1253. */
  1254. nodeThen = cuddT (node);
  1255. nodeElse = cuddE (node);
  1256. StoreCnfBestSharedRecur (ddMgr, Cudd_Regular (nodeThen), bddIds, cnfIds,
  1257. fp, list, clauseN, varMax);
  1258. StoreCnfBestSharedRecur (ddMgr, Cudd_Regular (nodeElse), bddIds, cnfIds,
  1259. fp, list, clauseN, varMax);
  1260. return (DDDMP_SUCCESS);
  1261. }
  1262. /**Function********************************************************************
  1263. Synopsis [Print One Cube in CNF Format.]
  1264. Description [Print One Cube in CNF Format.
  1265. Return DDDMP_SUCCESS if something is printed out, DDDMP_FAILURE
  1266. is nothing is printed out.
  1267. ]
  1268. SideEffects [None]
  1269. SeeAlso []
  1270. ******************************************************************************/
  1271. static int
  1272. printCubeCnf (
  1273. DdManager *ddMgr /* IN: DD Manager */,
  1274. DdNode *node /* IN: BDD to store */,
  1275. int *cnfIds /* IN: CNF identifiers */,
  1276. FILE *fp /* IN: file pointer */,
  1277. int *list /* IN: temporary array to store cubes */,
  1278. int *varMax /* OUT: maximum identifier of the variables created */
  1279. )
  1280. {
  1281. int i, retValue;
  1282. DdNode *one;
  1283. retValue = DDDMP_FAILURE;
  1284. one = ddMgr->one;
  1285. if (node != one) {
  1286. for (i=0; i<ddMgr->size; i++) {
  1287. if (list[i] == 0) {
  1288. retValue = DDDMP_SUCCESS;
  1289. (void) fprintf (fp, "%d ", cnfIds[i]);
  1290. *varMax = GET_MAX(*varMax, cnfIds[i]);
  1291. } else {
  1292. if (list[i] == 1) {
  1293. retValue = DDDMP_SUCCESS;
  1294. (void) fprintf (fp, "-%d ", cnfIds[i]);
  1295. *varMax = GET_MAX(*varMax, cnfIds[i]);
  1296. }
  1297. }
  1298. }
  1299. }
  1300. return (retValue);
  1301. }