emergency commit
[cl-cudd.git] / distr / cudd / cuddUtil.c
blobf662f48314ef428cc263958a35b06e5b0b5b5c72
1 /**CFile***********************************************************************
3 FileName [cuddUtil.c]
5 PackageName [cudd]
7 Synopsis [Utility functions.]
9 Description [External procedures included in this module:
10 <ul>
11 <li> Cudd_PrintMinterm()
12 <li> Cudd_bddPrintCover()
13 <li> Cudd_PrintDebug()
14 <li> Cudd_DagSize()
15 <li> Cudd_EstimateCofactor()
16 <li> Cudd_EstimateCofactorSimple()
17 <li> Cudd_SharingSize()
18 <li> Cudd_CountMinterm()
19 <li> Cudd_EpdCountMinterm()
20 <li> Cudd_CountPath()
21 <li> Cudd_CountPathsToNonZero()
22 <li> Cudd_Support()
23 <li> Cudd_SupportIndex()
24 <li> Cudd_SupportSize()
25 <li> Cudd_VectorSupport()
26 <li> Cudd_VectorSupportIndex()
27 <li> Cudd_VectorSupportSize()
28 <li> Cudd_ClassifySupport()
29 <li> Cudd_CountLeaves()
30 <li> Cudd_bddPickOneCube()
31 <li> Cudd_bddPickOneMinterm()
32 <li> Cudd_bddPickArbitraryMinterms()
33 <li> Cudd_SubsetWithMaskVars()
34 <li> Cudd_FirstCube()
35 <li> Cudd_NextCube()
36 <li> Cudd_bddComputeCube()
37 <li> Cudd_addComputeCube()
38 <li> Cudd_FirstNode()
39 <li> Cudd_NextNode()
40 <li> Cudd_GenFree()
41 <li> Cudd_IsGenEmpty()
42 <li> Cudd_IndicesToCube()
43 <li> Cudd_PrintVersion()
44 <li> Cudd_AverageDistance()
45 <li> Cudd_Random()
46 <li> Cudd_Srandom()
47 <li> Cudd_Density()
48 </ul>
49 Internal procedures included in this module:
50 <ul>
51 <li> cuddP()
52 <li> cuddStCountfree()
53 <li> cuddCollectNodes()
54 <li> cuddNodeArray()
55 </ul>
56 Static procedures included in this module:
57 <ul>
58 <li> dp2()
59 <li> ddPrintMintermAux()
60 <li> ddDagInt()
61 <li> ddCountMintermAux()
62 <li> ddEpdCountMintermAux()
63 <li> ddCountPathAux()
64 <li> ddSupportStep()
65 <li> ddClearFlag()
66 <li> ddLeavesInt()
67 <li> ddPickArbitraryMinterms()
68 <li> ddPickRepresentativeCube()
69 <li> ddEpdFree()
70 </ul>]
72 Author [Fabio Somenzi]
74 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
76 All rights reserved.
78 Redistribution and use in source and binary forms, with or without
79 modification, are permitted provided that the following conditions
80 are met:
82 Redistributions of source code must retain the above copyright
83 notice, this list of conditions and the following disclaimer.
85 Redistributions in binary form must reproduce the above copyright
86 notice, this list of conditions and the following disclaimer in the
87 documentation and/or other materials provided with the distribution.
89 Neither the name of the University of Colorado nor the names of its
90 contributors may be used to endorse or promote products derived from
91 this software without specific prior written permission.
93 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
94 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
95 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
96 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
97 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
98 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
99 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
100 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
101 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
102 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
103 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
104 POSSIBILITY OF SUCH DAMAGE.]
106 ******************************************************************************/
108 #include "util.h"
109 #include "cuddInt.h"
111 /*---------------------------------------------------------------------------*/
112 /* Constant declarations */
113 /*---------------------------------------------------------------------------*/
115 /* Random generator constants. */
116 #define MODULUS1 2147483563
117 #define LEQA1 40014
118 #define LEQQ1 53668
119 #define LEQR1 12211
120 #define MODULUS2 2147483399
121 #define LEQA2 40692
122 #define LEQQ2 52774
123 #define LEQR2 3791
124 #define STAB_SIZE 64
125 #define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
127 /*---------------------------------------------------------------------------*/
128 /* Stucture declarations */
129 /*---------------------------------------------------------------------------*/
131 /*---------------------------------------------------------------------------*/
132 /* Type declarations */
133 /*---------------------------------------------------------------------------*/
136 /*---------------------------------------------------------------------------*/
137 /* Variable declarations */
138 /*---------------------------------------------------------------------------*/
140 #ifndef lint
141 static char rcsid[] DD_UNUSED = "$Id: cuddUtil.c,v 1.81 2009/03/08 02:49:02 fabio Exp $";
142 #endif
144 static DdNode *background, *zero;
146 static long cuddRand = 0;
147 static long cuddRand2;
148 static long shuffleSelect;
149 static long shuffleTable[STAB_SIZE];
151 /*---------------------------------------------------------------------------*/
152 /* Macro declarations */
153 /*---------------------------------------------------------------------------*/
155 #define bang(f) ((Cudd_IsComplement(f)) ? '!' : ' ')
157 #ifdef __cplusplus
158 extern "C" {
159 #endif
161 /**AutomaticStart*************************************************************/
163 /*---------------------------------------------------------------------------*/
164 /* Static function prototypes */
165 /*---------------------------------------------------------------------------*/
167 static int dp2 (DdManager *dd, DdNode *f, st_table *t);
168 static void ddPrintMintermAux (DdManager *dd, DdNode *node, int *list);
169 static int ddDagInt (DdNode *n);
170 static int cuddNodeArrayRecur (DdNode *f, DdNodePtr *table, int index);
171 static int cuddEstimateCofactor (DdManager *dd, st_table *table, DdNode * node, int i, int phase, DdNode ** ptr);
172 static DdNode * cuddUniqueLookup (DdManager * unique, int index, DdNode * T, DdNode * E);
173 static int cuddEstimateCofactorSimple (DdNode * node, int i);
174 static double ddCountMintermAux (DdNode *node, double max, DdHashTable *table);
175 static int ddEpdCountMintermAux (DdNode *node, EpDouble *max, EpDouble *epd, st_table *table);
176 static double ddCountPathAux (DdNode *node, st_table *table);
177 static double ddCountPathsToNonZero (DdNode * N, st_table * table);
178 static void ddSupportStep (DdNode *f, int *support);
179 static void ddClearFlag (DdNode *f);
180 static int ddLeavesInt (DdNode *n);
181 static int ddPickArbitraryMinterms (DdManager *dd, DdNode *node, int nvars, int nminterms, char **string);
182 static int ddPickRepresentativeCube (DdManager *dd, DdNode *node, double *weight, char *string);
183 static enum st_retval ddEpdFree (char * key, char * value, char * arg);
185 /**AutomaticEnd***************************************************************/
187 #ifdef __cplusplus
189 #endif
191 /*---------------------------------------------------------------------------*/
192 /* Definition of exported functions */
193 /*---------------------------------------------------------------------------*/
196 /**Function********************************************************************
198 Synopsis [Prints a disjoint sum of products.]
200 Description [Prints a disjoint sum of product cover for the function
201 rooted at node. Each product corresponds to a path from node to a
202 leaf node different from the logical zero, and different from the
203 background value. Uses the package default output file. Returns 1
204 if successful; 0 otherwise.]
206 SideEffects [None]
208 SeeAlso [Cudd_PrintDebug Cudd_bddPrintCover]
210 ******************************************************************************/
212 Cudd_PrintMinterm(
213 DdManager * manager,
214 DdNode * node)
216 int i, *list;
218 background = manager->background;
219 zero = Cudd_Not(manager->one);
220 list = ALLOC(int,manager->size);
221 if (list == NULL) {
222 manager->errorCode = CUDD_MEMORY_OUT;
223 return(0);
225 for (i = 0; i < manager->size; i++) list[i] = 2;
226 ddPrintMintermAux(manager,node,list);
227 FREE(list);
228 return(1);
230 } /* end of Cudd_PrintMinterm */
233 /**Function********************************************************************
235 Synopsis [Prints a sum of prime implicants of a BDD.]
237 Description [Prints a sum of product cover for an incompletely
238 specified function given by a lower bound and an upper bound. Each
239 product is a prime implicant obtained by expanding the product
240 corresponding to a path from node to the constant one. Uses the
241 package default output file. Returns 1 if successful; 0 otherwise.]
243 SideEffects [None]
245 SeeAlso [Cudd_PrintMinterm]
247 ******************************************************************************/
249 Cudd_bddPrintCover(
250 DdManager *dd,
251 DdNode *l,
252 DdNode *u)
254 int *array;
255 int q, result;
256 DdNode *lb;
257 #ifdef DD_DEBUG
258 DdNode *cover;
259 #endif
261 array = ALLOC(int, Cudd_ReadSize(dd));
262 if (array == NULL) return(0);
263 lb = l;
264 cuddRef(lb);
265 #ifdef DD_DEBUG
266 cover = Cudd_ReadLogicZero(dd);
267 cuddRef(cover);
268 #endif
269 while (lb != Cudd_ReadLogicZero(dd)) {
270 DdNode *implicant, *prime, *tmp;
271 int length;
272 implicant = Cudd_LargestCube(dd,lb,&length);
273 if (implicant == NULL) {
274 Cudd_RecursiveDeref(dd,lb);
275 FREE(array);
276 return(0);
278 cuddRef(implicant);
279 prime = Cudd_bddMakePrime(dd,implicant,u);
280 if (prime == NULL) {
281 Cudd_RecursiveDeref(dd,lb);
282 Cudd_RecursiveDeref(dd,implicant);
283 FREE(array);
284 return(0);
286 cuddRef(prime);
287 Cudd_RecursiveDeref(dd,implicant);
288 tmp = Cudd_bddAnd(dd,lb,Cudd_Not(prime));
289 if (tmp == NULL) {
290 Cudd_RecursiveDeref(dd,lb);
291 Cudd_RecursiveDeref(dd,prime);
292 FREE(array);
293 return(0);
295 cuddRef(tmp);
296 Cudd_RecursiveDeref(dd,lb);
297 lb = tmp;
298 result = Cudd_BddToCubeArray(dd,prime,array);
299 if (result == 0) {
300 Cudd_RecursiveDeref(dd,lb);
301 Cudd_RecursiveDeref(dd,prime);
302 FREE(array);
303 return(0);
305 for (q = 0; q < dd->size; q++) {
306 switch (array[q]) {
307 case 0:
308 (void) fprintf(dd->out, "0");
309 break;
310 case 1:
311 (void) fprintf(dd->out, "1");
312 break;
313 case 2:
314 (void) fprintf(dd->out, "-");
315 break;
316 default:
317 (void) fprintf(dd->out, "?");
320 (void) fprintf(dd->out, " 1\n");
321 #ifdef DD_DEBUG
322 tmp = Cudd_bddOr(dd,prime,cover);
323 if (tmp == NULL) {
324 Cudd_RecursiveDeref(dd,cover);
325 Cudd_RecursiveDeref(dd,lb);
326 Cudd_RecursiveDeref(dd,prime);
327 FREE(array);
328 return(0);
330 cuddRef(tmp);
331 Cudd_RecursiveDeref(dd,cover);
332 cover = tmp;
333 #endif
334 Cudd_RecursiveDeref(dd,prime);
336 (void) fprintf(dd->out, "\n");
337 Cudd_RecursiveDeref(dd,lb);
338 FREE(array);
339 #ifdef DD_DEBUG
340 if (!Cudd_bddLeq(dd,cover,u) || !Cudd_bddLeq(dd,l,cover)) {
341 Cudd_RecursiveDeref(dd,cover);
342 return(0);
344 Cudd_RecursiveDeref(dd,cover);
345 #endif
346 return(1);
348 } /* end of Cudd_bddPrintCover */
351 /**Function********************************************************************
353 Synopsis [Prints to the standard output a DD and its statistics.]
355 Description [Prints to the standard output a DD and its statistics.
356 The statistics include the number of nodes, the number of leaves, and
357 the number of minterms. (The number of minterms is the number of
358 assignments to the variables that cause the function to be different
359 from the logical zero (for BDDs) and from the background value (for
360 ADDs.) The statistics are printed if pr &gt; 0. Specifically:
361 <ul>
362 <li> pr = 0 : prints nothing
363 <li> pr = 1 : prints counts of nodes and minterms
364 <li> pr = 2 : prints counts + disjoint sum of product
365 <li> pr = 3 : prints counts + list of nodes
366 <li> pr &gt; 3 : prints counts + disjoint sum of product + list of nodes
367 </ul>
368 For the purpose of counting the number of minterms, the function is
369 supposed to depend on n variables. Returns 1 if successful; 0 otherwise.]
371 SideEffects [None]
373 SeeAlso [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm
374 Cudd_PrintMinterm]
376 ******************************************************************************/
378 Cudd_PrintDebug(
379 DdManager * dd,
380 DdNode * f,
381 int n,
382 int pr)
384 DdNode *azero, *bzero;
385 int nodes;
386 int leaves;
387 double minterms;
388 int retval = 1;
390 if (f == NULL) {
391 (void) fprintf(dd->out,": is the NULL DD\n");
392 (void) fflush(dd->out);
393 return(0);
395 azero = DD_ZERO(dd);
396 bzero = Cudd_Not(DD_ONE(dd));
397 if ((f == azero || f == bzero) && pr > 0){
398 (void) fprintf(dd->out,": is the zero DD\n");
399 (void) fflush(dd->out);
400 return(1);
402 if (pr > 0) {
403 nodes = Cudd_DagSize(f);
404 if (nodes == CUDD_OUT_OF_MEM) retval = 0;
405 leaves = Cudd_CountLeaves(f);
406 if (leaves == CUDD_OUT_OF_MEM) retval = 0;
407 minterms = Cudd_CountMinterm(dd, f, n);
408 if (minterms == (double)CUDD_OUT_OF_MEM) retval = 0;
409 (void) fprintf(dd->out,": %d nodes %d leaves %g minterms\n",
410 nodes, leaves, minterms);
411 if (pr > 2) {
412 if (!cuddP(dd, f)) retval = 0;
414 if (pr == 2 || pr > 3) {
415 if (!Cudd_PrintMinterm(dd,f)) retval = 0;
416 (void) fprintf(dd->out,"\n");
418 (void) fflush(dd->out);
420 return(retval);
422 } /* end of Cudd_PrintDebug */
425 /**Function********************************************************************
427 Synopsis [Counts the number of nodes in a DD.]
429 Description [Counts the number of nodes in a DD. Returns the number
430 of nodes in the graph rooted at node.]
432 SideEffects [None]
434 SeeAlso [Cudd_SharingSize Cudd_PrintDebug]
436 ******************************************************************************/
438 Cudd_DagSize(
439 DdNode * node)
441 int i;
443 i = ddDagInt(Cudd_Regular(node));
444 ddClearFlag(Cudd_Regular(node));
446 return(i);
448 } /* end of Cudd_DagSize */
451 /**Function********************************************************************
453 Synopsis [Estimates the number of nodes in a cofactor of a DD.]
455 Description [Estimates the number of nodes in a cofactor of a DD.
456 Returns an estimate of the number of nodes in a cofactor of
457 the graph rooted at node with respect to the variable whose index is i.
458 In case of failure, returns CUDD_OUT_OF_MEM.
459 This function uses a refinement of the algorithm of Cabodi et al.
460 (ICCAD96). The refinement allows the procedure to account for part
461 of the recombination that may occur in the part of the cofactor above
462 the cofactoring variable. This procedure does no create any new node.
463 It does keep a small table of results; therefore it may run out of memory.
464 If this is a concern, one should use Cudd_EstimateCofactorSimple, which
465 is faster, does not allocate any memory, but is less accurate.]
467 SideEffects [None]
469 SeeAlso [Cudd_DagSize Cudd_EstimateCofactorSimple]
471 ******************************************************************************/
473 Cudd_EstimateCofactor(
474 DdManager *dd /* manager */,
475 DdNode * f /* function */,
476 int i /* index of variable */,
477 int phase /* 1: positive; 0: negative */
480 int val;
481 DdNode *ptr;
482 st_table *table;
484 table = st_init_table(st_ptrcmp,st_ptrhash);
485 if (table == NULL) return(CUDD_OUT_OF_MEM);
486 val = cuddEstimateCofactor(dd,table,Cudd_Regular(f),i,phase,&ptr);
487 ddClearFlag(Cudd_Regular(f));
488 st_free_table(table);
490 return(val);
492 } /* end of Cudd_EstimateCofactor */
495 /**Function********************************************************************
497 Synopsis [Estimates the number of nodes in a cofactor of a DD.]
499 Description [Estimates the number of nodes in a cofactor of a DD.
500 Returns an estimate of the number of nodes in the positive cofactor of
501 the graph rooted at node with respect to the variable whose index is i.
502 This procedure implements with minor changes the algorithm of Cabodi et al.
503 (ICCAD96). It does not allocate any memory, it does not change the
504 state of the manager, and it is fast. However, it has been observed to
505 overestimate the size of the cofactor by as much as a factor of 2.]
507 SideEffects [None]
509 SeeAlso [Cudd_DagSize]
511 ******************************************************************************/
513 Cudd_EstimateCofactorSimple(
514 DdNode * node,
515 int i)
517 int val;
519 val = cuddEstimateCofactorSimple(Cudd_Regular(node),i);
520 ddClearFlag(Cudd_Regular(node));
522 return(val);
524 } /* end of Cudd_EstimateCofactorSimple */
527 /**Function********************************************************************
529 Synopsis [Counts the number of nodes in an array of DDs.]
531 Description [Counts the number of nodes in an array of DDs. Shared
532 nodes are counted only once. Returns the total number of nodes.]
534 SideEffects [None]
536 SeeAlso [Cudd_DagSize]
538 ******************************************************************************/
540 Cudd_SharingSize(
541 DdNode ** nodeArray,
542 int n)
544 int i,j;
546 i = 0;
547 for (j = 0; j < n; j++) {
548 i += ddDagInt(Cudd_Regular(nodeArray[j]));
550 for (j = 0; j < n; j++) {
551 ddClearFlag(Cudd_Regular(nodeArray[j]));
553 return(i);
555 } /* end of Cudd_SharingSize */
558 /**Function********************************************************************
560 Synopsis [Counts the number of minterms of a DD.]
562 Description [Counts the number of minterms of a DD. The function is
563 assumed to depend on nvars variables. The minterm count is
564 represented as a double, to allow for a larger number of variables.
565 Returns the number of minterms of the function rooted at node if
566 successful; (double) CUDD_OUT_OF_MEM otherwise.]
568 SideEffects [None]
570 SeeAlso [Cudd_PrintDebug Cudd_CountPath]
572 ******************************************************************************/
573 double
574 Cudd_CountMinterm(
575 DdManager * manager,
576 DdNode * node,
577 int nvars)
579 double max;
580 DdHashTable *table;
581 double res;
582 CUDD_VALUE_TYPE epsilon;
584 background = manager->background;
585 zero = Cudd_Not(manager->one);
587 max = pow(2.0,(double)nvars);
588 table = cuddHashTableInit(manager,1,2);
589 if (table == NULL) {
590 return((double)CUDD_OUT_OF_MEM);
592 epsilon = Cudd_ReadEpsilon(manager);
593 Cudd_SetEpsilon(manager,(CUDD_VALUE_TYPE)0.0);
594 res = ddCountMintermAux(node,max,table);
595 cuddHashTableQuit(table);
596 Cudd_SetEpsilon(manager,epsilon);
598 return(res);
600 } /* end of Cudd_CountMinterm */
603 /**Function********************************************************************
605 Synopsis [Counts the number of paths of a DD.]
607 Description [Counts the number of paths of a DD. Paths to all
608 terminal nodes are counted. The path count is represented as a
609 double, to allow for a larger number of variables. Returns the
610 number of paths of the function rooted at node if successful;
611 (double) CUDD_OUT_OF_MEM otherwise.]
613 SideEffects [None]
615 SeeAlso [Cudd_CountMinterm]
617 ******************************************************************************/
618 double
619 Cudd_CountPath(
620 DdNode * node)
623 st_table *table;
624 double i;
626 table = st_init_table(st_ptrcmp,st_ptrhash);
627 if (table == NULL) {
628 return((double)CUDD_OUT_OF_MEM);
630 i = ddCountPathAux(Cudd_Regular(node),table);
631 st_foreach(table, cuddStCountfree, NULL);
632 st_free_table(table);
633 return(i);
635 } /* end of Cudd_CountPath */
638 /**Function********************************************************************
640 Synopsis [Counts the number of minterms of a DD with extended precision.]
642 Description [Counts the number of minterms of a DD with extended precision.
643 The function is assumed to depend on nvars variables. The minterm count is
644 represented as an EpDouble, to allow any number of variables.
645 Returns 0 if successful; CUDD_OUT_OF_MEM otherwise.]
647 SideEffects [None]
649 SeeAlso [Cudd_PrintDebug Cudd_CountPath]
651 ******************************************************************************/
653 Cudd_EpdCountMinterm(
654 DdManager * manager,
655 DdNode * node,
656 int nvars,
657 EpDouble * epd)
659 EpDouble max, tmp;
660 st_table *table;
661 int status;
663 background = manager->background;
664 zero = Cudd_Not(manager->one);
666 EpdPow2(nvars, &max);
667 table = st_init_table(EpdCmp, st_ptrhash);
668 if (table == NULL) {
669 EpdMakeZero(epd, 0);
670 return(CUDD_OUT_OF_MEM);
672 status = ddEpdCountMintermAux(Cudd_Regular(node),&max,epd,table);
673 st_foreach(table, ddEpdFree, NULL);
674 st_free_table(table);
675 if (status == CUDD_OUT_OF_MEM) {
676 EpdMakeZero(epd, 0);
677 return(CUDD_OUT_OF_MEM);
679 if (Cudd_IsComplement(node)) {
680 EpdSubtract3(&max, epd, &tmp);
681 EpdCopy(&tmp, epd);
683 return(0);
685 } /* end of Cudd_EpdCountMinterm */
688 /**Function********************************************************************
690 Synopsis [Counts the number of paths to a non-zero terminal of a DD.]
692 Description [Counts the number of paths to a non-zero terminal of a
693 DD. The path count is
694 represented as a double, to allow for a larger number of variables.
695 Returns the number of paths of the function rooted at node.]
697 SideEffects [None]
699 SeeAlso [Cudd_CountMinterm Cudd_CountPath]
701 ******************************************************************************/
702 double
703 Cudd_CountPathsToNonZero(
704 DdNode * node)
707 st_table *table;
708 double i;
710 table = st_init_table(st_ptrcmp,st_ptrhash);
711 if (table == NULL) {
712 return((double)CUDD_OUT_OF_MEM);
714 i = ddCountPathsToNonZero(node,table);
715 st_foreach(table, cuddStCountfree, NULL);
716 st_free_table(table);
717 return(i);
719 } /* end of Cudd_CountPathsToNonZero */
722 /**Function********************************************************************
724 Synopsis [Finds the variables on which a DD depends.]
726 Description [Finds the variables on which a DD depends.
727 Returns a BDD consisting of the product of the variables if
728 successful; NULL otherwise.]
730 SideEffects [None]
732 SeeAlso [Cudd_VectorSupport Cudd_ClassifySupport]
734 ******************************************************************************/
735 DdNode *
736 Cudd_Support(
737 DdManager * dd /* manager */,
738 DdNode * f /* DD whose support is sought */)
740 int *support;
741 DdNode *res, *tmp, *var;
742 int i,j;
743 int size;
745 /* Allocate and initialize support array for ddSupportStep. */
746 size = ddMax(dd->size, dd->sizeZ);
747 support = ALLOC(int,size);
748 if (support == NULL) {
749 dd->errorCode = CUDD_MEMORY_OUT;
750 return(NULL);
752 for (i = 0; i < size; i++) {
753 support[i] = 0;
756 /* Compute support and clean up markers. */
757 ddSupportStep(Cudd_Regular(f),support);
758 ddClearFlag(Cudd_Regular(f));
760 /* Transform support from array to cube. */
761 do {
762 dd->reordered = 0;
763 res = DD_ONE(dd);
764 cuddRef(res);
765 for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
766 i = (j >= dd->size) ? j : dd->invperm[j];
767 if (support[i] == 1) {
768 /* The following call to cuddUniqueInter is guaranteed
769 ** not to trigger reordering because the node we look up
770 ** already exists. */
771 var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
772 cuddRef(var);
773 tmp = cuddBddAndRecur(dd,res,var);
774 if (tmp == NULL) {
775 Cudd_RecursiveDeref(dd,res);
776 Cudd_RecursiveDeref(dd,var);
777 res = NULL;
778 break;
780 cuddRef(tmp);
781 Cudd_RecursiveDeref(dd,res);
782 Cudd_RecursiveDeref(dd,var);
783 res = tmp;
786 } while (dd->reordered == 1);
788 FREE(support);
789 if (res != NULL) cuddDeref(res);
790 return(res);
792 } /* end of Cudd_Support */
795 /**Function********************************************************************
797 Synopsis [Finds the variables on which a DD depends.]
799 Description [Finds the variables on which a DD depends. Returns an
800 index array of the variables if successful; NULL otherwise. The
801 size of the array equals the number of variables in the manager.
802 Each entry of the array is 1 if the corresponding variable is in the
803 support of the DD and 0 otherwise.]
805 SideEffects [None]
807 SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
809 ******************************************************************************/
810 int *
811 Cudd_SupportIndex(
812 DdManager * dd /* manager */,
813 DdNode * f /* DD whose support is sought */)
815 int *support;
816 int i;
817 int size;
819 /* Allocate and initialize support array for ddSupportStep. */
820 size = ddMax(dd->size, dd->sizeZ);
821 support = ALLOC(int,size);
822 if (support == NULL) {
823 dd->errorCode = CUDD_MEMORY_OUT;
824 return(NULL);
826 for (i = 0; i < size; i++) {
827 support[i] = 0;
830 /* Compute support and clean up markers. */
831 ddSupportStep(Cudd_Regular(f),support);
832 ddClearFlag(Cudd_Regular(f));
834 return(support);
836 } /* end of Cudd_SupportIndex */
839 /**Function********************************************************************
841 Synopsis [Counts the variables on which a DD depends.]
843 Description [Counts the variables on which a DD depends.
844 Returns the number of the variables if successful; CUDD_OUT_OF_MEM
845 otherwise.]
847 SideEffects [None]
849 SeeAlso [Cudd_Support]
851 ******************************************************************************/
853 Cudd_SupportSize(
854 DdManager * dd /* manager */,
855 DdNode * f /* DD whose support size is sought */)
857 int *support;
858 int i;
859 int size;
860 int count;
862 /* Allocate and initialize support array for ddSupportStep. */
863 size = ddMax(dd->size, dd->sizeZ);
864 support = ALLOC(int,size);
865 if (support == NULL) {
866 dd->errorCode = CUDD_MEMORY_OUT;
867 return(CUDD_OUT_OF_MEM);
869 for (i = 0; i < size; i++) {
870 support[i] = 0;
873 /* Compute support and clean up markers. */
874 ddSupportStep(Cudd_Regular(f),support);
875 ddClearFlag(Cudd_Regular(f));
877 /* Count support variables. */
878 count = 0;
879 for (i = 0; i < size; i++) {
880 if (support[i] == 1) count++;
883 FREE(support);
884 return(count);
886 } /* end of Cudd_SupportSize */
889 /**Function********************************************************************
891 Synopsis [Finds the variables on which a set of DDs depends.]
893 Description [Finds the variables on which a set of DDs depends.
894 The set must contain either BDDs and ADDs, or ZDDs.
895 Returns a BDD consisting of the product of the variables if
896 successful; NULL otherwise.]
898 SideEffects [None]
900 SeeAlso [Cudd_Support Cudd_ClassifySupport]
902 ******************************************************************************/
903 DdNode *
904 Cudd_VectorSupport(
905 DdManager * dd /* manager */,
906 DdNode ** F /* array of DDs whose support is sought */,
907 int n /* size of the array */)
909 int *support;
910 DdNode *res, *tmp, *var;
911 int i,j;
912 int size;
914 /* Allocate and initialize support array for ddSupportStep. */
915 size = ddMax(dd->size, dd->sizeZ);
916 support = ALLOC(int,size);
917 if (support == NULL) {
918 dd->errorCode = CUDD_MEMORY_OUT;
919 return(NULL);
921 for (i = 0; i < size; i++) {
922 support[i] = 0;
925 /* Compute support and clean up markers. */
926 for (i = 0; i < n; i++) {
927 ddSupportStep(Cudd_Regular(F[i]),support);
929 for (i = 0; i < n; i++) {
930 ddClearFlag(Cudd_Regular(F[i]));
933 /* Transform support from array to cube. */
934 res = DD_ONE(dd);
935 cuddRef(res);
936 for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
937 i = (j >= dd->size) ? j : dd->invperm[j];
938 if (support[i] == 1) {
939 var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
940 cuddRef(var);
941 tmp = Cudd_bddAnd(dd,res,var);
942 if (tmp == NULL) {
943 Cudd_RecursiveDeref(dd,res);
944 Cudd_RecursiveDeref(dd,var);
945 FREE(support);
946 return(NULL);
948 cuddRef(tmp);
949 Cudd_RecursiveDeref(dd,res);
950 Cudd_RecursiveDeref(dd,var);
951 res = tmp;
955 FREE(support);
956 cuddDeref(res);
957 return(res);
959 } /* end of Cudd_VectorSupport */
962 /**Function********************************************************************
964 Synopsis [Finds the variables on which a set of DDs depends.]
966 Description [Finds the variables on which a set of DDs depends.
967 The set must contain either BDDs and ADDs, or ZDDs.
968 Returns an index array of the variables if successful; NULL otherwise.]
970 SideEffects [None]
972 SeeAlso [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport]
974 ******************************************************************************/
975 int *
976 Cudd_VectorSupportIndex(
977 DdManager * dd /* manager */,
978 DdNode ** F /* array of DDs whose support is sought */,
979 int n /* size of the array */)
981 int *support;
982 int i;
983 int size;
985 /* Allocate and initialize support array for ddSupportStep. */
986 size = ddMax(dd->size, dd->sizeZ);
987 support = ALLOC(int,size);
988 if (support == NULL) {
989 dd->errorCode = CUDD_MEMORY_OUT;
990 return(NULL);
992 for (i = 0; i < size; i++) {
993 support[i] = 0;
996 /* Compute support and clean up markers. */
997 for (i = 0; i < n; i++) {
998 ddSupportStep(Cudd_Regular(F[i]),support);
1000 for (i = 0; i < n; i++) {
1001 ddClearFlag(Cudd_Regular(F[i]));
1004 return(support);
1006 } /* end of Cudd_VectorSupportIndex */
1009 /**Function********************************************************************
1011 Synopsis [Counts the variables on which a set of DDs depends.]
1013 Description [Counts the variables on which a set of DDs depends.
1014 The set must contain either BDDs and ADDs, or ZDDs.
1015 Returns the number of the variables if successful; CUDD_OUT_OF_MEM
1016 otherwise.]
1018 SideEffects [None]
1020 SeeAlso [Cudd_VectorSupport Cudd_SupportSize]
1022 ******************************************************************************/
1024 Cudd_VectorSupportSize(
1025 DdManager * dd /* manager */,
1026 DdNode ** F /* array of DDs whose support is sought */,
1027 int n /* size of the array */)
1029 int *support;
1030 int i;
1031 int size;
1032 int count;
1034 /* Allocate and initialize support array for ddSupportStep. */
1035 size = ddMax(dd->size, dd->sizeZ);
1036 support = ALLOC(int,size);
1037 if (support == NULL) {
1038 dd->errorCode = CUDD_MEMORY_OUT;
1039 return(CUDD_OUT_OF_MEM);
1041 for (i = 0; i < size; i++) {
1042 support[i] = 0;
1045 /* Compute support and clean up markers. */
1046 for (i = 0; i < n; i++) {
1047 ddSupportStep(Cudd_Regular(F[i]),support);
1049 for (i = 0; i < n; i++) {
1050 ddClearFlag(Cudd_Regular(F[i]));
1053 /* Count vriables in support. */
1054 count = 0;
1055 for (i = 0; i < size; i++) {
1056 if (support[i] == 1) count++;
1059 FREE(support);
1060 return(count);
1062 } /* end of Cudd_VectorSupportSize */
1065 /**Function********************************************************************
1067 Synopsis [Classifies the variables in the support of two DDs.]
1069 Description [Classifies the variables in the support of two DDs
1070 <code>f</code> and <code>g</code>, depending on whther they appear
1071 in both DDs, only in <code>f</code>, or only in <code>g</code>.
1072 Returns 1 if successful; 0 otherwise.]
1074 SideEffects [The cubes of the three classes of variables are
1075 returned as side effects.]
1077 SeeAlso [Cudd_Support Cudd_VectorSupport]
1079 ******************************************************************************/
1081 Cudd_ClassifySupport(
1082 DdManager * dd /* manager */,
1083 DdNode * f /* first DD */,
1084 DdNode * g /* second DD */,
1085 DdNode ** common /* cube of shared variables */,
1086 DdNode ** onlyF /* cube of variables only in f */,
1087 DdNode ** onlyG /* cube of variables only in g */)
1089 int *supportF, *supportG;
1090 DdNode *tmp, *var;
1091 int i,j;
1092 int size;
1094 /* Allocate and initialize support arrays for ddSupportStep. */
1095 size = ddMax(dd->size, dd->sizeZ);
1096 supportF = ALLOC(int,size);
1097 if (supportF == NULL) {
1098 dd->errorCode = CUDD_MEMORY_OUT;
1099 return(0);
1101 supportG = ALLOC(int,size);
1102 if (supportG == NULL) {
1103 dd->errorCode = CUDD_MEMORY_OUT;
1104 FREE(supportF);
1105 return(0);
1107 for (i = 0; i < size; i++) {
1108 supportF[i] = 0;
1109 supportG[i] = 0;
1112 /* Compute supports and clean up markers. */
1113 ddSupportStep(Cudd_Regular(f),supportF);
1114 ddClearFlag(Cudd_Regular(f));
1115 ddSupportStep(Cudd_Regular(g),supportG);
1116 ddClearFlag(Cudd_Regular(g));
1118 /* Classify variables and create cubes. */
1119 *common = *onlyF = *onlyG = DD_ONE(dd);
1120 cuddRef(*common); cuddRef(*onlyF); cuddRef(*onlyG);
1121 for (j = size - 1; j >= 0; j--) { /* for each level bottom-up */
1122 i = (j >= dd->size) ? j : dd->invperm[j];
1123 if (supportF[i] == 0 && supportG[i] == 0) continue;
1124 var = cuddUniqueInter(dd,i,dd->one,Cudd_Not(dd->one));
1125 cuddRef(var);
1126 if (supportG[i] == 0) {
1127 tmp = Cudd_bddAnd(dd,*onlyF,var);
1128 if (tmp == NULL) {
1129 Cudd_RecursiveDeref(dd,*common);
1130 Cudd_RecursiveDeref(dd,*onlyF);
1131 Cudd_RecursiveDeref(dd,*onlyG);
1132 Cudd_RecursiveDeref(dd,var);
1133 FREE(supportF); FREE(supportG);
1134 return(0);
1136 cuddRef(tmp);
1137 Cudd_RecursiveDeref(dd,*onlyF);
1138 *onlyF = tmp;
1139 } else if (supportF[i] == 0) {
1140 tmp = Cudd_bddAnd(dd,*onlyG,var);
1141 if (tmp == NULL) {
1142 Cudd_RecursiveDeref(dd,*common);
1143 Cudd_RecursiveDeref(dd,*onlyF);
1144 Cudd_RecursiveDeref(dd,*onlyG);
1145 Cudd_RecursiveDeref(dd,var);
1146 FREE(supportF); FREE(supportG);
1147 return(0);
1149 cuddRef(tmp);
1150 Cudd_RecursiveDeref(dd,*onlyG);
1151 *onlyG = tmp;
1152 } else {
1153 tmp = Cudd_bddAnd(dd,*common,var);
1154 if (tmp == NULL) {
1155 Cudd_RecursiveDeref(dd,*common);
1156 Cudd_RecursiveDeref(dd,*onlyF);
1157 Cudd_RecursiveDeref(dd,*onlyG);
1158 Cudd_RecursiveDeref(dd,var);
1159 FREE(supportF); FREE(supportG);
1160 return(0);
1162 cuddRef(tmp);
1163 Cudd_RecursiveDeref(dd,*common);
1164 *common = tmp;
1166 Cudd_RecursiveDeref(dd,var);
1169 FREE(supportF); FREE(supportG);
1170 cuddDeref(*common); cuddDeref(*onlyF); cuddDeref(*onlyG);
1171 return(1);
1173 } /* end of Cudd_ClassifySupport */
1176 /**Function********************************************************************
1178 Synopsis [Counts the number of leaves in a DD.]
1180 Description [Counts the number of leaves in a DD. Returns the number
1181 of leaves in the DD rooted at node if successful; CUDD_OUT_OF_MEM
1182 otherwise.]
1184 SideEffects [None]
1186 SeeAlso [Cudd_PrintDebug]
1188 ******************************************************************************/
1190 Cudd_CountLeaves(
1191 DdNode * node)
1193 int i;
1195 i = ddLeavesInt(Cudd_Regular(node));
1196 ddClearFlag(Cudd_Regular(node));
1197 return(i);
1199 } /* end of Cudd_CountLeaves */
1202 /**Function********************************************************************
1204 Synopsis [Picks one on-set cube randomly from the given DD.]
1206 Description [Picks one on-set cube randomly from the given DD. The
1207 cube is written into an array of characters. The array must have at
1208 least as many entries as there are variables. Returns 1 if
1209 successful; 0 otherwise.]
1211 SideEffects [None]
1213 SeeAlso [Cudd_bddPickOneMinterm]
1215 ******************************************************************************/
1217 Cudd_bddPickOneCube(
1218 DdManager * ddm,
1219 DdNode * node,
1220 char * string)
1222 DdNode *N, *T, *E;
1223 DdNode *one, *bzero;
1224 char dir;
1225 int i;
1227 if (string == NULL || node == NULL) return(0);
1229 /* The constant 0 function has no on-set cubes. */
1230 one = DD_ONE(ddm);
1231 bzero = Cudd_Not(one);
1232 if (node == bzero) return(0);
1234 for (i = 0; i < ddm->size; i++) string[i] = 2;
1236 for (;;) {
1238 if (node == one) break;
1240 N = Cudd_Regular(node);
1242 T = cuddT(N); E = cuddE(N);
1243 if (Cudd_IsComplement(node)) {
1244 T = Cudd_Not(T); E = Cudd_Not(E);
1246 if (T == bzero) {
1247 string[N->index] = 0;
1248 node = E;
1249 } else if (E == bzero) {
1250 string[N->index] = 1;
1251 node = T;
1252 } else {
1253 dir = (char) ((Cudd_Random() & 0x2000) >> 13);
1254 string[N->index] = dir;
1255 node = dir ? T : E;
1258 return(1);
1260 } /* end of Cudd_bddPickOneCube */
1263 /**Function********************************************************************
1265 Synopsis [Picks one on-set minterm randomly from the given DD.]
1267 Description [Picks one on-set minterm randomly from the given
1268 DD. The minterm is in terms of <code>vars</code>. The array
1269 <code>vars</code> should contain at least all variables in the
1270 support of <code>f</code>; if this condition is not met the minterm
1271 built by this procedure may not be contained in
1272 <code>f</code>. Builds a BDD for the minterm and returns a pointer
1273 to it if successful; NULL otherwise. There are three reasons why the
1274 procedure may fail:
1275 <ul>
1276 <li> It may run out of memory;
1277 <li> the function <code>f</code> may be the constant 0;
1278 <li> the minterm may not be contained in <code>f</code>.
1279 </ul>]
1281 SideEffects [None]
1283 SeeAlso [Cudd_bddPickOneCube]
1285 ******************************************************************************/
1286 DdNode *
1287 Cudd_bddPickOneMinterm(
1288 DdManager * dd /* manager */,
1289 DdNode * f /* function from which to pick one minterm */,
1290 DdNode ** vars /* array of variables */,
1291 int n /* size of <code>vars</code> */)
1293 char *string;
1294 int i, size;
1295 int *indices;
1296 int result;
1297 DdNode *old, *neW;
1299 size = dd->size;
1300 string = ALLOC(char, size);
1301 if (string == NULL) {
1302 dd->errorCode = CUDD_MEMORY_OUT;
1303 return(NULL);
1305 indices = ALLOC(int,n);
1306 if (indices == NULL) {
1307 dd->errorCode = CUDD_MEMORY_OUT;
1308 FREE(string);
1309 return(NULL);
1312 for (i = 0; i < n; i++) {
1313 indices[i] = vars[i]->index;
1316 result = Cudd_bddPickOneCube(dd,f,string);
1317 if (result == 0) {
1318 FREE(string);
1319 FREE(indices);
1320 return(NULL);
1323 /* Randomize choice for don't cares. */
1324 for (i = 0; i < n; i++) {
1325 if (string[indices[i]] == 2)
1326 string[indices[i]] = (char) ((Cudd_Random() & 0x20) >> 5);
1329 /* Build result BDD. */
1330 old = Cudd_ReadOne(dd);
1331 cuddRef(old);
1333 for (i = n-1; i >= 0; i--) {
1334 neW = Cudd_bddAnd(dd,old,Cudd_NotCond(vars[i],string[indices[i]]==0));
1335 if (neW == NULL) {
1336 FREE(string);
1337 FREE(indices);
1338 Cudd_RecursiveDeref(dd,old);
1339 return(NULL);
1341 cuddRef(neW);
1342 Cudd_RecursiveDeref(dd,old);
1343 old = neW;
1346 #ifdef DD_DEBUG
1347 /* Test. */
1348 if (Cudd_bddLeq(dd,old,f)) {
1349 cuddDeref(old);
1350 } else {
1351 Cudd_RecursiveDeref(dd,old);
1352 old = NULL;
1354 #else
1355 cuddDeref(old);
1356 #endif
1358 FREE(string);
1359 FREE(indices);
1360 return(old);
1362 } /* end of Cudd_bddPickOneMinterm */
1365 /**Function********************************************************************
1367 Synopsis [Picks k on-set minterms evenly distributed from given DD.]
1369 Description [Picks k on-set minterms evenly distributed from given DD.
1370 The minterms are in terms of <code>vars</code>. The array
1371 <code>vars</code> should contain at least all variables in the
1372 support of <code>f</code>; if this condition is not met the minterms
1373 built by this procedure may not be contained in
1374 <code>f</code>. Builds an array of BDDs for the minterms and returns a
1375 pointer to it if successful; NULL otherwise. There are three reasons
1376 why the procedure may fail:
1377 <ul>
1378 <li> It may run out of memory;
1379 <li> the function <code>f</code> may be the constant 0;
1380 <li> the minterms may not be contained in <code>f</code>.
1381 </ul>]
1383 SideEffects [None]
1385 SeeAlso [Cudd_bddPickOneMinterm Cudd_bddPickOneCube]
1387 ******************************************************************************/
1388 DdNode **
1389 Cudd_bddPickArbitraryMinterms(
1390 DdManager * dd /* manager */,
1391 DdNode * f /* function from which to pick k minterms */,
1392 DdNode ** vars /* array of variables */,
1393 int n /* size of <code>vars</code> */,
1394 int k /* number of minterms to find */)
1396 char **string;
1397 int i, j, l, size;
1398 int *indices;
1399 int result;
1400 DdNode **old, *neW;
1401 double minterms;
1402 char *saveString;
1403 int saveFlag, savePoint, isSame;
1405 minterms = Cudd_CountMinterm(dd,f,n);
1406 if ((double)k > minterms) {
1407 return(NULL);
1410 size = dd->size;
1411 string = ALLOC(char *, k);
1412 if (string == NULL) {
1413 dd->errorCode = CUDD_MEMORY_OUT;
1414 return(NULL);
1416 for (i = 0; i < k; i++) {
1417 string[i] = ALLOC(char, size + 1);
1418 if (string[i] == NULL) {
1419 for (j = 0; j < i; j++)
1420 FREE(string[i]);
1421 FREE(string);
1422 dd->errorCode = CUDD_MEMORY_OUT;
1423 return(NULL);
1425 for (j = 0; j < size; j++) string[i][j] = '2';
1426 string[i][size] = '\0';
1428 indices = ALLOC(int,n);
1429 if (indices == NULL) {
1430 dd->errorCode = CUDD_MEMORY_OUT;
1431 for (i = 0; i < k; i++)
1432 FREE(string[i]);
1433 FREE(string);
1434 return(NULL);
1437 for (i = 0; i < n; i++) {
1438 indices[i] = vars[i]->index;
1441 result = ddPickArbitraryMinterms(dd,f,n,k,string);
1442 if (result == 0) {
1443 for (i = 0; i < k; i++)
1444 FREE(string[i]);
1445 FREE(string);
1446 FREE(indices);
1447 return(NULL);
1450 old = ALLOC(DdNode *, k);
1451 if (old == NULL) {
1452 dd->errorCode = CUDD_MEMORY_OUT;
1453 for (i = 0; i < k; i++)
1454 FREE(string[i]);
1455 FREE(string);
1456 FREE(indices);
1457 return(NULL);
1459 saveString = ALLOC(char, size + 1);
1460 if (saveString == NULL) {
1461 dd->errorCode = CUDD_MEMORY_OUT;
1462 for (i = 0; i < k; i++)
1463 FREE(string[i]);
1464 FREE(string);
1465 FREE(indices);
1466 FREE(old);
1467 return(NULL);
1469 saveFlag = 0;
1471 /* Build result BDD array. */
1472 for (i = 0; i < k; i++) {
1473 isSame = 0;
1474 if (!saveFlag) {
1475 for (j = i + 1; j < k; j++) {
1476 if (strcmp(string[i], string[j]) == 0) {
1477 savePoint = i;
1478 strcpy(saveString, string[i]);
1479 saveFlag = 1;
1480 break;
1483 } else {
1484 if (strcmp(string[i], saveString) == 0) {
1485 isSame = 1;
1486 } else {
1487 saveFlag = 0;
1488 for (j = i + 1; j < k; j++) {
1489 if (strcmp(string[i], string[j]) == 0) {
1490 savePoint = i;
1491 strcpy(saveString, string[i]);
1492 saveFlag = 1;
1493 break;
1498 /* Randomize choice for don't cares. */
1499 for (j = 0; j < n; j++) {
1500 if (string[i][indices[j]] == '2')
1501 string[i][indices[j]] =
1502 (char) ((Cudd_Random() & 0x20) ? '1' : '0');
1505 while (isSame) {
1506 isSame = 0;
1507 for (j = savePoint; j < i; j++) {
1508 if (strcmp(string[i], string[j]) == 0) {
1509 isSame = 1;
1510 break;
1513 if (isSame) {
1514 strcpy(string[i], saveString);
1515 /* Randomize choice for don't cares. */
1516 for (j = 0; j < n; j++) {
1517 if (string[i][indices[j]] == '2')
1518 string[i][indices[j]] =
1519 (char) ((Cudd_Random() & 0x20) ? '1' : '0');
1524 old[i] = Cudd_ReadOne(dd);
1525 cuddRef(old[i]);
1527 for (j = 0; j < n; j++) {
1528 if (string[i][indices[j]] == '0') {
1529 neW = Cudd_bddAnd(dd,old[i],Cudd_Not(vars[j]));
1530 } else {
1531 neW = Cudd_bddAnd(dd,old[i],vars[j]);
1533 if (neW == NULL) {
1534 FREE(saveString);
1535 for (l = 0; l < k; l++)
1536 FREE(string[l]);
1537 FREE(string);
1538 FREE(indices);
1539 for (l = 0; l <= i; l++)
1540 Cudd_RecursiveDeref(dd,old[l]);
1541 FREE(old);
1542 return(NULL);
1544 cuddRef(neW);
1545 Cudd_RecursiveDeref(dd,old[i]);
1546 old[i] = neW;
1549 /* Test. */
1550 if (!Cudd_bddLeq(dd,old[i],f)) {
1551 FREE(saveString);
1552 for (l = 0; l < k; l++)
1553 FREE(string[l]);
1554 FREE(string);
1555 FREE(indices);
1556 for (l = 0; l <= i; l++)
1557 Cudd_RecursiveDeref(dd,old[l]);
1558 FREE(old);
1559 return(NULL);
1563 FREE(saveString);
1564 for (i = 0; i < k; i++) {
1565 cuddDeref(old[i]);
1566 FREE(string[i]);
1568 FREE(string);
1569 FREE(indices);
1570 return(old);
1572 } /* end of Cudd_bddPickArbitraryMinterms */
1575 /**Function********************************************************************
1577 Synopsis [Extracts a subset from a BDD.]
1579 Description [Extracts a subset from a BDD in the following procedure.
1580 1. Compute the weight for each mask variable by counting the number of
1581 minterms for both positive and negative cofactors of the BDD with
1582 respect to each mask variable. (weight = #positive - #negative)
1583 2. Find a representative cube of the BDD by using the weight. From the
1584 top variable of the BDD, for each variable, if the weight is greater
1585 than 0.0, choose THEN branch, othereise ELSE branch, until meeting
1586 the constant 1.
1587 3. Quantify out the variables not in maskVars from the representative
1588 cube and if a variable in maskVars is don't care, replace the
1589 variable with a constant(1 or 0) depending on the weight.
1590 4. Make a subset of the BDD by multiplying with the modified cube.]
1592 SideEffects [None]
1594 SeeAlso []
1596 ******************************************************************************/
1597 DdNode *
1598 Cudd_SubsetWithMaskVars(
1599 DdManager * dd /* manager */,
1600 DdNode * f /* function from which to pick a cube */,
1601 DdNode ** vars /* array of variables */,
1602 int nvars /* size of <code>vars</code> */,
1603 DdNode ** maskVars /* array of variables */,
1604 int mvars /* size of <code>maskVars</code> */)
1606 double *weight;
1607 char *string;
1608 int i, size;
1609 int *indices, *mask;
1610 int result;
1611 DdNode *zero, *cube, *newCube, *subset;
1612 DdNode *cof;
1614 DdNode *support;
1615 support = Cudd_Support(dd,f);
1616 cuddRef(support);
1617 Cudd_RecursiveDeref(dd,support);
1619 zero = Cudd_Not(dd->one);
1620 size = dd->size;
1622 weight = ALLOC(double,size);
1623 if (weight == NULL) {
1624 dd->errorCode = CUDD_MEMORY_OUT;
1625 return(NULL);
1627 for (i = 0; i < size; i++) {
1628 weight[i] = 0.0;
1630 for (i = 0; i < mvars; i++) {
1631 cof = Cudd_Cofactor(dd, f, maskVars[i]);
1632 cuddRef(cof);
1633 weight[i] = Cudd_CountMinterm(dd, cof, nvars);
1634 Cudd_RecursiveDeref(dd,cof);
1636 cof = Cudd_Cofactor(dd, f, Cudd_Not(maskVars[i]));
1637 cuddRef(cof);
1638 weight[i] -= Cudd_CountMinterm(dd, cof, nvars);
1639 Cudd_RecursiveDeref(dd,cof);
1642 string = ALLOC(char, size + 1);
1643 if (string == NULL) {
1644 dd->errorCode = CUDD_MEMORY_OUT;
1645 FREE(weight);
1646 return(NULL);
1648 mask = ALLOC(int, size);
1649 if (mask == NULL) {
1650 dd->errorCode = CUDD_MEMORY_OUT;
1651 FREE(weight);
1652 FREE(string);
1653 return(NULL);
1655 for (i = 0; i < size; i++) {
1656 string[i] = '2';
1657 mask[i] = 0;
1659 string[size] = '\0';
1660 indices = ALLOC(int,nvars);
1661 if (indices == NULL) {
1662 dd->errorCode = CUDD_MEMORY_OUT;
1663 FREE(weight);
1664 FREE(string);
1665 FREE(mask);
1666 return(NULL);
1668 for (i = 0; i < nvars; i++) {
1669 indices[i] = vars[i]->index;
1672 result = ddPickRepresentativeCube(dd,f,weight,string);
1673 if (result == 0) {
1674 FREE(weight);
1675 FREE(string);
1676 FREE(mask);
1677 FREE(indices);
1678 return(NULL);
1681 cube = Cudd_ReadOne(dd);
1682 cuddRef(cube);
1683 zero = Cudd_Not(Cudd_ReadOne(dd));
1684 for (i = 0; i < nvars; i++) {
1685 if (string[indices[i]] == '0') {
1686 newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
1687 } else if (string[indices[i]] == '1') {
1688 newCube = Cudd_bddIte(dd,cube,vars[i],zero);
1689 } else
1690 continue;
1691 if (newCube == NULL) {
1692 FREE(weight);
1693 FREE(string);
1694 FREE(mask);
1695 FREE(indices);
1696 Cudd_RecursiveDeref(dd,cube);
1697 return(NULL);
1699 cuddRef(newCube);
1700 Cudd_RecursiveDeref(dd,cube);
1701 cube = newCube;
1703 Cudd_RecursiveDeref(dd,cube);
1705 for (i = 0; i < mvars; i++) {
1706 mask[maskVars[i]->index] = 1;
1708 for (i = 0; i < nvars; i++) {
1709 if (mask[indices[i]]) {
1710 if (string[indices[i]] == '2') {
1711 if (weight[indices[i]] >= 0.0)
1712 string[indices[i]] = '1';
1713 else
1714 string[indices[i]] = '0';
1716 } else {
1717 string[indices[i]] = '2';
1721 cube = Cudd_ReadOne(dd);
1722 cuddRef(cube);
1723 zero = Cudd_Not(Cudd_ReadOne(dd));
1725 /* Build result BDD. */
1726 for (i = 0; i < nvars; i++) {
1727 if (string[indices[i]] == '0') {
1728 newCube = Cudd_bddIte(dd,cube,Cudd_Not(vars[i]),zero);
1729 } else if (string[indices[i]] == '1') {
1730 newCube = Cudd_bddIte(dd,cube,vars[i],zero);
1731 } else
1732 continue;
1733 if (newCube == NULL) {
1734 FREE(weight);
1735 FREE(string);
1736 FREE(mask);
1737 FREE(indices);
1738 Cudd_RecursiveDeref(dd,cube);
1739 return(NULL);
1741 cuddRef(newCube);
1742 Cudd_RecursiveDeref(dd,cube);
1743 cube = newCube;
1746 subset = Cudd_bddAnd(dd,f,cube);
1747 cuddRef(subset);
1748 Cudd_RecursiveDeref(dd,cube);
1750 /* Test. */
1751 if (Cudd_bddLeq(dd,subset,f)) {
1752 cuddDeref(subset);
1753 } else {
1754 Cudd_RecursiveDeref(dd,subset);
1755 subset = NULL;
1758 FREE(weight);
1759 FREE(string);
1760 FREE(mask);
1761 FREE(indices);
1762 return(subset);
1764 } /* end of Cudd_SubsetWithMaskVars */
1767 /**Function********************************************************************
1769 Synopsis [Finds the first cube of a decision diagram.]
1771 Description [Defines an iterator on the onset of a decision diagram
1772 and finds its first cube. Returns a generator that contains the
1773 information necessary to continue the enumeration if successful; NULL
1774 otherwise.<p>
1775 A cube is represented as an array of literals, which are integers in
1776 {0, 1, 2}; 0 represents a complemented literal, 1 represents an
1777 uncomplemented literal, and 2 stands for don't care. The enumeration
1778 produces a disjoint cover of the function associated with the diagram.
1779 The size of the array equals the number of variables in the manager at
1780 the time Cudd_FirstCube is called.<p>
1781 For each cube, a value is also returned. This value is always 1 for a
1782 BDD, while it may be different from 1 for an ADD.
1783 For BDDs, the offset is the set of cubes whose value is the logical zero.
1784 For ADDs, the offset is the set of cubes whose value is the
1785 background value. The cubes of the offset are not enumerated.]
1787 SideEffects [The first cube and its value are returned as side effects.]
1789 SeeAlso [Cudd_ForeachCube Cudd_NextCube Cudd_GenFree Cudd_IsGenEmpty
1790 Cudd_FirstNode]
1792 ******************************************************************************/
1793 DdGen *
1794 Cudd_FirstCube(
1795 DdManager * dd,
1796 DdNode * f,
1797 int ** cube,
1798 CUDD_VALUE_TYPE * value)
1800 DdGen *gen;
1801 DdNode *top, *treg, *next, *nreg, *prev, *preg;
1802 int i;
1803 int nvars;
1805 /* Sanity Check. */
1806 if (dd == NULL || f == NULL) return(NULL);
1808 /* Allocate generator an initialize it. */
1809 gen = ALLOC(DdGen,1);
1810 if (gen == NULL) {
1811 dd->errorCode = CUDD_MEMORY_OUT;
1812 return(NULL);
1815 gen->manager = dd;
1816 gen->type = CUDD_GEN_CUBES;
1817 gen->status = CUDD_GEN_EMPTY;
1818 gen->gen.cubes.cube = NULL;
1819 gen->gen.cubes.value = DD_ZERO_VAL;
1820 gen->stack.sp = 0;
1821 gen->stack.stack = NULL;
1822 gen->node = NULL;
1824 nvars = dd->size;
1825 gen->gen.cubes.cube = ALLOC(int,nvars);
1826 if (gen->gen.cubes.cube == NULL) {
1827 dd->errorCode = CUDD_MEMORY_OUT;
1828 FREE(gen);
1829 return(NULL);
1831 for (i = 0; i < nvars; i++) gen->gen.cubes.cube[i] = 2;
1833 /* The maximum stack depth is one plus the number of variables.
1834 ** because a path may have nodes at all levels, including the
1835 ** constant level.
1837 gen->stack.stack = ALLOC(DdNodePtr, nvars+1);
1838 if (gen->stack.stack == NULL) {
1839 dd->errorCode = CUDD_MEMORY_OUT;
1840 FREE(gen->gen.cubes.cube);
1841 FREE(gen);
1842 return(NULL);
1844 for (i = 0; i <= nvars; i++) gen->stack.stack[i] = NULL;
1846 /* Find the first cube of the onset. */
1847 gen->stack.stack[gen->stack.sp] = f; gen->stack.sp++;
1849 while (1) {
1850 top = gen->stack.stack[gen->stack.sp-1];
1851 treg = Cudd_Regular(top);
1852 if (!cuddIsConstant(treg)) {
1853 /* Take the else branch first. */
1854 gen->gen.cubes.cube[treg->index] = 0;
1855 next = cuddE(treg);
1856 if (top != treg) next = Cudd_Not(next);
1857 gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
1858 } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
1859 /* Backtrack */
1860 while (1) {
1861 if (gen->stack.sp == 1) {
1862 /* The current node has no predecessor. */
1863 gen->status = CUDD_GEN_EMPTY;
1864 gen->stack.sp--;
1865 goto done;
1867 prev = gen->stack.stack[gen->stack.sp-2];
1868 preg = Cudd_Regular(prev);
1869 nreg = cuddT(preg);
1870 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
1871 if (next != top) { /* follow the then branch next */
1872 gen->gen.cubes.cube[preg->index] = 1;
1873 gen->stack.stack[gen->stack.sp-1] = next;
1874 break;
1876 /* Pop the stack and try again. */
1877 gen->gen.cubes.cube[preg->index] = 2;
1878 gen->stack.sp--;
1879 top = gen->stack.stack[gen->stack.sp-1];
1880 treg = Cudd_Regular(top);
1882 } else {
1883 gen->status = CUDD_GEN_NONEMPTY;
1884 gen->gen.cubes.value = cuddV(top);
1885 goto done;
1889 done:
1890 *cube = gen->gen.cubes.cube;
1891 *value = gen->gen.cubes.value;
1892 return(gen);
1894 } /* end of Cudd_FirstCube */
1897 /**Function********************************************************************
1899 Synopsis [Generates the next cube of a decision diagram onset.]
1901 Description [Generates the next cube of a decision diagram onset,
1902 using generator gen. Returns 0 if the enumeration is completed; 1
1903 otherwise.]
1905 SideEffects [The cube and its value are returned as side effects. The
1906 generator is modified.]
1908 SeeAlso [Cudd_ForeachCube Cudd_FirstCube Cudd_GenFree Cudd_IsGenEmpty
1909 Cudd_NextNode]
1911 ******************************************************************************/
1913 Cudd_NextCube(
1914 DdGen * gen,
1915 int ** cube,
1916 CUDD_VALUE_TYPE * value)
1918 DdNode *top, *treg, *next, *nreg, *prev, *preg;
1919 DdManager *dd = gen->manager;
1921 /* Backtrack from previously reached terminal node. */
1922 while (1) {
1923 if (gen->stack.sp == 1) {
1924 /* The current node has no predecessor. */
1925 gen->status = CUDD_GEN_EMPTY;
1926 gen->stack.sp--;
1927 goto done;
1929 top = gen->stack.stack[gen->stack.sp-1];
1930 treg = Cudd_Regular(top);
1931 prev = gen->stack.stack[gen->stack.sp-2];
1932 preg = Cudd_Regular(prev);
1933 nreg = cuddT(preg);
1934 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
1935 if (next != top) { /* follow the then branch next */
1936 gen->gen.cubes.cube[preg->index] = 1;
1937 gen->stack.stack[gen->stack.sp-1] = next;
1938 break;
1940 /* Pop the stack and try again. */
1941 gen->gen.cubes.cube[preg->index] = 2;
1942 gen->stack.sp--;
1945 while (1) {
1946 top = gen->stack.stack[gen->stack.sp-1];
1947 treg = Cudd_Regular(top);
1948 if (!cuddIsConstant(treg)) {
1949 /* Take the else branch first. */
1950 gen->gen.cubes.cube[treg->index] = 0;
1951 next = cuddE(treg);
1952 if (top != treg) next = Cudd_Not(next);
1953 gen->stack.stack[gen->stack.sp] = next; gen->stack.sp++;
1954 } else if (top == Cudd_Not(DD_ONE(dd)) || top == dd->background) {
1955 /* Backtrack */
1956 while (1) {
1957 if (gen->stack.sp == 1) {
1958 /* The current node has no predecessor. */
1959 gen->status = CUDD_GEN_EMPTY;
1960 gen->stack.sp--;
1961 goto done;
1963 prev = gen->stack.stack[gen->stack.sp-2];
1964 preg = Cudd_Regular(prev);
1965 nreg = cuddT(preg);
1966 if (prev != preg) {next = Cudd_Not(nreg);} else {next = nreg;}
1967 if (next != top) { /* follow the then branch next */
1968 gen->gen.cubes.cube[preg->index] = 1;
1969 gen->stack.stack[gen->stack.sp-1] = next;
1970 break;
1972 /* Pop the stack and try again. */
1973 gen->gen.cubes.cube[preg->index] = 2;
1974 gen->stack.sp--;
1975 top = gen->stack.stack[gen->stack.sp-1];
1976 treg = Cudd_Regular(top);
1978 } else {
1979 gen->status = CUDD_GEN_NONEMPTY;
1980 gen->gen.cubes.value = cuddV(top);
1981 goto done;
1985 done:
1986 if (gen->status == CUDD_GEN_EMPTY) return(0);
1987 *cube = gen->gen.cubes.cube;
1988 *value = gen->gen.cubes.value;
1989 return(1);
1991 } /* end of Cudd_NextCube */
1994 /**Function********************************************************************
1996 Synopsis [Finds the first prime of a Boolean function.]
1998 Description [Defines an iterator on a pair of BDDs describing a
1999 (possibly incompletely specified) Boolean functions and finds the
2000 first cube of a cover of the function. Returns a generator
2001 that contains the information necessary to continue the enumeration
2002 if successful; NULL otherwise.<p>
2004 The two argument BDDs are the lower and upper bounds of an interval.
2005 It is a mistake to call this function with a lower bound that is not
2006 less than or equal to the upper bound.<p>
2008 A cube is represented as an array of literals, which are integers in
2009 {0, 1, 2}; 0 represents a complemented literal, 1 represents an
2010 uncomplemented literal, and 2 stands for don't care. The enumeration
2011 produces a prime and irredundant cover of the function associated
2012 with the two BDDs. The size of the array equals the number of
2013 variables in the manager at the time Cudd_FirstCube is called.<p>
2015 This iterator can only be used on BDDs.]
2017 SideEffects [The first cube is returned as side effect.]
2019 SeeAlso [Cudd_ForeachPrime Cudd_NextPrime Cudd_GenFree Cudd_IsGenEmpty
2020 Cudd_FirstCube Cudd_FirstNode]
2022 ******************************************************************************/
2023 DdGen *
2024 Cudd_FirstPrime(
2025 DdManager *dd,
2026 DdNode *l,
2027 DdNode *u,
2028 int **cube)
2030 DdGen *gen;
2031 DdNode *implicant, *prime, *tmp;
2032 int length, result;
2034 /* Sanity Check. */
2035 if (dd == NULL || l == NULL || u == NULL) return(NULL);
2037 /* Allocate generator an initialize it. */
2038 gen = ALLOC(DdGen,1);
2039 if (gen == NULL) {
2040 dd->errorCode = CUDD_MEMORY_OUT;
2041 return(NULL);
2044 gen->manager = dd;
2045 gen->type = CUDD_GEN_PRIMES;
2046 gen->status = CUDD_GEN_EMPTY;
2047 gen->gen.primes.cube = NULL;
2048 gen->gen.primes.ub = u;
2049 gen->stack.sp = 0;
2050 gen->stack.stack = NULL;
2051 gen->node = l;
2052 cuddRef(l);
2054 gen->gen.primes.cube = ALLOC(int,dd->size);
2055 if (gen->gen.primes.cube == NULL) {
2056 dd->errorCode = CUDD_MEMORY_OUT;
2057 FREE(gen);
2058 return(NULL);
2061 if (gen->node == Cudd_ReadLogicZero(dd)) {
2062 gen->status = CUDD_GEN_EMPTY;
2063 } else {
2064 implicant = Cudd_LargestCube(dd,gen->node,&length);
2065 if (implicant == NULL) {
2066 Cudd_RecursiveDeref(dd,gen->node);
2067 FREE(gen->gen.primes.cube);
2068 FREE(gen);
2069 return(NULL);
2071 cuddRef(implicant);
2072 prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
2073 if (prime == NULL) {
2074 Cudd_RecursiveDeref(dd,gen->node);
2075 Cudd_RecursiveDeref(dd,implicant);
2076 FREE(gen->gen.primes.cube);
2077 FREE(gen);
2078 return(NULL);
2080 cuddRef(prime);
2081 Cudd_RecursiveDeref(dd,implicant);
2082 tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
2083 if (tmp == NULL) {
2084 Cudd_RecursiveDeref(dd,gen->node);
2085 Cudd_RecursiveDeref(dd,prime);
2086 FREE(gen->gen.primes.cube);
2087 FREE(gen);
2088 return(NULL);
2090 cuddRef(tmp);
2091 Cudd_RecursiveDeref(dd,gen->node);
2092 gen->node = tmp;
2093 result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
2094 if (result == 0) {
2095 Cudd_RecursiveDeref(dd,gen->node);
2096 Cudd_RecursiveDeref(dd,prime);
2097 FREE(gen->gen.primes.cube);
2098 FREE(gen);
2099 return(NULL);
2101 Cudd_RecursiveDeref(dd,prime);
2102 gen->status = CUDD_GEN_NONEMPTY;
2104 *cube = gen->gen.primes.cube;
2105 return(gen);
2107 } /* end of Cudd_FirstPrime */
2110 /**Function********************************************************************
2112 Synopsis [Generates the next prime of a Boolean function.]
2114 Description [Generates the next cube of a Boolean function,
2115 using generator gen. Returns 0 if the enumeration is completed; 1
2116 otherwise.]
2118 SideEffects [The cube and is returned as side effects. The
2119 generator is modified.]
2121 SeeAlso [Cudd_ForeachPrime Cudd_FirstPrime Cudd_GenFree Cudd_IsGenEmpty
2122 Cudd_NextCube Cudd_NextNode]
2124 ******************************************************************************/
2126 Cudd_NextPrime(
2127 DdGen *gen,
2128 int **cube)
2130 DdNode *implicant, *prime, *tmp;
2131 DdManager *dd = gen->manager;
2132 int length, result;
2134 if (gen->node == Cudd_ReadLogicZero(dd)) {
2135 gen->status = CUDD_GEN_EMPTY;
2136 } else {
2137 implicant = Cudd_LargestCube(dd,gen->node,&length);
2138 if (implicant == NULL) {
2139 gen->status = CUDD_GEN_EMPTY;
2140 return(0);
2142 cuddRef(implicant);
2143 prime = Cudd_bddMakePrime(dd,implicant,gen->gen.primes.ub);
2144 if (prime == NULL) {
2145 Cudd_RecursiveDeref(dd,implicant);
2146 gen->status = CUDD_GEN_EMPTY;
2147 return(0);
2149 cuddRef(prime);
2150 Cudd_RecursiveDeref(dd,implicant);
2151 tmp = Cudd_bddAnd(dd,gen->node,Cudd_Not(prime));
2152 if (tmp == NULL) {
2153 Cudd_RecursiveDeref(dd,prime);
2154 gen->status = CUDD_GEN_EMPTY;
2155 return(0);
2157 cuddRef(tmp);
2158 Cudd_RecursiveDeref(dd,gen->node);
2159 gen->node = tmp;
2160 result = Cudd_BddToCubeArray(dd,prime,gen->gen.primes.cube);
2161 if (result == 0) {
2162 Cudd_RecursiveDeref(dd,prime);
2163 gen->status = CUDD_GEN_EMPTY;
2164 return(0);
2166 Cudd_RecursiveDeref(dd,prime);
2167 gen->status = CUDD_GEN_NONEMPTY;
2169 if (gen->status == CUDD_GEN_EMPTY) return(0);
2170 *cube = gen->gen.primes.cube;
2171 return(1);
2173 } /* end of Cudd_NextPrime */
2176 /**Function********************************************************************
2178 Synopsis [Computes the cube of an array of BDD variables.]
2180 Description [Computes the cube of an array of BDD variables. If
2181 non-null, the phase argument indicates which literal of each
2182 variable should appear in the cube. If phase\[i\] is nonzero, then the
2183 positive literal is used. If phase is NULL, the cube is positive unate.
2184 Returns a pointer to the result if successful; NULL otherwise.]
2186 SideEffects [None]
2188 SeeAlso [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd]
2190 ******************************************************************************/
2191 DdNode *
2192 Cudd_bddComputeCube(
2193 DdManager * dd,
2194 DdNode ** vars,
2195 int * phase,
2196 int n)
2198 DdNode *cube;
2199 DdNode *fn;
2200 int i;
2202 cube = DD_ONE(dd);
2203 cuddRef(cube);
2205 for (i = n - 1; i >= 0; i--) {
2206 if (phase == NULL || phase[i] != 0) {
2207 fn = Cudd_bddAnd(dd,vars[i],cube);
2208 } else {
2209 fn = Cudd_bddAnd(dd,Cudd_Not(vars[i]),cube);
2211 if (fn == NULL) {
2212 Cudd_RecursiveDeref(dd,cube);
2213 return(NULL);
2215 cuddRef(fn);
2216 Cudd_RecursiveDeref(dd,cube);
2217 cube = fn;
2219 cuddDeref(cube);
2221 return(cube);
2223 } /* end of Cudd_bddComputeCube */
2226 /**Function********************************************************************
2228 Synopsis [Computes the cube of an array of ADD variables.]
2230 Description [Computes the cube of an array of ADD variables. If
2231 non-null, the phase argument indicates which literal of each
2232 variable should appear in the cube. If phase\[i\] is nonzero, then the
2233 positive literal is used. If phase is NULL, the cube is positive unate.
2234 Returns a pointer to the result if successful; NULL otherwise.]
2236 SideEffects [none]
2238 SeeAlso [Cudd_bddComputeCube]
2240 ******************************************************************************/
2241 DdNode *
2242 Cudd_addComputeCube(
2243 DdManager * dd,
2244 DdNode ** vars,
2245 int * phase,
2246 int n)
2248 DdNode *cube, *zero;
2249 DdNode *fn;
2250 int i;
2252 cube = DD_ONE(dd);
2253 cuddRef(cube);
2254 zero = DD_ZERO(dd);
2256 for (i = n - 1; i >= 0; i--) {
2257 if (phase == NULL || phase[i] != 0) {
2258 fn = Cudd_addIte(dd,vars[i],cube,zero);
2259 } else {
2260 fn = Cudd_addIte(dd,vars[i],zero,cube);
2262 if (fn == NULL) {
2263 Cudd_RecursiveDeref(dd,cube);
2264 return(NULL);
2266 cuddRef(fn);
2267 Cudd_RecursiveDeref(dd,cube);
2268 cube = fn;
2270 cuddDeref(cube);
2272 return(cube);
2274 } /* end of Cudd_addComputeCube */
2277 /**Function********************************************************************
2279 Synopsis [Builds the BDD of a cube from a positional array.]
2281 Description [Builds a cube from a positional array. The array must
2282 have one integer entry for each BDD variable. If the i-th entry is
2283 1, the variable of index i appears in true form in the cube; If the
2284 i-th entry is 0, the variable of index i appears complemented in the
2285 cube; otherwise the variable does not appear in the cube. Returns a
2286 pointer to the BDD for the cube if successful; NULL otherwise.]
2288 SideEffects [None]
2290 SeeAlso [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray]
2292 ******************************************************************************/
2293 DdNode *
2294 Cudd_CubeArrayToBdd(
2295 DdManager *dd,
2296 int *array)
2298 DdNode *cube, *var, *tmp;
2299 int i;
2300 int size = Cudd_ReadSize(dd);
2302 cube = DD_ONE(dd);
2303 cuddRef(cube);
2304 for (i = size - 1; i >= 0; i--) {
2305 if ((array[i] & ~1) == 0) {
2306 var = Cudd_bddIthVar(dd,i);
2307 tmp = Cudd_bddAnd(dd,cube,Cudd_NotCond(var,array[i]==0));
2308 if (tmp == NULL) {
2309 Cudd_RecursiveDeref(dd,cube);
2310 return(NULL);
2312 cuddRef(tmp);
2313 Cudd_RecursiveDeref(dd,cube);
2314 cube = tmp;
2317 cuddDeref(cube);
2318 return(cube);
2320 } /* end of Cudd_CubeArrayToBdd */
2323 /**Function********************************************************************
2325 Synopsis [Builds a positional array from the BDD of a cube.]
2327 Description [Builds a positional array from the BDD of a cube.
2328 Array must have one entry for each BDD variable. The positional
2329 array has 1 in i-th position if the variable of index i appears in
2330 true form in the cube; it has 0 in i-th position if the variable of
2331 index i appears in complemented form in the cube; finally, it has 2
2332 in i-th position if the variable of index i does not appear in the
2333 cube. Returns 1 if successful (the BDD is indeed a cube); 0
2334 otherwise.]
2336 SideEffects [The result is in the array passed by reference.]
2338 SeeAlso [Cudd_CubeArrayToBdd]
2340 ******************************************************************************/
2342 Cudd_BddToCubeArray(
2343 DdManager *dd,
2344 DdNode *cube,
2345 int *array)
2347 DdNode *scan, *t, *e;
2348 int i;
2349 int size = Cudd_ReadSize(dd);
2350 DdNode *zero = Cudd_Not(DD_ONE(dd));
2352 for (i = size-1; i >= 0; i--) {
2353 array[i] = 2;
2355 scan = cube;
2356 while (!Cudd_IsConstant(scan)) {
2357 int index = Cudd_Regular(scan)->index;
2358 cuddGetBranches(scan,&t,&e);
2359 if (t == zero) {
2360 array[index] = 0;
2361 scan = e;
2362 } else if (e == zero) {
2363 array[index] = 1;
2364 scan = t;
2365 } else {
2366 return(0); /* cube is not a cube */
2369 if (scan == zero) {
2370 return(0);
2371 } else {
2372 return(1);
2375 } /* end of Cudd_BddToCubeArray */
2378 /**Function********************************************************************
2380 Synopsis [Finds the first node of a decision diagram.]
2382 Description [Defines an iterator on the nodes of a decision diagram
2383 and finds its first node. Returns a generator that contains the
2384 information necessary to continue the enumeration if successful;
2385 NULL otherwise. The nodes are enumerated in a reverse topological
2386 order, so that a node is always preceded in the enumeration by its
2387 descendants.]
2389 SideEffects [The first node is returned as a side effect.]
2391 SeeAlso [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty
2392 Cudd_FirstCube]
2394 ******************************************************************************/
2395 DdGen *
2396 Cudd_FirstNode(
2397 DdManager * dd,
2398 DdNode * f,
2399 DdNode ** node)
2401 DdGen *gen;
2402 int size;
2404 /* Sanity Check. */
2405 if (dd == NULL || f == NULL) return(NULL);
2407 /* Allocate generator an initialize it. */
2408 gen = ALLOC(DdGen,1);
2409 if (gen == NULL) {
2410 dd->errorCode = CUDD_MEMORY_OUT;
2411 return(NULL);
2414 gen->manager = dd;
2415 gen->type = CUDD_GEN_NODES;
2416 gen->status = CUDD_GEN_EMPTY;
2417 gen->stack.sp = 0;
2418 gen->node = NULL;
2420 /* Collect all the nodes on the generator stack for later perusal. */
2421 gen->stack.stack = cuddNodeArray(Cudd_Regular(f), &size);
2422 if (gen->stack.stack == NULL) {
2423 FREE(gen);
2424 dd->errorCode = CUDD_MEMORY_OUT;
2425 return(NULL);
2427 gen->gen.nodes.size = size;
2429 /* Find the first node. */
2430 if (gen->stack.sp < gen->gen.nodes.size) {
2431 gen->status = CUDD_GEN_NONEMPTY;
2432 gen->node = gen->stack.stack[gen->stack.sp];
2433 *node = gen->node;
2436 return(gen);
2438 } /* end of Cudd_FirstNode */
2441 /**Function********************************************************************
2443 Synopsis [Finds the next node of a decision diagram.]
2445 Description [Finds the node of a decision diagram, using generator
2446 gen. Returns 0 if the enumeration is completed; 1 otherwise.]
2448 SideEffects [The next node is returned as a side effect.]
2450 SeeAlso [Cudd_ForeachNode Cudd_FirstNode Cudd_GenFree Cudd_IsGenEmpty
2451 Cudd_NextCube]
2453 ******************************************************************************/
2455 Cudd_NextNode(
2456 DdGen * gen,
2457 DdNode ** node)
2459 /* Find the next node. */
2460 gen->stack.sp++;
2461 if (gen->stack.sp < gen->gen.nodes.size) {
2462 gen->node = gen->stack.stack[gen->stack.sp];
2463 *node = gen->node;
2464 return(1);
2465 } else {
2466 gen->status = CUDD_GEN_EMPTY;
2467 return(0);
2470 } /* end of Cudd_NextNode */
2473 /**Function********************************************************************
2475 Synopsis [Frees a CUDD generator.]
2477 Description [Frees a CUDD generator. Always returns 0, so that it can
2478 be used in mis-like foreach constructs.]
2480 SideEffects [None]
2482 SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
2483 Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty]
2485 ******************************************************************************/
2487 Cudd_GenFree(
2488 DdGen * gen)
2490 if (gen == NULL) return(0);
2491 switch (gen->type) {
2492 case CUDD_GEN_CUBES:
2493 case CUDD_GEN_ZDD_PATHS:
2494 FREE(gen->gen.cubes.cube);
2495 FREE(gen->stack.stack);
2496 break;
2497 case CUDD_GEN_PRIMES:
2498 FREE(gen->gen.primes.cube);
2499 Cudd_RecursiveDeref(gen->manager,gen->node);
2500 break;
2501 case CUDD_GEN_NODES:
2502 FREE(gen->stack.stack);
2503 break;
2504 default:
2505 return(0);
2507 FREE(gen);
2508 return(0);
2510 } /* end of Cudd_GenFree */
2513 /**Function********************************************************************
2515 Synopsis [Queries the status of a generator.]
2517 Description [Queries the status of a generator. Returns 1 if the
2518 generator is empty or NULL; 0 otherswise.]
2520 SideEffects [None]
2522 SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
2523 Cudd_FirstNode Cudd_NextNode Cudd_GenFree]
2525 ******************************************************************************/
2527 Cudd_IsGenEmpty(
2528 DdGen * gen)
2530 if (gen == NULL) return(1);
2531 return(gen->status == CUDD_GEN_EMPTY);
2533 } /* end of Cudd_IsGenEmpty */
2536 /**Function********************************************************************
2538 Synopsis [Builds a cube of BDD variables from an array of indices.]
2540 Description [Builds a cube of BDD variables from an array of indices.
2541 Returns a pointer to the result if successful; NULL otherwise.]
2543 SideEffects [None]
2545 SeeAlso [Cudd_bddComputeCube Cudd_CubeArrayToBdd]
2547 ******************************************************************************/
2548 DdNode *
2549 Cudd_IndicesToCube(
2550 DdManager * dd,
2551 int * array,
2552 int n)
2554 DdNode *cube, *tmp;
2555 int i;
2557 cube = DD_ONE(dd);
2558 cuddRef(cube);
2559 for (i = n - 1; i >= 0; i--) {
2560 tmp = Cudd_bddAnd(dd,Cudd_bddIthVar(dd,array[i]),cube);
2561 if (tmp == NULL) {
2562 Cudd_RecursiveDeref(dd,cube);
2563 return(NULL);
2565 cuddRef(tmp);
2566 Cudd_RecursiveDeref(dd,cube);
2567 cube = tmp;
2570 cuddDeref(cube);
2571 return(cube);
2573 } /* end of Cudd_IndicesToCube */
2576 /**Function********************************************************************
2578 Synopsis [Prints the package version number.]
2580 Description []
2582 SideEffects [None]
2584 SeeAlso []
2586 ******************************************************************************/
2587 void
2588 Cudd_PrintVersion(
2589 FILE * fp)
2591 (void) fprintf(fp, "%s\n", CUDD_VERSION);
2593 } /* end of Cudd_PrintVersion */
2596 /**Function********************************************************************
2598 Synopsis [Computes the average distance between adjacent nodes.]
2600 Description [Computes the average distance between adjacent nodes in
2601 the manager. Adjacent nodes are node pairs such that the second node
2602 is the then child, else child, or next node in the collision list.]
2604 SideEffects [None]
2606 SeeAlso []
2608 ******************************************************************************/
2609 double
2610 Cudd_AverageDistance(
2611 DdManager * dd)
2613 double tetotal, nexttotal;
2614 double tesubtotal, nextsubtotal;
2615 double temeasured, nextmeasured;
2616 int i, j;
2617 int slots, nvars;
2618 long diff;
2619 DdNode *scan;
2620 DdNodePtr *nodelist;
2621 DdNode *sentinel = &(dd->sentinel);
2623 nvars = dd->size;
2624 if (nvars == 0) return(0.0);
2626 /* Initialize totals. */
2627 tetotal = 0.0;
2628 nexttotal = 0.0;
2629 temeasured = 0.0;
2630 nextmeasured = 0.0;
2632 /* Scan the variable subtables. */
2633 for (i = 0; i < nvars; i++) {
2634 nodelist = dd->subtables[i].nodelist;
2635 tesubtotal = 0.0;
2636 nextsubtotal = 0.0;
2637 slots = dd->subtables[i].slots;
2638 for (j = 0; j < slots; j++) {
2639 scan = nodelist[j];
2640 while (scan != sentinel) {
2641 diff = (long) scan - (long) cuddT(scan);
2642 tesubtotal += (double) ddAbs(diff);
2643 diff = (long) scan - (long) Cudd_Regular(cuddE(scan));
2644 tesubtotal += (double) ddAbs(diff);
2645 temeasured += 2.0;
2646 if (scan->next != sentinel) {
2647 diff = (long) scan - (long) scan->next;
2648 nextsubtotal += (double) ddAbs(diff);
2649 nextmeasured += 1.0;
2651 scan = scan->next;
2654 tetotal += tesubtotal;
2655 nexttotal += nextsubtotal;
2658 /* Scan the constant table. */
2659 nodelist = dd->constants.nodelist;
2660 nextsubtotal = 0.0;
2661 slots = dd->constants.slots;
2662 for (j = 0; j < slots; j++) {
2663 scan = nodelist[j];
2664 while (scan != NULL) {
2665 if (scan->next != NULL) {
2666 diff = (long) scan - (long) scan->next;
2667 nextsubtotal += (double) ddAbs(diff);
2668 nextmeasured += 1.0;
2670 scan = scan->next;
2673 nexttotal += nextsubtotal;
2675 return((tetotal + nexttotal) / (temeasured + nextmeasured));
2677 } /* end of Cudd_AverageDistance */
2680 /**Function********************************************************************
2682 Synopsis [Portable random number generator.]
2684 Description [Portable number generator based on ran2 from "Numerical
2685 Recipes in C." It is a long period (> 2 * 10^18) random number generator
2686 of L'Ecuyer with Bays-Durham shuffle. Returns a long integer uniformly
2687 distributed between 0 and 2147483561 (inclusive of the endpoint values).
2688 The random generator can be explicitly initialized by calling
2689 Cudd_Srandom. If no explicit initialization is performed, then the
2690 seed 1 is assumed.]
2692 SideEffects [None]
2694 SeeAlso [Cudd_Srandom]
2696 ******************************************************************************/
2697 long
2698 Cudd_Random(void)
2700 int i; /* index in the shuffle table */
2701 long int w; /* work variable */
2703 /* cuddRand == 0 if the geneartor has not been initialized yet. */
2704 if (cuddRand == 0) Cudd_Srandom(1);
2706 /* Compute cuddRand = (cuddRand * LEQA1) % MODULUS1 avoiding
2707 ** overflows by Schrage's method.
2709 w = cuddRand / LEQQ1;
2710 cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
2711 cuddRand += (cuddRand < 0) * MODULUS1;
2713 /* Compute cuddRand2 = (cuddRand2 * LEQA2) % MODULUS2 avoiding
2714 ** overflows by Schrage's method.
2716 w = cuddRand2 / LEQQ2;
2717 cuddRand2 = LEQA2 * (cuddRand2 - w * LEQQ2) - w * LEQR2;
2718 cuddRand2 += (cuddRand2 < 0) * MODULUS2;
2720 /* cuddRand is shuffled with the Bays-Durham algorithm.
2721 ** shuffleSelect and cuddRand2 are combined to generate the output.
2724 /* Pick one element from the shuffle table; "i" will be in the range
2725 ** from 0 to STAB_SIZE-1.
2727 i = (int) (shuffleSelect / STAB_DIV);
2728 /* Mix the element of the shuffle table with the current iterate of
2729 ** the second sub-generator, and replace the chosen element of the
2730 ** shuffle table with the current iterate of the first sub-generator.
2732 shuffleSelect = shuffleTable[i] - cuddRand2;
2733 shuffleTable[i] = cuddRand;
2734 shuffleSelect += (shuffleSelect < 1) * (MODULUS1 - 1);
2735 /* Since shuffleSelect != 0, and we want to be able to return 0,
2736 ** here we subtract 1 before returning.
2738 return(shuffleSelect - 1);
2740 } /* end of Cudd_Random */
2743 /**Function********************************************************************
2745 Synopsis [Initializer for the portable random number generator.]
2747 Description [Initializer for the portable number generator based on
2748 ran2 in "Numerical Recipes in C." The input is the seed for the
2749 generator. If it is negative, its absolute value is taken as seed.
2750 If it is 0, then 1 is taken as seed. The initialized sets up the two
2751 recurrences used to generate a long-period stream, and sets up the
2752 shuffle table.]
2754 SideEffects [None]
2756 SeeAlso [Cudd_Random]
2758 ******************************************************************************/
2759 void
2760 Cudd_Srandom(
2761 long seed)
2763 int i;
2765 if (seed < 0) cuddRand = -seed;
2766 else if (seed == 0) cuddRand = 1;
2767 else cuddRand = seed;
2768 cuddRand2 = cuddRand;
2769 /* Load the shuffle table (after 11 warm-ups). */
2770 for (i = 0; i < STAB_SIZE + 11; i++) {
2771 long int w;
2772 w = cuddRand / LEQQ1;
2773 cuddRand = LEQA1 * (cuddRand - w * LEQQ1) - w * LEQR1;
2774 cuddRand += (cuddRand < 0) * MODULUS1;
2775 shuffleTable[i % STAB_SIZE] = cuddRand;
2777 shuffleSelect = shuffleTable[1 % STAB_SIZE];
2779 } /* end of Cudd_Srandom */
2782 /**Function********************************************************************
2784 Synopsis [Computes the density of a BDD or ADD.]
2786 Description [Computes the density of a BDD or ADD. The density is
2787 the ratio of the number of minterms to the number of nodes. If 0 is
2788 passed as number of variables, the number of variables existing in
2789 the manager is used. Returns the density if successful; (double)
2790 CUDD_OUT_OF_MEM otherwise.]
2792 SideEffects [None]
2794 SeeAlso [Cudd_CountMinterm Cudd_DagSize]
2796 ******************************************************************************/
2797 double
2798 Cudd_Density(
2799 DdManager * dd /* manager */,
2800 DdNode * f /* function whose density is sought */,
2801 int nvars /* size of the support of f */)
2803 double minterms;
2804 int nodes;
2805 double density;
2807 if (nvars == 0) nvars = dd->size;
2808 minterms = Cudd_CountMinterm(dd,f,nvars);
2809 if (minterms == (double) CUDD_OUT_OF_MEM) return(minterms);
2810 nodes = Cudd_DagSize(f);
2811 density = minterms / (double) nodes;
2812 return(density);
2814 } /* end of Cudd_Density */
2817 /**Function********************************************************************
2819 Synopsis [Warns that a memory allocation failed.]
2821 Description [Warns that a memory allocation failed.
2822 This function can be used as replacement of MMout_of_memory to prevent
2823 the safe_mem functions of the util package from exiting when malloc
2824 returns NULL. One possible use is in case of discretionary allocations;
2825 for instance, the allocation of memory to enlarge the computed table.]
2827 SideEffects [None]
2829 SeeAlso []
2831 ******************************************************************************/
2832 void
2833 Cudd_OutOfMem(
2834 long size /* size of the allocation that failed */)
2836 (void) fflush(stdout);
2837 (void) fprintf(stderr, "\nunable to allocate %ld bytes\n", size);
2838 return;
2840 } /* end of Cudd_OutOfMem */
2843 /*---------------------------------------------------------------------------*/
2844 /* Definition of internal functions */
2845 /*---------------------------------------------------------------------------*/
2848 /**Function********************************************************************
2850 Synopsis [Prints a DD to the standard output. One line per node is
2851 printed.]
2853 Description [Prints a DD to the standard output. One line per node is
2854 printed. Returns 1 if successful; 0 otherwise.]
2856 SideEffects [None]
2858 SeeAlso [Cudd_PrintDebug]
2860 ******************************************************************************/
2862 cuddP(
2863 DdManager * dd,
2864 DdNode * f)
2866 int retval;
2867 st_table *table = st_init_table(st_ptrcmp,st_ptrhash);
2869 if (table == NULL) return(0);
2871 retval = dp2(dd,f,table);
2872 st_free_table(table);
2873 (void) fputc('\n',dd->out);
2874 return(retval);
2876 } /* end of cuddP */
2879 /**Function********************************************************************
2881 Synopsis [Frees the memory used to store the minterm counts recorded
2882 in the visited table.]
2884 Description [Frees the memory used to store the minterm counts
2885 recorded in the visited table. Returns ST_CONTINUE.]
2887 SideEffects [None]
2889 ******************************************************************************/
2890 enum st_retval
2891 cuddStCountfree(
2892 char * key,
2893 char * value,
2894 char * arg)
2896 double *d;
2898 d = (double *)value;
2899 FREE(d);
2900 return(ST_CONTINUE);
2902 } /* end of cuddStCountfree */
2905 /**Function********************************************************************
2907 Synopsis [Recursively collects all the nodes of a DD in a symbol
2908 table.]
2910 Description [Traverses the DD f and collects all its nodes in a
2911 symbol table. f is assumed to be a regular pointer and
2912 cuddCollectNodes guarantees this assumption in the recursive calls.
2913 Returns 1 in case of success; 0 otherwise.]
2915 SideEffects [None]
2917 SeeAlso []
2919 ******************************************************************************/
2921 cuddCollectNodes(
2922 DdNode * f,
2923 st_table * visited)
2925 DdNode *T, *E;
2926 int retval;
2928 #ifdef DD_DEBUG
2929 assert(!Cudd_IsComplement(f));
2930 #endif
2932 /* If already visited, nothing to do. */
2933 if (st_is_member(visited, (char *) f) == 1)
2934 return(1);
2936 /* Check for abnormal condition that should never happen. */
2937 if (f == NULL)
2938 return(0);
2940 /* Mark node as visited. */
2941 if (st_add_direct(visited, (char *) f, NULL) == ST_OUT_OF_MEM)
2942 return(0);
2944 /* Check terminal case. */
2945 if (cuddIsConstant(f))
2946 return(1);
2948 /* Recursive calls. */
2949 T = cuddT(f);
2950 retval = cuddCollectNodes(T,visited);
2951 if (retval != 1) return(retval);
2952 E = Cudd_Regular(cuddE(f));
2953 retval = cuddCollectNodes(E,visited);
2954 return(retval);
2956 } /* end of cuddCollectNodes */
2959 /**Function********************************************************************
2961 Synopsis [Recursively collects all the nodes of a DD in an array.]
2963 Description [Traverses the DD f and collects all its nodes in an array.
2964 The caller should free the array returned by cuddNodeArray.
2965 Returns a pointer to the array of nodes in case of success; NULL
2966 otherwise. The nodes are collected in reverse topological order, so
2967 that a node is always preceded in the array by all its descendants.]
2969 SideEffects [The number of nodes is returned as a side effect.]
2971 SeeAlso [Cudd_FirstNode]
2973 ******************************************************************************/
2974 DdNodePtr *
2975 cuddNodeArray(
2976 DdNode *f,
2977 int *n)
2979 DdNodePtr *table;
2980 int size, retval;
2982 size = ddDagInt(Cudd_Regular(f));
2983 table = ALLOC(DdNodePtr, size);
2984 if (table == NULL) {
2985 ddClearFlag(Cudd_Regular(f));
2986 return(NULL);
2989 retval = cuddNodeArrayRecur(f, table, 0);
2990 assert(retval == size);
2992 *n = size;
2993 return(table);
2995 } /* cuddNodeArray */
2998 /*---------------------------------------------------------------------------*/
2999 /* Definition of static functions */
3000 /*---------------------------------------------------------------------------*/
3003 /**Function********************************************************************
3005 Synopsis [Performs the recursive step of cuddP.]
3007 Description [Performs the recursive step of cuddP. Returns 1 in case
3008 of success; 0 otherwise.]
3010 SideEffects [None]
3012 ******************************************************************************/
3013 static int
3014 dp2(
3015 DdManager *dd,
3016 DdNode * f,
3017 st_table * t)
3019 DdNode *g, *n, *N;
3020 int T,E;
3022 if (f == NULL) {
3023 return(0);
3025 g = Cudd_Regular(f);
3026 if (cuddIsConstant(g)) {
3027 #if SIZEOF_VOID_P == 8
3028 (void) fprintf(dd->out,"ID = %c0x%lx\tvalue = %-9g\n", bang(f),
3029 (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
3030 #else
3031 (void) fprintf(dd->out,"ID = %c0x%x\tvalue = %-9g\n", bang(f),
3032 (ptruint) g / (ptruint) sizeof(DdNode),cuddV(g));
3033 #endif
3034 return(1);
3036 if (st_is_member(t,(char *) g) == 1) {
3037 return(1);
3039 if (st_add_direct(t,(char *) g,NULL) == ST_OUT_OF_MEM)
3040 return(0);
3041 #ifdef DD_STATS
3042 #if SIZEOF_VOID_P == 8
3043 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %d\tr = %d\t", bang(f),
3044 (ptruint) g / (ptruint) sizeof(DdNode), g->index, g->ref);
3045 #else
3046 (void) fprintf(dd->out,"ID = %c0x%x\tindex = %d\tr = %d\t", bang(f),
3047 (ptruint) g / (ptruint) sizeof(DdNode),g->index,g->ref);
3048 #endif
3049 #else
3050 #if SIZEOF_VOID_P == 8
3051 (void) fprintf(dd->out,"ID = %c0x%lx\tindex = %u\t", bang(f),
3052 (ptruint) g / (ptruint) sizeof(DdNode),g->index);
3053 #else
3054 (void) fprintf(dd->out,"ID = %c0x%x\tindex = %hu\t", bang(f),
3055 (ptruint) g / (ptruint) sizeof(DdNode),g->index);
3056 #endif
3057 #endif
3058 n = cuddT(g);
3059 if (cuddIsConstant(n)) {
3060 (void) fprintf(dd->out,"T = %-9g\t",cuddV(n));
3061 T = 1;
3062 } else {
3063 #if SIZEOF_VOID_P == 8
3064 (void) fprintf(dd->out,"T = 0x%lx\t",(ptruint) n / (ptruint) sizeof(DdNode));
3065 #else
3066 (void) fprintf(dd->out,"T = 0x%x\t",(ptruint) n / (ptruint) sizeof(DdNode));
3067 #endif
3068 T = 0;
3071 n = cuddE(g);
3072 N = Cudd_Regular(n);
3073 if (cuddIsConstant(N)) {
3074 (void) fprintf(dd->out,"E = %c%-9g\n",bang(n),cuddV(N));
3075 E = 1;
3076 } else {
3077 #if SIZEOF_VOID_P == 8
3078 (void) fprintf(dd->out,"E = %c0x%lx\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
3079 #else
3080 (void) fprintf(dd->out,"E = %c0x%x\n", bang(n), (ptruint) N/(ptruint) sizeof(DdNode));
3081 #endif
3082 E = 0;
3084 if (E == 0) {
3085 if (dp2(dd,N,t) == 0)
3086 return(0);
3088 if (T == 0) {
3089 if (dp2(dd,cuddT(g),t) == 0)
3090 return(0);
3092 return(1);
3094 } /* end of dp2 */
3097 /**Function********************************************************************
3099 Synopsis [Performs the recursive step of Cudd_PrintMinterm.]
3101 Description []
3103 SideEffects [None]
3105 ******************************************************************************/
3106 static void
3107 ddPrintMintermAux(
3108 DdManager * dd /* manager */,
3109 DdNode * node /* current node */,
3110 int * list /* current recursion path */)
3112 DdNode *N,*Nv,*Nnv;
3113 int i,v,index;
3115 N = Cudd_Regular(node);
3117 if (cuddIsConstant(N)) {
3118 /* Terminal case: Print one cube based on the current recursion
3119 ** path, unless we have reached the background value (ADDs) or
3120 ** the logical zero (BDDs).
3122 if (node != background && node != zero) {
3123 for (i = 0; i < dd->size; i++) {
3124 v = list[i];
3125 if (v == 0) (void) fprintf(dd->out,"0");
3126 else if (v == 1) (void) fprintf(dd->out,"1");
3127 else (void) fprintf(dd->out,"-");
3129 (void) fprintf(dd->out," % g\n", cuddV(node));
3131 } else {
3132 Nv = cuddT(N);
3133 Nnv = cuddE(N);
3134 if (Cudd_IsComplement(node)) {
3135 Nv = Cudd_Not(Nv);
3136 Nnv = Cudd_Not(Nnv);
3138 index = N->index;
3139 list[index] = 0;
3140 ddPrintMintermAux(dd,Nnv,list);
3141 list[index] = 1;
3142 ddPrintMintermAux(dd,Nv,list);
3143 list[index] = 2;
3145 return;
3147 } /* end of ddPrintMintermAux */
3150 /**Function********************************************************************
3152 Synopsis [Performs the recursive step of Cudd_DagSize.]
3154 Description [Performs the recursive step of Cudd_DagSize. Returns the
3155 number of nodes in the graph rooted at n.]
3157 SideEffects [None]
3159 ******************************************************************************/
3160 static int
3161 ddDagInt(
3162 DdNode * n)
3164 int tval, eval;
3166 if (Cudd_IsComplement(n->next)) {
3167 return(0);
3169 n->next = Cudd_Not(n->next);
3170 if (cuddIsConstant(n)) {
3171 return(1);
3173 tval = ddDagInt(cuddT(n));
3174 eval = ddDagInt(Cudd_Regular(cuddE(n)));
3175 return(1 + tval + eval);
3177 } /* end of ddDagInt */
3180 /**Function********************************************************************
3182 Synopsis [Performs the recursive step of cuddNodeArray.]
3184 Description [Performs the recursive step of cuddNodeArray. Returns
3185 an the number of nodes in the DD. Clear the least significant bit
3186 of the next field that was used as visited flag by
3187 cuddNodeArrayRecur when counting the nodes. node is supposed to be
3188 regular; the invariant is maintained by this procedure.]
3190 SideEffects [None]
3192 SeeAlso []
3194 ******************************************************************************/
3195 static int
3196 cuddNodeArrayRecur(
3197 DdNode *f,
3198 DdNodePtr *table,
3199 int index)
3201 int tindex, eindex;
3203 if (!Cudd_IsComplement(f->next)) {
3204 return(index);
3206 /* Clear visited flag. */
3207 f->next = Cudd_Regular(f->next);
3208 if (cuddIsConstant(f)) {
3209 table[index] = f;
3210 return(index + 1);
3212 tindex = cuddNodeArrayRecur(cuddT(f), table, index);
3213 eindex = cuddNodeArrayRecur(Cudd_Regular(cuddE(f)), table, tindex);
3214 table[eindex] = f;
3215 return(eindex + 1);
3217 } /* end of cuddNodeArrayRecur */
3220 /**Function********************************************************************
3222 Synopsis [Performs the recursive step of Cudd_CofactorEstimate.]
3224 Description [Performs the recursive step of Cudd_CofactorEstimate.
3225 Returns an estimate of the number of nodes in the DD of a
3226 cofactor of node. Uses the least significant bit of the next field as
3227 visited flag. node is supposed to be regular; the invariant is maintained
3228 by this procedure.]
3230 SideEffects [None]
3232 SeeAlso []
3234 ******************************************************************************/
3235 static int
3236 cuddEstimateCofactor(
3237 DdManager *dd,
3238 st_table *table,
3239 DdNode * node,
3240 int i,
3241 int phase,
3242 DdNode ** ptr)
3244 int tval, eval, val;
3245 DdNode *ptrT, *ptrE;
3247 if (Cudd_IsComplement(node->next)) {
3248 if (!st_lookup(table,(char *)node,(char **)ptr)) {
3249 if (st_add_direct(table,(char *)node,(char *)node) ==
3250 ST_OUT_OF_MEM)
3251 return(CUDD_OUT_OF_MEM);
3252 *ptr = node;
3254 return(0);
3256 node->next = Cudd_Not(node->next);
3257 if (cuddIsConstant(node)) {
3258 *ptr = node;
3259 if (st_add_direct(table,(char *)node,(char *)node) == ST_OUT_OF_MEM)
3260 return(CUDD_OUT_OF_MEM);
3261 return(1);
3263 if ((int) node->index == i) {
3264 if (phase == 1) {
3265 *ptr = cuddT(node);
3266 val = ddDagInt(cuddT(node));
3267 } else {
3268 *ptr = cuddE(node);
3269 val = ddDagInt(Cudd_Regular(cuddE(node)));
3271 if (node->ref > 1) {
3272 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
3273 ST_OUT_OF_MEM)
3274 return(CUDD_OUT_OF_MEM);
3276 return(val);
3278 if (dd->perm[node->index] > dd->perm[i]) {
3279 *ptr = node;
3280 tval = ddDagInt(cuddT(node));
3281 eval = ddDagInt(Cudd_Regular(cuddE(node)));
3282 if (node->ref > 1) {
3283 if (st_add_direct(table,(char *)node,(char *)node) ==
3284 ST_OUT_OF_MEM)
3285 return(CUDD_OUT_OF_MEM);
3287 val = 1 + tval + eval;
3288 return(val);
3290 tval = cuddEstimateCofactor(dd,table,cuddT(node),i,phase,&ptrT);
3291 eval = cuddEstimateCofactor(dd,table,Cudd_Regular(cuddE(node)),i,
3292 phase,&ptrE);
3293 ptrE = Cudd_NotCond(ptrE,Cudd_IsComplement(cuddE(node)));
3294 if (ptrT == ptrE) { /* recombination */
3295 *ptr = ptrT;
3296 val = tval;
3297 if (node->ref > 1) {
3298 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
3299 ST_OUT_OF_MEM)
3300 return(CUDD_OUT_OF_MEM);
3302 } else if ((ptrT != cuddT(node) || ptrE != cuddE(node)) &&
3303 (*ptr = cuddUniqueLookup(dd,node->index,ptrT,ptrE)) != NULL) {
3304 if (Cudd_IsComplement((*ptr)->next)) {
3305 val = 0;
3306 } else {
3307 val = 1 + tval + eval;
3309 if (node->ref > 1) {
3310 if (st_add_direct(table,(char *)node,(char *)*ptr) ==
3311 ST_OUT_OF_MEM)
3312 return(CUDD_OUT_OF_MEM);
3314 } else {
3315 *ptr = node;
3316 val = 1 + tval + eval;
3318 return(val);
3320 } /* end of cuddEstimateCofactor */
3323 /**Function********************************************************************
3325 Synopsis [Checks the unique table for the existence of an internal node.]
3327 Description [Checks the unique table for the existence of an internal
3328 node. Returns a pointer to the node if it is in the table; NULL otherwise.]
3330 SideEffects [None]
3332 SeeAlso [cuddUniqueInter]
3334 ******************************************************************************/
3335 static DdNode *
3336 cuddUniqueLookup(
3337 DdManager * unique,
3338 int index,
3339 DdNode * T,
3340 DdNode * E)
3342 int posn;
3343 unsigned int level;
3344 DdNodePtr *nodelist;
3345 DdNode *looking;
3346 DdSubtable *subtable;
3348 if (index >= unique->size) {
3349 return(NULL);
3352 level = unique->perm[index];
3353 subtable = &(unique->subtables[level]);
3355 #ifdef DD_DEBUG
3356 assert(level < (unsigned) cuddI(unique,T->index));
3357 assert(level < (unsigned) cuddI(unique,Cudd_Regular(E)->index));
3358 #endif
3360 posn = ddHash(T, E, subtable->shift);
3361 nodelist = subtable->nodelist;
3362 looking = nodelist[posn];
3364 while (T < cuddT(looking)) {
3365 looking = Cudd_Regular(looking->next);
3367 while (T == cuddT(looking) && E < cuddE(looking)) {
3368 looking = Cudd_Regular(looking->next);
3370 if (cuddT(looking) == T && cuddE(looking) == E) {
3371 return(looking);
3374 return(NULL);
3376 } /* end of cuddUniqueLookup */
3379 /**Function********************************************************************
3381 Synopsis [Performs the recursive step of Cudd_CofactorEstimateSimple.]
3383 Description [Performs the recursive step of Cudd_CofactorEstimateSimple.
3384 Returns an estimate of the number of nodes in the DD of the positive
3385 cofactor of node. Uses the least significant bit of the next field as
3386 visited flag. node is supposed to be regular; the invariant is maintained
3387 by this procedure.]
3389 SideEffects [None]
3391 SeeAlso []
3393 ******************************************************************************/
3394 static int
3395 cuddEstimateCofactorSimple(
3396 DdNode * node,
3397 int i)
3399 int tval, eval;
3401 if (Cudd_IsComplement(node->next)) {
3402 return(0);
3404 node->next = Cudd_Not(node->next);
3405 if (cuddIsConstant(node)) {
3406 return(1);
3408 tval = cuddEstimateCofactorSimple(cuddT(node),i);
3409 if ((int) node->index == i) return(tval);
3410 eval = cuddEstimateCofactorSimple(Cudd_Regular(cuddE(node)),i);
3411 return(1 + tval + eval);
3413 } /* end of cuddEstimateCofactorSimple */
3416 /**Function********************************************************************
3418 Synopsis [Performs the recursive step of Cudd_CountMinterm.]
3420 Description [Performs the recursive step of Cudd_CountMinterm.
3421 It is based on the following identity. Let |f| be the
3422 number of minterms of f. Then:
3423 <xmp>
3424 |f| = (|f0|+|f1|)/2
3425 </xmp>
3426 where f0 and f1 are the two cofactors of f. Does not use the
3427 identity |f'| = max - |f|, to minimize loss of accuracy due to
3428 roundoff. Returns the number of minterms of the function rooted at
3429 node.]
3431 SideEffects [None]
3433 ******************************************************************************/
3434 static double
3435 ddCountMintermAux(
3436 DdNode * node,
3437 double max,
3438 DdHashTable * table)
3440 DdNode *N, *Nt, *Ne;
3441 double min, minT, minE;
3442 DdNode *res;
3444 N = Cudd_Regular(node);
3446 if (cuddIsConstant(N)) {
3447 if (node == background || node == zero) {
3448 return(0.0);
3449 } else {
3450 return(max);
3453 if (N->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
3454 min = cuddV(res);
3455 if (res->ref == 0) {
3456 table->manager->dead++;
3457 table->manager->constants.dead++;
3459 return(min);
3462 Nt = cuddT(N); Ne = cuddE(N);
3463 if (Cudd_IsComplement(node)) {
3464 Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
3467 minT = ddCountMintermAux(Nt,max,table);
3468 if (minT == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3469 minT *= 0.5;
3470 minE = ddCountMintermAux(Ne,max,table);
3471 if (minE == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3472 minE *= 0.5;
3473 min = minT + minE;
3475 if (N->ref != 1) {
3476 ptrint fanout = (ptrint) N->ref;
3477 cuddSatDec(fanout);
3478 res = cuddUniqueConst(table->manager,min);
3479 if (!cuddHashTableInsert1(table,node,res,fanout)) {
3480 cuddRef(res); Cudd_RecursiveDeref(table->manager, res);
3481 return((double)CUDD_OUT_OF_MEM);
3485 return(min);
3487 } /* end of ddCountMintermAux */
3490 /**Function********************************************************************
3492 Synopsis [Performs the recursive step of Cudd_CountPath.]
3494 Description [Performs the recursive step of Cudd_CountPath.
3495 It is based on the following identity. Let |f| be the
3496 number of paths of f. Then:
3497 <xmp>
3498 |f| = |f0|+|f1|
3499 </xmp>
3500 where f0 and f1 are the two cofactors of f. Uses the
3501 identity |f'| = |f|, to improve the utilization of the (local) cache.
3502 Returns the number of paths of the function rooted at node.]
3504 SideEffects [None]
3506 ******************************************************************************/
3507 static double
3508 ddCountPathAux(
3509 DdNode * node,
3510 st_table * table)
3513 DdNode *Nv, *Nnv;
3514 double paths, *ppaths, paths1, paths2;
3515 double *dummy;
3518 if (cuddIsConstant(node)) {
3519 return(1.0);
3521 if (st_lookup(table, node, &dummy)) {
3522 paths = *dummy;
3523 return(paths);
3526 Nv = cuddT(node); Nnv = cuddE(node);
3528 paths1 = ddCountPathAux(Nv,table);
3529 if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3530 paths2 = ddCountPathAux(Cudd_Regular(Nnv),table);
3531 if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3532 paths = paths1 + paths2;
3534 ppaths = ALLOC(double,1);
3535 if (ppaths == NULL) {
3536 return((double)CUDD_OUT_OF_MEM);
3539 *ppaths = paths;
3541 if (st_add_direct(table,(char *)node, (char *)ppaths) == ST_OUT_OF_MEM) {
3542 FREE(ppaths);
3543 return((double)CUDD_OUT_OF_MEM);
3545 return(paths);
3547 } /* end of ddCountPathAux */
3550 /**Function********************************************************************
3552 Synopsis [Performs the recursive step of Cudd_EpdCountMinterm.]
3554 Description [Performs the recursive step of Cudd_EpdCountMinterm.
3555 It is based on the following identity. Let |f| be the
3556 number of minterms of f. Then:
3557 <xmp>
3558 |f| = (|f0|+|f1|)/2
3559 </xmp>
3560 where f0 and f1 are the two cofactors of f. Does not use the
3561 identity |f'| = max - |f|, to minimize loss of accuracy due to
3562 roundoff. Returns the number of minterms of the function rooted at
3563 node.]
3565 SideEffects [None]
3567 ******************************************************************************/
3568 static int
3569 ddEpdCountMintermAux(
3570 DdNode * node,
3571 EpDouble * max,
3572 EpDouble * epd,
3573 st_table * table)
3575 DdNode *Nt, *Ne;
3576 EpDouble *min, minT, minE;
3577 EpDouble *res;
3578 int status;
3580 /* node is assumed to be regular */
3581 if (cuddIsConstant(node)) {
3582 if (node == background || node == zero) {
3583 EpdMakeZero(epd, 0);
3584 } else {
3585 EpdCopy(max, epd);
3587 return(0);
3589 if (node->ref != 1 && st_lookup(table, node, &res)) {
3590 EpdCopy(res, epd);
3591 return(0);
3594 Nt = cuddT(node); Ne = cuddE(node);
3596 status = ddEpdCountMintermAux(Nt,max,&minT,table);
3597 if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
3598 EpdMultiply(&minT, (double)0.5);
3599 status = ddEpdCountMintermAux(Cudd_Regular(Ne),max,&minE,table);
3600 if (status == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
3601 if (Cudd_IsComplement(Ne)) {
3602 EpdSubtract3(max, &minE, epd);
3603 EpdCopy(epd, &minE);
3605 EpdMultiply(&minE, (double)0.5);
3606 EpdAdd3(&minT, &minE, epd);
3608 if (node->ref > 1) {
3609 min = EpdAlloc();
3610 if (!min)
3611 return(CUDD_OUT_OF_MEM);
3612 EpdCopy(epd, min);
3613 if (st_insert(table, (char *)node, (char *)min) == ST_OUT_OF_MEM) {
3614 EpdFree(min);
3615 return(CUDD_OUT_OF_MEM);
3619 return(0);
3621 } /* end of ddEpdCountMintermAux */
3624 /**Function********************************************************************
3626 Synopsis [Performs the recursive step of Cudd_CountPathsToNonZero.]
3628 Description [Performs the recursive step of Cudd_CountPathsToNonZero.
3629 It is based on the following identity. Let |f| be the
3630 number of paths of f. Then:
3631 <xmp>
3632 |f| = |f0|+|f1|
3633 </xmp>
3634 where f0 and f1 are the two cofactors of f. Returns the number of
3635 paths of the function rooted at node.]
3637 SideEffects [None]
3639 ******************************************************************************/
3640 static double
3641 ddCountPathsToNonZero(
3642 DdNode * N,
3643 st_table * table)
3646 DdNode *node, *Nt, *Ne;
3647 double paths, *ppaths, paths1, paths2;
3648 double *dummy;
3650 node = Cudd_Regular(N);
3651 if (cuddIsConstant(node)) {
3652 return((double) !(Cudd_IsComplement(N) || cuddV(node)==DD_ZERO_VAL));
3654 if (st_lookup(table, N, &dummy)) {
3655 paths = *dummy;
3656 return(paths);
3659 Nt = cuddT(node); Ne = cuddE(node);
3660 if (node != N) {
3661 Nt = Cudd_Not(Nt); Ne = Cudd_Not(Ne);
3664 paths1 = ddCountPathsToNonZero(Nt,table);
3665 if (paths1 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3666 paths2 = ddCountPathsToNonZero(Ne,table);
3667 if (paths2 == (double)CUDD_OUT_OF_MEM) return((double)CUDD_OUT_OF_MEM);
3668 paths = paths1 + paths2;
3670 ppaths = ALLOC(double,1);
3671 if (ppaths == NULL) {
3672 return((double)CUDD_OUT_OF_MEM);
3675 *ppaths = paths;
3677 if (st_add_direct(table,(char *)N, (char *)ppaths) == ST_OUT_OF_MEM) {
3678 FREE(ppaths);
3679 return((double)CUDD_OUT_OF_MEM);
3681 return(paths);
3683 } /* end of ddCountPathsToNonZero */
3686 /**Function********************************************************************
3688 Synopsis [Performs the recursive step of Cudd_Support.]
3690 Description [Performs the recursive step of Cudd_Support. Performs a
3691 DFS from f. The support is accumulated in supp as a side effect. Uses
3692 the LSB of the then pointer as visited flag.]
3694 SideEffects [None]
3696 SeeAlso [ddClearFlag]
3698 ******************************************************************************/
3699 static void
3700 ddSupportStep(
3701 DdNode * f,
3702 int * support)
3704 if (cuddIsConstant(f) || Cudd_IsComplement(f->next)) {
3705 return;
3708 support[f->index] = 1;
3709 ddSupportStep(cuddT(f),support);
3710 ddSupportStep(Cudd_Regular(cuddE(f)),support);
3711 /* Mark as visited. */
3712 f->next = Cudd_Not(f->next);
3713 return;
3715 } /* end of ddSupportStep */
3718 /**Function********************************************************************
3720 Synopsis [Performs a DFS from f, clearing the LSB of the next
3721 pointers.]
3723 Description []
3725 SideEffects [None]
3727 SeeAlso [ddSupportStep ddDagInt]
3729 ******************************************************************************/
3730 static void
3731 ddClearFlag(
3732 DdNode * f)
3734 if (!Cudd_IsComplement(f->next)) {
3735 return;
3737 /* Clear visited flag. */
3738 f->next = Cudd_Regular(f->next);
3739 if (cuddIsConstant(f)) {
3740 return;
3742 ddClearFlag(cuddT(f));
3743 ddClearFlag(Cudd_Regular(cuddE(f)));
3744 return;
3746 } /* end of ddClearFlag */
3749 /**Function********************************************************************
3751 Synopsis [Performs the recursive step of Cudd_CountLeaves.]
3753 Description [Performs the recursive step of Cudd_CountLeaves. Returns
3754 the number of leaves in the DD rooted at n.]
3756 SideEffects [None]
3758 SeeAlso [Cudd_CountLeaves]
3760 ******************************************************************************/
3761 static int
3762 ddLeavesInt(
3763 DdNode * n)
3765 int tval, eval;
3767 if (Cudd_IsComplement(n->next)) {
3768 return(0);
3770 n->next = Cudd_Not(n->next);
3771 if (cuddIsConstant(n)) {
3772 return(1);
3774 tval = ddLeavesInt(cuddT(n));
3775 eval = ddLeavesInt(Cudd_Regular(cuddE(n)));
3776 return(tval + eval);
3778 } /* end of ddLeavesInt */
3781 /**Function********************************************************************
3783 Synopsis [Performs the recursive step of Cudd_bddPickArbitraryMinterms.]
3785 Description [Performs the recursive step of Cudd_bddPickArbitraryMinterms.
3786 Returns 1 if successful; 0 otherwise.]
3788 SideEffects [none]
3790 SeeAlso [Cudd_bddPickArbitraryMinterms]
3792 ******************************************************************************/
3793 static int
3794 ddPickArbitraryMinterms(
3795 DdManager *dd,
3796 DdNode *node,
3797 int nvars,
3798 int nminterms,
3799 char **string)
3801 DdNode *N, *T, *E;
3802 DdNode *one, *bzero;
3803 int i, t, result;
3804 double min1, min2;
3806 if (string == NULL || node == NULL) return(0);
3808 /* The constant 0 function has no on-set cubes. */
3809 one = DD_ONE(dd);
3810 bzero = Cudd_Not(one);
3811 if (nminterms == 0 || node == bzero) return(1);
3812 if (node == one) {
3813 return(1);
3816 N = Cudd_Regular(node);
3817 T = cuddT(N); E = cuddE(N);
3818 if (Cudd_IsComplement(node)) {
3819 T = Cudd_Not(T); E = Cudd_Not(E);
3822 min1 = Cudd_CountMinterm(dd, T, nvars) / 2.0;
3823 if (min1 == (double)CUDD_OUT_OF_MEM) return(0);
3824 min2 = Cudd_CountMinterm(dd, E, nvars) / 2.0;
3825 if (min2 == (double)CUDD_OUT_OF_MEM) return(0);
3827 t = (int)((double)nminterms * min1 / (min1 + min2) + 0.5);
3828 for (i = 0; i < t; i++)
3829 string[i][N->index] = '1';
3830 for (i = t; i < nminterms; i++)
3831 string[i][N->index] = '0';
3833 result = ddPickArbitraryMinterms(dd,T,nvars,t,&string[0]);
3834 if (result == 0)
3835 return(0);
3836 result = ddPickArbitraryMinterms(dd,E,nvars,nminterms-t,&string[t]);
3837 return(result);
3839 } /* end of ddPickArbitraryMinterms */
3842 /**Function********************************************************************
3844 Synopsis [Finds a representative cube of a BDD.]
3846 Description [Finds a representative cube of a BDD with the weight of
3847 each variable. From the top variable, if the weight is greater than or
3848 equal to 0.0, choose THEN branch unless the child is the constant 0.
3849 Otherwise, choose ELSE branch unless the child is the constant 0.]
3851 SideEffects [Cudd_SubsetWithMaskVars Cudd_bddPickOneCube]
3853 ******************************************************************************/
3854 static int
3855 ddPickRepresentativeCube(
3856 DdManager *dd,
3857 DdNode *node,
3858 double *weight,
3859 char *string)
3861 DdNode *N, *T, *E;
3862 DdNode *one, *bzero;
3864 if (string == NULL || node == NULL) return(0);
3866 /* The constant 0 function has no on-set cubes. */
3867 one = DD_ONE(dd);
3868 bzero = Cudd_Not(one);
3869 if (node == bzero) return(0);
3871 if (node == DD_ONE(dd)) return(1);
3873 for (;;) {
3874 N = Cudd_Regular(node);
3875 if (N == one)
3876 break;
3877 T = cuddT(N);
3878 E = cuddE(N);
3879 if (Cudd_IsComplement(node)) {
3880 T = Cudd_Not(T);
3881 E = Cudd_Not(E);
3883 if (weight[N->index] >= 0.0) {
3884 if (T == bzero) {
3885 node = E;
3886 string[N->index] = '0';
3887 } else {
3888 node = T;
3889 string[N->index] = '1';
3891 } else {
3892 if (E == bzero) {
3893 node = T;
3894 string[N->index] = '1';
3895 } else {
3896 node = E;
3897 string[N->index] = '0';
3901 return(1);
3903 } /* end of ddPickRepresentativeCube */
3906 /**Function********************************************************************
3908 Synopsis [Frees the memory used to store the minterm counts recorded
3909 in the visited table.]
3911 Description [Frees the memory used to store the minterm counts
3912 recorded in the visited table. Returns ST_CONTINUE.]
3914 SideEffects [None]
3916 ******************************************************************************/
3917 static enum st_retval
3918 ddEpdFree(
3919 char * key,
3920 char * value,
3921 char * arg)
3923 EpDouble *epd;
3925 epd = (EpDouble *) value;
3926 EpdFree(epd);
3927 return(ST_CONTINUE);
3929 } /* end of ddEpdFree */