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.

931 lines
25 KiB

  1. /**CFile**********************************************************************
  2. FileName [dddmpNodeCnf.c]
  3. PackageName [dddmp]
  4. Synopsis [Functions to handle BDD node infos and numbering
  5. while storing a CNF formula from a BDD or an array of BDDs]
  6. Description [Functions to handle BDD node infos and numbering
  7. while storing a CNF formula from a BDD or an array of BDDs.
  8. ]
  9. Author [Gianpiero Cabodi and Stefano Quer]
  10. Copyright [
  11. Copyright (c) 2004 by Politecnico di Torino.
  12. All Rights Reserved. This software is for educational purposes only.
  13. Permission is given to academic institutions to use, copy, and modify
  14. this software and its documentation provided that this introductory
  15. message is not removed, that this software and its documentation is
  16. used for the institutions' internal research and educational purposes,
  17. and that no monies are exchanged. No guarantee is expressed or implied
  18. by the distribution of this code.
  19. Send bug-reports and/or questions to:
  20. {gianpiero.cabodi,stefano.quer}@polito.it.
  21. ]
  22. ******************************************************************************/
  23. #include "dddmpInt.h"
  24. /*---------------------------------------------------------------------------*/
  25. /* Stucture declarations */
  26. /*---------------------------------------------------------------------------*/
  27. /*---------------------------------------------------------------------------*/
  28. /* Type declarations */
  29. /*---------------------------------------------------------------------------*/
  30. /*---------------------------------------------------------------------------*/
  31. /* Variable declarations */
  32. /*---------------------------------------------------------------------------*/
  33. #define DDDMP_DEBUG_CNF 0
  34. /*---------------------------------------------------------------------------*/
  35. /* Macro declarations */
  36. /*---------------------------------------------------------------------------*/
  37. /**AutomaticStart*************************************************************/
  38. /*---------------------------------------------------------------------------*/
  39. /* Static function prototypes */
  40. /*---------------------------------------------------------------------------*/
  41. static int DddmpWriteNodeIndexCnfWithTerminalCheck(DdNode *f, int *cnfIds, int id);
  42. #if 0
  43. static int DddmpClearVisitedCnfRecur(DdNode *f);
  44. #endif
  45. static void DddmpClearVisitedCnf(DdNode *f);
  46. static int NumberNodeRecurCnf(DdNode *f, int *cnfIds, int id);
  47. static void DddmpDdNodesCheckIncomingAndScanPath(DdNode *f, int pathLengthCurrent, int edgeInTh, int pathLengthTh);
  48. static int DddmpDdNodesNumberEdgesRecur(DdNode *f, int *cnfIds, int id);
  49. static int DddmpDdNodesResetCountRecur(DdNode *f);
  50. static int DddmpDdNodesCountEdgesRecur(DdNode *f);
  51. static void RemoveFromUniqueRecurCnf(DdManager *ddMgr, DdNode *f);
  52. static void RestoreInUniqueRecurCnf(DdManager *ddMgr, DdNode *f);
  53. static int DddmpPrintBddAndNextRecur(DdManager *ddMgr, DdNode *f);
  54. /**AutomaticEnd***************************************************************/
  55. /*---------------------------------------------------------------------------*/
  56. /* Definition of exported functions */
  57. /*---------------------------------------------------------------------------*/
  58. /*---------------------------------------------------------------------------*/
  59. /* Definition of internal functions */
  60. /*---------------------------------------------------------------------------*/
  61. /**Function********************************************************************
  62. Synopsis [Removes nodes from unique table and numbers them]
  63. Description [Node numbering is required to convert pointers to integers.
  64. Since nodes are removed from unique table, no new nodes should
  65. be generated before re-inserting nodes in the unique table
  66. (DddmpUnnumberDdNodesCnf()).
  67. ]
  68. SideEffects [Nodes are temporarily removed from unique table]
  69. SeeAlso [RemoveFromUniqueRecurCnf(), NumberNodeRecurCnf(),
  70. DddmpUnnumberDdNodesCnf()]
  71. ******************************************************************************/
  72. int
  73. DddmpNumberDdNodesCnf (
  74. DdManager *ddMgr /* IN: DD Manager */,
  75. DdNode **f /* IN: array of BDDs */,
  76. int rootN /* IN: number of BDD roots in the array of BDDs */,
  77. int *cnfIds /* OUT: CNF identifiers for variables */,
  78. int id /* OUT: number of Temporary Variables Introduced */
  79. )
  80. {
  81. int i;
  82. for (i=0; i<rootN; i++) {
  83. RemoveFromUniqueRecurCnf (ddMgr, f[i]);
  84. }
  85. for (i=0; i<rootN; i++) {
  86. id = NumberNodeRecurCnf (f[i], cnfIds, id);
  87. }
  88. return (id);
  89. }
  90. /**Function********************************************************************
  91. Synopsis [Removes nodes from unique table and numbers each node according
  92. to the number of its incoming BDD edges.
  93. ]
  94. Description [Removes nodes from unique table and numbers each node according
  95. to the number of its incoming BDD edges.
  96. ]
  97. SideEffects [Nodes are temporarily removed from unique table]
  98. SeeAlso [RemoveFromUniqueRecurCnf()]
  99. ******************************************************************************/
  100. int
  101. DddmpDdNodesCountEdgesAndNumber (
  102. DdManager *ddMgr /* IN: DD Manager */,
  103. DdNode **f /* IN: Array of BDDs */,
  104. int rootN /* IN: Number of BDD roots in the array of BDDs */,
  105. int edgeInTh /* IN: Max # In-Edges, after a Insert Cut Point */,
  106. int pathLengthTh /* IN: Max Path Length (after, Insert a Cut Point) */,
  107. int *cnfIds /* OUT: CNF identifiers for variables */,
  108. int id /* OUT: Number of Temporary Variables Introduced */
  109. )
  110. {
  111. int i;
  112. /*-------------------------- Remove From Unique ---------------------------*/
  113. for (i=0; i<rootN; i++) {
  114. RemoveFromUniqueRecurCnf (ddMgr, f[i]);
  115. }
  116. /*-------------------- Reset Counter and Reset Visited --------------------*/
  117. for (i=0; i<rootN; i++) {
  118. (void) DddmpDdNodesResetCountRecur (f[i]);
  119. }
  120. /* Here we must have:
  121. * cnfIndex = 0
  122. * visitedFlag = 0
  123. * FOR ALL nodes
  124. */
  125. #if DDDMP_DEBUG_CNF
  126. fprintf (stdout, "###---> BDDs After Count Reset:\n");
  127. DddmpPrintBddAndNext (ddMgr, f, rootN);
  128. #endif
  129. /*----------------------- Count Incoming Edges ----------------------------*/
  130. for (i=0; i<rootN; i++) {
  131. (void) DddmpDdNodesCountEdgesRecur (f[i]);
  132. }
  133. /* Here we must have:
  134. * cnfIndex = incoming edge count
  135. * visitedFlag = 0 (AGAIN ... remains untouched)
  136. * FOR ALL nodes
  137. */
  138. #if DDDMP_DEBUG_CNF
  139. fprintf (stdout, "###---> BDDs After Count Recur:\n");
  140. DddmpPrintBddAndNext (ddMgr, f, rootN);
  141. #endif
  142. /*------------------------- Count Path Length ----------------------------*/
  143. for (i=0; i<rootN; i++) {
  144. DddmpDdNodesCheckIncomingAndScanPath (f[i], 0, edgeInTh,
  145. pathLengthTh);
  146. }
  147. /* Here we must have:
  148. * cnfIndex = 1 if we want to insert there a cut point
  149. * 0 if we do NOT want to insert there a cut point
  150. * visitedFlag = 1
  151. * FOR ALL nodes
  152. */
  153. #if DDDMP_DEBUG_CNF
  154. fprintf (stdout, "###---> BDDs After Check Incoming And Scan Path:\n");
  155. DddmpPrintBddAndNext (ddMgr, f, rootN);
  156. #endif
  157. /*-------------------- Number Nodes and Set Visited -----------------------*/
  158. for (i=0; i<rootN; i++) {
  159. id = DddmpDdNodesNumberEdgesRecur (f[i], cnfIds, id);
  160. }
  161. /* Here we must have:
  162. * cnfIndex = CNF auxiliary variable enumeration
  163. * visitedFlag = 0
  164. * FOR ALL nodes
  165. */
  166. #if DDDMP_DEBUG_CNF
  167. fprintf (stdout, "###---> BDDs After Count Edges Recur:\n");
  168. DddmpPrintBddAndNext (ddMgr, f, rootN);
  169. #endif
  170. return (id);
  171. }
  172. /**Function********************************************************************
  173. Synopsis [Restores nodes in unique table, loosing numbering]
  174. Description [Node indexes are no more needed. Nodes are re-linked in the
  175. unique table.
  176. ]
  177. SideEffects [None]
  178. SeeAlso [DddmpNumberDdNode()]
  179. ******************************************************************************/
  180. void
  181. DddmpUnnumberDdNodesCnf(
  182. DdManager *ddMgr /* IN: DD Manager */,
  183. DdNode **f /* IN: array of BDDs */,
  184. int rootN /* IN: number of BDD roots in the array of BDDs */
  185. )
  186. {
  187. int i;
  188. for (i=0; i<rootN; i++) {
  189. RestoreInUniqueRecurCnf (ddMgr, f[i]);
  190. }
  191. return;
  192. }
  193. /**Function********************************************************************
  194. Synopsis [Prints debug information]
  195. Description [Prints debug information for an array of BDDs on the screen]
  196. SideEffects [None]
  197. SeeAlso []
  198. ******************************************************************************/
  199. int
  200. DddmpPrintBddAndNext (
  201. DdManager *ddMgr /* IN: DD Manager */,
  202. DdNode **f /* IN: Array of BDDs to be displayed */,
  203. int rootN /* IN: Number of BDD roots in the array of BDDs */
  204. )
  205. {
  206. int i;
  207. for (i=0; i<rootN; i++) {
  208. fprintf (stdout, "---> Bdd %d:\n", i);
  209. fflush (stdout);
  210. DddmpPrintBddAndNextRecur (ddMgr, f[i]);
  211. }
  212. return (DDDMP_SUCCESS);
  213. }
  214. /**Function********************************************************************
  215. Synopsis [Write index to node]
  216. Description [The index of the node is written in the "next" field of
  217. a DdNode struct. LSB is not used (set to 0). It is used as
  218. "visited" flag in DD traversals.
  219. ]
  220. SideEffects [None]
  221. SeeAlso [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (),
  222. DddmpVisitedCnf ()
  223. ]
  224. ******************************************************************************/
  225. int
  226. DddmpWriteNodeIndexCnf (
  227. DdNode *f /* IN: BDD node */,
  228. int id /* IN: index to be written */
  229. )
  230. {
  231. if (!Cudd_IsConstant (f)) {
  232. f->next = (struct DdNode *)((ptruint)id<<1);
  233. }
  234. return (DDDMP_SUCCESS);
  235. }
  236. /**Function********************************************************************
  237. Synopsis [Returns true if node is visited]
  238. Description [Returns true if node is visited]
  239. SideEffects [None]
  240. SeeAlso [DddmpSetVisitedCnf (), DddmpClearVisitedCnf ()]
  241. ******************************************************************************/
  242. int
  243. DddmpVisitedCnf (
  244. DdNode *f /* IN: BDD node to be tested */
  245. )
  246. {
  247. f = Cudd_Regular(f);
  248. return ((int)((ptruint)(f->next)) & (01));
  249. }
  250. /**Function********************************************************************
  251. Synopsis [Marks a node as visited]
  252. Description [Marks a node as visited]
  253. SideEffects [None]
  254. SeeAlso [DddmpVisitedCnf (), DddmpClearVisitedCnf ()]
  255. ******************************************************************************/
  256. void
  257. DddmpSetVisitedCnf (
  258. DdNode *f /* IN: BDD node to be marked (as visited) */
  259. )
  260. {
  261. f = Cudd_Regular(f);
  262. f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next))|01);
  263. return;
  264. }
  265. /**Function********************************************************************
  266. Synopsis [Reads the index of a node]
  267. Description [Reads the index of a node. LSB is skipped (used as visited
  268. flag).
  269. ]
  270. SideEffects [None]
  271. SeeAlso [DddmpWriteNodeIndexCnf(), DddmpSetVisitedCnf (),
  272. DddmpVisitedCnf ()]
  273. ******************************************************************************/
  274. int
  275. DddmpReadNodeIndexCnf (
  276. DdNode *f /* IN: BDD node */
  277. )
  278. {
  279. if (!Cudd_IsConstant (f)) {
  280. return ((int)(((ptruint)(f->next))>>1));
  281. } else {
  282. return (1);
  283. }
  284. }
  285. /*---------------------------------------------------------------------------*/
  286. /* Definition of static functions */
  287. /*---------------------------------------------------------------------------*/
  288. /**Function********************************************************************
  289. Synopsis [Write index to node]
  290. Description [The index of the node is written in the "next" field of
  291. a DdNode struct. LSB is not used (set to 0). It is used as
  292. "visited" flag in DD traversals. The index corresponds to
  293. the BDD node variable if both the node's children are a
  294. constant node, otherwise a new CNF variable is used.
  295. ]
  296. SideEffects [None]
  297. SeeAlso [DddmpReadNodeIndexCnf(), DddmpSetVisitedCnf (),
  298. DddmpVisitedCnf ()]
  299. *****************************************************************************/
  300. static int
  301. DddmpWriteNodeIndexCnfWithTerminalCheck (
  302. DdNode *f /* IN: BDD node */,
  303. int *cnfIds /* IN: possible source for the index to be written */,
  304. int id /* IN: possible source for the index to be written */
  305. )
  306. {
  307. if (!Cudd_IsConstant (f)) {
  308. if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) {
  309. /* If Variable SET ID as Variable ID */
  310. f->next = (struct DdNode *)((ptruint)cnfIds[f->index]<<1);
  311. } else {
  312. f->next = (struct DdNode *)((ptruint)id<<1);
  313. id++;
  314. }
  315. }
  316. return(id);
  317. }
  318. #if 0
  319. /**Function********************************************************************
  320. Synopsis [Mark ALL nodes as not visited]
  321. Description [Mark ALL nodes as not visited (it recurs on the node children)]
  322. SideEffects [None]
  323. SeeAlso [DddmpVisitedCnf (), DddmpSetVisitedCnf ()]
  324. ******************************************************************************/
  325. static int
  326. DddmpClearVisitedCnfRecur (
  327. DdNode *f /* IN: root of the BDD to be marked */
  328. )
  329. {
  330. f = Cudd_Regular(f);
  331. if (cuddIsConstant (f)) {
  332. return (DDDMP_SUCCESS);
  333. }
  334. if (!DddmpVisitedCnf (f)) {
  335. return (DDDMP_SUCCESS);
  336. }
  337. (void) DddmpClearVisitedCnfRecur (cuddT (f));
  338. (void) DddmpClearVisitedCnfRecur (cuddE (f));
  339. DddmpClearVisitedCnf (f);
  340. return (DDDMP_SUCCESS);
  341. }
  342. #endif
  343. /**Function********************************************************************
  344. Synopsis [Marks a node as not visited]
  345. Description [Marks a node as not visited]
  346. SideEffects [None]
  347. SeeAlso [DddmpVisitedCnf (), DddmpSetVisitedCnf ()]
  348. ******************************************************************************/
  349. static void
  350. DddmpClearVisitedCnf (
  351. DdNode *f /* IN: BDD node to be marked (as not visited) */
  352. )
  353. {
  354. f = Cudd_Regular (f);
  355. f->next = (DdNode *)(ptruint)((int)((ptruint)(f->next)) & (~01));
  356. return;
  357. }
  358. /**Function********************************************************************
  359. Synopsis [Number nodes recursively in post-order]
  360. Description [Number nodes recursively in post-order.
  361. The "visited" flag is used with inverse polarity, because all nodes
  362. were set "visited" when removing them from unique.
  363. ]
  364. SideEffects ["visited" flags are reset.]
  365. SeeAlso []
  366. ******************************************************************************/
  367. static int
  368. NumberNodeRecurCnf(
  369. DdNode *f /* IN: root of the BDD to be numbered */,
  370. int *cnfIds /* IN: possible source for numbering */,
  371. int id /* IN/OUT: possible source for numbering */
  372. )
  373. {
  374. f = Cudd_Regular(f);
  375. if (!DddmpVisitedCnf (f)) {
  376. return (id);
  377. }
  378. if (!cuddIsConstant (f)) {
  379. id = NumberNodeRecurCnf (cuddT (f), cnfIds, id);
  380. id = NumberNodeRecurCnf (cuddE (f), cnfIds, id);
  381. }
  382. id = DddmpWriteNodeIndexCnfWithTerminalCheck (f, cnfIds, id);
  383. DddmpClearVisitedCnf (f);
  384. return (id);
  385. }
  386. /**Function********************************************************************
  387. Synopsis [Number nodes recursively in post-order]
  388. Description [Number nodes recursively in post-order.
  389. The "visited" flag is used with the right polarity.
  390. The node is assigned to a new CNF variable only if it is a "shared"
  391. node (i.e. the number of its incoming edges is greater than 1).
  392. ]
  393. SideEffects ["visited" flags are set.]
  394. SeeAlso []
  395. ******************************************************************************/
  396. static void
  397. DddmpDdNodesCheckIncomingAndScanPath (
  398. DdNode *f /* IN: BDD node to be numbered */,
  399. int pathLengthCurrent /* IN: Current Path Length */,
  400. int edgeInTh /* IN: Max # In-Edges, after a Insert Cut Point */,
  401. int pathLengthTh /* IN: Max Path Length (after, Insert a Cut Point) */
  402. )
  403. {
  404. int retValue;
  405. f = Cudd_Regular(f);
  406. if (DddmpVisitedCnf (f)) {
  407. return;
  408. }
  409. if (cuddIsConstant (f)) {
  410. return;
  411. }
  412. pathLengthCurrent++;
  413. retValue = DddmpReadNodeIndexCnf (f);
  414. if ( ((edgeInTh >= 0) && (retValue > edgeInTh)) ||
  415. ((pathLengthTh >= 0) && (pathLengthCurrent > pathLengthTh))
  416. ) {
  417. DddmpWriteNodeIndexCnf (f, 1);
  418. pathLengthCurrent = 0;
  419. } else {
  420. DddmpWriteNodeIndexCnf (f, 0);
  421. }
  422. DddmpDdNodesCheckIncomingAndScanPath (cuddT (f), pathLengthCurrent,
  423. edgeInTh, pathLengthTh);
  424. DddmpDdNodesCheckIncomingAndScanPath (cuddE (f), pathLengthCurrent,
  425. edgeInTh, pathLengthTh);
  426. DddmpSetVisitedCnf (f);
  427. return;
  428. }
  429. /**Function********************************************************************
  430. Synopsis [Number nodes recursively in post-order]
  431. Description [Number nodes recursively in post-order.
  432. The "visited" flag is used with the inverse polarity.
  433. Numbering follows the subsequent strategy:
  434. * if the index = 0 it remains so
  435. * if the index >= 1 it gets enumerated.
  436. This implies that the node is assigned to a new CNF variable only if
  437. it is not a terminal node otherwise it is assigned the index of
  438. the BDD variable.
  439. ]
  440. SideEffects ["visited" flags are reset.]
  441. SeeAlso []
  442. ******************************************************************************/
  443. static int
  444. DddmpDdNodesNumberEdgesRecur (
  445. DdNode *f /* IN: BDD node to be numbered */,
  446. int *cnfIds /* IN: possible source for numbering */,
  447. int id /* IN/OUT: possible source for numbering */
  448. )
  449. {
  450. int retValue;
  451. f = Cudd_Regular(f);
  452. if (!DddmpVisitedCnf (f)) {
  453. return (id);
  454. }
  455. if (cuddIsConstant (f)) {
  456. return (id);
  457. }
  458. id = DddmpDdNodesNumberEdgesRecur (cuddT (f), cnfIds, id);
  459. id = DddmpDdNodesNumberEdgesRecur (cuddE (f), cnfIds, id);
  460. retValue = DddmpReadNodeIndexCnf (f);
  461. if (retValue >= 1) {
  462. id = DddmpWriteNodeIndexCnfWithTerminalCheck (f, cnfIds, id);
  463. } else {
  464. DddmpWriteNodeIndexCnf (f, 0);
  465. }
  466. DddmpClearVisitedCnf (f);
  467. return (id);
  468. }
  469. /**Function********************************************************************
  470. Synopsis [Resets counter and visited flag for ALL nodes of a BDD]
  471. Description [Resets counter and visited flag for ALL nodes of a BDD (it
  472. recurs on the node children). The index field of the node is
  473. used as counter.
  474. ]
  475. SideEffects []
  476. SeeAlso []
  477. ******************************************************************************/
  478. static int
  479. DddmpDdNodesResetCountRecur (
  480. DdNode *f /* IN: root of the BDD whose counters are reset */
  481. )
  482. {
  483. f = Cudd_Regular (f);
  484. if (!DddmpVisitedCnf (f)) {
  485. return (DDDMP_SUCCESS);
  486. }
  487. if (!cuddIsConstant (f)) {
  488. (void) DddmpDdNodesResetCountRecur (cuddT (f));
  489. (void) DddmpDdNodesResetCountRecur (cuddE (f));
  490. }
  491. DddmpWriteNodeIndexCnf (f, 0);
  492. DddmpClearVisitedCnf (f);
  493. return (DDDMP_SUCCESS);
  494. }
  495. /**Function********************************************************************
  496. Synopsis [Counts the number of incoming edges for each node of a BDD]
  497. Description [Counts (recursively) the number of incoming edges for each
  498. node of a BDD. This number is stored in the index field.
  499. ]
  500. SideEffects ["visited" flags remain untouched.]
  501. SeeAlso []
  502. ******************************************************************************/
  503. static int
  504. DddmpDdNodesCountEdgesRecur (
  505. DdNode *f /* IN: root of the BDD */
  506. )
  507. {
  508. int indexValue;
  509. f = Cudd_Regular (f);
  510. if (cuddIsConstant (f)) {
  511. return (DDDMP_SUCCESS);
  512. }
  513. if (Cudd_IsConstant (cuddT (f)) && Cudd_IsConstant (cuddE (f))) {
  514. return (DDDMP_SUCCESS);
  515. }
  516. indexValue = DddmpReadNodeIndexCnf (f);
  517. /* IF (first time) THEN recur */
  518. if (indexValue == 0) {
  519. (void) DddmpDdNodesCountEdgesRecur (cuddT (f));
  520. (void) DddmpDdNodesCountEdgesRecur (cuddE (f));
  521. }
  522. /* Increment Incoming-Edge Count Flag */
  523. indexValue++;
  524. DddmpWriteNodeIndexCnf (f, indexValue);
  525. return (DDDMP_SUCCESS);
  526. }
  527. /**Function********************************************************************
  528. Synopsis [Removes a node from unique table]
  529. Description [Removes a node from the unique table by locating the proper
  530. subtable and unlinking the node from it. It recurs on on the
  531. children of the node. Constants remain untouched.
  532. ]
  533. SideEffects [Nodes are left with the "visited" flag true.]
  534. SeeAlso [RestoreInUniqueRecurCnf()]
  535. ******************************************************************************/
  536. static void
  537. RemoveFromUniqueRecurCnf (
  538. DdManager *ddMgr /* IN: DD Manager */,
  539. DdNode *f /* IN: root of the BDD to be extracted */
  540. )
  541. {
  542. DdNode *node, *last, *next;
  543. DdNode *sentinel = &(ddMgr->sentinel);
  544. DdNodePtr *nodelist;
  545. DdSubtable *subtable;
  546. int pos, level;
  547. f = Cudd_Regular (f);
  548. if (DddmpVisitedCnf (f)) {
  549. return;
  550. }
  551. if (!cuddIsConstant (f)) {
  552. RemoveFromUniqueRecurCnf (ddMgr, cuddT (f));
  553. RemoveFromUniqueRecurCnf (ddMgr, cuddE (f));
  554. level = ddMgr->perm[f->index];
  555. subtable = &(ddMgr->subtables[level]);
  556. nodelist = subtable->nodelist;
  557. pos = ddHash (cuddT (f), cuddE (f), subtable->shift);
  558. node = nodelist[pos];
  559. last = NULL;
  560. while (node != sentinel) {
  561. next = node->next;
  562. if (node == f) {
  563. if (last != NULL)
  564. last->next = next;
  565. else
  566. nodelist[pos] = next;
  567. break;
  568. } else {
  569. last = node;
  570. node = next;
  571. }
  572. }
  573. f->next = NULL;
  574. }
  575. DddmpSetVisitedCnf (f);
  576. return;
  577. }
  578. /**Function********************************************************************
  579. Synopsis [Restores a node in unique table]
  580. Description [Restores a node in unique table (recursive)]
  581. SideEffects [Nodes are not restored in the same order as before removal]
  582. SeeAlso [RemoveFromUnique()]
  583. ******************************************************************************/
  584. static void
  585. RestoreInUniqueRecurCnf (
  586. DdManager *ddMgr /* IN: DD Manager */,
  587. DdNode *f /* IN: root of the BDD to be restored */
  588. )
  589. {
  590. DdNodePtr *nodelist;
  591. DdNode *T, *E, *looking;
  592. DdNodePtr *previousP;
  593. DdSubtable *subtable;
  594. int pos, level;
  595. #ifdef DDDMP_DEBUG
  596. DdNode *node;
  597. DdNode *sentinel = &(ddMgr->sentinel);
  598. #endif
  599. f = Cudd_Regular(f);
  600. if (!Cudd_IsComplement (f->next)) {
  601. return;
  602. }
  603. if (cuddIsConstant (f)) {
  604. /* StQ 11.02.2004:
  605. Bug fixed --> restore NULL within the next field */
  606. /*DddmpClearVisitedCnf (f);*/
  607. f->next = NULL;
  608. return;
  609. }
  610. RestoreInUniqueRecurCnf (ddMgr, cuddT (f));
  611. RestoreInUniqueRecurCnf (ddMgr, cuddE (f));
  612. level = ddMgr->perm[f->index];
  613. subtable = &(ddMgr->subtables[level]);
  614. nodelist = subtable->nodelist;
  615. pos = ddHash (cuddT (f), cuddE (f), subtable->shift);
  616. #ifdef DDDMP_DEBUG
  617. /* verify uniqueness to avoid duplicate nodes in unique table */
  618. for (node=nodelist[pos]; node != sentinel; node=node->next)
  619. assert(node!=f);
  620. #endif
  621. T = cuddT (f);
  622. E = cuddE (f);
  623. previousP = &(nodelist[pos]);
  624. looking = *previousP;
  625. while (T < cuddT (looking)) {
  626. previousP = &(looking->next);
  627. looking = *previousP;
  628. }
  629. while (T == cuddT (looking) && E < cuddE (looking)) {
  630. previousP = &(looking->next);
  631. looking = *previousP;
  632. }
  633. f->next = *previousP;
  634. *previousP = f;
  635. return;
  636. }
  637. /**Function********************************************************************
  638. Synopsis [Prints debug info]
  639. Description [Prints debug info for a BDD on the screen. It recurs on
  640. node's children.
  641. ]
  642. SideEffects []
  643. SeeAlso []
  644. ******************************************************************************/
  645. static int
  646. DddmpPrintBddAndNextRecur (
  647. DdManager *ddMgr /* IN: DD Manager */,
  648. DdNode *f /* IN: root of the BDD to be displayed */
  649. )
  650. {
  651. DdNode *fPtr, *tPtr, *ePtr;
  652. fPtr = Cudd_Regular (f);
  653. if (Cudd_IsComplement (f)) {
  654. fprintf (stdout, "sign=- ptr=%" PRIiPTR " ", ((ptrint) fPtr));
  655. } else {
  656. fprintf (stdout, "sign=+ ptr=%" PRIiPTR " ", ((ptrint) fPtr));
  657. }
  658. if (cuddIsConstant (fPtr)) {
  659. fprintf (stdout, "one\n");
  660. fflush (stdout);
  661. return (DDDMP_SUCCESS);
  662. }
  663. fprintf (stdout,
  664. "thenPtr=%" PRIiPTR " elsePtr=%" PRIiPTR " BddId=%d CnfId=%d Visited=%d\n",
  665. ((ptrint) cuddT (fPtr)), ((ptrint) cuddE (fPtr)),
  666. fPtr->index, DddmpReadNodeIndexCnf (fPtr),
  667. DddmpVisitedCnf (fPtr));
  668. tPtr = cuddT (fPtr);
  669. ePtr = cuddE (fPtr);
  670. if (Cudd_IsComplement (f)) {
  671. tPtr = Cudd_Not (tPtr);
  672. ePtr = Cudd_Not (ePtr);
  673. }
  674. (void) DddmpPrintBddAndNextRecur (ddMgr, tPtr);
  675. (void) DddmpPrintBddAndNextRecur (ddMgr, ePtr);
  676. return (DDDMP_SUCCESS);
  677. }