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.

1749 lines
49 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddCompose.c]
  3. PackageName [cudd]
  4. Synopsis [Functional composition and variable permutation of DDs.]
  5. Description [External procedures included in this module:
  6. <ul>
  7. <li> Cudd_bddCompose()
  8. <li> Cudd_addCompose()
  9. <li> Cudd_addPermute()
  10. <li> Cudd_addSwapVariables()
  11. <li> Cudd_bddPermute()
  12. <li> Cudd_bddVarMap()
  13. <li> Cudd_SetVarMap()
  14. <li> Cudd_bddSwapVariables()
  15. <li> Cudd_bddAdjPermuteX()
  16. <li> Cudd_addVectorCompose()
  17. <li> Cudd_addGeneralVectorCompose()
  18. <li> Cudd_addNonSimCompose()
  19. <li> Cudd_bddVectorCompose()
  20. </ul>
  21. Internal procedures included in this module:
  22. <ul>
  23. <li> cuddBddComposeRecur()
  24. <li> cuddAddComposeRecur()
  25. </ul>
  26. Static procedures included in this module:
  27. <ul>
  28. <li> cuddAddPermuteRecur()
  29. <li> cuddBddPermuteRecur()
  30. <li> cuddBddVarMapRecur()
  31. <li> cuddAddVectorComposeRecur()
  32. <li> cuddAddGeneralVectorComposeRecur()
  33. <li> cuddAddNonSimComposeRecur()
  34. <li> cuddBddVectorComposeRecur()
  35. <li> ddIsIthAddVar()
  36. <li> ddIsIthAddVarPair()
  37. </ul>
  38. The permutation functions use a local cache because the results to
  39. be remembered depend on the permutation being applied. Since the
  40. permutation is just an array, it cannot be stored in the global
  41. cache. There are different procedured for BDDs and ADDs. This is
  42. because bddPermuteRecur uses cuddBddIteRecur. If this were changed,
  43. the procedures could be merged.]
  44. Author [Fabio Somenzi and Kavita Ravi]
  45. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  46. All rights reserved.
  47. Redistribution and use in source and binary forms, with or without
  48. modification, are permitted provided that the following conditions
  49. are met:
  50. Redistributions of source code must retain the above copyright
  51. notice, this list of conditions and the following disclaimer.
  52. Redistributions in binary form must reproduce the above copyright
  53. notice, this list of conditions and the following disclaimer in the
  54. documentation and/or other materials provided with the distribution.
  55. Neither the name of the University of Colorado nor the names of its
  56. contributors may be used to endorse or promote products derived from
  57. this software without specific prior written permission.
  58. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  59. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  60. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  61. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  62. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  63. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  64. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  65. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  66. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  67. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  68. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  69. POSSIBILITY OF SUCH DAMAGE.]
  70. ******************************************************************************/
  71. #include "util.h"
  72. #include "cuddInt.h"
  73. /*---------------------------------------------------------------------------*/
  74. /* Constant declarations */
  75. /*---------------------------------------------------------------------------*/
  76. /*---------------------------------------------------------------------------*/
  77. /* Stucture declarations */
  78. /*---------------------------------------------------------------------------*/
  79. /*---------------------------------------------------------------------------*/
  80. /* Type declarations */
  81. /*---------------------------------------------------------------------------*/
  82. /*---------------------------------------------------------------------------*/
  83. /* Variable declarations */
  84. /*---------------------------------------------------------------------------*/
  85. #ifndef lint
  86. static char rcsid[] DD_UNUSED = "$Id: cuddCompose.c,v 1.46 2012/02/05 01:07:18 fabio Exp $";
  87. #endif
  88. #ifdef DD_DEBUG
  89. static int addPermuteRecurHits;
  90. static int bddPermuteRecurHits;
  91. static int bddVectorComposeHits;
  92. static int addVectorComposeHits;
  93. static int addGeneralVectorComposeHits;
  94. #endif
  95. /*---------------------------------------------------------------------------*/
  96. /* Macro declarations */
  97. /*---------------------------------------------------------------------------*/
  98. /**AutomaticStart*************************************************************/
  99. /*---------------------------------------------------------------------------*/
  100. /* Static function prototypes */
  101. /*---------------------------------------------------------------------------*/
  102. static DdNode * cuddAddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut);
  103. static DdNode * cuddBddPermuteRecur (DdManager *manager, DdHashTable *table, DdNode *node, int *permut);
  104. static DdNode * cuddBddVarMapRecur (DdManager *manager, DdNode *f);
  105. static DdNode * cuddAddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest);
  106. static DdNode * cuddAddNonSimComposeRecur (DdManager *dd, DdNode *f, DdNode **vector, DdNode *key, DdNode *cube, int lastsub);
  107. static DdNode * cuddBddVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vector, int deepest);
  108. DD_INLINE static int ddIsIthAddVar (DdManager *dd, DdNode *f, unsigned int i);
  109. static DdNode * cuddAddGeneralVectorComposeRecur (DdManager *dd, DdHashTable *table, DdNode *f, DdNode **vectorOn, DdNode **vectorOff, int deepest);
  110. DD_INLINE static int ddIsIthAddVarPair (DdManager *dd, DdNode *f, DdNode *g, unsigned int i);
  111. /**AutomaticEnd***************************************************************/
  112. /*---------------------------------------------------------------------------*/
  113. /* Definition of exported functions */
  114. /*---------------------------------------------------------------------------*/
  115. /**Function********************************************************************
  116. Synopsis [Substitutes g for x_v in the BDD for f.]
  117. Description [Substitutes g for x_v in the BDD for f. v is the index of the
  118. variable to be substituted. Cudd_bddCompose passes the corresponding
  119. projection function to the recursive procedure, so that the cache may
  120. be used. Returns the composed BDD if successful; NULL otherwise.]
  121. SideEffects [None]
  122. SeeAlso [Cudd_addCompose]
  123. ******************************************************************************/
  124. DdNode *
  125. Cudd_bddCompose(
  126. DdManager * dd,
  127. DdNode * f,
  128. DdNode * g,
  129. int v)
  130. {
  131. DdNode *proj, *res;
  132. /* Sanity check. */
  133. if (v < 0 || v >= dd->size) return(NULL);
  134. proj = dd->vars[v];
  135. do {
  136. dd->reordered = 0;
  137. res = cuddBddComposeRecur(dd,f,g,proj);
  138. } while (dd->reordered == 1);
  139. return(res);
  140. } /* end of Cudd_bddCompose */
  141. /**Function********************************************************************
  142. Synopsis [Substitutes g for x_v in the ADD for f.]
  143. Description [Substitutes g for x_v in the ADD for f. v is the index of the
  144. variable to be substituted. g must be a 0-1 ADD. Cudd_bddCompose passes
  145. the corresponding projection function to the recursive procedure, so
  146. that the cache may be used. Returns the composed ADD if successful;
  147. NULL otherwise.]
  148. SideEffects [None]
  149. SeeAlso [Cudd_bddCompose]
  150. ******************************************************************************/
  151. DdNode *
  152. Cudd_addCompose(
  153. DdManager * dd,
  154. DdNode * f,
  155. DdNode * g,
  156. int v)
  157. {
  158. DdNode *proj, *res;
  159. /* Sanity check. */
  160. if (v < 0 || v >= dd->size) return(NULL);
  161. proj = dd->vars[v];
  162. do {
  163. dd->reordered = 0;
  164. res = cuddAddComposeRecur(dd,f,g,proj);
  165. } while (dd->reordered == 1);
  166. return(res);
  167. } /* end of Cudd_addCompose */
  168. /**Function********************************************************************
  169. Synopsis [Permutes the variables of an ADD.]
  170. Description [Given a permutation in array permut, creates a new ADD
  171. with permuted variables. There should be an entry in array permut
  172. for each variable in the manager. The i-th entry of permut holds the
  173. index of the variable that is to substitute the i-th
  174. variable. Returns a pointer to the resulting ADD if successful; NULL
  175. otherwise.]
  176. SideEffects [None]
  177. SeeAlso [Cudd_bddPermute Cudd_addSwapVariables]
  178. ******************************************************************************/
  179. DdNode *
  180. Cudd_addPermute(
  181. DdManager * manager,
  182. DdNode * node,
  183. int * permut)
  184. {
  185. DdHashTable *table;
  186. DdNode *res;
  187. do {
  188. manager->reordered = 0;
  189. table = cuddHashTableInit(manager,1,2);
  190. if (table == NULL) return(NULL);
  191. /* Recursively solve the problem. */
  192. res = cuddAddPermuteRecur(manager,table,node,permut);
  193. if (res != NULL) cuddRef(res);
  194. /* Dispose of local cache. */
  195. cuddHashTableQuit(table);
  196. } while (manager->reordered == 1);
  197. if (res != NULL) cuddDeref(res);
  198. return(res);
  199. } /* end of Cudd_addPermute */
  200. /**Function********************************************************************
  201. Synopsis [Swaps two sets of variables of the same size (x and y) in
  202. the ADD f.]
  203. Description [Swaps two sets of variables of the same size (x and y) in
  204. the ADD f. The size is given by n. The two sets of variables are
  205. assumed to be disjoint. Returns a pointer to the resulting ADD if
  206. successful; NULL otherwise.]
  207. SideEffects [None]
  208. SeeAlso [Cudd_addPermute Cudd_bddSwapVariables]
  209. ******************************************************************************/
  210. DdNode *
  211. Cudd_addSwapVariables(
  212. DdManager * dd,
  213. DdNode * f,
  214. DdNode ** x,
  215. DdNode ** y,
  216. int n)
  217. {
  218. DdNode *swapped;
  219. int i, j, k;
  220. int *permut;
  221. permut = ALLOC(int,dd->size);
  222. if (permut == NULL) {
  223. dd->errorCode = CUDD_MEMORY_OUT;
  224. return(NULL);
  225. }
  226. for (i = 0; i < dd->size; i++) permut[i] = i;
  227. for (i = 0; i < n; i++) {
  228. j = x[i]->index;
  229. k = y[i]->index;
  230. permut[j] = k;
  231. permut[k] = j;
  232. }
  233. swapped = Cudd_addPermute(dd,f,permut);
  234. FREE(permut);
  235. return(swapped);
  236. } /* end of Cudd_addSwapVariables */
  237. /**Function********************************************************************
  238. Synopsis [Permutes the variables of a BDD.]
  239. Description [Given a permutation in array permut, creates a new BDD
  240. with permuted variables. There should be an entry in array permut
  241. for each variable in the manager. The i-th entry of permut holds the
  242. index of the variable that is to substitute the i-th variable.
  243. Returns a pointer to the resulting BDD if successful; NULL
  244. otherwise.]
  245. SideEffects [None]
  246. SeeAlso [Cudd_addPermute Cudd_bddSwapVariables]
  247. ******************************************************************************/
  248. DdNode *
  249. Cudd_bddPermute(
  250. DdManager * manager,
  251. DdNode * node,
  252. int * permut)
  253. {
  254. DdHashTable *table;
  255. DdNode *res;
  256. do {
  257. manager->reordered = 0;
  258. table = cuddHashTableInit(manager,1,2);
  259. if (table == NULL) return(NULL);
  260. res = cuddBddPermuteRecur(manager,table,node,permut);
  261. if (res != NULL) cuddRef(res);
  262. /* Dispose of local cache. */
  263. cuddHashTableQuit(table);
  264. } while (manager->reordered == 1);
  265. if (res != NULL) cuddDeref(res);
  266. return(res);
  267. } /* end of Cudd_bddPermute */
  268. /**Function********************************************************************
  269. Synopsis [Remaps the variables of a BDD using the default variable map.]
  270. Description [Remaps the variables of a BDD using the default
  271. variable map. A typical use of this function is to swap two sets of
  272. variables. The variable map must be registered with Cudd_SetVarMap.
  273. Returns a pointer to the resulting BDD if successful; NULL
  274. otherwise.]
  275. SideEffects [None]
  276. SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables Cudd_SetVarMap]
  277. ******************************************************************************/
  278. DdNode *
  279. Cudd_bddVarMap(
  280. DdManager * manager /* DD manager */,
  281. DdNode * f /* function in which to remap variables */)
  282. {
  283. DdNode *res;
  284. if (manager->map == NULL) return(NULL);
  285. do {
  286. manager->reordered = 0;
  287. res = cuddBddVarMapRecur(manager, f);
  288. } while (manager->reordered == 1);
  289. return(res);
  290. } /* end of Cudd_bddVarMap */
  291. /**Function********************************************************************
  292. Synopsis [Registers a variable mapping with the manager.]
  293. Description [Registers with the manager a variable mapping described
  294. by two sets of variables. This variable mapping is then used by
  295. functions like Cudd_bddVarMap. This function is convenient for
  296. those applications that perform the same mapping several times.
  297. However, if several different permutations are used, it may be more
  298. efficient not to rely on the registered mapping, because changing
  299. mapping causes the cache to be cleared. (The initial setting,
  300. however, does not clear the cache.) The two sets of variables (x and
  301. y) must have the same size (x and y). The size is given by n. The
  302. two sets of variables are normally disjoint, but this restriction is
  303. not imposeded by the function. When new variables are created, the
  304. map is automatically extended (each new variable maps to
  305. itself). The typical use, however, is to wait until all variables
  306. are created, and then create the map. Returns 1 if the mapping is
  307. successfully registered with the manager; 0 otherwise.]
  308. SideEffects [Modifies the manager. May clear the cache.]
  309. SeeAlso [Cudd_bddVarMap Cudd_bddPermute Cudd_bddSwapVariables]
  310. ******************************************************************************/
  311. int
  312. Cudd_SetVarMap (
  313. DdManager *manager /* DD manager */,
  314. DdNode **x /* first array of variables */,
  315. DdNode **y /* second array of variables */,
  316. int n /* length of both arrays */)
  317. {
  318. int i;
  319. if (manager->map != NULL) {
  320. cuddCacheFlush(manager);
  321. } else {
  322. manager->map = ALLOC(int,manager->maxSize);
  323. if (manager->map == NULL) {
  324. manager->errorCode = CUDD_MEMORY_OUT;
  325. return(0);
  326. }
  327. manager->memused += sizeof(int) * manager->maxSize;
  328. }
  329. /* Initialize the map to the identity. */
  330. for (i = 0; i < manager->size; i++) {
  331. manager->map[i] = i;
  332. }
  333. /* Create the map. */
  334. for (i = 0; i < n; i++) {
  335. manager->map[x[i]->index] = y[i]->index;
  336. manager->map[y[i]->index] = x[i]->index;
  337. }
  338. return(1);
  339. } /* end of Cudd_SetVarMap */
  340. /**Function********************************************************************
  341. Synopsis [Swaps two sets of variables of the same size (x and y) in
  342. the BDD f.]
  343. Description [Swaps two sets of variables of the same size (x and y)
  344. in the BDD f. The size is given by n. The two sets of variables are
  345. assumed to be disjoint. Returns a pointer to the resulting BDD if
  346. successful; NULL otherwise.]
  347. SideEffects [None]
  348. SeeAlso [Cudd_bddPermute Cudd_addSwapVariables]
  349. ******************************************************************************/
  350. DdNode *
  351. Cudd_bddSwapVariables(
  352. DdManager * dd,
  353. DdNode * f,
  354. DdNode ** x,
  355. DdNode ** y,
  356. int n)
  357. {
  358. DdNode *swapped;
  359. int i, j, k;
  360. int *permut;
  361. permut = ALLOC(int,dd->size);
  362. if (permut == NULL) {
  363. dd->errorCode = CUDD_MEMORY_OUT;
  364. return(NULL);
  365. }
  366. for (i = 0; i < dd->size; i++) permut[i] = i;
  367. for (i = 0; i < n; i++) {
  368. j = x[i]->index;
  369. k = y[i]->index;
  370. permut[j] = k;
  371. permut[k] = j;
  372. }
  373. swapped = Cudd_bddPermute(dd,f,permut);
  374. FREE(permut);
  375. return(swapped);
  376. } /* end of Cudd_bddSwapVariables */
  377. /**Function********************************************************************
  378. Synopsis [Rearranges a set of variables in the BDD B.]
  379. Description [Rearranges a set of variables in the BDD B. The size of
  380. the set is given by n. This procedure is intended for the
  381. `randomization' of the priority functions. Returns a pointer to the
  382. BDD if successful; NULL otherwise.]
  383. SideEffects [None]
  384. SeeAlso [Cudd_bddPermute Cudd_bddSwapVariables
  385. Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_PrioritySelect]
  386. ******************************************************************************/
  387. DdNode *
  388. Cudd_bddAdjPermuteX(
  389. DdManager * dd,
  390. DdNode * B,
  391. DdNode ** x,
  392. int n)
  393. {
  394. DdNode *swapped;
  395. int i, j, k;
  396. int *permut;
  397. permut = ALLOC(int,dd->size);
  398. if (permut == NULL) {
  399. dd->errorCode = CUDD_MEMORY_OUT;
  400. return(NULL);
  401. }
  402. for (i = 0; i < dd->size; i++) permut[i] = i;
  403. for (i = 0; i < n-2; i += 3) {
  404. j = x[i]->index;
  405. k = x[i+1]->index;
  406. permut[j] = k;
  407. permut[k] = j;
  408. }
  409. swapped = Cudd_bddPermute(dd,B,permut);
  410. FREE(permut);
  411. return(swapped);
  412. } /* end of Cudd_bddAdjPermuteX */
  413. /**Function********************************************************************
  414. Synopsis [Composes an ADD with a vector of 0-1 ADDs.]
  415. Description [Given a vector of 0-1 ADDs, creates a new ADD by
  416. substituting the 0-1 ADDs for the variables of the ADD f. There
  417. should be an entry in vector for each variable in the manager.
  418. If no substitution is sought for a given variable, the corresponding
  419. projection function should be specified in the vector.
  420. This function implements simultaneous composition.
  421. Returns a pointer to the resulting ADD if successful; NULL
  422. otherwise.]
  423. SideEffects [None]
  424. SeeAlso [Cudd_addNonSimCompose Cudd_addPermute Cudd_addCompose
  425. Cudd_bddVectorCompose]
  426. ******************************************************************************/
  427. DdNode *
  428. Cudd_addVectorCompose(
  429. DdManager * dd,
  430. DdNode * f,
  431. DdNode ** vector)
  432. {
  433. DdHashTable *table;
  434. DdNode *res;
  435. int deepest;
  436. int i;
  437. do {
  438. dd->reordered = 0;
  439. /* Initialize local cache. */
  440. table = cuddHashTableInit(dd,1,2);
  441. if (table == NULL) return(NULL);
  442. /* Find deepest real substitution. */
  443. for (deepest = dd->size - 1; deepest >= 0; deepest--) {
  444. i = dd->invperm[deepest];
  445. if (!ddIsIthAddVar(dd,vector[i],i)) {
  446. break;
  447. }
  448. }
  449. /* Recursively solve the problem. */
  450. res = cuddAddVectorComposeRecur(dd,table,f,vector,deepest);
  451. if (res != NULL) cuddRef(res);
  452. /* Dispose of local cache. */
  453. cuddHashTableQuit(table);
  454. } while (dd->reordered == 1);
  455. if (res != NULL) cuddDeref(res);
  456. return(res);
  457. } /* end of Cudd_addVectorCompose */
  458. /**Function********************************************************************
  459. Synopsis [Composes an ADD with a vector of ADDs.]
  460. Description [Given a vector of ADDs, creates a new ADD by substituting the
  461. ADDs for the variables of the ADD f. vectorOn contains ADDs to be substituted
  462. for the x_v and vectorOff the ADDs to be substituted for x_v'. There should
  463. be an entry in vector for each variable in the manager. If no substitution
  464. is sought for a given variable, the corresponding projection function should
  465. be specified in the vector. This function implements simultaneous
  466. composition. Returns a pointer to the resulting ADD if successful; NULL
  467. otherwise.]
  468. SideEffects [None]
  469. SeeAlso [Cudd_addVectorCompose Cudd_addNonSimCompose Cudd_addPermute
  470. Cudd_addCompose Cudd_bddVectorCompose]
  471. ******************************************************************************/
  472. DdNode *
  473. Cudd_addGeneralVectorCompose(
  474. DdManager * dd,
  475. DdNode * f,
  476. DdNode ** vectorOn,
  477. DdNode ** vectorOff)
  478. {
  479. DdHashTable *table;
  480. DdNode *res;
  481. int deepest;
  482. int i;
  483. do {
  484. dd->reordered = 0;
  485. /* Initialize local cache. */
  486. table = cuddHashTableInit(dd,1,2);
  487. if (table == NULL) return(NULL);
  488. /* Find deepest real substitution. */
  489. for (deepest = dd->size - 1; deepest >= 0; deepest--) {
  490. i = dd->invperm[deepest];
  491. if (!ddIsIthAddVarPair(dd,vectorOn[i],vectorOff[i],i)) {
  492. break;
  493. }
  494. }
  495. /* Recursively solve the problem. */
  496. res = cuddAddGeneralVectorComposeRecur(dd,table,f,vectorOn,
  497. vectorOff,deepest);
  498. if (res != NULL) cuddRef(res);
  499. /* Dispose of local cache. */
  500. cuddHashTableQuit(table);
  501. } while (dd->reordered == 1);
  502. if (res != NULL) cuddDeref(res);
  503. return(res);
  504. } /* end of Cudd_addGeneralVectorCompose */
  505. /**Function********************************************************************
  506. Synopsis [Composes an ADD with a vector of 0-1 ADDs.]
  507. Description [Given a vector of 0-1 ADDs, creates a new ADD by
  508. substituting the 0-1 ADDs for the variables of the ADD f. There
  509. should be an entry in vector for each variable in the manager.
  510. This function implements non-simultaneous composition. If any of the
  511. functions being composed depends on any of the variables being
  512. substituted, then the result depends on the order of composition,
  513. which in turn depends on the variable order: The variables farther from
  514. the roots in the order are substituted first.
  515. Returns a pointer to the resulting ADD if successful; NULL
  516. otherwise.]
  517. SideEffects [None]
  518. SeeAlso [Cudd_addVectorCompose Cudd_addPermute Cudd_addCompose]
  519. ******************************************************************************/
  520. DdNode *
  521. Cudd_addNonSimCompose(
  522. DdManager * dd,
  523. DdNode * f,
  524. DdNode ** vector)
  525. {
  526. DdNode *cube, *key, *var, *tmp, *piece;
  527. DdNode *res;
  528. int i, lastsub;
  529. /* The cache entry for this function is composed of three parts:
  530. ** f itself, the replacement relation, and the cube of the
  531. ** variables being substituted.
  532. ** The replacement relation is the product of the terms (yi EXNOR gi).
  533. ** This apporach allows us to use the global cache for this function,
  534. ** with great savings in memory with respect to using arrays for the
  535. ** cache entries.
  536. ** First we build replacement relation and cube of substituted
  537. ** variables from the vector specifying the desired composition.
  538. */
  539. key = DD_ONE(dd);
  540. cuddRef(key);
  541. cube = DD_ONE(dd);
  542. cuddRef(cube);
  543. for (i = (int) dd->size - 1; i >= 0; i--) {
  544. if (ddIsIthAddVar(dd,vector[i],(unsigned int)i)) {
  545. continue;
  546. }
  547. var = Cudd_addIthVar(dd,i);
  548. if (var == NULL) {
  549. Cudd_RecursiveDeref(dd,key);
  550. Cudd_RecursiveDeref(dd,cube);
  551. return(NULL);
  552. }
  553. cuddRef(var);
  554. /* Update cube. */
  555. tmp = Cudd_addApply(dd,Cudd_addTimes,var,cube);
  556. if (tmp == NULL) {
  557. Cudd_RecursiveDeref(dd,key);
  558. Cudd_RecursiveDeref(dd,cube);
  559. Cudd_RecursiveDeref(dd,var);
  560. return(NULL);
  561. }
  562. cuddRef(tmp);
  563. Cudd_RecursiveDeref(dd,cube);
  564. cube = tmp;
  565. /* Update replacement relation. */
  566. piece = Cudd_addApply(dd,Cudd_addXnor,var,vector[i]);
  567. if (piece == NULL) {
  568. Cudd_RecursiveDeref(dd,key);
  569. Cudd_RecursiveDeref(dd,var);
  570. return(NULL);
  571. }
  572. cuddRef(piece);
  573. Cudd_RecursiveDeref(dd,var);
  574. tmp = Cudd_addApply(dd,Cudd_addTimes,key,piece);
  575. if (tmp == NULL) {
  576. Cudd_RecursiveDeref(dd,key);
  577. Cudd_RecursiveDeref(dd,piece);
  578. return(NULL);
  579. }
  580. cuddRef(tmp);
  581. Cudd_RecursiveDeref(dd,key);
  582. Cudd_RecursiveDeref(dd,piece);
  583. key = tmp;
  584. }
  585. /* Now try composition, until no reordering occurs. */
  586. do {
  587. /* Find real substitution with largest index. */
  588. for (lastsub = dd->size - 1; lastsub >= 0; lastsub--) {
  589. if (!ddIsIthAddVar(dd,vector[lastsub],(unsigned int)lastsub)) {
  590. break;
  591. }
  592. }
  593. /* Recursively solve the problem. */
  594. dd->reordered = 0;
  595. res = cuddAddNonSimComposeRecur(dd,f,vector,key,cube,lastsub+1);
  596. if (res != NULL) cuddRef(res);
  597. } while (dd->reordered == 1);
  598. Cudd_RecursiveDeref(dd,key);
  599. Cudd_RecursiveDeref(dd,cube);
  600. if (res != NULL) cuddDeref(res);
  601. return(res);
  602. } /* end of Cudd_addNonSimCompose */
  603. /**Function********************************************************************
  604. Synopsis [Composes a BDD with a vector of BDDs.]
  605. Description [Given a vector of BDDs, creates a new BDD by
  606. substituting the BDDs for the variables of the BDD f. There
  607. should be an entry in vector for each variable in the manager.
  608. If no substitution is sought for a given variable, the corresponding
  609. projection function should be specified in the vector.
  610. This function implements simultaneous composition.
  611. Returns a pointer to the resulting BDD if successful; NULL
  612. otherwise.]
  613. SideEffects [None]
  614. SeeAlso [Cudd_bddPermute Cudd_bddCompose Cudd_addVectorCompose]
  615. ******************************************************************************/
  616. DdNode *
  617. Cudd_bddVectorCompose(
  618. DdManager * dd,
  619. DdNode * f,
  620. DdNode ** vector)
  621. {
  622. DdHashTable *table;
  623. DdNode *res;
  624. int deepest;
  625. int i;
  626. do {
  627. dd->reordered = 0;
  628. /* Initialize local cache. */
  629. table = cuddHashTableInit(dd,1,2);
  630. if (table == NULL) return(NULL);
  631. /* Find deepest real substitution. */
  632. for (deepest = dd->size - 1; deepest >= 0; deepest--) {
  633. i = dd->invperm[deepest];
  634. if (vector[i] != dd->vars[i]) {
  635. break;
  636. }
  637. }
  638. /* Recursively solve the problem. */
  639. res = cuddBddVectorComposeRecur(dd,table,f,vector, deepest);
  640. if (res != NULL) cuddRef(res);
  641. /* Dispose of local cache. */
  642. cuddHashTableQuit(table);
  643. } while (dd->reordered == 1);
  644. if (res != NULL) cuddDeref(res);
  645. return(res);
  646. } /* end of Cudd_bddVectorCompose */
  647. /*---------------------------------------------------------------------------*/
  648. /* Definition of internal functions */
  649. /*---------------------------------------------------------------------------*/
  650. /**Function********************************************************************
  651. Synopsis [Performs the recursive step of Cudd_bddCompose.]
  652. Description [Performs the recursive step of Cudd_bddCompose.
  653. Exploits the fact that the composition of f' with g
  654. produces the complement of the composition of f with g to better
  655. utilize the cache. Returns the composed BDD if successful; NULL
  656. otherwise.]
  657. SideEffects [None]
  658. SeeAlso [Cudd_bddCompose]
  659. ******************************************************************************/
  660. DdNode *
  661. cuddBddComposeRecur(
  662. DdManager * dd,
  663. DdNode * f,
  664. DdNode * g,
  665. DdNode * proj)
  666. {
  667. DdNode *F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
  668. unsigned int v, topf, topg, topindex;
  669. int comple;
  670. statLine(dd);
  671. v = dd->perm[proj->index];
  672. F = Cudd_Regular(f);
  673. topf = cuddI(dd,F->index);
  674. /* Terminal case. Subsumes the test for constant f. */
  675. if (topf > v) return(f);
  676. /* We solve the problem for a regular pointer, and then complement
  677. ** the result if the pointer was originally complemented.
  678. */
  679. comple = Cudd_IsComplement(f);
  680. /* Check cache. */
  681. r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
  682. if (r != NULL) {
  683. return(Cudd_NotCond(r,comple));
  684. }
  685. if (topf == v) {
  686. /* Compose. */
  687. f1 = cuddT(F);
  688. f0 = cuddE(F);
  689. r = cuddBddIteRecur(dd, g, f1, f0);
  690. if (r == NULL) return(NULL);
  691. } else {
  692. /* Compute cofactors of f and g. Remember the index of the top
  693. ** variable.
  694. */
  695. G = Cudd_Regular(g);
  696. topg = cuddI(dd,G->index);
  697. if (topf > topg) {
  698. topindex = G->index;
  699. f1 = f0 = F;
  700. } else {
  701. topindex = F->index;
  702. f1 = cuddT(F);
  703. f0 = cuddE(F);
  704. }
  705. if (topg > topf) {
  706. g1 = g0 = g;
  707. } else {
  708. g1 = cuddT(G);
  709. g0 = cuddE(G);
  710. if (g != G) {
  711. g1 = Cudd_Not(g1);
  712. g0 = Cudd_Not(g0);
  713. }
  714. }
  715. /* Recursive step. */
  716. t = cuddBddComposeRecur(dd, f1, g1, proj);
  717. if (t == NULL) return(NULL);
  718. cuddRef(t);
  719. e = cuddBddComposeRecur(dd, f0, g0, proj);
  720. if (e == NULL) {
  721. Cudd_IterDerefBdd(dd, t);
  722. return(NULL);
  723. }
  724. cuddRef(e);
  725. r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
  726. if (r == NULL) {
  727. Cudd_IterDerefBdd(dd, t);
  728. Cudd_IterDerefBdd(dd, e);
  729. return(NULL);
  730. }
  731. cuddRef(r);
  732. Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
  733. Cudd_IterDerefBdd(dd, e);
  734. cuddDeref(r);
  735. }
  736. cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);
  737. return(Cudd_NotCond(r,comple));
  738. } /* end of cuddBddComposeRecur */
  739. /**Function********************************************************************
  740. Synopsis [Performs the recursive step of Cudd_addCompose.]
  741. Description [Performs the recursive step of Cudd_addCompose.
  742. Returns the composed BDD if successful; NULL otherwise.]
  743. SideEffects [None]
  744. SeeAlso [Cudd_addCompose]
  745. ******************************************************************************/
  746. DdNode *
  747. cuddAddComposeRecur(
  748. DdManager * dd,
  749. DdNode * f,
  750. DdNode * g,
  751. DdNode * proj)
  752. {
  753. DdNode *f1, *f0, *g1, *g0, *r, *t, *e;
  754. unsigned int v, topf, topg, topindex;
  755. statLine(dd);
  756. v = dd->perm[proj->index];
  757. topf = cuddI(dd,f->index);
  758. /* Terminal case. Subsumes the test for constant f. */
  759. if (topf > v) return(f);
  760. /* Check cache. */
  761. r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj);
  762. if (r != NULL) {
  763. return(r);
  764. }
  765. if (topf == v) {
  766. /* Compose. */
  767. f1 = cuddT(f);
  768. f0 = cuddE(f);
  769. r = cuddAddIteRecur(dd, g, f1, f0);
  770. if (r == NULL) return(NULL);
  771. } else {
  772. /* Compute cofactors of f and g. Remember the index of the top
  773. ** variable.
  774. */
  775. topg = cuddI(dd,g->index);
  776. if (topf > topg) {
  777. topindex = g->index;
  778. f1 = f0 = f;
  779. } else {
  780. topindex = f->index;
  781. f1 = cuddT(f);
  782. f0 = cuddE(f);
  783. }
  784. if (topg > topf) {
  785. g1 = g0 = g;
  786. } else {
  787. g1 = cuddT(g);
  788. g0 = cuddE(g);
  789. }
  790. /* Recursive step. */
  791. t = cuddAddComposeRecur(dd, f1, g1, proj);
  792. if (t == NULL) return(NULL);
  793. cuddRef(t);
  794. e = cuddAddComposeRecur(dd, f0, g0, proj);
  795. if (e == NULL) {
  796. Cudd_RecursiveDeref(dd, t);
  797. return(NULL);
  798. }
  799. cuddRef(e);
  800. if (t == e) {
  801. r = t;
  802. } else {
  803. r = cuddUniqueInter(dd, (int) topindex, t, e);
  804. if (r == NULL) {
  805. Cudd_RecursiveDeref(dd, t);
  806. Cudd_RecursiveDeref(dd, e);
  807. return(NULL);
  808. }
  809. }
  810. cuddDeref(t);
  811. cuddDeref(e);
  812. }
  813. cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r);
  814. return(r);
  815. } /* end of cuddAddComposeRecur */
  816. /*---------------------------------------------------------------------------*/
  817. /* Definition of static functions */
  818. /*---------------------------------------------------------------------------*/
  819. /**Function********************************************************************
  820. Synopsis [Implements the recursive step of Cudd_addPermute.]
  821. Description [ Recursively puts the ADD in the order given in the
  822. array permut. Checks for trivial cases to terminate recursion, then
  823. splits on the children of this node. Once the solutions for the
  824. children are obtained, it puts into the current position the node
  825. from the rest of the ADD that should be here. Then returns this ADD.
  826. The key here is that the node being visited is NOT put in its proper
  827. place by this instance, but rather is switched when its proper
  828. position is reached in the recursion tree.<p>
  829. The DdNode * that is returned is the same ADD as passed in as node,
  830. but in the new order.]
  831. SideEffects [None]
  832. SeeAlso [Cudd_addPermute cuddBddPermuteRecur]
  833. ******************************************************************************/
  834. static DdNode *
  835. cuddAddPermuteRecur(
  836. DdManager * manager /* DD manager */,
  837. DdHashTable * table /* computed table */,
  838. DdNode * node /* ADD to be reordered */,
  839. int * permut /* permutation array */)
  840. {
  841. DdNode *T,*E;
  842. DdNode *res,*var;
  843. int index;
  844. statLine(manager);
  845. /* Check for terminal case of constant node. */
  846. if (cuddIsConstant(node)) {
  847. return(node);
  848. }
  849. /* If problem already solved, look up answer and return. */
  850. if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
  851. #ifdef DD_DEBUG
  852. addPermuteRecurHits++;
  853. #endif
  854. return(res);
  855. }
  856. /* Split and recur on children of this node. */
  857. T = cuddAddPermuteRecur(manager,table,cuddT(node),permut);
  858. if (T == NULL) return(NULL);
  859. cuddRef(T);
  860. E = cuddAddPermuteRecur(manager,table,cuddE(node),permut);
  861. if (E == NULL) {
  862. Cudd_RecursiveDeref(manager, T);
  863. return(NULL);
  864. }
  865. cuddRef(E);
  866. /* Move variable that should be in this position to this position
  867. ** by creating a single var ADD for that variable, and calling
  868. ** cuddAddIteRecur with the T and E we just created.
  869. */
  870. index = permut[node->index];
  871. var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager));
  872. if (var == NULL) return(NULL);
  873. cuddRef(var);
  874. res = cuddAddIteRecur(manager,var,T,E);
  875. if (res == NULL) {
  876. Cudd_RecursiveDeref(manager,var);
  877. Cudd_RecursiveDeref(manager, T);
  878. Cudd_RecursiveDeref(manager, E);
  879. return(NULL);
  880. }
  881. cuddRef(res);
  882. Cudd_RecursiveDeref(manager,var);
  883. Cudd_RecursiveDeref(manager, T);
  884. Cudd_RecursiveDeref(manager, E);
  885. /* Do not keep the result if the reference count is only 1, since
  886. ** it will not be visited again.
  887. */
  888. if (node->ref != 1) {
  889. ptrint fanout = (ptrint) node->ref;
  890. cuddSatDec(fanout);
  891. if (!cuddHashTableInsert1(table,node,res,fanout)) {
  892. Cudd_RecursiveDeref(manager, res);
  893. return(NULL);
  894. }
  895. }
  896. cuddDeref(res);
  897. return(res);
  898. } /* end of cuddAddPermuteRecur */
  899. /**Function********************************************************************
  900. Synopsis [Implements the recursive step of Cudd_bddPermute.]
  901. Description [ Recursively puts the BDD in the order given in the array permut.
  902. Checks for trivial cases to terminate recursion, then splits on the
  903. children of this node. Once the solutions for the children are
  904. obtained, it puts into the current position the node from the rest of
  905. the BDD that should be here. Then returns this BDD.
  906. The key here is that the node being visited is NOT put in its proper
  907. place by this instance, but rather is switched when its proper position
  908. is reached in the recursion tree.<p>
  909. The DdNode * that is returned is the same BDD as passed in as node,
  910. but in the new order.]
  911. SideEffects [None]
  912. SeeAlso [Cudd_bddPermute cuddAddPermuteRecur]
  913. ******************************************************************************/
  914. static DdNode *
  915. cuddBddPermuteRecur(
  916. DdManager * manager /* DD manager */,
  917. DdHashTable * table /* computed table */,
  918. DdNode * node /* BDD to be reordered */,
  919. int * permut /* permutation array */)
  920. {
  921. DdNode *N,*T,*E;
  922. DdNode *res;
  923. int index;
  924. statLine(manager);
  925. N = Cudd_Regular(node);
  926. /* Check for terminal case of constant node. */
  927. if (cuddIsConstant(N)) {
  928. return(node);
  929. }
  930. /* If problem already solved, look up answer and return. */
  931. if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) {
  932. #ifdef DD_DEBUG
  933. bddPermuteRecurHits++;
  934. #endif
  935. return(Cudd_NotCond(res,N != node));
  936. }
  937. /* Split and recur on children of this node. */
  938. T = cuddBddPermuteRecur(manager,table,cuddT(N),permut);
  939. if (T == NULL) return(NULL);
  940. cuddRef(T);
  941. E = cuddBddPermuteRecur(manager,table,cuddE(N),permut);
  942. if (E == NULL) {
  943. Cudd_IterDerefBdd(manager, T);
  944. return(NULL);
  945. }
  946. cuddRef(E);
  947. /* Move variable that should be in this position to this position
  948. ** by retrieving the single var BDD for that variable, and calling
  949. ** cuddBddIteRecur with the T and E we just created.
  950. */
  951. index = permut[N->index];
  952. res = cuddBddIteRecur(manager,manager->vars[index],T,E);
  953. if (res == NULL) {
  954. Cudd_IterDerefBdd(manager, T);
  955. Cudd_IterDerefBdd(manager, E);
  956. return(NULL);
  957. }
  958. cuddRef(res);
  959. Cudd_IterDerefBdd(manager, T);
  960. Cudd_IterDerefBdd(manager, E);
  961. /* Do not keep the result if the reference count is only 1, since
  962. ** it will not be visited again.
  963. */
  964. if (N->ref != 1) {
  965. ptrint fanout = (ptrint) N->ref;
  966. cuddSatDec(fanout);
  967. if (!cuddHashTableInsert1(table,N,res,fanout)) {
  968. Cudd_IterDerefBdd(manager, res);
  969. return(NULL);
  970. }
  971. }
  972. cuddDeref(res);
  973. return(Cudd_NotCond(res,N != node));
  974. } /* end of cuddBddPermuteRecur */
  975. /**Function********************************************************************
  976. Synopsis [Implements the recursive step of Cudd_bddVarMap.]
  977. Description [Implements the recursive step of Cudd_bddVarMap.
  978. Returns a pointer to the result if successful; NULL otherwise.]
  979. SideEffects [None]
  980. SeeAlso [Cudd_bddVarMap]
  981. ******************************************************************************/
  982. static DdNode *
  983. cuddBddVarMapRecur(
  984. DdManager *manager /* DD manager */,
  985. DdNode *f /* BDD to be remapped */)
  986. {
  987. DdNode *F, *T, *E;
  988. DdNode *res;
  989. int index;
  990. statLine(manager);
  991. F = Cudd_Regular(f);
  992. /* Check for terminal case of constant node. */
  993. if (cuddIsConstant(F)) {
  994. return(f);
  995. }
  996. /* If problem already solved, look up answer and return. */
  997. if (F->ref != 1 &&
  998. (res = cuddCacheLookup1(manager,Cudd_bddVarMap,F)) != NULL) {
  999. return(Cudd_NotCond(res,F != f));
  1000. }
  1001. /* Split and recur on children of this node. */
  1002. T = cuddBddVarMapRecur(manager,cuddT(F));
  1003. if (T == NULL) return(NULL);
  1004. cuddRef(T);
  1005. E = cuddBddVarMapRecur(manager,cuddE(F));
  1006. if (E == NULL) {
  1007. Cudd_IterDerefBdd(manager, T);
  1008. return(NULL);
  1009. }
  1010. cuddRef(E);
  1011. /* Move variable that should be in this position to this position
  1012. ** by retrieving the single var BDD for that variable, and calling
  1013. ** cuddBddIteRecur with the T and E we just created.
  1014. */
  1015. index = manager->map[F->index];
  1016. res = cuddBddIteRecur(manager,manager->vars[index],T,E);
  1017. if (res == NULL) {
  1018. Cudd_IterDerefBdd(manager, T);
  1019. Cudd_IterDerefBdd(manager, E);
  1020. return(NULL);
  1021. }
  1022. cuddRef(res);
  1023. Cudd_IterDerefBdd(manager, T);
  1024. Cudd_IterDerefBdd(manager, E);
  1025. /* Do not keep the result if the reference count is only 1, since
  1026. ** it will not be visited again.
  1027. */
  1028. if (F->ref != 1) {
  1029. cuddCacheInsert1(manager,Cudd_bddVarMap,F,res);
  1030. }
  1031. cuddDeref(res);
  1032. return(Cudd_NotCond(res,F != f));
  1033. } /* end of cuddBddVarMapRecur */
  1034. /**Function********************************************************************
  1035. Synopsis [Performs the recursive step of Cudd_addVectorCompose.]
  1036. Description []
  1037. SideEffects [None]
  1038. SeeAlso []
  1039. ******************************************************************************/
  1040. static DdNode *
  1041. cuddAddVectorComposeRecur(
  1042. DdManager * dd /* DD manager */,
  1043. DdHashTable * table /* computed table */,
  1044. DdNode * f /* ADD in which to compose */,
  1045. DdNode ** vector /* functions to substitute */,
  1046. int deepest /* depth of deepest substitution */)
  1047. {
  1048. DdNode *T,*E;
  1049. DdNode *res;
  1050. statLine(dd);
  1051. /* If we are past the deepest substitution, return f. */
  1052. if (cuddI(dd,f->index) > deepest) {
  1053. return(f);
  1054. }
  1055. if ((res = cuddHashTableLookup1(table,f)) != NULL) {
  1056. #ifdef DD_DEBUG
  1057. addVectorComposeHits++;
  1058. #endif
  1059. return(res);
  1060. }
  1061. /* Split and recur on children of this node. */
  1062. T = cuddAddVectorComposeRecur(dd,table,cuddT(f),vector,deepest);
  1063. if (T == NULL) return(NULL);
  1064. cuddRef(T);
  1065. E = cuddAddVectorComposeRecur(dd,table,cuddE(f),vector,deepest);
  1066. if (E == NULL) {
  1067. Cudd_RecursiveDeref(dd, T);
  1068. return(NULL);
  1069. }
  1070. cuddRef(E);
  1071. /* Retrieve the 0-1 ADD for the current top variable and call
  1072. ** cuddAddIteRecur with the T and E we just created.
  1073. */
  1074. res = cuddAddIteRecur(dd,vector[f->index],T,E);
  1075. if (res == NULL) {
  1076. Cudd_RecursiveDeref(dd, T);
  1077. Cudd_RecursiveDeref(dd, E);
  1078. return(NULL);
  1079. }
  1080. cuddRef(res);
  1081. Cudd_RecursiveDeref(dd, T);
  1082. Cudd_RecursiveDeref(dd, E);
  1083. /* Do not keep the result if the reference count is only 1, since
  1084. ** it will not be visited again
  1085. */
  1086. if (f->ref != 1) {
  1087. ptrint fanout = (ptrint) f->ref;
  1088. cuddSatDec(fanout);
  1089. if (!cuddHashTableInsert1(table,f,res,fanout)) {
  1090. Cudd_RecursiveDeref(dd, res);
  1091. return(NULL);
  1092. }
  1093. }
  1094. cuddDeref(res);
  1095. return(res);
  1096. } /* end of cuddAddVectorComposeRecur */
  1097. /**Function********************************************************************
  1098. Synopsis [Performs the recursive step of Cudd_addGeneralVectorCompose.]
  1099. Description []
  1100. SideEffects [None]
  1101. SeeAlso []
  1102. ******************************************************************************/
  1103. static DdNode *
  1104. cuddAddGeneralVectorComposeRecur(
  1105. DdManager * dd /* DD manager */,
  1106. DdHashTable * table /* computed table */,
  1107. DdNode * f /* ADD in which to compose */,
  1108. DdNode ** vectorOn /* functions to substitute for x_i */,
  1109. DdNode ** vectorOff /* functions to substitute for x_i' */,
  1110. int deepest /* depth of deepest substitution */)
  1111. {
  1112. DdNode *T,*E,*t,*e;
  1113. DdNode *res;
  1114. /* If we are past the deepest substitution, return f. */
  1115. if (cuddI(dd,f->index) > deepest) {
  1116. return(f);
  1117. }
  1118. if ((res = cuddHashTableLookup1(table,f)) != NULL) {
  1119. #ifdef DD_DEBUG
  1120. addGeneralVectorComposeHits++;
  1121. #endif
  1122. return(res);
  1123. }
  1124. /* Split and recur on children of this node. */
  1125. T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f),
  1126. vectorOn,vectorOff,deepest);
  1127. if (T == NULL) return(NULL);
  1128. cuddRef(T);
  1129. E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f),
  1130. vectorOn,vectorOff,deepest);
  1131. if (E == NULL) {
  1132. Cudd_RecursiveDeref(dd, T);
  1133. return(NULL);
  1134. }
  1135. cuddRef(E);
  1136. /* Retrieve the compose ADDs for the current top variable and call
  1137. ** cuddAddApplyRecur with the T and E we just created.
  1138. */
  1139. t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T);
  1140. if (t == NULL) {
  1141. Cudd_RecursiveDeref(dd,T);
  1142. Cudd_RecursiveDeref(dd,E);
  1143. return(NULL);
  1144. }
  1145. cuddRef(t);
  1146. e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E);
  1147. if (e == NULL) {
  1148. Cudd_RecursiveDeref(dd,T);
  1149. Cudd_RecursiveDeref(dd,E);
  1150. Cudd_RecursiveDeref(dd,t);
  1151. return(NULL);
  1152. }
  1153. cuddRef(e);
  1154. res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
  1155. if (res == NULL) {
  1156. Cudd_RecursiveDeref(dd,T);
  1157. Cudd_RecursiveDeref(dd,E);
  1158. Cudd_RecursiveDeref(dd,t);
  1159. Cudd_RecursiveDeref(dd,e);
  1160. return(NULL);
  1161. }
  1162. cuddRef(res);
  1163. Cudd_RecursiveDeref(dd,T);
  1164. Cudd_RecursiveDeref(dd,E);
  1165. Cudd_RecursiveDeref(dd,t);
  1166. Cudd_RecursiveDeref(dd,e);
  1167. /* Do not keep the result if the reference count is only 1, since
  1168. ** it will not be visited again
  1169. */
  1170. if (f->ref != 1) {
  1171. ptrint fanout = (ptrint) f->ref;
  1172. cuddSatDec(fanout);
  1173. if (!cuddHashTableInsert1(table,f,res,fanout)) {
  1174. Cudd_RecursiveDeref(dd, res);
  1175. return(NULL);
  1176. }
  1177. }
  1178. cuddDeref(res);
  1179. return(res);
  1180. } /* end of cuddAddGeneralVectorComposeRecur */
  1181. /**Function********************************************************************
  1182. Synopsis [Performs the recursive step of Cudd_addNonSimCompose.]
  1183. Description []
  1184. SideEffects [None]
  1185. SeeAlso []
  1186. ******************************************************************************/
  1187. static DdNode *
  1188. cuddAddNonSimComposeRecur(
  1189. DdManager * dd,
  1190. DdNode * f,
  1191. DdNode ** vector,
  1192. DdNode * key,
  1193. DdNode * cube,
  1194. int lastsub)
  1195. {
  1196. DdNode *f1, *f0, *key1, *key0, *cube1, *var;
  1197. DdNode *T,*E;
  1198. DdNode *r;
  1199. unsigned int top, topf, topk, topc;
  1200. unsigned int index;
  1201. int i;
  1202. DdNode **vect1;
  1203. DdNode **vect0;
  1204. statLine(dd);
  1205. /* If we are past the deepest substitution, return f. */
  1206. if (cube == DD_ONE(dd) || cuddIsConstant(f)) {
  1207. return(f);
  1208. }
  1209. /* If problem already solved, look up answer and return. */
  1210. r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube);
  1211. if (r != NULL) {
  1212. return(r);
  1213. }
  1214. /* Find top variable. we just need to look at f, key, and cube,
  1215. ** because all the varibles in the gi are in key.
  1216. */
  1217. topf = cuddI(dd,f->index);
  1218. topk = cuddI(dd,key->index);
  1219. top = ddMin(topf,topk);
  1220. topc = cuddI(dd,cube->index);
  1221. top = ddMin(top,topc);
  1222. index = dd->invperm[top];
  1223. /* Compute the cofactors. */
  1224. if (topf == top) {
  1225. f1 = cuddT(f);
  1226. f0 = cuddE(f);
  1227. } else {
  1228. f1 = f0 = f;
  1229. }
  1230. if (topc == top) {
  1231. cube1 = cuddT(cube);
  1232. /* We want to eliminate vector[index] from key. Otherwise
  1233. ** cache performance is severely affected. Hence we
  1234. ** existentially quantify the variable with index "index" from key.
  1235. */
  1236. var = Cudd_addIthVar(dd, (int) index);
  1237. if (var == NULL) {
  1238. return(NULL);
  1239. }
  1240. cuddRef(var);
  1241. key1 = cuddAddExistAbstractRecur(dd, key, var);
  1242. if (key1 == NULL) {
  1243. Cudd_RecursiveDeref(dd,var);
  1244. return(NULL);
  1245. }
  1246. cuddRef(key1);
  1247. Cudd_RecursiveDeref(dd,var);
  1248. key0 = key1;
  1249. } else {
  1250. cube1 = cube;
  1251. if (topk == top) {
  1252. key1 = cuddT(key);
  1253. key0 = cuddE(key);
  1254. } else {
  1255. key1 = key0 = key;
  1256. }
  1257. cuddRef(key1);
  1258. }
  1259. /* Allocate two new vectors for the cofactors of vector. */
  1260. vect1 = ALLOC(DdNode *,lastsub);
  1261. if (vect1 == NULL) {
  1262. dd->errorCode = CUDD_MEMORY_OUT;
  1263. Cudd_RecursiveDeref(dd,key1);
  1264. return(NULL);
  1265. }
  1266. vect0 = ALLOC(DdNode *,lastsub);
  1267. if (vect0 == NULL) {
  1268. dd->errorCode = CUDD_MEMORY_OUT;
  1269. Cudd_RecursiveDeref(dd,key1);
  1270. FREE(vect1);
  1271. return(NULL);
  1272. }
  1273. /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because
  1274. ** we do not need them.
  1275. */
  1276. for (i = 0; i < lastsub; i++) {
  1277. DdNode *gi = vector[i];
  1278. if (gi == NULL) {
  1279. vect1[i] = vect0[i] = NULL;
  1280. } else if (gi->index == index) {
  1281. vect1[i] = cuddT(gi);
  1282. vect0[i] = cuddE(gi);
  1283. } else {
  1284. vect1[i] = vect0[i] = gi;
  1285. }
  1286. }
  1287. vect1[index] = vect0[index] = NULL;
  1288. /* Recur on children. */
  1289. T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub);
  1290. FREE(vect1);
  1291. if (T == NULL) {
  1292. Cudd_RecursiveDeref(dd,key1);
  1293. FREE(vect0);
  1294. return(NULL);
  1295. }
  1296. cuddRef(T);
  1297. E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub);
  1298. FREE(vect0);
  1299. if (E == NULL) {
  1300. Cudd_RecursiveDeref(dd,key1);
  1301. Cudd_RecursiveDeref(dd,T);
  1302. return(NULL);
  1303. }
  1304. cuddRef(E);
  1305. Cudd_RecursiveDeref(dd,key1);
  1306. /* Retrieve the 0-1 ADD for the current top variable from vector,
  1307. ** and call cuddAddIteRecur with the T and E we just created.
  1308. */
  1309. r = cuddAddIteRecur(dd,vector[index],T,E);
  1310. if (r == NULL) {
  1311. Cudd_RecursiveDeref(dd,T);
  1312. Cudd_RecursiveDeref(dd,E);
  1313. return(NULL);
  1314. }
  1315. cuddRef(r);
  1316. Cudd_RecursiveDeref(dd,T);
  1317. Cudd_RecursiveDeref(dd,E);
  1318. cuddDeref(r);
  1319. /* Store answer to trim recursion. */
  1320. cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r);
  1321. return(r);
  1322. } /* end of cuddAddNonSimComposeRecur */
  1323. /**Function********************************************************************
  1324. Synopsis [Performs the recursive step of Cudd_bddVectorCompose.]
  1325. Description []
  1326. SideEffects [None]
  1327. SeeAlso []
  1328. ******************************************************************************/
  1329. static DdNode *
  1330. cuddBddVectorComposeRecur(
  1331. DdManager * dd /* DD manager */,
  1332. DdHashTable * table /* computed table */,
  1333. DdNode * f /* BDD in which to compose */,
  1334. DdNode ** vector /* functions to be composed */,
  1335. int deepest /* depth of the deepest substitution */)
  1336. {
  1337. DdNode *F,*T,*E;
  1338. DdNode *res;
  1339. statLine(dd);
  1340. F = Cudd_Regular(f);
  1341. /* If we are past the deepest substitution, return f. */
  1342. if (cuddI(dd,F->index) > deepest) {
  1343. return(f);
  1344. }
  1345. /* If problem already solved, look up answer and return. */
  1346. if ((res = cuddHashTableLookup1(table,F)) != NULL) {
  1347. #ifdef DD_DEBUG
  1348. bddVectorComposeHits++;
  1349. #endif
  1350. return(Cudd_NotCond(res,F != f));
  1351. }
  1352. /* Split and recur on children of this node. */
  1353. T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest);
  1354. if (T == NULL) return(NULL);
  1355. cuddRef(T);
  1356. E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest);
  1357. if (E == NULL) {
  1358. Cudd_IterDerefBdd(dd, T);
  1359. return(NULL);
  1360. }
  1361. cuddRef(E);
  1362. /* Call cuddBddIteRecur with the BDD that replaces the current top
  1363. ** variable and the T and E we just created.
  1364. */
  1365. res = cuddBddIteRecur(dd,vector[F->index],T,E);
  1366. if (res == NULL) {
  1367. Cudd_IterDerefBdd(dd, T);
  1368. Cudd_IterDerefBdd(dd, E);
  1369. return(NULL);
  1370. }
  1371. cuddRef(res);
  1372. Cudd_IterDerefBdd(dd, T);
  1373. Cudd_IterDerefBdd(dd, E);
  1374. /* Do not keep the result if the reference count is only 1, since
  1375. ** it will not be visited again.
  1376. */
  1377. if (F->ref != 1) {
  1378. ptrint fanout = (ptrint) F->ref;
  1379. cuddSatDec(fanout);
  1380. if (!cuddHashTableInsert1(table,F,res,fanout)) {
  1381. Cudd_IterDerefBdd(dd, res);
  1382. return(NULL);
  1383. }
  1384. }
  1385. cuddDeref(res);
  1386. return(Cudd_NotCond(res,F != f));
  1387. } /* end of cuddBddVectorComposeRecur */
  1388. /**Function********************************************************************
  1389. Synopsis [Comparison of a function to the i-th ADD variable.]
  1390. Description [Comparison of a function to the i-th ADD variable. Returns 1 if
  1391. the function is the i-th ADD variable; 0 otherwise.]
  1392. SideEffects [None]
  1393. SeeAlso []
  1394. ******************************************************************************/
  1395. DD_INLINE
  1396. static int
  1397. ddIsIthAddVar(
  1398. DdManager * dd,
  1399. DdNode * f,
  1400. unsigned int i)
  1401. {
  1402. return(f->index == i && cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd));
  1403. } /* end of ddIsIthAddVar */
  1404. /**Function********************************************************************
  1405. Synopsis [Comparison of a pair of functions to the i-th ADD variable.]
  1406. Description [Comparison of a pair of functions to the i-th ADD
  1407. variable. Returns 1 if the functions are the i-th ADD variable and its
  1408. complement; 0 otherwise.]
  1409. SideEffects [None]
  1410. SeeAlso []
  1411. ******************************************************************************/
  1412. DD_INLINE
  1413. static int
  1414. ddIsIthAddVarPair(
  1415. DdManager * dd,
  1416. DdNode * f,
  1417. DdNode * g,
  1418. unsigned int i)
  1419. {
  1420. return(f->index == i && g->index == i &&
  1421. cuddT(f) == DD_ONE(dd) && cuddE(f) == DD_ZERO(dd) &&
  1422. cuddT(g) == DD_ZERO(dd) && cuddE(g) == DD_ONE(dd));
  1423. } /* end of ddIsIthAddVarPair */