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.

4808 lines
103 KiB

  1. /**
  2. @file
  3. @ingroup cudd
  4. @brief Application interface functions.
  5. @author 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 "mtrInt.h"
  36. #include "cuddInt.h"
  37. /*---------------------------------------------------------------------------*/
  38. /* Constant declarations */
  39. /*---------------------------------------------------------------------------*/
  40. /*---------------------------------------------------------------------------*/
  41. /* Stucture declarations */
  42. /*---------------------------------------------------------------------------*/
  43. /*---------------------------------------------------------------------------*/
  44. /* Type declarations */
  45. /*---------------------------------------------------------------------------*/
  46. /*---------------------------------------------------------------------------*/
  47. /* Variable declarations */
  48. /*---------------------------------------------------------------------------*/
  49. /*---------------------------------------------------------------------------*/
  50. /* Macro declarations */
  51. /*---------------------------------------------------------------------------*/
  52. /** \cond */
  53. /*---------------------------------------------------------------------------*/
  54. /* Static function prototypes */
  55. /*---------------------------------------------------------------------------*/
  56. static void fixVarTree (MtrNode *treenode, int *perm, int size);
  57. static int addMultiplicityGroups (DdManager *dd, MtrNode *treenode, int multiplicity, char *vmask, char *lmask);
  58. /** \endcond */
  59. /*---------------------------------------------------------------------------*/
  60. /* Definition of exported functions */
  61. /*---------------------------------------------------------------------------*/
  62. /**
  63. @brief Returns a new %ADD variable.
  64. @details The new variable has an index equal to the largest previous
  65. index plus 1. An %ADD variable differs from a %BDD variable because
  66. it points to the arithmetic zero, instead of having a complement
  67. pointer to 1.
  68. @return a pointer to the new variable if successful; NULL otherwise.
  69. @sideeffect None
  70. @see Cudd_bddNewVar Cudd_addIthVar Cudd_addConst
  71. Cudd_addNewVarAtLevel
  72. */
  73. DdNode *
  74. Cudd_addNewVar(
  75. DdManager * dd)
  76. {
  77. DdNode *res;
  78. if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) {
  79. dd->errorCode = CUDD_INVALID_ARG;
  80. return(NULL);
  81. }
  82. do {
  83. dd->reordered = 0;
  84. res = cuddUniqueInter(dd,dd->size,DD_ONE(dd),DD_ZERO(dd));
  85. } while (dd->reordered == 1);
  86. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  87. dd->timeoutHandler(dd, dd->tohArg);
  88. }
  89. return(res);
  90. } /* end of Cudd_addNewVar */
  91. /**
  92. @brief Returns a new %ADD variable at a specified level.
  93. @details The new variable has an index equal to the largest previous
  94. index plus 1 and is positioned at the specified level in the order.
  95. @return a pointer to the new variable if successful; NULL otherwise.
  96. @sideeffect None
  97. @see Cudd_addNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel
  98. */
  99. DdNode *
  100. Cudd_addNewVarAtLevel(
  101. DdManager * dd,
  102. int level)
  103. {
  104. DdNode *res;
  105. if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) {
  106. dd->errorCode = CUDD_INVALID_ARG;
  107. return(NULL);
  108. }
  109. if (level >= dd->size) return(Cudd_addIthVar(dd,level));
  110. if (!cuddInsertSubtables(dd,1,level)) return(NULL);
  111. do {
  112. dd->reordered = 0;
  113. res = cuddUniqueInter(dd,dd->size - 1,DD_ONE(dd),DD_ZERO(dd));
  114. } while (dd->reordered == 1);
  115. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  116. dd->timeoutHandler(dd, dd->tohArg);
  117. }
  118. return(res);
  119. } /* end of Cudd_addNewVarAtLevel */
  120. /**
  121. @brief Returns a new %BDD variable.
  122. @details The new variable has an index equal to the largest previous
  123. index plus 1.
  124. @return a pointer to the new variable if successful; NULL otherwise.
  125. @sideeffect None
  126. @see Cudd_addNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel
  127. */
  128. DdNode *
  129. Cudd_bddNewVar(
  130. DdManager * dd)
  131. {
  132. DdNode *res;
  133. if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) {
  134. dd->errorCode = CUDD_INVALID_ARG;
  135. return(NULL);
  136. }
  137. res = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
  138. return(res);
  139. } /* end of Cudd_bddNewVar */
  140. /**
  141. @brief Returns a new %BDD variable at a specified level.
  142. @details The new variable has an index equal to the largest previous
  143. index plus 1 and is positioned at the specified level in the order.
  144. @return a pointer to the new variable if successful; NULL otherwise.
  145. @sideeffect None
  146. @see Cudd_bddNewVar Cudd_bddIthVar Cudd_addNewVarAtLevel
  147. */
  148. DdNode *
  149. Cudd_bddNewVarAtLevel(
  150. DdManager * dd,
  151. int level)
  152. {
  153. DdNode *res;
  154. if ((unsigned int) dd->size >= CUDD_MAXINDEX - 1) {
  155. dd->errorCode = CUDD_INVALID_ARG;
  156. return(NULL);
  157. }
  158. if (level >= dd->size) return(Cudd_bddIthVar(dd,level));
  159. if (!cuddInsertSubtables(dd,1,level)) return(NULL);
  160. res = dd->vars[dd->size - 1];
  161. return(res);
  162. } /* end of Cudd_bddNewVarAtLevel */
  163. /**
  164. @brief Returns 1 if the given node is a %BDD variable; 0 otherwise.
  165. @sideeffect None
  166. */
  167. int
  168. Cudd_bddIsVar(
  169. DdManager * dd,
  170. DdNode * f)
  171. {
  172. DdNode *one = DD_ONE(dd);
  173. return(f != 0 && cuddT(f) == one && cuddE(f) == Cudd_Not(one));
  174. } /* end of Cudd_bddIsVar */
  175. /**
  176. @brief Returns the %ADD variable with index i.
  177. @details Retrieves the %ADD variable with index i if it already
  178. exists, or creates a new %ADD variable. An %ADD variable differs from
  179. a %BDD variable because it points to the arithmetic zero, instead of
  180. having a complement pointer to 1.
  181. @return a pointer to the variable if successful; NULL otherwise.
  182. @sideeffect None
  183. @see Cudd_addNewVar Cudd_bddIthVar Cudd_addConst
  184. Cudd_addNewVarAtLevel
  185. */
  186. DdNode *
  187. Cudd_addIthVar(
  188. DdManager * dd,
  189. int i)
  190. {
  191. DdNode *res;
  192. if ((unsigned int) i >= CUDD_MAXINDEX - 1) {
  193. dd->errorCode = CUDD_INVALID_ARG;
  194. return(NULL);
  195. }
  196. do {
  197. dd->reordered = 0;
  198. res = cuddUniqueInter(dd,i,DD_ONE(dd),DD_ZERO(dd));
  199. } while (dd->reordered == 1);
  200. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  201. dd->timeoutHandler(dd, dd->tohArg);
  202. }
  203. return(res);
  204. } /* end of Cudd_addIthVar */
  205. /**
  206. @brief Returns the %BDD variable with index i.
  207. @details Retrieves the %BDD variable with index i if it already
  208. exists, or creates a new %BDD variable.
  209. @return a pointer to the variable if successful; NULL otherwise.
  210. @sideeffect None
  211. @see Cudd_bddNewVar Cudd_addIthVar Cudd_bddNewVarAtLevel
  212. Cudd_ReadVars
  213. */
  214. DdNode *
  215. Cudd_bddIthVar(
  216. DdManager * dd,
  217. int i)
  218. {
  219. DdNode *res;
  220. if ((unsigned int) i >= CUDD_MAXINDEX - 1) {
  221. dd->errorCode = CUDD_INVALID_ARG;
  222. return(NULL);
  223. }
  224. if (i < dd->size) {
  225. res = dd->vars[i];
  226. } else {
  227. res = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
  228. }
  229. return(res);
  230. } /* end of Cudd_bddIthVar */
  231. /**
  232. @brief Returns the %ZDD variable with index i.
  233. @details Retrieves the %ZDD variable with index i if it already
  234. exists, or creates a new %ZDD variable.
  235. @return a pointer to the variable if successful; NULL otherwise.
  236. @sideeffect None
  237. @see Cudd_bddIthVar Cudd_addIthVar
  238. */
  239. DdNode *
  240. Cudd_zddIthVar(
  241. DdManager * dd,
  242. int i)
  243. {
  244. DdNode *res;
  245. DdNode *zvar;
  246. DdNode *lower;
  247. int j;
  248. if ((unsigned int) i >= CUDD_MAXINDEX - 1) {
  249. dd->errorCode = CUDD_INVALID_ARG;
  250. return(NULL);
  251. }
  252. /* The i-th variable function has the following structure:
  253. ** at the level corresponding to index i there is a node whose "then"
  254. ** child points to the universe, and whose "else" child points to zero.
  255. ** Above that level there are nodes with identical children.
  256. */
  257. /* First we build the node at the level of index i. */
  258. lower = (i < dd->sizeZ - 1) ? dd->univ[dd->permZ[i]+1] : DD_ONE(dd);
  259. do {
  260. dd->reordered = 0;
  261. zvar = cuddUniqueInterZdd(dd, i, lower, DD_ZERO(dd));
  262. } while (dd->reordered == 1);
  263. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  264. dd->timeoutHandler(dd, dd->tohArg);
  265. }
  266. if (zvar == NULL)
  267. return(NULL);
  268. cuddRef(zvar);
  269. /* Now we add the "filler" nodes above the level of index i. */
  270. for (j = dd->permZ[i] - 1; j >= 0; j--) {
  271. do {
  272. dd->reordered = 0;
  273. res = cuddUniqueInterZdd(dd, dd->invpermZ[j], zvar, zvar);
  274. } while (dd->reordered == 1);
  275. if (res == NULL) {
  276. Cudd_RecursiveDerefZdd(dd,zvar);
  277. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  278. dd->timeoutHandler(dd, dd->tohArg);
  279. }
  280. return(NULL);
  281. }
  282. cuddRef(res);
  283. Cudd_RecursiveDerefZdd(dd,zvar);
  284. zvar = res;
  285. }
  286. cuddDeref(zvar);
  287. return(zvar);
  288. } /* end of Cudd_zddIthVar */
  289. /**
  290. @brief Creates one or more %ZDD variables for each %BDD variable.
  291. @details If some %ZDD variables already exist, only the missing
  292. variables are created. Parameter multiplicity allows the caller to
  293. control how many variables are created for each %BDD variable in
  294. existence. For instance, if ZDDs are used to represent covers, two
  295. %ZDD variables are required for each %BDD variable. The order of the
  296. %BDD variables is transferred to the %ZDD variables. If a variable
  297. group tree exists for the %BDD variables, a corresponding %ZDD
  298. variable group tree is created by expanding the %BDD variable
  299. tree. In any case, the %ZDD variables derived from the same %BDD
  300. variable are merged in a %ZDD variable group. If a %ZDD variable group
  301. tree exists, it is freed.
  302. @return 1 if successful; 0 otherwise.
  303. @sideeffect None
  304. @see Cudd_bddNewVar Cudd_bddIthVar Cudd_bddNewVarAtLevel
  305. */
  306. int
  307. Cudd_zddVarsFromBddVars(
  308. DdManager * dd /**< %DD manager */,
  309. int multiplicity /**< how many %ZDD variables are created for each %BDD variable */)
  310. {
  311. int res;
  312. int i, j;
  313. int allnew;
  314. int *permutation;
  315. if (multiplicity < 1) {
  316. dd->errorCode = CUDD_INVALID_ARG;
  317. return(0);
  318. }
  319. allnew = dd->sizeZ == 0;
  320. if (dd->size * multiplicity > dd->sizeZ) {
  321. res = cuddResizeTableZdd(dd,dd->size * multiplicity - 1);
  322. if (res == 0) return(0);
  323. }
  324. /* Impose the order of the BDD variables to the ZDD variables. */
  325. if (allnew) {
  326. for (i = 0; i < dd->size; i++) {
  327. for (j = 0; j < multiplicity; j++) {
  328. dd->permZ[i * multiplicity + j] =
  329. dd->perm[i] * multiplicity + j;
  330. dd->invpermZ[dd->permZ[i * multiplicity + j]] =
  331. i * multiplicity + j;
  332. }
  333. }
  334. for (i = 0; i < dd->sizeZ; i++) {
  335. dd->univ[i]->index = dd->invpermZ[i];
  336. }
  337. } else {
  338. permutation = ALLOC(int,dd->sizeZ);
  339. if (permutation == NULL) {
  340. dd->errorCode = CUDD_MEMORY_OUT;
  341. return(0);
  342. }
  343. for (i = 0; i < dd->size; i++) {
  344. for (j = 0; j < multiplicity; j++) {
  345. permutation[i * multiplicity + j] =
  346. dd->invperm[i] * multiplicity + j;
  347. }
  348. }
  349. for (i = dd->size * multiplicity; i < dd->sizeZ; i++) {
  350. permutation[i] = i;
  351. }
  352. res = Cudd_zddShuffleHeap(dd, permutation);
  353. FREE(permutation);
  354. if (res == 0) return(0);
  355. }
  356. /* Copy and expand the variable group tree if it exists. */
  357. if (dd->treeZ != NULL) {
  358. Cudd_FreeZddTree(dd);
  359. }
  360. if (dd->tree != NULL) {
  361. dd->treeZ = Mtr_CopyTree(dd->tree, multiplicity);
  362. if (dd->treeZ == NULL) return(0);
  363. } else if (multiplicity > 1) {
  364. dd->treeZ = Mtr_InitGroupTree(0, dd->sizeZ);
  365. if (dd->treeZ == NULL) return(0);
  366. dd->treeZ->index = dd->invpermZ[0];
  367. }
  368. /* Create groups for the ZDD variables derived from the same BDD variable.
  369. */
  370. if (multiplicity > 1) {
  371. char *vmask, *lmask;
  372. vmask = ALLOC(char, dd->size);
  373. if (vmask == NULL) {
  374. dd->errorCode = CUDD_MEMORY_OUT;
  375. return(0);
  376. }
  377. lmask = ALLOC(char, dd->size);
  378. if (lmask == NULL) {
  379. dd->errorCode = CUDD_MEMORY_OUT;
  380. return(0);
  381. }
  382. for (i = 0; i < dd->size; i++) {
  383. vmask[i] = lmask[i] = 0;
  384. }
  385. res = addMultiplicityGroups(dd,dd->treeZ,multiplicity,vmask,lmask);
  386. FREE(vmask);
  387. FREE(lmask);
  388. if (res == 0) return(0);
  389. }
  390. return(1);
  391. } /* end of Cudd_zddVarsFromBddVars */
  392. /**
  393. @brief Returns the maximum possible index for a variable.
  394. @sideeffect None
  395. */
  396. unsigned int
  397. Cudd_ReadMaxIndex(void)
  398. {
  399. return(CUDD_MAXINDEX);
  400. } /* end of Cudd_ReadMaxIndex */
  401. /**
  402. @brief Returns the %ADD for constant c.
  403. @details Retrieves the %ADD for constant c if it already
  404. exists, or creates a new %ADD.
  405. @return a pointer to the %ADD if successful; NULL otherwise.
  406. @sideeffect None
  407. @see Cudd_addNewVar Cudd_addIthVar
  408. */
  409. DdNode *
  410. Cudd_addConst(
  411. DdManager * dd,
  412. CUDD_VALUE_TYPE c)
  413. {
  414. return(cuddUniqueConst(dd,c));
  415. } /* end of Cudd_addConst */
  416. /**
  417. @brief Returns 1 if the node is a constant node.
  418. @details A constant node is not an internal node. The pointer
  419. passed to Cudd_IsConstant may be either regular or complemented.
  420. @sideeffect none
  421. */
  422. int Cudd_IsConstant(DdNode *node)
  423. {
  424. return Cudd_Regular(node)->index == CUDD_CONST_INDEX;
  425. } /* end of Cudd_IsConstant */
  426. /**
  427. @brief Returns 1 if a %DD node is not constant.
  428. @details This function is useful to test the results of
  429. Cudd_bddIteConstant, Cudd_addIteConstant, Cudd_addEvalConst. These
  430. results may be a special value signifying non-constant. In the other
  431. cases Cudd_IsConstant can be used.
  432. @sideeffect None
  433. @see Cudd_IsConstant Cudd_bddIteConstant Cudd_addIteConstant
  434. Cudd_addEvalConst
  435. */
  436. int
  437. Cudd_IsNonConstant(
  438. DdNode *f)
  439. {
  440. return(f == DD_NON_CONSTANT || !Cudd_IsConstantInt(f));
  441. } /* end of Cudd_IsNonConstant */
  442. /**
  443. @brief Returns the then child of an internal node.
  444. @details If <code>node</code> is a constant node, the result is
  445. unpredictable.
  446. @sideeffect none
  447. @see Cudd_E Cudd_V
  448. */
  449. DdNode const *
  450. Cudd_T_const(DdNode const *node)
  451. {
  452. return Cudd_Regular(node)->type.kids.T;
  453. } /* end of Cudd_T */
  454. /**
  455. @brief Returns the else child of an internal node.
  456. @details If <code>node</code> is a constant node, the result is
  457. unpredictable.
  458. @sideeffect none
  459. @see Cudd_T Cudd_V
  460. */
  461. DdNode const *
  462. Cudd_E_const(DdNode const * node)
  463. {
  464. return Cudd_Regular(node)->type.kids.E;
  465. } /* end of Cudd_E */
  466. /**
  467. @brief Returns the then child of an internal node.
  468. @details If <code>node</code> is a constant node, the result is
  469. unpredictable.
  470. @sideeffect none
  471. @see Cudd_E Cudd_V
  472. */
  473. DdNode *
  474. Cudd_T(DdNode * node)
  475. {
  476. return Cudd_Regular(node)->type.kids.T;
  477. } /* end of Cudd_T */
  478. /**
  479. @brief Returns the else child of an internal node.
  480. @details If <code>node</code> is a constant node, the result is
  481. unpredictable.
  482. @sideeffect none
  483. @see Cudd_T Cudd_V
  484. */
  485. DdNode *
  486. Cudd_E(DdNode * node)
  487. {
  488. return Cudd_Regular(node)->type.kids.E;
  489. } /* end of Cudd_E */
  490. /**
  491. @brief Returns the value of a constant node.
  492. @details If <code>node</code> is an internal node, the result is
  493. unpredictable.
  494. @sideeffect none
  495. @see Cudd_T Cudd_E
  496. */
  497. CUDD_VALUE_TYPE
  498. Cudd_V(DdNode const *node)
  499. {
  500. return Cudd_Regular(node)->type.value;
  501. } /* end of Cudd_V */
  502. /**
  503. @brief Returns the start time of the manager.
  504. @details This is initially set to the number of milliseconds since
  505. the program started, but may be reset by the application.
  506. @sideeffect None
  507. @see Cudd_SetStartTime Cudd_ResetStartTime Cudd_ReadTimeLimit
  508. */
  509. unsigned long
  510. Cudd_ReadStartTime(
  511. DdManager * unique)
  512. {
  513. return unique->startTime;
  514. } /* end of Cudd_ReadStartTime */
  515. /**
  516. @brief Returns the time elapsed since the start time of the manager.
  517. @details The time is expressed in milliseconds.
  518. @sideeffect None
  519. @see Cudd_ReadStartTime Cudd_SetStartTime
  520. */
  521. unsigned long
  522. Cudd_ReadElapsedTime(
  523. DdManager * unique)
  524. {
  525. return util_cpu_time() - unique->startTime;
  526. } /* end of Cudd_ReadElapsedTime */
  527. /**
  528. @brief Sets the start time of the manager.
  529. @details The time must be expressed in milliseconds.
  530. @sideeffect None
  531. @see Cudd_ReadStartTime Cudd_ResetStartTime Cudd_ReadElapsedTime
  532. Cudd_SetTimeLimit
  533. */
  534. void
  535. Cudd_SetStartTime(
  536. DdManager * unique,
  537. unsigned long st)
  538. {
  539. unique->startTime = st;
  540. } /* end of Cudd_SetStartTime */
  541. /**
  542. @brief Resets the start time of the manager.
  543. @sideeffect None
  544. @see Cudd_ReadStartTime Cudd_SetStartTime Cudd_SetTimeLimit
  545. */
  546. void
  547. Cudd_ResetStartTime(
  548. DdManager * unique)
  549. {
  550. unique->startTime = util_cpu_time();
  551. } /* end of Cudd_ResetStartTime */
  552. /**
  553. @brief Returns the time limit for the manager.
  554. @details This is initially set to a very large number, but may be
  555. reset by the application. The time is expressed in milliseconds.
  556. @sideeffect None
  557. @see Cudd_SetTimeLimit Cudd_UpdateTimeLimit Cudd_UnsetTimeLimit
  558. Cudd_IncreaseTimeLimit Cudd_TimeLimited Cudd_ReadStartTime
  559. */
  560. unsigned long
  561. Cudd_ReadTimeLimit(
  562. DdManager * unique)
  563. {
  564. return unique->timeLimit;
  565. } /* end of Cudd_ReadTimeLimit */
  566. /**
  567. @brief Sets the time limit for the manager.
  568. @details The time must be expressed in milliseconds.
  569. @return the old time limit.
  570. @sideeffect None
  571. @see Cudd_ReadTimeLimit Cudd_UnsetTimeLimit Cudd_UpdateTimeLimit
  572. Cudd_IncreaseTimeLimit Cudd_TimeLimited Cudd_SetStartTime
  573. */
  574. unsigned long
  575. Cudd_SetTimeLimit(
  576. DdManager * unique,
  577. unsigned long tl)
  578. {
  579. unsigned long ret = unique->timeLimit;
  580. unique->timeLimit = tl;
  581. return(ret);
  582. } /* end of Cudd_SetTimeLimit */
  583. /**
  584. @brief Updates the time limit for the manager.
  585. @details Updates the time limit for the manager by subtracting the
  586. elapsed time from it.
  587. @sideeffect None
  588. @see Cudd_ReadTimeLimit Cudd_SetTimeLimit Cudd_UnsetTimeLimit
  589. Cudd_IncreaseTimeLimit Cudd_TimeLimited Cudd_SetStartTime
  590. */
  591. void
  592. Cudd_UpdateTimeLimit(
  593. DdManager * unique)
  594. {
  595. unsigned long elapsed;
  596. if (unique->timeLimit == ~0UL)
  597. return;
  598. elapsed = util_cpu_time() - unique->startTime;
  599. if (unique->timeLimit >= elapsed) {
  600. unique->timeLimit -= elapsed;
  601. } else {
  602. unique->timeLimit = 0;
  603. }
  604. } /* end of Cudd_UpdateTimeLimit */
  605. /**
  606. @brief Increases the time limit for the manager.
  607. @details The time increase must be expressed in milliseconds.
  608. @sideeffect None
  609. @see Cudd_ReadTimeLimit Cudd_SetTimeLimit Cudd_UnsetTimeLimit
  610. Cudd_UpdateTimeLimit Cudd_TimeLimited Cudd_SetStartTime
  611. */
  612. void
  613. Cudd_IncreaseTimeLimit(
  614. DdManager * unique,
  615. unsigned long increase)
  616. {
  617. if (unique->timeLimit == ~0UL)
  618. unique->timeLimit = increase;
  619. else
  620. unique->timeLimit += increase;
  621. } /* end of Cudd_IncreaseTimeLimit */
  622. /**
  623. @brief Unsets the time limit for the manager.
  624. @details Actually, sets it to a very large value.
  625. @sideeffect None
  626. @see Cudd_ReadTimeLimit Cudd_SetTimeLimit Cudd_UpdateTimeLimit
  627. Cudd_IncreaseTimeLimit Cudd_TimeLimited Cudd_SetStartTime
  628. */
  629. void
  630. Cudd_UnsetTimeLimit(
  631. DdManager * unique)
  632. {
  633. unique->timeLimit = ~0UL;
  634. } /* end of Cudd_UnsetTimeLimit */
  635. /**
  636. @brief Returns true if the time limit for the manager is set.
  637. @sideeffect None
  638. @see Cudd_ReadTimeLimit Cudd_SetTimeLimit Cudd_UpdateTimeLimit
  639. Cudd_UnsetTimeLimit Cudd_IncreaseTimeLimit
  640. */
  641. int
  642. Cudd_TimeLimited(
  643. DdManager * unique)
  644. {
  645. return unique->timeLimit != ~0UL;
  646. } /* end of Cudd_TimeLimited */
  647. /**
  648. @brief Installs a termination callback.
  649. @details Registers a callback function that is called from time
  650. to time to decide whether computation should be abandoned.
  651. @sideeffect None
  652. @see Cudd_UnregisterTerminationCallback
  653. */
  654. void
  655. Cudd_RegisterTerminationCallback(
  656. DdManager *unique,
  657. DD_THFP callback,
  658. void * callback_arg)
  659. {
  660. unique->terminationCallback = callback;
  661. unique->tcbArg = callback_arg;
  662. } /* end of Cudd_RegisterTerminationCallback */
  663. /**
  664. @brief Unregisters a termination callback.
  665. @sideeffect None
  666. @see Cudd_RegisterTerminationCallback
  667. */
  668. void
  669. Cudd_UnregisterTerminationCallback(
  670. DdManager *unique)
  671. {
  672. unique->terminationCallback = NULL;
  673. unique->tcbArg = NULL;
  674. } /* end of Cudd_UnregisterTerminationCallback */
  675. /**
  676. @brief Installs an out-of-memory callback.
  677. @details Registers a callback function that is called when
  678. a discretionary memory allocation fails.
  679. @return the old callback function.
  680. @sideeffect None
  681. @see Cudd_UnregisterOutOfMemoryCallback Cudd_OutOfMem Cudd_OutOfMemSilent
  682. */
  683. DD_OOMFP
  684. Cudd_RegisterOutOfMemoryCallback(
  685. DdManager *unique,
  686. DD_OOMFP callback)
  687. {
  688. DD_OOMFP ret = unique->outOfMemCallback;
  689. unique->outOfMemCallback = callback;
  690. return(ret);
  691. } /* end of Cudd_RegisterOutOfMemoryCallback */
  692. /**
  693. @brief Unregister an out-of-memory callback.
  694. @sideeffect None
  695. @see Cudd_RegisterOutOfMemoryCallback Cudd_OutOfMem Cudd_OutOfMemSilent
  696. */
  697. void
  698. Cudd_UnregisterOutOfMemoryCallback(
  699. DdManager *unique)
  700. {
  701. unique->outOfMemCallback = Cudd_OutOfMemSilent;
  702. } /* end of Cudd_UnregisterOutOfMemoryCallback */
  703. /**
  704. @brief Register a timeout handler function.
  705. @details To unregister a handler, register a NULL pointer.
  706. @sideeffect None
  707. @see Cudd_ReadTimeoutHandler
  708. */
  709. void
  710. Cudd_RegisterTimeoutHandler(
  711. DdManager *unique,
  712. DD_TOHFP handler,
  713. void *arg)
  714. {
  715. unique->timeoutHandler = handler;
  716. unique->tohArg = arg;
  717. } /* end of Cudd_RegisterTimeoutHandler */
  718. /**
  719. @brief Read the current timeout handler function.
  720. @sideeffect If argp is non-null, the second argument to
  721. the handler is written to the location it points to.
  722. @see Cudd_RegisterTimeoutHandler
  723. */
  724. DD_TOHFP
  725. Cudd_ReadTimeoutHandler(
  726. DdManager *unique,
  727. void **argp)
  728. {
  729. if (argp != NULL)
  730. *argp = unique->tohArg;
  731. return unique->timeoutHandler;
  732. } /* end of Cudd_ReadTimeoutHandler */
  733. /**
  734. @brief Enables automatic dynamic reordering of BDDs and ADDs.
  735. @details Parameter method is used to determine the method used for
  736. reordering. If CUDD_REORDER_SAME is passed, the method is unchanged.
  737. @sideeffect None
  738. @see Cudd_AutodynDisable Cudd_ReorderingStatus
  739. Cudd_AutodynEnableZdd
  740. */
  741. void
  742. Cudd_AutodynEnable(
  743. DdManager * unique,
  744. Cudd_ReorderingType method)
  745. {
  746. unique->autoDyn = 1;
  747. if (method != CUDD_REORDER_SAME) {
  748. unique->autoMethod = method;
  749. }
  750. #ifndef DD_NO_DEATH_ROW
  751. /* If reordering is enabled, using the death row causes too many
  752. ** invocations. Hence, we shrink the death row to just one entry.
  753. */
  754. cuddClearDeathRow(unique);
  755. unique->deathRowDepth = 1;
  756. unique->deadMask = unique->deathRowDepth - 1;
  757. if ((unsigned) unique->nextDead > unique->deadMask) {
  758. unique->nextDead = 0;
  759. }
  760. unique->deathRow = REALLOC(DdNodePtr, unique->deathRow,
  761. unique->deathRowDepth);
  762. #endif
  763. return;
  764. } /* end of Cudd_AutodynEnable */
  765. /**
  766. @brief Disables automatic dynamic reordering.
  767. @sideeffect None
  768. @see Cudd_AutodynEnable Cudd_ReorderingStatus
  769. Cudd_AutodynDisableZdd
  770. */
  771. void
  772. Cudd_AutodynDisable(
  773. DdManager * unique)
  774. {
  775. unique->autoDyn = 0;
  776. return;
  777. } /* end of Cudd_AutodynDisable */
  778. /**
  779. @brief Reports the status of automatic dynamic reordering of BDDs
  780. and ADDs.
  781. @details The location pointed by parameter method is set to
  782. the reordering method currently selected if method is non-null.
  783. @return 1 if automatic reordering is enabled; 0 otherwise.
  784. @sideeffect The location pointed by parameter method is set to the
  785. reordering method currently selected if method is non-null.
  786. @see Cudd_AutodynEnable Cudd_AutodynDisable
  787. Cudd_ReorderingStatusZdd
  788. */
  789. int
  790. Cudd_ReorderingStatus(
  791. DdManager * unique,
  792. Cudd_ReorderingType * method)
  793. {
  794. if (method)
  795. *method = unique->autoMethod;
  796. return(unique->autoDyn);
  797. } /* end of Cudd_ReorderingStatus */
  798. /**
  799. @brief Enables automatic dynamic reordering of ZDDs.
  800. @details Parameter method is used to determine the method used for
  801. reordering ZDDs. If CUDD_REORDER_SAME is passed, the method is
  802. unchanged.
  803. @sideeffect None
  804. @see Cudd_AutodynDisableZdd Cudd_ReorderingStatusZdd
  805. Cudd_AutodynEnable
  806. */
  807. void
  808. Cudd_AutodynEnableZdd(
  809. DdManager * unique,
  810. Cudd_ReorderingType method)
  811. {
  812. unique->autoDynZ = 1;
  813. if (method != CUDD_REORDER_SAME) {
  814. unique->autoMethodZ = method;
  815. }
  816. return;
  817. } /* end of Cudd_AutodynEnableZdd */
  818. /**
  819. @brief Disables automatic dynamic reordering of ZDDs.
  820. @sideeffect None
  821. @see Cudd_AutodynEnableZdd Cudd_ReorderingStatusZdd
  822. Cudd_AutodynDisable
  823. */
  824. void
  825. Cudd_AutodynDisableZdd(
  826. DdManager * unique)
  827. {
  828. unique->autoDynZ = 0;
  829. return;
  830. } /* end of Cudd_AutodynDisableZdd */
  831. /**
  832. @brief Reports the status of automatic dynamic reordering of ZDDs.
  833. @details Parameter method is set to the %ZDD reordering method currently
  834. selected.
  835. @return 1 if automatic reordering is enabled; 0 otherwise.
  836. @sideeffect Parameter method is set to the %ZDD reordering method currently
  837. selected.
  838. @see Cudd_AutodynEnableZdd Cudd_AutodynDisableZdd
  839. Cudd_ReorderingStatus
  840. */
  841. int
  842. Cudd_ReorderingStatusZdd(
  843. DdManager * unique,
  844. Cudd_ReorderingType * method)
  845. {
  846. *method = unique->autoMethodZ;
  847. return(unique->autoDynZ);
  848. } /* end of Cudd_ReorderingStatusZdd */
  849. /**
  850. @brief Tells whether the realignment of %ZDD order to %BDD order is
  851. enabled.
  852. @return 1 if the realignment of %ZDD order to %BDD order is enabled; 0
  853. otherwise.
  854. @sideeffect None
  855. @see Cudd_zddRealignEnable Cudd_zddRealignDisable
  856. Cudd_bddRealignEnable Cudd_bddRealignDisable
  857. */
  858. int
  859. Cudd_zddRealignmentEnabled(
  860. DdManager * unique)
  861. {
  862. return(unique->realign);
  863. } /* end of Cudd_zddRealignmentEnabled */
  864. /**
  865. @brief Enables realignment of %ZDD order to %BDD order.
  866. @details Enables realignment of the %ZDD variable order to the
  867. %BDD variable order after the BDDs and ADDs have been reordered. The
  868. number of %ZDD variables must be a multiple of the number of %BDD
  869. variables for realignment to make sense. If this condition is not met,
  870. Cudd_ReduceHeap will return 0. Let <code>M</code> be the
  871. ratio of the two numbers. For the purpose of realignment, the %ZDD
  872. variables from <code>M*i</code> to <code>(M+1)*i-1</code> are
  873. reagarded as corresponding to %BDD variable <code>i</code>. Realignment
  874. is initially disabled.
  875. @sideeffect None
  876. @see Cudd_ReduceHeap Cudd_zddRealignDisable
  877. Cudd_zddRealignmentEnabled Cudd_bddRealignDisable
  878. Cudd_bddRealignmentEnabled
  879. */
  880. void
  881. Cudd_zddRealignEnable(
  882. DdManager * unique)
  883. {
  884. unique->realign = 1;
  885. return;
  886. } /* end of Cudd_zddRealignEnable */
  887. /**
  888. @brief Disables realignment of %ZDD order to %BDD order.
  889. @sideeffect None
  890. @see Cudd_zddRealignEnable Cudd_zddRealignmentEnabled
  891. Cudd_bddRealignEnable Cudd_bddRealignmentEnabled
  892. */
  893. void
  894. Cudd_zddRealignDisable(
  895. DdManager * unique)
  896. {
  897. unique->realign = 0;
  898. return;
  899. } /* end of Cudd_zddRealignDisable */
  900. /**
  901. @brief Tells whether the realignment of %BDD order to %ZDD order is
  902. enabled.
  903. @return 1 if the realignment of %BDD order to %ZDD order is enabled; 0
  904. otherwise.
  905. @sideeffect None
  906. @see Cudd_bddRealignEnable Cudd_bddRealignDisable
  907. Cudd_zddRealignEnable Cudd_zddRealignDisable
  908. */
  909. int
  910. Cudd_bddRealignmentEnabled(
  911. DdManager * unique)
  912. {
  913. return(unique->realignZ);
  914. } /* end of Cudd_bddRealignmentEnabled */
  915. /**
  916. @brief Enables realignment of %BDD order to %ZDD order.
  917. @details Enables realignment of the %BDD variable order to the
  918. %ZDD variable order after the ZDDs have been reordered. The
  919. number of %ZDD variables must be a multiple of the number of %BDD
  920. variables for realignment to make sense. If this condition is not met,
  921. Cudd_zddReduceHeap will return 0. Let <code>M</code> be the
  922. ratio of the two numbers. For the purpose of realignment, the %ZDD
  923. variables from <code>M*i</code> to <code>(M+1)*i-1</code> are
  924. reagarded as corresponding to %BDD variable <code>i</code>. Realignment
  925. is initially disabled.
  926. @sideeffect None
  927. @see Cudd_zddReduceHeap Cudd_bddRealignDisable
  928. Cudd_bddRealignmentEnabled Cudd_zddRealignDisable
  929. Cudd_zddRealignmentEnabled
  930. */
  931. void
  932. Cudd_bddRealignEnable(
  933. DdManager * unique)
  934. {
  935. unique->realignZ = 1;
  936. return;
  937. } /* end of Cudd_bddRealignEnable */
  938. /**
  939. @brief Disables realignment of %ZDD order to %BDD order.
  940. @sideeffect None
  941. @see Cudd_bddRealignEnable Cudd_bddRealignmentEnabled
  942. Cudd_zddRealignEnable Cudd_zddRealignmentEnabled
  943. */
  944. void
  945. Cudd_bddRealignDisable(
  946. DdManager * unique)
  947. {
  948. unique->realignZ = 0;
  949. return;
  950. } /* end of Cudd_bddRealignDisable */
  951. /**
  952. @brief Returns the one constant of the manager.
  953. @details The one constant is common to ADDs and BDDs.
  954. @sideeffect None
  955. @see Cudd_ReadZero Cudd_ReadLogicZero Cudd_ReadZddOne
  956. */
  957. DdNode *
  958. Cudd_ReadOne(
  959. DdManager * dd)
  960. {
  961. return(dd->one);
  962. } /* end of Cudd_ReadOne */
  963. /**
  964. @brief Returns the %ZDD for the constant 1 function.
  965. @details The representation of the constant 1 function as a %ZDD
  966. depends on how many variables it (nominally) depends on. The index
  967. of the topmost variable in the support is given as argument
  968. <code>i</code>.
  969. @sideeffect None
  970. @see Cudd_ReadOne
  971. */
  972. DdNode *
  973. Cudd_ReadZddOne(
  974. DdManager * dd,
  975. int i)
  976. {
  977. if (i < 0)
  978. return(NULL);
  979. return(i < dd->sizeZ ? dd->univ[i] : DD_ONE(dd));
  980. } /* end of Cudd_ReadZddOne */
  981. /**
  982. @brief Returns the zero constant of the manager.
  983. @details The zero constant is the arithmetic zero, rather than the
  984. logic zero. The latter is the complement of the one constant.
  985. @sideeffect None
  986. @see Cudd_ReadOne Cudd_ReadLogicZero
  987. */
  988. DdNode *
  989. Cudd_ReadZero(
  990. DdManager * dd)
  991. {
  992. return(DD_ZERO(dd));
  993. } /* end of Cudd_ReadZero */
  994. /**
  995. @brief Returns the logic zero constant of the manager.
  996. @details The logic zero constant is the complement of the one
  997. constant, and is distinct from the arithmetic zero.
  998. @sideeffect None
  999. @see Cudd_ReadOne Cudd_ReadZero
  1000. */
  1001. DdNode *
  1002. Cudd_ReadLogicZero(
  1003. DdManager * dd)
  1004. {
  1005. return(Cudd_Not(DD_ONE(dd)));
  1006. } /* end of Cudd_ReadLogicZero */
  1007. /**
  1008. @brief Reads the plus-infinity constant from the manager.
  1009. @sideeffect None
  1010. */
  1011. DdNode *
  1012. Cudd_ReadPlusInfinity(
  1013. DdManager * dd)
  1014. {
  1015. return(dd->plusinfinity);
  1016. } /* end of Cudd_ReadPlusInfinity */
  1017. /**
  1018. @brief Reads the minus-infinity constant from the manager.
  1019. @sideeffect None
  1020. */
  1021. DdNode *
  1022. Cudd_ReadMinusInfinity(
  1023. DdManager * dd)
  1024. {
  1025. return(dd->minusinfinity);
  1026. } /* end of Cudd_ReadMinusInfinity */
  1027. /**
  1028. @brief Reads the background constant of the manager.
  1029. @sideeffect None
  1030. */
  1031. DdNode *
  1032. Cudd_ReadBackground(
  1033. DdManager * dd)
  1034. {
  1035. return(dd->background);
  1036. } /* end of Cudd_ReadBackground */
  1037. /**
  1038. @brief Sets the background constant of the manager.
  1039. @details It assumes that the DdNode pointer bck is already
  1040. referenced.
  1041. @sideeffect None
  1042. */
  1043. void
  1044. Cudd_SetBackground(
  1045. DdManager * dd,
  1046. DdNode * bck)
  1047. {
  1048. dd->background = bck;
  1049. } /* end of Cudd_SetBackground */
  1050. /**
  1051. @brief Reads the number of slots in the cache.
  1052. @sideeffect None
  1053. @see Cudd_ReadCacheUsedSlots
  1054. */
  1055. unsigned int
  1056. Cudd_ReadCacheSlots(
  1057. DdManager * dd)
  1058. {
  1059. return(dd->cacheSlots);
  1060. } /* end of Cudd_ReadCacheSlots */
  1061. /**
  1062. @brief Reads the fraction of used slots in the cache.
  1063. @details The unused slots are those in which no valid data is
  1064. stored. Garbage collection, variable reordering, and cache resizing
  1065. may cause used slots to become unused.
  1066. @sideeffect None
  1067. @see Cudd_ReadCacheSlots
  1068. */
  1069. double
  1070. Cudd_ReadCacheUsedSlots(
  1071. DdManager * dd)
  1072. {
  1073. size_t used = 0;
  1074. int slots = dd->cacheSlots;
  1075. DdCache *cache = dd->cache;
  1076. int i;
  1077. for (i = 0; i < slots; i++) {
  1078. used += cache[i].h != 0;
  1079. }
  1080. return((double)used / (double) dd->cacheSlots);
  1081. } /* end of Cudd_ReadCacheUsedSlots */
  1082. /**
  1083. @brief Returns the number of cache look-ups.
  1084. @sideeffect None
  1085. @see Cudd_ReadCacheHits
  1086. */
  1087. double
  1088. Cudd_ReadCacheLookUps(
  1089. DdManager * dd)
  1090. {
  1091. return(dd->cacheHits + dd->cacheMisses +
  1092. dd->totCachehits + dd->totCacheMisses);
  1093. } /* end of Cudd_ReadCacheLookUps */
  1094. /**
  1095. @brief Returns the number of cache hits.
  1096. @sideeffect None
  1097. @see Cudd_ReadCacheLookUps
  1098. */
  1099. double
  1100. Cudd_ReadCacheHits(
  1101. DdManager * dd)
  1102. {
  1103. return(dd->cacheHits + dd->totCachehits);
  1104. } /* end of Cudd_ReadCacheHits */
  1105. /**
  1106. @brief Returns the number of recursive calls.
  1107. @details Returns the number of recursive calls if the package is
  1108. compiled with DD_COUNT defined.
  1109. @sideeffect None
  1110. */
  1111. double
  1112. Cudd_ReadRecursiveCalls(
  1113. DdManager * dd)
  1114. {
  1115. #ifdef DD_COUNT
  1116. return(dd->recursiveCalls);
  1117. #else
  1118. (void) dd; /* avoid warning */
  1119. return(-1.0);
  1120. #endif
  1121. } /* end of Cudd_ReadRecursiveCalls */
  1122. /**
  1123. @brief Reads the hit rate that causes resizinig of the computed
  1124. table.
  1125. @sideeffect None
  1126. @see Cudd_SetMinHit
  1127. */
  1128. unsigned int
  1129. Cudd_ReadMinHit(
  1130. DdManager * dd)
  1131. {
  1132. /* Internally, the package manipulates the ratio of hits to
  1133. ** misses instead of the ratio of hits to accesses. */
  1134. return((unsigned int) (0.5 + 100 * dd->minHit / (1 + dd->minHit)));
  1135. } /* end of Cudd_ReadMinHit */
  1136. /**
  1137. @brief Sets the hit rate that causes resizinig of the computed
  1138. table.
  1139. @details Sets the minHit parameter of the manager. This
  1140. parameter controls the resizing of the computed table. If the hit
  1141. rate is larger than the specified value, and the cache is not
  1142. already too large, then its size is doubled.
  1143. @sideeffect None
  1144. @see Cudd_ReadMinHit
  1145. */
  1146. void
  1147. Cudd_SetMinHit(
  1148. DdManager * dd,
  1149. unsigned int hr)
  1150. {
  1151. /* Internally, the package manipulates the ratio of hits to
  1152. ** misses instead of the ratio of hits to accesses. */
  1153. dd->minHit = (double) hr / (100.0 - (double) hr);
  1154. } /* end of Cudd_SetMinHit */
  1155. /**
  1156. @brief Reads the looseUpTo parameter of the manager.
  1157. @sideeffect None
  1158. @see Cudd_SetLooseUpTo Cudd_ReadMinHit Cudd_ReadMinDead
  1159. */
  1160. unsigned int
  1161. Cudd_ReadLooseUpTo(
  1162. DdManager * dd)
  1163. {
  1164. return(dd->looseUpTo);
  1165. } /* end of Cudd_ReadLooseUpTo */
  1166. /**
  1167. @brief Sets the looseUpTo parameter of the manager.
  1168. @details This parameter of the manager controls the threshold beyond
  1169. which no fast growth of the unique table is allowed. The threshold
  1170. is given as a number of slots. If the value passed to this function
  1171. is 0, the function determines a suitable value based on the
  1172. available memory.
  1173. @sideeffect None
  1174. @see Cudd_ReadLooseUpTo Cudd_SetMinHit
  1175. */
  1176. void
  1177. Cudd_SetLooseUpTo(
  1178. DdManager * dd,
  1179. unsigned int lut)
  1180. {
  1181. if (lut == 0) {
  1182. unsigned long datalimit = getSoftDataLimit();
  1183. lut = (unsigned int) (datalimit / (sizeof(DdNode) *
  1184. DD_MAX_LOOSE_FRACTION));
  1185. }
  1186. dd->looseUpTo = lut;
  1187. } /* end of Cudd_SetLooseUpTo */
  1188. /**
  1189. @brief Returns the soft limit for the cache size.
  1190. @sideeffect None
  1191. @see Cudd_ReadMaxCacheHard
  1192. */
  1193. unsigned int
  1194. Cudd_ReadMaxCache(
  1195. DdManager * dd)
  1196. {
  1197. return(2 * dd->cacheSlots + dd->cacheSlack);
  1198. } /* end of Cudd_ReadMaxCache */
  1199. /**
  1200. @brief Reads the maxCacheHard parameter of the manager.
  1201. @sideeffect None
  1202. @see Cudd_SetMaxCacheHard Cudd_ReadMaxCache
  1203. */
  1204. unsigned int
  1205. Cudd_ReadMaxCacheHard(
  1206. DdManager * dd)
  1207. {
  1208. return(dd->maxCacheHard);
  1209. } /* end of Cudd_ReadMaxCache */
  1210. /**
  1211. @brief Sets the maxCacheHard parameter of the manager.
  1212. @details The cache cannot grow larger than maxCacheHard
  1213. entries. This parameter allows an application to control the
  1214. trade-off of memory versus speed. If the value passed to this
  1215. function is 0, the function determines a suitable maximum cache size
  1216. based on the available memory.
  1217. @sideeffect None
  1218. @see Cudd_ReadMaxCacheHard Cudd_SetMaxCache
  1219. */
  1220. void
  1221. Cudd_SetMaxCacheHard(
  1222. DdManager * dd,
  1223. unsigned int mc)
  1224. {
  1225. if (mc == 0) {
  1226. unsigned long datalimit = getSoftDataLimit();
  1227. mc = (unsigned int) (datalimit / (sizeof(DdCache) *
  1228. DD_MAX_CACHE_FRACTION));
  1229. }
  1230. dd->maxCacheHard = mc;
  1231. } /* end of Cudd_SetMaxCacheHard */
  1232. /**
  1233. @brief Returns the number of %BDD variables in existance.
  1234. @sideeffect None
  1235. @see Cudd_ReadZddSize
  1236. */
  1237. int
  1238. Cudd_ReadSize(
  1239. DdManager * dd)
  1240. {
  1241. return(dd->size);
  1242. } /* end of Cudd_ReadSize */
  1243. /**
  1244. @brief Returns the number of %ZDD variables in existance.
  1245. @sideeffect None
  1246. @see Cudd_ReadSize
  1247. */
  1248. int
  1249. Cudd_ReadZddSize(
  1250. DdManager * dd)
  1251. {
  1252. return(dd->sizeZ);
  1253. } /* end of Cudd_ReadZddSize */
  1254. /**
  1255. @brief Returns the total number of slots of the unique table.
  1256. @details This number is mainly for diagnostic purposes.
  1257. @sideeffect None
  1258. */
  1259. unsigned int
  1260. Cudd_ReadSlots(
  1261. DdManager * dd)
  1262. {
  1263. return(dd->slots);
  1264. } /* end of Cudd_ReadSlots */
  1265. /**
  1266. @brief Reads the fraction of used slots in the unique table.
  1267. @details The unused slots are those in which no valid data is
  1268. stored. Garbage collection, variable reordering, and subtable
  1269. resizing may cause used slots to become unused.
  1270. @sideeffect None
  1271. @see Cudd_ReadSlots
  1272. */
  1273. double
  1274. Cudd_ReadUsedSlots(
  1275. DdManager * dd)
  1276. {
  1277. size_t used = 0;
  1278. int i, j;
  1279. int size = dd->size;
  1280. DdNodePtr *nodelist;
  1281. DdSubtable *subtable;
  1282. DdNode *node;
  1283. DdNode *sentinel = &(dd->sentinel);
  1284. /* Scan each BDD/ADD subtable. */
  1285. for (i = 0; i < size; i++) {
  1286. subtable = &(dd->subtables[i]);
  1287. nodelist = subtable->nodelist;
  1288. for (j = 0; (unsigned) j < subtable->slots; j++) {
  1289. node = nodelist[j];
  1290. if (node != sentinel) {
  1291. used++;
  1292. }
  1293. }
  1294. }
  1295. /* Scan the ZDD subtables. */
  1296. size = dd->sizeZ;
  1297. for (i = 0; i < size; i++) {
  1298. subtable = &(dd->subtableZ[i]);
  1299. nodelist = subtable->nodelist;
  1300. for (j = 0; (unsigned) j < subtable->slots; j++) {
  1301. node = nodelist[j];
  1302. if (node != NULL) {
  1303. used++;
  1304. }
  1305. }
  1306. }
  1307. /* Constant table. */
  1308. subtable = &(dd->constants);
  1309. nodelist = subtable->nodelist;
  1310. for (j = 0; (unsigned) j < subtable->slots; j++) {
  1311. node = nodelist[j];
  1312. if (node != NULL) {
  1313. used++;
  1314. }
  1315. }
  1316. return((double)used / (double) dd->slots);
  1317. } /* end of Cudd_ReadUsedSlots */
  1318. /**
  1319. @brief Computes the expected fraction of used slots in the unique
  1320. table.
  1321. @details This expected value is based on the assumption that the
  1322. hash function distributes the keys randomly; it can be compared with
  1323. the result of Cudd_ReadUsedSlots to monitor the performance of the
  1324. unique table hash function.
  1325. @sideeffect None
  1326. @see Cudd_ReadSlots Cudd_ReadUsedSlots
  1327. */
  1328. double
  1329. Cudd_ExpectedUsedSlots(
  1330. DdManager * dd)
  1331. {
  1332. int i;
  1333. int size = dd->size;
  1334. DdSubtable *subtable;
  1335. double empty = 0.0;
  1336. /* To each subtable we apply the corollary to Theorem 8.5 (occupancy
  1337. ** distribution) from Sedgewick and Flajolet's Analysis of Algorithms.
  1338. ** The corollary says that for a table with M buckets and a load ratio
  1339. ** of r, the expected number of empty buckets is asymptotically given
  1340. ** by M * exp(-r).
  1341. */
  1342. /* Scan each BDD/ADD subtable. */
  1343. for (i = 0; i < size; i++) {
  1344. subtable = &(dd->subtables[i]);
  1345. empty += (double) subtable->slots *
  1346. exp(-(double) subtable->keys / (double) subtable->slots);
  1347. }
  1348. /* Scan the ZDD subtables. */
  1349. size = dd->sizeZ;
  1350. for (i = 0; i < size; i++) {
  1351. subtable = &(dd->subtableZ[i]);
  1352. empty += (double) subtable->slots *
  1353. exp(-(double) subtable->keys / (double) subtable->slots);
  1354. }
  1355. /* Constant table. */
  1356. subtable = &(dd->constants);
  1357. empty += (double) subtable->slots *
  1358. exp(-(double) subtable->keys / (double) subtable->slots);
  1359. return(1.0 - empty / (double) dd->slots);
  1360. } /* end of Cudd_ExpectedUsedSlots */
  1361. /**
  1362. @brief Returns the number of nodes in the unique table.
  1363. @details Returns the total number of nodes currently in the unique
  1364. table, including the dead nodes.
  1365. @sideeffect None
  1366. @see Cudd_ReadDead
  1367. */
  1368. unsigned int
  1369. Cudd_ReadKeys(
  1370. DdManager * dd)
  1371. {
  1372. return(dd->keys);
  1373. } /* end of Cudd_ReadKeys */
  1374. /**
  1375. @brief Returns the number of dead nodes in the unique table.
  1376. @sideeffect None
  1377. @see Cudd_ReadKeys
  1378. */
  1379. unsigned int
  1380. Cudd_ReadDead(
  1381. DdManager * dd)
  1382. {
  1383. return(dd->dead);
  1384. } /* end of Cudd_ReadDead */
  1385. /**
  1386. @brief Reads the minDead parameter of the manager.
  1387. @details The minDead parameter is used by the package to decide
  1388. whether to collect garbage or resize a subtable of the unique table
  1389. when the subtable becomes too full. The application can indirectly
  1390. control the value of minDead by setting the looseUpTo parameter.
  1391. @sideeffect None
  1392. @see Cudd_ReadDead Cudd_ReadLooseUpTo Cudd_SetLooseUpTo
  1393. */
  1394. unsigned int
  1395. Cudd_ReadMinDead(
  1396. DdManager * dd)
  1397. {
  1398. return(dd->minDead);
  1399. } /* end of Cudd_ReadMinDead */
  1400. /**
  1401. @brief Returns the number of times reordering has occurred.
  1402. @details The number includes both the calls to Cudd_ReduceHeap from
  1403. the application program and those automatically performed by the
  1404. package. However, calls that do not even initiate reordering are not
  1405. counted. A call may not initiate reordering if there are fewer than
  1406. minsize live nodes in the manager, or if CUDD_REORDER_NONE is specified
  1407. as reordering method. The calls to Cudd_ShuffleHeap are not counted.
  1408. @sideeffect None
  1409. @see Cudd_ReduceHeap Cudd_ReadReorderingTime
  1410. */
  1411. unsigned int
  1412. Cudd_ReadReorderings(
  1413. DdManager * dd)
  1414. {
  1415. return(dd->reorderings);
  1416. } /* end of Cudd_ReadReorderings */
  1417. /**
  1418. @brief Returns the maximum number of times reordering may be invoked.
  1419. @sideeffect None
  1420. @see Cudd_ReadReorderings Cudd_SetMaxReorderings Cudd_ReduceHeap
  1421. */
  1422. unsigned int
  1423. Cudd_ReadMaxReorderings(
  1424. DdManager * dd)
  1425. {
  1426. return(dd->maxReorderings);
  1427. } /* end of Cudd_ReadMaxReorderings */
  1428. /**
  1429. @brief Sets the maximum number of times reordering may be invoked.
  1430. @details The default value is (practically) infinite.
  1431. @sideeffect None
  1432. @see Cudd_ReadReorderings Cudd_ReadMaxReorderings Cudd_ReduceHeap
  1433. */
  1434. void
  1435. Cudd_SetMaxReorderings(
  1436. DdManager * dd, unsigned int mr)
  1437. {
  1438. dd->maxReorderings = mr;
  1439. } /* end of Cudd_SetMaxReorderings */
  1440. /**
  1441. @brief Returns the time spent in reordering.
  1442. @details Returns the number of milliseconds spent reordering
  1443. variables since the manager was initialized. The time spent in collecting
  1444. garbage before reordering is included.
  1445. @sideeffect None
  1446. @see Cudd_ReadReorderings
  1447. */
  1448. long
  1449. Cudd_ReadReorderingTime(
  1450. DdManager * dd)
  1451. {
  1452. return(dd->reordTime);
  1453. } /* end of Cudd_ReadReorderingTime */
  1454. /**
  1455. @brief Returns the number of times garbage collection has occurred.
  1456. @details The number includes both the calls from reordering
  1457. procedures and those caused by requests to create new nodes.
  1458. @sideeffect None
  1459. @see Cudd_ReadGarbageCollectionTime
  1460. */
  1461. int
  1462. Cudd_ReadGarbageCollections(
  1463. DdManager * dd)
  1464. {
  1465. return(dd->garbageCollections);
  1466. } /* end of Cudd_ReadGarbageCollections */
  1467. /**
  1468. @brief Returns the time spent in garbage collection.
  1469. @details Returns the number of milliseconds spent doing garbage
  1470. collection since the manager was initialized.
  1471. @sideeffect None
  1472. @see Cudd_ReadGarbageCollections
  1473. */
  1474. long
  1475. Cudd_ReadGarbageCollectionTime(
  1476. DdManager * dd)
  1477. {
  1478. return(dd->GCTime);
  1479. } /* end of Cudd_ReadGarbageCollectionTime */
  1480. /**
  1481. @brief Returns the number of nodes freed.
  1482. @details Returns the number of nodes returned to the free list if the
  1483. keeping of this statistic is enabled; -1 otherwise. This statistic is
  1484. enabled only if the package is compiled with DD_STATS defined.
  1485. @sideeffect None
  1486. @see Cudd_ReadNodesDropped
  1487. */
  1488. double
  1489. Cudd_ReadNodesFreed(
  1490. DdManager * dd)
  1491. {
  1492. #ifdef DD_STATS
  1493. return(dd->nodesFreed);
  1494. #else
  1495. (void) dd; /* avoid warning */
  1496. return(-1.0);
  1497. #endif
  1498. } /* end of Cudd_ReadNodesFreed */
  1499. /**
  1500. @brief Returns the number of nodes dropped.
  1501. @details Returns the number of nodes killed by dereferencing if the
  1502. keeping of this statistic is enabled; -1 otherwise. This statistic is
  1503. enabled only if the package is compiled with DD_STATS defined.
  1504. @sideeffect None
  1505. @see Cudd_ReadNodesFreed
  1506. */
  1507. double
  1508. Cudd_ReadNodesDropped(
  1509. DdManager * dd)
  1510. {
  1511. #ifdef DD_STATS
  1512. return(dd->nodesDropped);
  1513. #else
  1514. (void) dd; /* avoid warning */
  1515. return(-1.0);
  1516. #endif
  1517. } /* end of Cudd_ReadNodesDropped */
  1518. /**
  1519. @brief Returns the number of look-ups in the unique table.
  1520. @details Returns the number of look-ups in the unique table if the
  1521. keeping of this statistic is enabled; -1 otherwise. This statistic is
  1522. enabled only if the package is compiled with DD_UNIQUE_PROFILE defined.
  1523. @sideeffect None
  1524. @see Cudd_ReadUniqueLinks
  1525. */
  1526. double
  1527. Cudd_ReadUniqueLookUps(
  1528. DdManager * dd)
  1529. {
  1530. #ifdef DD_UNIQUE_PROFILE
  1531. return(dd->uniqueLookUps);
  1532. #else
  1533. (void) dd; /* avoid warning */
  1534. return(-1.0);
  1535. #endif
  1536. } /* end of Cudd_ReadUniqueLookUps */
  1537. /**
  1538. @brief Returns the number of links followed in the unique table.
  1539. @details Returns the number of links followed during look-ups in the
  1540. unique table if the keeping of this statistic is enabled; -1 otherwise.
  1541. If an item is found in the first position of its collision list, the
  1542. number of links followed is taken to be 0. If it is in second position,
  1543. the number of links is 1, and so on. This statistic is enabled only if
  1544. the package is compiled with DD_UNIQUE_PROFILE defined.
  1545. @sideeffect None
  1546. @see Cudd_ReadUniqueLookUps
  1547. */
  1548. double
  1549. Cudd_ReadUniqueLinks(
  1550. DdManager * dd)
  1551. {
  1552. #ifdef DD_UNIQUE_PROFILE
  1553. return(dd->uniqueLinks);
  1554. #else
  1555. (void) dd; /* avoid warning */
  1556. return(-1.0);
  1557. #endif
  1558. } /* end of Cudd_ReadUniqueLinks */
  1559. /**
  1560. @brief Reads the siftMaxVar parameter of the manager.
  1561. @details This parameter gives the maximum number of variables that
  1562. will be sifted for each invocation of sifting.
  1563. @sideeffect None
  1564. @see Cudd_ReadSiftMaxSwap Cudd_SetSiftMaxVar
  1565. */
  1566. int
  1567. Cudd_ReadSiftMaxVar(
  1568. DdManager * dd)
  1569. {
  1570. return(dd->siftMaxVar);
  1571. } /* end of Cudd_ReadSiftMaxVar */
  1572. /**
  1573. @brief Sets the siftMaxVar parameter of the manager.
  1574. @details This parameter gives the maximum number of variables that
  1575. will be sifted for each invocation of sifting.
  1576. @sideeffect None
  1577. @see Cudd_SetSiftMaxSwap Cudd_ReadSiftMaxVar
  1578. */
  1579. void
  1580. Cudd_SetSiftMaxVar(
  1581. DdManager * dd,
  1582. int smv)
  1583. {
  1584. dd->siftMaxVar = smv;
  1585. } /* end of Cudd_SetSiftMaxVar */
  1586. /**
  1587. @brief Reads the siftMaxSwap parameter of the manager.
  1588. @details This parameter gives the maximum number of swaps that will
  1589. be attempted for each invocation of sifting. The real number of
  1590. swaps may exceed the set limit because the package will always
  1591. complete the sifting of the variable that causes the limit to be
  1592. reached.
  1593. @sideeffect None
  1594. @see Cudd_ReadSiftMaxVar Cudd_SetSiftMaxSwap
  1595. */
  1596. int
  1597. Cudd_ReadSiftMaxSwap(
  1598. DdManager * dd)
  1599. {
  1600. return(dd->siftMaxSwap);
  1601. } /* end of Cudd_ReadSiftMaxSwap */
  1602. /**
  1603. @brief Sets the siftMaxSwap parameter of the manager.
  1604. @details This parameter gives the maximum number of swaps that will
  1605. be attempted for each invocation of sifting. The real number of
  1606. swaps may exceed the set limit because the package will always
  1607. complete the sifting of the variable that causes the limit to be
  1608. reached.
  1609. @sideeffect None
  1610. @see Cudd_SetSiftMaxVar Cudd_ReadSiftMaxSwap
  1611. */
  1612. void
  1613. Cudd_SetSiftMaxSwap(
  1614. DdManager * dd,
  1615. int sms)
  1616. {
  1617. dd->siftMaxSwap = sms;
  1618. } /* end of Cudd_SetSiftMaxSwap */
  1619. /**
  1620. @brief Reads the maxGrowth parameter of the manager.
  1621. @details This parameter determines how much the number of nodes can
  1622. grow during sifting of a variable. Overall, sifting never increases
  1623. the size of the decision diagrams. This parameter only refers to
  1624. intermediate results. A lower value will speed up sifting, possibly
  1625. at the expense of quality.
  1626. @sideeffect None
  1627. @see Cudd_SetMaxGrowth Cudd_ReadMaxGrowthAlternate
  1628. */
  1629. double
  1630. Cudd_ReadMaxGrowth(
  1631. DdManager * dd)
  1632. {
  1633. return(dd->maxGrowth);
  1634. } /* end of Cudd_ReadMaxGrowth */
  1635. /**
  1636. @brief Sets the maxGrowth parameter of the manager.
  1637. @details This parameter determines how much the number of nodes can
  1638. grow during sifting of a variable. Overall, sifting never increases
  1639. the size of the decision diagrams. This parameter only refers to
  1640. intermediate results. A lower value will speed up sifting, possibly
  1641. at the expense of quality.
  1642. @sideeffect None
  1643. @see Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate
  1644. */
  1645. void
  1646. Cudd_SetMaxGrowth(
  1647. DdManager * dd,
  1648. double mg)
  1649. {
  1650. dd->maxGrowth = mg;
  1651. } /* end of Cudd_SetMaxGrowth */
  1652. /**
  1653. @brief Reads the maxGrowthAlt parameter of the manager.
  1654. @details This parameter is analogous to the maxGrowth paramter, and
  1655. is used every given number of reorderings instead of maxGrowth. The
  1656. number of reorderings is set with Cudd_SetReorderingCycle. If the
  1657. number of reorderings is 0 (default) maxGrowthAlt is never used.
  1658. @sideeffect None
  1659. @see Cudd_ReadMaxGrowth Cudd_SetMaxGrowthAlternate
  1660. Cudd_SetReorderingCycle Cudd_ReadReorderingCycle
  1661. */
  1662. double
  1663. Cudd_ReadMaxGrowthAlternate(
  1664. DdManager * dd)
  1665. {
  1666. return(dd->maxGrowthAlt);
  1667. } /* end of Cudd_ReadMaxGrowthAlternate */
  1668. /**
  1669. @brief Sets the maxGrowthAlt parameter of the manager.
  1670. @details This parameter is analogous to the maxGrowth paramter, and
  1671. is used every given number of reorderings instead of maxGrowth. The
  1672. number of reorderings is set with Cudd_SetReorderingCycle. If the
  1673. number of reorderings is 0 (default) maxGrowthAlt is never used.
  1674. @sideeffect None
  1675. @see Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowth
  1676. Cudd_SetReorderingCycle Cudd_ReadReorderingCycle
  1677. */
  1678. void
  1679. Cudd_SetMaxGrowthAlternate(
  1680. DdManager * dd,
  1681. double mg)
  1682. {
  1683. dd->maxGrowthAlt = mg;
  1684. } /* end of Cudd_SetMaxGrowthAlternate */
  1685. /**
  1686. @brief Reads the reordCycle parameter of the manager.
  1687. @details This parameter determines how often the alternate threshold
  1688. on maximum growth is used in reordering.
  1689. @sideeffect None
  1690. @see Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate
  1691. Cudd_SetReorderingCycle
  1692. */
  1693. int
  1694. Cudd_ReadReorderingCycle(
  1695. DdManager * dd)
  1696. {
  1697. return(dd->reordCycle);
  1698. } /* end of Cudd_ReadReorderingCycle */
  1699. /**
  1700. @brief Sets the reordCycle parameter of the manager.
  1701. @details This parameter determines how often the alternate threshold
  1702. on maximum growth is used in reordering.
  1703. @sideeffect None
  1704. @see Cudd_ReadMaxGrowthAlternate Cudd_SetMaxGrowthAlternate
  1705. Cudd_ReadReorderingCycle
  1706. */
  1707. void
  1708. Cudd_SetReorderingCycle(
  1709. DdManager * dd,
  1710. int cycle)
  1711. {
  1712. dd->reordCycle = cycle;
  1713. } /* end of Cudd_SetReorderingCycle */
  1714. /**
  1715. @brief Returns the variable group tree of the manager.
  1716. @sideeffect None
  1717. @see Cudd_SetTree Cudd_FreeTree Cudd_ReadZddTree
  1718. */
  1719. MtrNode *
  1720. Cudd_ReadTree(
  1721. DdManager * dd)
  1722. {
  1723. return(dd->tree);
  1724. } /* end of Cudd_ReadTree */
  1725. /**
  1726. @brief Sets the variable group tree of the manager.
  1727. @sideeffect None
  1728. @see Cudd_FreeTree Cudd_ReadTree Cudd_SetZddTree
  1729. */
  1730. void
  1731. Cudd_SetTree(
  1732. DdManager * dd,
  1733. MtrNode * tree)
  1734. {
  1735. if (dd->tree != NULL) {
  1736. Mtr_FreeTree(dd->tree);
  1737. }
  1738. dd->tree = tree;
  1739. if (tree == NULL) return;
  1740. fixVarTree(tree, dd->perm, dd->size);
  1741. return;
  1742. } /* end of Cudd_SetTree */
  1743. /**
  1744. @brief Frees the variable group tree of the manager.
  1745. @sideeffect None
  1746. @see Cudd_SetTree Cudd_ReadTree Cudd_FreeZddTree
  1747. */
  1748. void
  1749. Cudd_FreeTree(
  1750. DdManager * dd)
  1751. {
  1752. if (dd->tree != NULL) {
  1753. Mtr_FreeTree(dd->tree);
  1754. dd->tree = NULL;
  1755. }
  1756. return;
  1757. } /* end of Cudd_FreeTree */
  1758. /**
  1759. @brief Returns the variable group tree of the manager.
  1760. @sideeffect None
  1761. @see Cudd_SetZddTree Cudd_FreeZddTree Cudd_ReadTree
  1762. */
  1763. MtrNode *
  1764. Cudd_ReadZddTree(
  1765. DdManager * dd)
  1766. {
  1767. return(dd->treeZ);
  1768. } /* end of Cudd_ReadZddTree */
  1769. /**
  1770. @brief Sets the %ZDD variable group tree of the manager.
  1771. @sideeffect None
  1772. @see Cudd_FreeZddTree Cudd_ReadZddTree Cudd_SetTree
  1773. */
  1774. void
  1775. Cudd_SetZddTree(
  1776. DdManager * dd,
  1777. MtrNode * tree)
  1778. {
  1779. if (dd->treeZ != NULL) {
  1780. Mtr_FreeTree(dd->treeZ);
  1781. }
  1782. dd->treeZ = tree;
  1783. if (tree == NULL) return;
  1784. fixVarTree(tree, dd->permZ, dd->sizeZ);
  1785. return;
  1786. } /* end of Cudd_SetZddTree */
  1787. /**
  1788. @brief Frees the variable group tree of the manager.
  1789. @sideeffect None
  1790. @see Cudd_SetZddTree Cudd_ReadZddTree Cudd_FreeTree
  1791. */
  1792. void
  1793. Cudd_FreeZddTree(
  1794. DdManager * dd)
  1795. {
  1796. if (dd->treeZ != NULL) {
  1797. Mtr_FreeTree(dd->treeZ);
  1798. dd->treeZ = NULL;
  1799. }
  1800. return;
  1801. } /* end of Cudd_FreeZddTree */
  1802. /**
  1803. @brief Returns the index of the node.
  1804. @details The node pointer can be either regular or complemented.
  1805. @sideeffect None
  1806. @see Cudd_ReadIndex
  1807. */
  1808. unsigned int
  1809. Cudd_NodeReadIndex(
  1810. DdNode const * node)
  1811. {
  1812. return((unsigned int) Cudd_Regular(node)->index);
  1813. } /* end of Cudd_NodeReadIndex */
  1814. /**
  1815. @brief Returns the current position of the i-th variable in the
  1816. order.
  1817. @details If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX;
  1818. otherwise, if the index is out of bounds returns -1.
  1819. @sideeffect None
  1820. @see Cudd_ReadInvPerm Cudd_ReadPermZdd
  1821. */
  1822. int
  1823. Cudd_ReadPerm(
  1824. DdManager * dd,
  1825. int i)
  1826. {
  1827. if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
  1828. if (i < 0 || i >= dd->size) return(-1);
  1829. return(dd->perm[i]);
  1830. } /* end of Cudd_ReadPerm */
  1831. /**
  1832. @brief Returns the current position of the i-th %ZDD variable in the
  1833. order.
  1834. @details If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX;
  1835. otherwise, if the index is out of bounds returns -1.
  1836. @sideeffect None
  1837. @see Cudd_ReadInvPermZdd Cudd_ReadPerm
  1838. */
  1839. int
  1840. Cudd_ReadPermZdd(
  1841. DdManager * dd,
  1842. int i)
  1843. {
  1844. if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
  1845. if (i < 0 || i >= dd->sizeZ) return(-1);
  1846. return(dd->permZ[i]);
  1847. } /* end of Cudd_ReadPermZdd */
  1848. /**
  1849. @brief Returns the index of the variable currently in the i-th
  1850. position of the order.
  1851. @details If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX;
  1852. otherwise, if the index is out of bounds returns -1.
  1853. @sideeffect None
  1854. @see Cudd_ReadPerm Cudd_ReadInvPermZdd
  1855. */
  1856. int
  1857. Cudd_ReadInvPerm(
  1858. DdManager * dd,
  1859. int i)
  1860. {
  1861. if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
  1862. if (i < 0 || i >= dd->size) return(-1);
  1863. return(dd->invperm[i]);
  1864. } /* end of Cudd_ReadInvPerm */
  1865. /**
  1866. @brief Returns the index of the %ZDD variable currently in the i-th
  1867. position of the order.
  1868. @details If the index is CUDD_CONST_INDEX, returns CUDD_CONST_INDEX;
  1869. otherwise, if the index is out of bounds returns -1.
  1870. @sideeffect None
  1871. @see Cudd_ReadPerm Cudd_ReadInvPermZdd
  1872. */
  1873. int
  1874. Cudd_ReadInvPermZdd(
  1875. DdManager * dd,
  1876. int i)
  1877. {
  1878. if (i == CUDD_CONST_INDEX) return(CUDD_CONST_INDEX);
  1879. if (i < 0 || i >= dd->sizeZ) return(-1);
  1880. return(dd->invpermZ[i]);
  1881. } /* end of Cudd_ReadInvPermZdd */
  1882. /**
  1883. @brief Returns the i-th element of the vars array.
  1884. @details Returns the i-th element of the vars array if it falls
  1885. within the array bounds; NULL otherwise. If i is the index of an
  1886. existing variable, this function produces the same result as
  1887. Cudd_bddIthVar. However, if the i-th var does not exist yet,
  1888. Cudd_bddIthVar will create it, whereas Cudd_ReadVars will not.
  1889. @sideeffect None
  1890. @see Cudd_bddIthVar
  1891. */
  1892. DdNode *
  1893. Cudd_ReadVars(
  1894. DdManager * dd,
  1895. int i)
  1896. {
  1897. if (i < 0 || i > dd->size) return(NULL);
  1898. return(dd->vars[i]);
  1899. } /* end of Cudd_ReadVars */
  1900. /**
  1901. @brief Reads the epsilon parameter of the manager.
  1902. @details The epsilon parameter control the comparison between
  1903. floating point numbers.
  1904. @sideeffect None
  1905. @see Cudd_SetEpsilon
  1906. */
  1907. CUDD_VALUE_TYPE
  1908. Cudd_ReadEpsilon(
  1909. DdManager * dd)
  1910. {
  1911. return(dd->epsilon);
  1912. } /* end of Cudd_ReadEpsilon */
  1913. /**
  1914. @brief Sets the epsilon parameter of the manager to ep.
  1915. @details The epsilon parameter control the comparison between
  1916. floating point numbers.
  1917. @sideeffect None
  1918. @see Cudd_ReadEpsilon
  1919. */
  1920. void
  1921. Cudd_SetEpsilon(
  1922. DdManager * dd,
  1923. CUDD_VALUE_TYPE ep)
  1924. {
  1925. dd->epsilon = ep;
  1926. } /* end of Cudd_SetEpsilon */
  1927. /**
  1928. @brief Reads the groupcheck parameter of the manager.
  1929. @details The groupcheck parameter determines the aggregation
  1930. criterion in group sifting.
  1931. @sideeffect None
  1932. @see Cudd_SetGroupcheck
  1933. */
  1934. Cudd_AggregationType
  1935. Cudd_ReadGroupcheck(
  1936. DdManager * dd)
  1937. {
  1938. return(dd->groupcheck);
  1939. } /* end of Cudd_ReadGroupCheck */
  1940. /**
  1941. @brief Sets the parameter groupcheck of the manager to gc.
  1942. @details The groupcheck parameter determines the aggregation
  1943. criterion in group sifting.
  1944. @sideeffect None
  1945. @see Cudd_ReadGroupCheck
  1946. */
  1947. void
  1948. Cudd_SetGroupcheck(
  1949. DdManager * dd,
  1950. Cudd_AggregationType gc)
  1951. {
  1952. dd->groupcheck = gc;
  1953. } /* end of Cudd_SetGroupcheck */
  1954. /**
  1955. @brief Tells whether garbage collection is enabled.
  1956. @return 1 if garbage collection is enabled; 0 otherwise.
  1957. @sideeffect None
  1958. @see Cudd_EnableGarbageCollection Cudd_DisableGarbageCollection
  1959. */
  1960. int
  1961. Cudd_GarbageCollectionEnabled(
  1962. DdManager * dd)
  1963. {
  1964. return(dd->gcEnabled);
  1965. } /* end of Cudd_GarbageCollectionEnabled */
  1966. /**
  1967. @brief Enables garbage collection.
  1968. @details Garbage collection is initially enabled. Therefore it is
  1969. necessary to call this function only if garbage collection has been
  1970. explicitly disabled.
  1971. @sideeffect None
  1972. @see Cudd_DisableGarbageCollection Cudd_GarbageCollectionEnabled
  1973. */
  1974. void
  1975. Cudd_EnableGarbageCollection(
  1976. DdManager * dd)
  1977. {
  1978. dd->gcEnabled = 1;
  1979. } /* end of Cudd_EnableGarbageCollection */
  1980. /**
  1981. @brief Disables garbage collection.
  1982. @details Garbage collection is initially enabled. This function may
  1983. be called to disable it. However, garbage collection will still
  1984. occur when a new node must be created and no memory is left, or when
  1985. garbage collection is required for correctness. (E.g., before
  1986. reordering.)
  1987. @sideeffect None
  1988. @see Cudd_EnableGarbageCollection Cudd_GarbageCollectionEnabled
  1989. */
  1990. void
  1991. Cudd_DisableGarbageCollection(
  1992. DdManager * dd)
  1993. {
  1994. dd->gcEnabled = 0;
  1995. } /* end of Cudd_DisableGarbageCollection */
  1996. /**
  1997. @brief Tells whether dead nodes are counted towards triggering
  1998. reordering.
  1999. @return 1 if dead nodes are counted; 0 otherwise.
  2000. @sideeffect None
  2001. @see Cudd_TurnOnCountDead Cudd_TurnOffCountDead
  2002. */
  2003. int
  2004. Cudd_DeadAreCounted(
  2005. DdManager * dd)
  2006. {
  2007. return(dd->countDead == 0 ? 1 : 0);
  2008. } /* end of Cudd_DeadAreCounted */
  2009. /**
  2010. @brief Causes the dead nodes to be counted towards triggering
  2011. reordering.
  2012. @details This causes more frequent reorderings. By default dead
  2013. nodes are not counted.
  2014. @sideeffect Changes the manager.
  2015. @see Cudd_TurnOffCountDead Cudd_DeadAreCounted
  2016. */
  2017. void
  2018. Cudd_TurnOnCountDead(
  2019. DdManager * dd)
  2020. {
  2021. dd->countDead = 0;
  2022. } /* end of Cudd_TurnOnCountDead */
  2023. /**
  2024. @brief Causes the dead nodes not to be counted towards triggering
  2025. reordering.
  2026. @details This causes less frequent reorderings. By default dead
  2027. nodes are not counted. Therefore there is no need to call this
  2028. function unless Cudd_TurnOnCountDead has been previously called.
  2029. @sideeffect Changes the manager.
  2030. @see Cudd_TurnOnCountDead Cudd_DeadAreCounted
  2031. */
  2032. void
  2033. Cudd_TurnOffCountDead(
  2034. DdManager * dd)
  2035. {
  2036. dd->countDead = ~0U;
  2037. } /* end of Cudd_TurnOffCountDead */
  2038. /**
  2039. @brief Returns the current value of the recombination parameter used
  2040. in group sifting.
  2041. @details A larger (positive) value makes the aggregation of
  2042. variables due to the second difference criterion more likely. A
  2043. smaller (negative) value makes aggregation less likely.
  2044. @sideeffect None
  2045. @see Cudd_SetRecomb
  2046. */
  2047. int
  2048. Cudd_ReadRecomb(
  2049. DdManager * dd)
  2050. {
  2051. return(dd->recomb);
  2052. } /* end of Cudd_ReadRecomb */
  2053. /**
  2054. @brief Sets the value of the recombination parameter used in group
  2055. sifting.
  2056. @details A larger (positive) value makes the aggregation of
  2057. variables due to the second difference criterion more likely. A
  2058. smaller (negative) value makes aggregation less likely. The default
  2059. value is 0.
  2060. @sideeffect Changes the manager.
  2061. @see Cudd_ReadRecomb
  2062. */
  2063. void
  2064. Cudd_SetRecomb(
  2065. DdManager * dd,
  2066. int recomb)
  2067. {
  2068. dd->recomb = recomb;
  2069. } /* end of Cudd_SetRecomb */
  2070. /**
  2071. @brief Returns the current value of the symmviolation parameter used
  2072. in group sifting.
  2073. @details This parameter is used in group sifting to decide how many
  2074. violations to the symmetry conditions <code>f10 = f01</code> or
  2075. <code>f11 = f00</code> are tolerable when checking for aggregation
  2076. due to extended symmetry. The value should be between 0 and 100. A
  2077. small value causes fewer variables to be aggregated. The default
  2078. value is 0.
  2079. @sideeffect None
  2080. @see Cudd_SetSymmviolation
  2081. */
  2082. int
  2083. Cudd_ReadSymmviolation(
  2084. DdManager * dd)
  2085. {
  2086. return(dd->symmviolation);
  2087. } /* end of Cudd_ReadSymmviolation */
  2088. /**
  2089. @brief Sets the value of the symmviolation parameter used
  2090. in group sifting.
  2091. @details This parameter is used in group sifting to decide how many
  2092. violations to the symmetry conditions <code>f10 = f01</code> or
  2093. <code>f11 = f00</code> are tolerable when checking for aggregation
  2094. due to extended symmetry. The value should be between 0 and 100. A
  2095. small value causes fewer variables to be aggregated. The default
  2096. value is 0.
  2097. @sideeffect Changes the manager.
  2098. @see Cudd_ReadSymmviolation
  2099. */
  2100. void
  2101. Cudd_SetSymmviolation(
  2102. DdManager * dd,
  2103. int symmviolation)
  2104. {
  2105. dd->symmviolation = symmviolation;
  2106. } /* end of Cudd_SetSymmviolation */
  2107. /**
  2108. @brief Returns the current value of the arcviolation parameter used
  2109. in group sifting.
  2110. @details This parameter is used to decide how many arcs into
  2111. <code>y</code> not coming from <code>x</code> are tolerable when
  2112. checking for aggregation due to extended symmetry. The value should
  2113. be between 0 and 100. A small value causes fewer variables to be
  2114. aggregated. The default value is 0.
  2115. @sideeffect None
  2116. @see Cudd_SetArcviolation
  2117. */
  2118. int
  2119. Cudd_ReadArcviolation(
  2120. DdManager * dd)
  2121. {
  2122. return(dd->arcviolation);
  2123. } /* end of Cudd_ReadArcviolation */
  2124. /**
  2125. @brief Sets the value of the arcviolation parameter used
  2126. in group sifting.
  2127. @details This parameter is used to decide how many arcs into
  2128. <code>y</code> not coming from <code>x</code> are tolerable when
  2129. checking for aggregation due to extended symmetry. The value should
  2130. be between 0 and 100. A small value causes fewer variables to be
  2131. aggregated. The default value is 0.
  2132. @sideeffect None
  2133. @see Cudd_ReadArcviolation
  2134. */
  2135. void
  2136. Cudd_SetArcviolation(
  2137. DdManager * dd,
  2138. int arcviolation)
  2139. {
  2140. dd->arcviolation = arcviolation;
  2141. } /* end of Cudd_SetArcviolation */
  2142. /**
  2143. @brief Reads the current size of the population used by the
  2144. genetic algorithm for variable reordering.
  2145. @details A larger population size will cause the genetic algorithm
  2146. to take more time, but will generally produce better results. The
  2147. default value is 0, in which case the package uses three times the
  2148. number of variables as population size, with a maximum of 120.
  2149. @sideeffect None
  2150. @see Cudd_SetPopulationSize
  2151. */
  2152. int
  2153. Cudd_ReadPopulationSize(
  2154. DdManager * dd)
  2155. {
  2156. return(dd->populationSize);
  2157. } /* end of Cudd_ReadPopulationSize */
  2158. /**
  2159. @brief Sets the size of the population used by the
  2160. genetic algorithm for variable reordering.
  2161. @details A larger population size will cause the genetic algorithm
  2162. to take more time, but will generally produce better results. The
  2163. default value is 0, in which case the package uses three times the
  2164. number of variables as population size, with a maximum of 120.
  2165. @sideeffect Changes the manager.
  2166. @see Cudd_ReadPopulationSize
  2167. */
  2168. void
  2169. Cudd_SetPopulationSize(
  2170. DdManager * dd,
  2171. int populationSize)
  2172. {
  2173. dd->populationSize = populationSize;
  2174. } /* end of Cudd_SetPopulationSize */
  2175. /**
  2176. @brief Reads the current number of crossovers used by the
  2177. genetic algorithm for variable reordering.
  2178. @details A larger number of crossovers will cause the genetic
  2179. algorithm to take more time, but will generally produce better
  2180. results. The default value is 0, in which case the package uses
  2181. three times the number of variables as number of crossovers, with a
  2182. maximum of 60.
  2183. @sideeffect None
  2184. @see Cudd_SetNumberXovers
  2185. */
  2186. int
  2187. Cudd_ReadNumberXovers(
  2188. DdManager * dd)
  2189. {
  2190. return(dd->numberXovers);
  2191. } /* end of Cudd_ReadNumberXovers */
  2192. /**
  2193. @brief Sets the number of crossovers used by the
  2194. genetic algorithm for variable reordering.
  2195. @details A larger number of crossovers will cause the genetic
  2196. algorithm to take more time, but will generally produce better
  2197. results. The default value is 0, in which case the package uses
  2198. three times the number of variables as number of crossovers, with a
  2199. maximum of 60.
  2200. @sideeffect None
  2201. @see Cudd_ReadNumberXovers
  2202. */
  2203. void
  2204. Cudd_SetNumberXovers(
  2205. DdManager * dd,
  2206. int numberXovers)
  2207. {
  2208. dd->numberXovers = numberXovers;
  2209. } /* end of Cudd_SetNumberXovers */
  2210. /**
  2211. @brief Returns the order randomization factor.
  2212. @details If non-zero this factor is used to determine a perturbation
  2213. of the next reordering threshold. Larger factors cause larger
  2214. perturbations.
  2215. @sideeffect None
  2216. @see Cudd_SetOrderRandomization
  2217. */
  2218. unsigned int
  2219. Cudd_ReadOrderRandomization(
  2220. DdManager * dd)
  2221. {
  2222. return(dd->randomizeOrder);
  2223. } /* end of Cudd_ReadOrderRandomization */
  2224. /**
  2225. @brief Sets the order randomization factor.
  2226. @sideeffect None
  2227. @see Cudd_ReadOrderRandomization
  2228. */
  2229. void
  2230. Cudd_SetOrderRandomization(
  2231. DdManager * dd,
  2232. unsigned int factor)
  2233. {
  2234. dd->randomizeOrder = factor;
  2235. } /* end of Cudd_SetOrderRandomization */
  2236. /**
  2237. @brief Returns the memory in use by the manager measured in bytes.
  2238. @sideeffect None
  2239. */
  2240. size_t
  2241. Cudd_ReadMemoryInUse(
  2242. DdManager * dd)
  2243. {
  2244. return(dd->memused);
  2245. } /* end of Cudd_ReadMemoryInUse */
  2246. /**
  2247. @brief Prints out statistics and settings for a CUDD manager.
  2248. @return 1 if successful; 0 otherwise.
  2249. @sideeffect None
  2250. */
  2251. int
  2252. Cudd_PrintInfo(
  2253. DdManager * dd,
  2254. FILE * fp)
  2255. {
  2256. int retval;
  2257. Cudd_ReorderingType autoMethod, autoMethodZ;
  2258. /* Modifiable parameters. */
  2259. retval = fprintf(fp,"**** CUDD modifiable parameters ****\n");
  2260. if (retval == EOF) return(0);
  2261. retval = fprintf(fp,"Hard limit for cache size: %u\n",
  2262. Cudd_ReadMaxCacheHard(dd));
  2263. if (retval == EOF) return(0);
  2264. retval = fprintf(fp,"Cache hit threshold for resizing: %u%%\n",
  2265. Cudd_ReadMinHit(dd));
  2266. if (retval == EOF) return(0);
  2267. retval = fprintf(fp,"Garbage collection enabled: %s\n",
  2268. Cudd_GarbageCollectionEnabled(dd) ? "yes" : "no");
  2269. if (retval == EOF) return(0);
  2270. retval = fprintf(fp,"Limit for fast unique table growth: %u\n",
  2271. Cudd_ReadLooseUpTo(dd));
  2272. if (retval == EOF) return(0);
  2273. retval = fprintf(fp,
  2274. "Maximum number of variables sifted per reordering: %d\n",
  2275. Cudd_ReadSiftMaxVar(dd));
  2276. if (retval == EOF) return(0);
  2277. retval = fprintf(fp,
  2278. "Maximum number of variable swaps per reordering: %d\n",
  2279. Cudd_ReadSiftMaxSwap(dd));
  2280. if (retval == EOF) return(0);
  2281. retval = fprintf(fp,"Maximum growth while sifting a variable: %g\n",
  2282. Cudd_ReadMaxGrowth(dd));
  2283. if (retval == EOF) return(0);
  2284. retval = fprintf(fp,"Dynamic reordering of BDDs enabled: %s\n",
  2285. Cudd_ReorderingStatus(dd,&autoMethod) ? "yes" : "no");
  2286. if (retval == EOF) return(0);
  2287. retval = fprintf(fp,"Default BDD reordering method: %d\n",
  2288. (int) autoMethod);
  2289. if (retval == EOF) return(0);
  2290. retval = fprintf(fp,"Dynamic reordering of ZDDs enabled: %s\n",
  2291. Cudd_ReorderingStatusZdd(dd,&autoMethodZ) ? "yes" : "no");
  2292. if (retval == EOF) return(0);
  2293. retval = fprintf(fp,"Default ZDD reordering method: %d\n",
  2294. (int) autoMethodZ);
  2295. if (retval == EOF) return(0);
  2296. retval = fprintf(fp,"Realignment of ZDDs to BDDs enabled: %s\n",
  2297. Cudd_zddRealignmentEnabled(dd) ? "yes" : "no");
  2298. if (retval == EOF) return(0);
  2299. retval = fprintf(fp,"Realignment of BDDs to ZDDs enabled: %s\n",
  2300. Cudd_bddRealignmentEnabled(dd) ? "yes" : "no");
  2301. if (retval == EOF) return(0);
  2302. retval = fprintf(fp,"Dead nodes counted in triggering reordering: %s\n",
  2303. Cudd_DeadAreCounted(dd) ? "yes" : "no");
  2304. if (retval == EOF) return(0);
  2305. retval = fprintf(fp,"Group checking criterion: %u\n",
  2306. (unsigned int) Cudd_ReadGroupcheck(dd));
  2307. if (retval == EOF) return(0);
  2308. retval = fprintf(fp,"Recombination threshold: %d\n", Cudd_ReadRecomb(dd));
  2309. if (retval == EOF) return(0);
  2310. retval = fprintf(fp,"Symmetry violation threshold: %d\n",
  2311. Cudd_ReadSymmviolation(dd));
  2312. if (retval == EOF) return(0);
  2313. retval = fprintf(fp,"Arc violation threshold: %d\n",
  2314. Cudd_ReadArcviolation(dd));
  2315. if (retval == EOF) return(0);
  2316. retval = fprintf(fp,"GA population size: %d\n",
  2317. Cudd_ReadPopulationSize(dd));
  2318. if (retval == EOF) return(0);
  2319. retval = fprintf(fp,"Number of crossovers for GA: %d\n",
  2320. Cudd_ReadNumberXovers(dd));
  2321. if (retval == EOF) return(0);
  2322. retval = fprintf(fp,"Next reordering threshold: %u\n",
  2323. Cudd_ReadNextReordering(dd));
  2324. if (retval == EOF) return(0);
  2325. /* Non-modifiable parameters. */
  2326. retval = fprintf(fp,"**** CUDD non-modifiable parameters ****\n");
  2327. if (retval == EOF) return(0);
  2328. retval = fprintf(fp,"Memory in use: %" PRIszt "\n",
  2329. Cudd_ReadMemoryInUse(dd));
  2330. if (retval == EOF) return(0);
  2331. retval = fprintf(fp,"Peak number of nodes: %ld\n",
  2332. Cudd_ReadPeakNodeCount(dd));
  2333. if (retval == EOF) return(0);
  2334. retval = fprintf(fp,"Peak number of live nodes: %d\n",
  2335. Cudd_ReadPeakLiveNodeCount(dd));
  2336. if (retval == EOF) return(0);
  2337. retval = fprintf(fp,"Number of BDD variables: %d\n", dd->size);
  2338. if (retval == EOF) return(0);
  2339. retval = fprintf(fp,"Number of ZDD variables: %d\n", dd->sizeZ);
  2340. if (retval == EOF) return(0);
  2341. retval = fprintf(fp,"Number of cache entries: %u\n", dd->cacheSlots);
  2342. if (retval == EOF) return(0);
  2343. retval = fprintf(fp,"Number of cache look-ups: %.0f\n",
  2344. Cudd_ReadCacheLookUps(dd));
  2345. if (retval == EOF) return(0);
  2346. retval = fprintf(fp,"Number of cache hits: %.0f\n",
  2347. Cudd_ReadCacheHits(dd));
  2348. if (retval == EOF) return(0);
  2349. retval = fprintf(fp,"Number of cache insertions: %.0f\n",
  2350. dd->cacheinserts);
  2351. if (retval == EOF) return(0);
  2352. retval = fprintf(fp,"Number of cache collisions: %.0f\n",
  2353. dd->cachecollisions);
  2354. if (retval == EOF) return(0);
  2355. retval = fprintf(fp,"Number of cache deletions: %.0f\n",
  2356. dd->cachedeletions);
  2357. if (retval == EOF) return(0);
  2358. retval = cuddCacheProfile(dd,fp);
  2359. if (retval == 0) return(0);
  2360. retval = fprintf(fp,"Soft limit for cache size: %u\n",
  2361. Cudd_ReadMaxCache(dd));
  2362. if (retval == EOF) return(0);
  2363. retval = fprintf(fp,"Number of buckets in unique table: %u\n", dd->slots);
  2364. if (retval == EOF) return(0);
  2365. retval = fprintf(fp,"Used buckets in unique table: %.2f%% (expected %.2f%%)\n",
  2366. 100.0 * Cudd_ReadUsedSlots(dd),
  2367. 100.0 * Cudd_ExpectedUsedSlots(dd));
  2368. if (retval == EOF) return(0);
  2369. #ifdef DD_UNIQUE_PROFILE
  2370. retval = fprintf(fp,"Unique lookups: %.0f\n", dd->uniqueLookUps);
  2371. if (retval == EOF) return(0);
  2372. retval = fprintf(fp,"Unique links: %.0f (%g per lookup)\n",
  2373. dd->uniqueLinks, dd->uniqueLinks / dd->uniqueLookUps);
  2374. if (retval == EOF) return(0);
  2375. #endif
  2376. retval = fprintf(fp,"Number of BDD and ADD nodes: %u\n", dd->keys);
  2377. if (retval == EOF) return(0);
  2378. retval = fprintf(fp,"Number of ZDD nodes: %u\n", dd->keysZ);
  2379. if (retval == EOF) return(0);
  2380. retval = fprintf(fp,"Number of dead BDD and ADD nodes: %u\n", dd->dead);
  2381. if (retval == EOF) return(0);
  2382. retval = fprintf(fp,"Number of dead ZDD nodes: %u\n", dd->deadZ);
  2383. if (retval == EOF) return(0);
  2384. retval = fprintf(fp,"Total number of nodes allocated: %.0f\n",
  2385. dd->allocated);
  2386. if (retval == EOF) return(0);
  2387. retval = fprintf(fp,"Total number of nodes reclaimed: %.0f\n",
  2388. dd->reclaimed);
  2389. if (retval == EOF) return(0);
  2390. #ifdef DD_STATS
  2391. retval = fprintf(fp,"Nodes freed: %.0f\n", dd->nodesFreed);
  2392. if (retval == EOF) return(0);
  2393. retval = fprintf(fp,"Nodes dropped: %.0f\n", dd->nodesDropped);
  2394. if (retval == EOF) return(0);
  2395. #endif
  2396. #ifdef DD_COUNT
  2397. retval = fprintf(fp,"Number of recursive calls: %.0f\n",
  2398. Cudd_ReadRecursiveCalls(dd));
  2399. if (retval == EOF) return(0);
  2400. #endif
  2401. retval = fprintf(fp,"Garbage collections so far: %d\n",
  2402. Cudd_ReadGarbageCollections(dd));
  2403. if (retval == EOF) return(0);
  2404. retval = fprintf(fp,"Time for garbage collection: %.2f sec\n",
  2405. ((double)Cudd_ReadGarbageCollectionTime(dd)/1000.0));
  2406. if (retval == EOF) return(0);
  2407. retval = fprintf(fp,"Reorderings so far: %d\n", dd->reorderings);
  2408. if (retval == EOF) return(0);
  2409. retval = fprintf(fp,"Time for reordering: %.2f sec\n",
  2410. ((double)Cudd_ReadReorderingTime(dd)/1000.0));
  2411. if (retval == EOF) return(0);
  2412. #ifdef DD_COUNT
  2413. retval = fprintf(fp,"Node swaps in reordering: %.0f\n",
  2414. Cudd_ReadSwapSteps(dd));
  2415. if (retval == EOF) return(0);
  2416. #endif
  2417. return(1);
  2418. } /* end of Cudd_PrintInfo */
  2419. /**
  2420. @brief Reports the peak number of nodes.
  2421. @details This number includes node on the free list. At the peak,
  2422. the number of nodes on the free list is guaranteed to be less than
  2423. DD_MEM_CHUNK.
  2424. @sideeffect None
  2425. @see Cudd_ReadNodeCount Cudd_PrintInfo
  2426. */
  2427. long
  2428. Cudd_ReadPeakNodeCount(
  2429. DdManager * dd)
  2430. {
  2431. long count = 0;
  2432. DdNodePtr *scan = dd->memoryList;
  2433. while (scan != NULL) {
  2434. count += DD_MEM_CHUNK;
  2435. scan = (DdNodePtr *) *scan;
  2436. }
  2437. return(count);
  2438. } /* end of Cudd_ReadPeakNodeCount */
  2439. /**
  2440. @brief Reports the peak number of live nodes.
  2441. @sideeffect None
  2442. @see Cudd_ReadNodeCount Cudd_PrintInfo Cudd_ReadPeakNodeCount
  2443. */
  2444. int
  2445. Cudd_ReadPeakLiveNodeCount(
  2446. DdManager * dd)
  2447. {
  2448. unsigned int live = dd->keys - dd->dead;
  2449. if (live > dd->peakLiveNodes) {
  2450. dd->peakLiveNodes = live;
  2451. }
  2452. return((int)dd->peakLiveNodes);
  2453. } /* end of Cudd_ReadPeakLiveNodeCount */
  2454. /**
  2455. @brief Reports the number of nodes in BDDs and ADDs.
  2456. @details This number does not include the isolated projection
  2457. functions and the unused constants. These nodes that are not counted
  2458. are not part of the DDs manipulated by the application.
  2459. @sideeffect None
  2460. @see Cudd_ReadPeakNodeCount Cudd_zddReadNodeCount
  2461. */
  2462. long
  2463. Cudd_ReadNodeCount(
  2464. DdManager * dd)
  2465. {
  2466. long count;
  2467. int i;
  2468. #ifndef DD_NO_DEATH_ROW
  2469. cuddClearDeathRow(dd);
  2470. #endif
  2471. count = (long) (dd->keys - dd->dead);
  2472. /* Count isolated projection functions. Their number is subtracted
  2473. ** from the node count because they are not part of the BDDs.
  2474. */
  2475. for (i=0; i < dd->size; i++) {
  2476. if (dd->vars[i]->ref == 1) count--;
  2477. }
  2478. /* Subtract from the count the unused constants. */
  2479. if (DD_ZERO(dd)->ref == 1) count--;
  2480. if (DD_PLUS_INFINITY(dd)->ref == 1) count--;
  2481. if (DD_MINUS_INFINITY(dd)->ref == 1) count--;
  2482. return(count);
  2483. } /* end of Cudd_ReadNodeCount */
  2484. /**
  2485. @brief Reports the number of nodes in ZDDs.
  2486. @details This number always includes the two constants 1 and 0.
  2487. @sideeffect None
  2488. @see Cudd_ReadPeakNodeCount Cudd_ReadNodeCount
  2489. */
  2490. long
  2491. Cudd_zddReadNodeCount(
  2492. DdManager * dd)
  2493. {
  2494. return((long)(dd->keysZ - dd->deadZ + 2));
  2495. } /* end of Cudd_zddReadNodeCount */
  2496. /**
  2497. @brief Adds a function to a hook.
  2498. @details A hook is a list of
  2499. application-provided functions called on certain occasions by the
  2500. package.
  2501. @return 1 if the function is successfully added; 2 if the function
  2502. was already in the list; 0 otherwise.
  2503. @sideeffect None
  2504. @see Cudd_RemoveHook
  2505. */
  2506. int
  2507. Cudd_AddHook(
  2508. DdManager * dd,
  2509. DD_HFP f,
  2510. Cudd_HookType where)
  2511. {
  2512. DdHook **hook, *nextHook, *newHook;
  2513. switch (where) {
  2514. case CUDD_PRE_GC_HOOK:
  2515. hook = &(dd->preGCHook);
  2516. break;
  2517. case CUDD_POST_GC_HOOK:
  2518. hook = &(dd->postGCHook);
  2519. break;
  2520. case CUDD_PRE_REORDERING_HOOK:
  2521. hook = &(dd->preReorderingHook);
  2522. break;
  2523. case CUDD_POST_REORDERING_HOOK:
  2524. hook = &(dd->postReorderingHook);
  2525. break;
  2526. default:
  2527. return(0);
  2528. }
  2529. /* Scan the list and find whether the function is already there.
  2530. ** If so, just return. */
  2531. nextHook = *hook;
  2532. while (nextHook != NULL) {
  2533. if (nextHook->f == f) {
  2534. return(2);
  2535. }
  2536. hook = &(nextHook->next);
  2537. nextHook = nextHook->next;
  2538. }
  2539. /* The function was not in the list. Create a new item and append it
  2540. ** to the end of the list. */
  2541. newHook = ALLOC(DdHook,1);
  2542. if (newHook == NULL) {
  2543. dd->errorCode = CUDD_MEMORY_OUT;
  2544. return(0);
  2545. }
  2546. newHook->next = NULL;
  2547. newHook->f = f;
  2548. *hook = newHook;
  2549. return(1);
  2550. } /* end of Cudd_AddHook */
  2551. /**
  2552. @brief Removes a function from a hook.
  2553. @details A hook is a list of application-provided functions called
  2554. on certain occasions by the package.
  2555. @return 1 if successful; 0 the function was not in the list.
  2556. @sideeffect None
  2557. @see Cudd_AddHook
  2558. */
  2559. int
  2560. Cudd_RemoveHook(
  2561. DdManager * dd,
  2562. DD_HFP f,
  2563. Cudd_HookType where)
  2564. {
  2565. DdHook **hook, *nextHook;
  2566. switch (where) {
  2567. case CUDD_PRE_GC_HOOK:
  2568. hook = &(dd->preGCHook);
  2569. break;
  2570. case CUDD_POST_GC_HOOK:
  2571. hook = &(dd->postGCHook);
  2572. break;
  2573. case CUDD_PRE_REORDERING_HOOK:
  2574. hook = &(dd->preReorderingHook);
  2575. break;
  2576. case CUDD_POST_REORDERING_HOOK:
  2577. hook = &(dd->postReorderingHook);
  2578. break;
  2579. default:
  2580. return(0);
  2581. }
  2582. nextHook = *hook;
  2583. while (nextHook != NULL) {
  2584. if (nextHook->f == f) {
  2585. *hook = nextHook->next;
  2586. FREE(nextHook);
  2587. return(1);
  2588. }
  2589. hook = &(nextHook->next);
  2590. nextHook = nextHook->next;
  2591. }
  2592. return(0);
  2593. } /* end of Cudd_RemoveHook */
  2594. /**
  2595. @brief Checks whether a function is in a hook.
  2596. @details A hook is a list of application-provided functions called
  2597. on certain occasions by the package.
  2598. @return 1 if the function is found; 0 otherwise.
  2599. @sideeffect None
  2600. @see Cudd_AddHook Cudd_RemoveHook
  2601. */
  2602. int
  2603. Cudd_IsInHook(
  2604. DdManager * dd,
  2605. DD_HFP f,
  2606. Cudd_HookType where)
  2607. {
  2608. DdHook *hook;
  2609. switch (where) {
  2610. case CUDD_PRE_GC_HOOK:
  2611. hook = dd->preGCHook;
  2612. break;
  2613. case CUDD_POST_GC_HOOK:
  2614. hook = dd->postGCHook;
  2615. break;
  2616. case CUDD_PRE_REORDERING_HOOK:
  2617. hook = dd->preReorderingHook;
  2618. break;
  2619. case CUDD_POST_REORDERING_HOOK:
  2620. hook = dd->postReorderingHook;
  2621. break;
  2622. default:
  2623. return(0);
  2624. }
  2625. /* Scan the list and find whether the function is already there. */
  2626. while (hook != NULL) {
  2627. if (hook->f == f) {
  2628. return(1);
  2629. }
  2630. hook = hook->next;
  2631. }
  2632. return(0);
  2633. } /* end of Cudd_IsInHook */
  2634. /**
  2635. @brief Sample hook function to call before reordering.
  2636. @details Prints on the manager's stdout reordering method and initial size.
  2637. @return 1 if successful; 0 otherwise.
  2638. @sideeffect None
  2639. @see Cudd_StdPostReordHook
  2640. */
  2641. int
  2642. Cudd_StdPreReordHook(
  2643. DdManager *dd,
  2644. const char *str,
  2645. void *data)
  2646. {
  2647. Cudd_ReorderingType method = (Cudd_ReorderingType) (ptruint) data;
  2648. int retval;
  2649. retval = fprintf(dd->out,"%s reordering with ", str);
  2650. if (retval == EOF) return(0);
  2651. switch (method) {
  2652. case CUDD_REORDER_SIFT_CONVERGE:
  2653. case CUDD_REORDER_SYMM_SIFT_CONV:
  2654. case CUDD_REORDER_GROUP_SIFT_CONV:
  2655. case CUDD_REORDER_WINDOW2_CONV:
  2656. case CUDD_REORDER_WINDOW3_CONV:
  2657. case CUDD_REORDER_WINDOW4_CONV:
  2658. case CUDD_REORDER_LINEAR_CONVERGE:
  2659. retval = fprintf(dd->out,"converging ");
  2660. if (retval == EOF) return(0);
  2661. break;
  2662. default:
  2663. break;
  2664. }
  2665. switch (method) {
  2666. case CUDD_REORDER_RANDOM:
  2667. case CUDD_REORDER_RANDOM_PIVOT:
  2668. retval = fprintf(dd->out,"random");
  2669. break;
  2670. case CUDD_REORDER_SIFT:
  2671. case CUDD_REORDER_SIFT_CONVERGE:
  2672. retval = fprintf(dd->out,"sifting");
  2673. break;
  2674. case CUDD_REORDER_SYMM_SIFT:
  2675. case CUDD_REORDER_SYMM_SIFT_CONV:
  2676. retval = fprintf(dd->out,"symmetric sifting");
  2677. break;
  2678. case CUDD_REORDER_LAZY_SIFT:
  2679. retval = fprintf(dd->out,"lazy sifting");
  2680. break;
  2681. case CUDD_REORDER_GROUP_SIFT:
  2682. case CUDD_REORDER_GROUP_SIFT_CONV:
  2683. retval = fprintf(dd->out,"group sifting");
  2684. break;
  2685. case CUDD_REORDER_WINDOW2:
  2686. case CUDD_REORDER_WINDOW3:
  2687. case CUDD_REORDER_WINDOW4:
  2688. case CUDD_REORDER_WINDOW2_CONV:
  2689. case CUDD_REORDER_WINDOW3_CONV:
  2690. case CUDD_REORDER_WINDOW4_CONV:
  2691. retval = fprintf(dd->out,"window");
  2692. break;
  2693. case CUDD_REORDER_ANNEALING:
  2694. retval = fprintf(dd->out,"annealing");
  2695. break;
  2696. case CUDD_REORDER_GENETIC:
  2697. retval = fprintf(dd->out,"genetic");
  2698. break;
  2699. case CUDD_REORDER_LINEAR:
  2700. case CUDD_REORDER_LINEAR_CONVERGE:
  2701. retval = fprintf(dd->out,"linear sifting");
  2702. break;
  2703. case CUDD_REORDER_EXACT:
  2704. retval = fprintf(dd->out,"exact");
  2705. break;
  2706. default:
  2707. return(0);
  2708. }
  2709. if (retval == EOF) return(0);
  2710. retval = fprintf(dd->out,": from %ld to ... ", strcmp(str, "BDD") == 0 ?
  2711. Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd));
  2712. if (retval == EOF) return(0);
  2713. fflush(dd->out);
  2714. return(1);
  2715. } /* end of Cudd_StdPreReordHook */
  2716. /**
  2717. @brief Sample hook function to call after reordering.
  2718. @details Prints on the manager's stdout final size and reordering time.
  2719. @return 1 if successful; 0 otherwise.
  2720. @sideeffect None
  2721. @see Cudd_StdPreReordHook
  2722. */
  2723. int
  2724. Cudd_StdPostReordHook(
  2725. DdManager *dd,
  2726. const char *str,
  2727. void *data)
  2728. {
  2729. unsigned long initialTime = (unsigned long) (ptruint) data;
  2730. int retval;
  2731. unsigned long finalTime = util_cpu_time();
  2732. double totalTimeSec = (double)(finalTime - initialTime) / 1000.0;
  2733. retval = fprintf(dd->out,"%ld nodes in %g sec\n", strcmp(str, "BDD") == 0 ?
  2734. Cudd_ReadNodeCount(dd) : Cudd_zddReadNodeCount(dd),
  2735. totalTimeSec);
  2736. if (retval == EOF) return(0);
  2737. retval = fflush(dd->out);
  2738. if (retval == EOF) return(0);
  2739. return(1);
  2740. } /* end of Cudd_StdPostReordHook */
  2741. /**
  2742. @brief Enables reporting of reordering stats.
  2743. @return 1 if successful; 0 otherwise.
  2744. @sideeffect Installs functions in the pre-reordering and post-reordering
  2745. hooks.
  2746. @see Cudd_DisableReorderingReporting Cudd_ReorderingReporting
  2747. */
  2748. int
  2749. Cudd_EnableReorderingReporting(
  2750. DdManager *dd)
  2751. {
  2752. if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
  2753. return(0);
  2754. }
  2755. if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
  2756. return(0);
  2757. }
  2758. return(1);
  2759. } /* end of Cudd_EnableReorderingReporting */
  2760. /**
  2761. @brief Disables reporting of reordering stats.
  2762. @return 1 if successful; 0 otherwise.
  2763. @sideeffect Removes functions from the pre-reordering and post-reordering
  2764. hooks.
  2765. @see Cudd_EnableReorderingReporting Cudd_ReorderingReporting
  2766. */
  2767. int
  2768. Cudd_DisableReorderingReporting(
  2769. DdManager *dd)
  2770. {
  2771. if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
  2772. return(0);
  2773. }
  2774. if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
  2775. return(0);
  2776. }
  2777. return(1);
  2778. } /* end of Cudd_DisableReorderingReporting */
  2779. /**
  2780. @brief Returns 1 if reporting of reordering stats is enabled; 0
  2781. otherwise.
  2782. @sideeffect none
  2783. @see Cudd_EnableReorderingReporting Cudd_DisableReorderingReporting
  2784. */
  2785. int
  2786. Cudd_ReorderingReporting(
  2787. DdManager *dd)
  2788. {
  2789. return(Cudd_IsInHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK));
  2790. } /* end of Cudd_ReorderingReporting */
  2791. /**
  2792. @brief Hook function to print the current variable order.
  2793. @details It may be called before or after reordering. Prints on the
  2794. manager's stdout a parenthesized list that describes the variable
  2795. groups.
  2796. @return 1 if successful; 0 otherwise.
  2797. @sideeffect None
  2798. @see Cudd_StdPreReordHook
  2799. */
  2800. int
  2801. Cudd_PrintGroupedOrder(
  2802. DdManager * dd,
  2803. const char *str,
  2804. void *data)
  2805. {
  2806. (void) data; /* avoid warning */
  2807. int isBdd = strcmp(str, "ZDD");
  2808. MtrNode *tree = isBdd ? dd->tree : dd->treeZ;
  2809. int *invperm = isBdd ? dd->invperm : dd->invpermZ;
  2810. int size = isBdd ? dd->size : dd->sizeZ;
  2811. if (tree == NULL) {
  2812. int i, retval;
  2813. for (i=0; i < size; i++) {
  2814. retval = fprintf(dd->out, "%c%d", i==0 ? '(' : ',', invperm[i]);
  2815. if (retval == EOF) return(0);
  2816. }
  2817. retval = fprintf(dd->out,")\n");
  2818. return (retval != EOF);
  2819. } else {
  2820. return Mtr_PrintGroupedOrder(tree,invperm,dd->out);
  2821. }
  2822. } /* end of Cudd_PrintGroupedOrder */
  2823. /**
  2824. @brief Enables monitoring of ordering.
  2825. @return 1 if successful; 0 otherwise.
  2826. @sideeffect Installs functions in the pre-reordering and post-reordering
  2827. hooks.
  2828. @see Cudd_EnableReorderingReporting
  2829. */
  2830. int
  2831. Cudd_EnableOrderingMonitoring(
  2832. DdManager *dd)
  2833. {
  2834. if (!Cudd_AddHook(dd, Cudd_PrintGroupedOrder, CUDD_PRE_REORDERING_HOOK)) {
  2835. return(0);
  2836. }
  2837. if (!Cudd_AddHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
  2838. return(0);
  2839. }
  2840. if (!Cudd_AddHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
  2841. return(0);
  2842. }
  2843. if (!Cudd_AddHook(dd, Cudd_PrintGroupedOrder, CUDD_POST_REORDERING_HOOK)) {
  2844. return(0);
  2845. }
  2846. return(1);
  2847. } /* end of Cudd_EnableOrderingMonitoring */
  2848. /**
  2849. @brief Disables monitoring of ordering.
  2850. @return 1 if successful; 0 otherwise.
  2851. @sideeffect Removes functions from the pre-reordering and post-reordering
  2852. hooks.
  2853. @see Cudd_EnableOrderingMonitoring
  2854. */
  2855. int
  2856. Cudd_DisableOrderingMonitoring(
  2857. DdManager *dd)
  2858. {
  2859. if (!Cudd_RemoveHook(dd, Cudd_StdPreReordHook, CUDD_PRE_REORDERING_HOOK)) {
  2860. return(0);
  2861. }
  2862. if (!Cudd_RemoveHook(dd, Cudd_PrintGroupedOrder, CUDD_PRE_REORDERING_HOOK)) {
  2863. return(0);
  2864. }
  2865. if (!Cudd_RemoveHook(dd, Cudd_PrintGroupedOrder, CUDD_POST_REORDERING_HOOK)) {
  2866. return(0);
  2867. }
  2868. if (!Cudd_RemoveHook(dd, Cudd_StdPostReordHook, CUDD_POST_REORDERING_HOOK)) {
  2869. return(0);
  2870. }
  2871. return(1);
  2872. } /* end of Cudd_DisableOrderingMonitoring */
  2873. /**
  2874. @brief Returns 1 if monitoring of ordering is enabled; 0 otherwise.
  2875. @sideeffect none
  2876. @see Cudd_EnableOrderingMonitoring Cudd_DisableOrderingMonitoring
  2877. */
  2878. int
  2879. Cudd_OrderingMonitoring(
  2880. DdManager *dd)
  2881. {
  2882. return(Cudd_IsInHook(dd, Cudd_PrintGroupedOrder, CUDD_PRE_REORDERING_HOOK));
  2883. } /* end of Cudd_OrderingMonitoring */
  2884. /**
  2885. @brief Sets the application hook.
  2886. @sideeffect None
  2887. @see Cudd_ReadApplicationHook
  2888. */
  2889. void
  2890. Cudd_SetApplicationHook(
  2891. DdManager *dd,
  2892. void * value)
  2893. {
  2894. dd->hooks = value;
  2895. } /* end of Cudd_SetApplicationHook */
  2896. /**
  2897. @brief Reads the application hook.
  2898. @sideeffect None
  2899. @see Cudd_SetApplicationHook
  2900. */
  2901. void *
  2902. Cudd_ReadApplicationHook(
  2903. DdManager *dd)
  2904. {
  2905. return(dd->hooks);
  2906. } /* end of Cudd_ReadApplicationHook */
  2907. /**
  2908. @brief Returns the code of the last error.
  2909. @details The error codes are defined in cudd.h.
  2910. @sideeffect None
  2911. @see Cudd_ClearErrorCode
  2912. */
  2913. Cudd_ErrorType
  2914. Cudd_ReadErrorCode(
  2915. DdManager *dd)
  2916. {
  2917. return(dd->errorCode);
  2918. } /* end of Cudd_ReadErrorCode */
  2919. /**
  2920. @brief Clear the error code of a manager.
  2921. @sideeffect None
  2922. @see Cudd_ReadErrorCode
  2923. */
  2924. void
  2925. Cudd_ClearErrorCode(
  2926. DdManager *dd)
  2927. {
  2928. dd->errorCode = CUDD_NO_ERROR;
  2929. } /* end of Cudd_ClearErrorCode */
  2930. /**
  2931. @brief Installs a handler for failed memory allocations.
  2932. @details Changing the handler only has an effect if the wrappers
  2933. in safe_mem.c are in use.
  2934. @return the current handler.
  2935. */
  2936. DD_OOMFP
  2937. Cudd_InstallOutOfMemoryHandler(
  2938. DD_OOMFP newHandler)
  2939. {
  2940. DD_OOMFP oldHandler = MMoutOfMemory;
  2941. MMoutOfMemory = newHandler;
  2942. return oldHandler;
  2943. } /* end of Cudd_InstallOutOfMemoryHandler */
  2944. /**
  2945. @brief Reads the stdout of a manager.
  2946. @details This is the file pointer to which messages normally going
  2947. to stdout are written. It is initialized to stdout. Cudd_SetStdout
  2948. allows the application to redirect it.
  2949. @sideeffect None
  2950. @see Cudd_SetStdout Cudd_ReadStderr
  2951. */
  2952. FILE *
  2953. Cudd_ReadStdout(
  2954. DdManager *dd)
  2955. {
  2956. return(dd->out);
  2957. } /* end of Cudd_ReadStdout */
  2958. /**
  2959. @brief Sets the stdout of a manager.
  2960. @sideeffect None
  2961. @see Cudd_ReadStdout Cudd_SetStderr
  2962. */
  2963. void
  2964. Cudd_SetStdout(
  2965. DdManager *dd,
  2966. FILE *fp)
  2967. {
  2968. dd->out = fp;
  2969. } /* end of Cudd_SetStdout */
  2970. /**
  2971. @brief Reads the stderr of a manager.
  2972. @details This is the file pointer to which messages normally going
  2973. to stderr are written. It is initialized to stderr. Cudd_SetStderr
  2974. allows the application to redirect it.
  2975. @sideeffect None
  2976. @see Cudd_SetStderr Cudd_ReadStdout
  2977. */
  2978. FILE *
  2979. Cudd_ReadStderr(
  2980. DdManager *dd)
  2981. {
  2982. return(dd->err);
  2983. } /* end of Cudd_ReadStderr */
  2984. /**
  2985. @brief Sets the stderr of a manager.
  2986. @sideeffect None
  2987. @see Cudd_ReadStderr Cudd_SetStdout
  2988. */
  2989. void
  2990. Cudd_SetStderr(
  2991. DdManager *dd,
  2992. FILE *fp)
  2993. {
  2994. dd->err = fp;
  2995. } /* end of Cudd_SetStderr */
  2996. /**
  2997. @brief Returns the threshold for the next dynamic reordering.
  2998. @details The threshold is in terms of number of nodes and is in
  2999. effect only if reordering is enabled. The count does not include the
  3000. dead nodes, unless the countDead parameter of the manager has been
  3001. changed from its default setting.
  3002. @sideeffect None
  3003. @see Cudd_SetNextReordering
  3004. */
  3005. unsigned int
  3006. Cudd_ReadNextReordering(
  3007. DdManager *dd)
  3008. {
  3009. return(dd->nextDyn);
  3010. } /* end of Cudd_ReadNextReordering */
  3011. /**
  3012. @brief Sets the threshold for the next dynamic reordering.
  3013. @details The threshold is in terms of number of nodes and is in
  3014. effect only if reordering is enabled. The count does not include the
  3015. dead nodes, unless the countDead parameter of the manager has been
  3016. changed from its default setting.
  3017. @sideeffect None
  3018. @see Cudd_ReadNextReordering
  3019. */
  3020. void
  3021. Cudd_SetNextReordering(
  3022. DdManager *dd,
  3023. unsigned int next)
  3024. {
  3025. dd->nextDyn = next;
  3026. } /* end of Cudd_SetNextReordering */
  3027. /**
  3028. @brief Reads the number of elementary reordering steps.
  3029. @sideeffect none
  3030. */
  3031. double
  3032. Cudd_ReadSwapSteps(
  3033. DdManager *dd)
  3034. {
  3035. #ifdef DD_COUNT
  3036. return(dd->swapSteps);
  3037. #else
  3038. (void) dd; /* avoid warning */
  3039. return(-1);
  3040. #endif
  3041. } /* end of Cudd_ReadSwapSteps */
  3042. /**
  3043. @brief Reads the maximum allowed number of live nodes.
  3044. @details When this number is exceeded, the package returns NULL.
  3045. @sideeffect none
  3046. @see Cudd_SetMaxLive
  3047. */
  3048. unsigned int
  3049. Cudd_ReadMaxLive(
  3050. DdManager *dd)
  3051. {
  3052. return(dd->maxLive);
  3053. } /* end of Cudd_ReadMaxLive */
  3054. /**
  3055. @brief Sets the maximum allowed number of live nodes.
  3056. @details When this number is exceeded, the package returns NULL.
  3057. @sideeffect none
  3058. @see Cudd_ReadMaxLive
  3059. */
  3060. void
  3061. Cudd_SetMaxLive(
  3062. DdManager *dd,
  3063. unsigned int maxLive)
  3064. {
  3065. dd->maxLive = maxLive;
  3066. } /* end of Cudd_SetMaxLive */
  3067. /**
  3068. @brief Reads the maximum allowed memory.
  3069. @details When this number is exceeded, the package returns NULL.
  3070. @sideeffect none
  3071. @see Cudd_SetMaxMemory
  3072. */
  3073. size_t
  3074. Cudd_ReadMaxMemory(
  3075. DdManager *dd)
  3076. {
  3077. return(dd->maxmemhard);
  3078. } /* end of Cudd_ReadMaxMemory */
  3079. /**
  3080. @brief Sets the maximum allowed memory.
  3081. @details When this number is exceeded, the package returns NULL.
  3082. @return the previous limit.
  3083. @sideeffect none
  3084. @see Cudd_ReadMaxMemory
  3085. */
  3086. size_t
  3087. Cudd_SetMaxMemory(
  3088. DdManager *dd,
  3089. size_t maxMemory)
  3090. {
  3091. size_t oldLimit = dd->maxmemhard;
  3092. dd->maxmemhard = maxMemory;
  3093. return oldLimit;
  3094. } /* end of Cudd_SetMaxMemory */
  3095. /**
  3096. @brief Prevents sifting of a variable.
  3097. @details This function sets a flag to prevent sifting of a
  3098. variable.
  3099. @return 1 if successful; 0 otherwise (i.e., invalid variable index).
  3100. @sideeffect Changes the "bindVar" flag in DdSubtable.
  3101. @see Cudd_bddUnbindVar
  3102. */
  3103. int
  3104. Cudd_bddBindVar(
  3105. DdManager *dd /**< manager */,
  3106. int index /**< variable index */)
  3107. {
  3108. if (index >= dd->size || index < 0) return(0);
  3109. dd->subtables[dd->perm[index]].bindVar = 1;
  3110. return(1);
  3111. } /* end of Cudd_bddBindVar */
  3112. /**
  3113. @brief Allows the sifting of a variable.
  3114. @details This function resets the flag that prevents the sifting
  3115. of a variable. In successive variable reorderings, the variable will
  3116. NOT be skipped, that is, sifted. Initially all variables can be
  3117. sifted. It is necessary to call this function only to re-enable
  3118. sifting after a call to Cudd_bddBindVar.
  3119. @return 1 if successful; 0 otherwise (i.e., invalid variable index).
  3120. @sideeffect Changes the "bindVar" flag in DdSubtable.
  3121. @see Cudd_bddBindVar
  3122. */
  3123. int
  3124. Cudd_bddUnbindVar(
  3125. DdManager *dd /**< manager */,
  3126. int index /**< variable index */)
  3127. {
  3128. if (index >= dd->size || index < 0) return(0);
  3129. dd->subtables[dd->perm[index]].bindVar = 0;
  3130. return(1);
  3131. } /* end of Cudd_bddUnbindVar */
  3132. /**
  3133. @brief Tells whether a variable can be sifted.
  3134. @details This function returns 1 if a variable is enabled for
  3135. sifting. Initially all variables can be sifted. This function
  3136. returns 0 if there has been a previous call to Cudd_bddBindVar for
  3137. that variable not followed by a call to Cudd_bddUnbindVar. The
  3138. function returns 0 also in the case in which the index of the
  3139. variable is out of bounds.
  3140. @sideeffect none
  3141. @see Cudd_bddBindVar Cudd_bddUnbindVar
  3142. */
  3143. int
  3144. Cudd_bddVarIsBound(
  3145. DdManager *dd /**< manager */,
  3146. int index /**< variable index */)
  3147. {
  3148. if (index >= dd->size || index < 0) return(0);
  3149. return(dd->subtables[dd->perm[index]].bindVar);
  3150. } /* end of Cudd_bddVarIsBound */
  3151. /**
  3152. @brief Sets a variable type to primary input.
  3153. @details The variable type is used by lazy sifting.
  3154. @return 1 if successful; 0 otherwise.
  3155. @sideeffect modifies the manager
  3156. @see Cudd_bddSetPsVar Cudd_bddSetNsVar Cudd_bddIsPiVar
  3157. */
  3158. int
  3159. Cudd_bddSetPiVar(
  3160. DdManager *dd /**< manager */,
  3161. int index /**< variable index */)
  3162. {
  3163. if (index >= dd->size || index < 0) return (0);
  3164. dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRIMARY_INPUT;
  3165. return(1);
  3166. } /* end of Cudd_bddSetPiVar */
  3167. /**
  3168. @brief Sets a variable type to present state.
  3169. @details The variable type is used by lazy sifting.
  3170. @return 1 if successful; 0 otherwise.
  3171. @sideeffect modifies the manager
  3172. @see Cudd_bddSetPiVar Cudd_bddSetNsVar Cudd_bddIsPsVar
  3173. */
  3174. int
  3175. Cudd_bddSetPsVar(
  3176. DdManager *dd /**< manager */,
  3177. int index /**< variable index */)
  3178. {
  3179. if (index >= dd->size || index < 0) return (0);
  3180. dd->subtables[dd->perm[index]].varType = CUDD_VAR_PRESENT_STATE;
  3181. return(1);
  3182. } /* end of Cudd_bddSetPsVar */
  3183. /**
  3184. @brief Sets a variable type to next state.
  3185. @details The variable type is used by lazy sifting.
  3186. @return 1 if successful; 0 otherwise.
  3187. @sideeffect modifies the manager
  3188. @see Cudd_bddSetPiVar Cudd_bddSetPsVar Cudd_bddIsNsVar
  3189. */
  3190. int
  3191. Cudd_bddSetNsVar(
  3192. DdManager *dd /**< manager */,
  3193. int index /**< variable index */)
  3194. {
  3195. if (index >= dd->size || index < 0) return (0);
  3196. dd->subtables[dd->perm[index]].varType = CUDD_VAR_NEXT_STATE;
  3197. return(1);
  3198. } /* end of Cudd_bddSetNsVar */
  3199. /**
  3200. @brief Checks whether a variable is primary input.
  3201. @return 1 if the variable's type is primary input; 0 if the variable
  3202. exists but is not a primary input; -1 if the variable does not
  3203. exist.
  3204. @sideeffect none
  3205. @see Cudd_bddSetPiVar Cudd_bddIsPsVar Cudd_bddIsNsVar
  3206. */
  3207. int
  3208. Cudd_bddIsPiVar(
  3209. DdManager *dd /**< manager */,
  3210. int index /**< variable index */)
  3211. {
  3212. if (index >= dd->size || index < 0) return -1;
  3213. return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRIMARY_INPUT);
  3214. } /* end of Cudd_bddIsPiVar */
  3215. /**
  3216. @brief Checks whether a variable is present state.
  3217. @return 1 if the variable's type is present state; 0 if the variable
  3218. exists but is not a present state; -1 if the variable does not
  3219. exist.
  3220. @sideeffect none
  3221. @see Cudd_bddSetPsVar Cudd_bddIsPiVar Cudd_bddIsNsVar
  3222. */
  3223. int
  3224. Cudd_bddIsPsVar(
  3225. DdManager *dd,
  3226. int index)
  3227. {
  3228. if (index >= dd->size || index < 0) return -1;
  3229. return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_PRESENT_STATE);
  3230. } /* end of Cudd_bddIsPsVar */
  3231. /**
  3232. @brief Checks whether a variable is next state.
  3233. @return 1 if the variable's type is present state; 0 if the variable
  3234. exists but is not a present state; -1 if the variable does not
  3235. exist.
  3236. @sideeffect none
  3237. @see Cudd_bddSetNsVar Cudd_bddIsPiVar Cudd_bddIsPsVar
  3238. */
  3239. int
  3240. Cudd_bddIsNsVar(
  3241. DdManager *dd,
  3242. int index)
  3243. {
  3244. if (index >= dd->size || index < 0) return -1;
  3245. return (dd->subtables[dd->perm[index]].varType == CUDD_VAR_NEXT_STATE);
  3246. } /* end of Cudd_bddIsNsVar */
  3247. /**
  3248. @brief Sets a corresponding pair index for a given index.
  3249. @details These pair indices are present and next state variable.
  3250. @return 1 if successful; 0 otherwise.
  3251. @sideeffect modifies the manager
  3252. @see Cudd_bddReadPairIndex
  3253. */
  3254. int
  3255. Cudd_bddSetPairIndex(
  3256. DdManager *dd /**< manager */,
  3257. int index /**< variable index */,
  3258. int pairIndex /**< corresponding variable index */)
  3259. {
  3260. if (index >= dd->size || index < 0) return(0);
  3261. dd->subtables[dd->perm[index]].pairIndex = pairIndex;
  3262. return(1);
  3263. } /* end of Cudd_bddSetPairIndex */
  3264. /**
  3265. @brief Reads a corresponding pair index for a given index.
  3266. @details These pair indices are present and next state variable.
  3267. @return the corresponding variable index if the variable exists; -1
  3268. otherwise.
  3269. @sideeffect modifies the manager
  3270. @see Cudd_bddSetPairIndex
  3271. */
  3272. int
  3273. Cudd_bddReadPairIndex(
  3274. DdManager *dd,
  3275. int index)
  3276. {
  3277. if (index >= dd->size || index < 0) return -1;
  3278. return dd->subtables[dd->perm[index]].pairIndex;
  3279. } /* end of Cudd_bddReadPairIndex */
  3280. /**
  3281. @brief Sets a variable to be grouped.
  3282. @details This function is used for lazy sifting.
  3283. @return 1 if successful; 0 otherwise.
  3284. @sideeffect modifies the manager
  3285. @see Cudd_bddSetVarHardGroup Cudd_bddResetVarToBeGrouped
  3286. */
  3287. int
  3288. Cudd_bddSetVarToBeGrouped(
  3289. DdManager *dd,
  3290. int index)
  3291. {
  3292. if (index >= dd->size || index < 0) return(0);
  3293. if (dd->subtables[dd->perm[index]].varToBeGrouped <= CUDD_LAZY_SOFT_GROUP) {
  3294. dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_SOFT_GROUP;
  3295. }
  3296. return(1);
  3297. } /* end of Cudd_bddSetVarToBeGrouped */
  3298. /**
  3299. @brief Sets a variable to be a hard group.
  3300. @details This function is used for lazy sifting.
  3301. @return 1 if successful; 0 otherwise.
  3302. @sideeffect modifies the manager
  3303. @see Cudd_bddSetVarToBeGrouped Cudd_bddResetVarToBeGrouped
  3304. Cudd_bddIsVarHardGroup
  3305. */
  3306. int
  3307. Cudd_bddSetVarHardGroup(
  3308. DdManager *dd,
  3309. int index)
  3310. {
  3311. if (index >= dd->size || index < 0) return(0);
  3312. dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_HARD_GROUP;
  3313. return(1);
  3314. } /* end of Cudd_bddSetVarHardGrouped */
  3315. /**
  3316. @brief Resets a variable not to be grouped.
  3317. @details This function is used for lazy sifting.
  3318. @return 1 if successful; 0 otherwise.
  3319. @sideeffect modifies the manager
  3320. @see Cudd_bddSetVarToBeGrouped Cudd_bddSetVarHardGroup
  3321. */
  3322. int
  3323. Cudd_bddResetVarToBeGrouped(
  3324. DdManager *dd,
  3325. int index)
  3326. {
  3327. if (index >= dd->size || index < 0) return(0);
  3328. if (dd->subtables[dd->perm[index]].varToBeGrouped <=
  3329. CUDD_LAZY_SOFT_GROUP) {
  3330. dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_NONE;
  3331. }
  3332. return(1);
  3333. } /* end of Cudd_bddResetVarToBeGrouped */
  3334. /**
  3335. @brief Checks whether a variable is set to be grouped.
  3336. @details This function is used for lazy sifting.
  3337. @sideeffect none
  3338. */
  3339. int
  3340. Cudd_bddIsVarToBeGrouped(
  3341. DdManager *dd,
  3342. int index)
  3343. {
  3344. if (index >= dd->size || index < 0) return(-1);
  3345. if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP)
  3346. return(0);
  3347. else
  3348. return(dd->subtables[dd->perm[index]].varToBeGrouped);
  3349. } /* end of Cudd_bddIsVarToBeGrouped */
  3350. /**
  3351. @brief Sets a variable to be ungrouped.
  3352. @details This function is used for lazy sifting.
  3353. @return 1 if successful; 0 otherwise.
  3354. @sideeffect modifies the manager
  3355. @see Cudd_bddIsVarToBeUngrouped
  3356. */
  3357. int
  3358. Cudd_bddSetVarToBeUngrouped(
  3359. DdManager *dd,
  3360. int index)
  3361. {
  3362. if (index >= dd->size || index < 0) return(0);
  3363. dd->subtables[dd->perm[index]].varToBeGrouped = CUDD_LAZY_UNGROUP;
  3364. return(1);
  3365. } /* end of Cudd_bddSetVarToBeGrouped */
  3366. /**
  3367. @brief Checks whether a variable is set to be ungrouped.
  3368. @details This function is used for lazy sifting.
  3369. @return 1 if the variable is marked to be ungrouped; 0 if the
  3370. variable exists, but it is not marked to be ungrouped; -1 if the
  3371. variable does not exist.
  3372. @sideeffect none
  3373. @see Cudd_bddSetVarToBeUngrouped
  3374. */
  3375. int
  3376. Cudd_bddIsVarToBeUngrouped(
  3377. DdManager *dd,
  3378. int index)
  3379. {
  3380. if (index >= dd->size || index < 0) return(-1);
  3381. return dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_UNGROUP;
  3382. } /* end of Cudd_bddIsVarToBeGrouped */
  3383. /**
  3384. @brief Checks whether a variable is set to be in a hard group.
  3385. @details This function is used for lazy sifting.
  3386. @return 1 if the variable is marked to be in a hard group; 0 if the
  3387. variable exists, but it is not marked to be in a hard group; -1 if
  3388. the variable does not exist.
  3389. @sideeffect none
  3390. @see Cudd_bddSetVarHardGroup
  3391. */
  3392. int
  3393. Cudd_bddIsVarHardGroup(
  3394. DdManager *dd,
  3395. int index)
  3396. {
  3397. if (index >= dd->size || index < 0) return(-1);
  3398. if (dd->subtables[dd->perm[index]].varToBeGrouped == CUDD_LAZY_HARD_GROUP)
  3399. return(1);
  3400. return(0);
  3401. } /* end of Cudd_bddIsVarToBeGrouped */
  3402. /*---------------------------------------------------------------------------*/
  3403. /* Definition of internal functions */
  3404. /*---------------------------------------------------------------------------*/
  3405. /*---------------------------------------------------------------------------*/
  3406. /* Definition of static functions */
  3407. /*---------------------------------------------------------------------------*/
  3408. /**
  3409. @brief Fixes a variable group tree.
  3410. @sideeffect Changes the variable group tree.
  3411. */
  3412. static void
  3413. fixVarTree(
  3414. MtrNode * treenode,
  3415. int * perm,
  3416. int size)
  3417. {
  3418. treenode->index = treenode->low;
  3419. treenode->low = ((int) treenode->index < size) ?
  3420. (MtrHalfWord) perm[treenode->index] : treenode->index;
  3421. if (treenode->child != NULL)
  3422. fixVarTree(treenode->child, perm, size);
  3423. if (treenode->younger != NULL)
  3424. fixVarTree(treenode->younger, perm, size);
  3425. return;
  3426. } /* end of fixVarTree */
  3427. /**
  3428. @brief Adds multiplicity groups to a %ZDD variable group tree.
  3429. @details This function creates the groups for set of %ZDD variables
  3430. (whose cardinality is given by parameter multiplicity) that are
  3431. created for each %BDD variable in Cudd_zddVarsFromBddVars. The crux
  3432. of the matter is to determine the index each new group. (The index
  3433. of the first variable in the group.) We first build all the groups
  3434. for the children of a node, and then deal with the %ZDD variables
  3435. that are directly attached to the node. The problem for these is
  3436. that the tree itself does not provide information on their position
  3437. inside the group. While we deal with the children of the node,
  3438. therefore, we keep track of all the positions they occupy. The
  3439. remaining positions in the tree can be freely used. Also, we keep
  3440. track of all the variables placed in the children. All the remaining
  3441. variables are directly attached to the group. We can then place any
  3442. pair of variables not yet grouped in any pair of available positions
  3443. in the node.
  3444. @return 1 if successful; 0 otherwise.
  3445. @sideeffect Changes the variable group tree.
  3446. @see Cudd_zddVarsFromBddVars
  3447. */
  3448. static int
  3449. addMultiplicityGroups(
  3450. DdManager *dd /**< manager */,
  3451. MtrNode *treenode /**< current tree node */,
  3452. int multiplicity /**< how many %ZDD vars per %BDD var */,
  3453. char *vmask /**< variable pairs for which a group has been already built */,
  3454. char *lmask /**< levels for which a group has already been built*/)
  3455. {
  3456. int startV, stopV, startL;
  3457. int i, j;
  3458. MtrNode *auxnode = treenode;
  3459. while (auxnode != NULL) {
  3460. if (auxnode->child != NULL) {
  3461. addMultiplicityGroups(dd,auxnode->child,multiplicity,vmask,lmask);
  3462. }
  3463. /* Build remaining groups. */
  3464. startV = dd->permZ[auxnode->index] / multiplicity;
  3465. startL = auxnode->low / multiplicity;
  3466. stopV = startV + auxnode->size / multiplicity;
  3467. /* Walk down vmask starting at startV and build missing groups. */
  3468. for (i = startV, j = startL; i < stopV; i++) {
  3469. if (vmask[i] == 0) {
  3470. MtrNode *node;
  3471. while (lmask[j] == 1) j++;
  3472. node = Mtr_MakeGroup(auxnode, j * multiplicity, multiplicity,
  3473. MTR_FIXED);
  3474. if (node == NULL) {
  3475. return(0);
  3476. }
  3477. node->index = dd->invpermZ[i * multiplicity];
  3478. vmask[i] = 1;
  3479. lmask[j] = 1;
  3480. }
  3481. }
  3482. auxnode = auxnode->younger;
  3483. }
  3484. return(1);
  3485. } /* end of addMultiplicityGroups */