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.

4821 lines
104 KiB

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