1 /**CFile***********************************************************************
7 Synopsis [Utility functions.]
9 Description [External procedures included in this module:
11 <li> Cudd_PrintMinterm()
12 <li> Cudd_bddPrintCover()
13 <li> Cudd_PrintDebug()
15 <li> Cudd_EstimateCofactor()
16 <li> Cudd_EstimateCofactorSimple()
17 <li> Cudd_SharingSize()
18 <li> Cudd_CountMinterm()
19 <li> Cudd_EpdCountMinterm()
21 <li> Cudd_CountPathsToNonZero()
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()
36 <li> Cudd_bddComputeCube()
37 <li> Cudd_addComputeCube()
41 <li> Cudd_IsGenEmpty()
42 <li> Cudd_IndicesToCube()
43 <li> Cudd_PrintVersion()
44 <li> Cudd_AverageDistance()
49 Internal procedures included in this module:
52 <li> cuddStCountfree()
53 <li> cuddCollectNodes()
56 Static procedures included in this module:
59 <li> ddPrintMintermAux()
61 <li> ddCountMintermAux()
62 <li> ddEpdCountMintermAux()
67 <li> ddPickArbitraryMinterms()
68 <li> ddPickRepresentativeCube()
72 Author [Fabio Somenzi]
74 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
78 Redistribution and use in source and binary forms, with or without
79 modification, are permitted provided that the following conditions
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 ******************************************************************************/
111 /*---------------------------------------------------------------------------*/
112 /* Constant declarations */
113 /*---------------------------------------------------------------------------*/
115 /* Random generator constants. */
116 #define MODULUS1 2147483563
120 #define MODULUS2 2147483399
125 #define STAB_DIV (1 + (MODULUS1 - 1) / STAB_SIZE)
127 /*---------------------------------------------------------------------------*/
128 /* Stucture declarations */
129 /*---------------------------------------------------------------------------*/
131 /*---------------------------------------------------------------------------*/
132 /* Type declarations */
133 /*---------------------------------------------------------------------------*/
136 /*---------------------------------------------------------------------------*/
137 /* Variable declarations */
138 /*---------------------------------------------------------------------------*/
141 static char rcsid
[] DD_UNUSED
= "$Id: cuddUtil.c,v 1.81 2009/03/08 02:49:02 fabio Exp $";
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)) ? '!' : ' ')
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***************************************************************/
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.]
208 SeeAlso [Cudd_PrintDebug Cudd_bddPrintCover]
210 ******************************************************************************/
218 background
= manager
->background
;
219 zero
= Cudd_Not(manager
->one
);
220 list
= ALLOC(int,manager
->size
);
222 manager
->errorCode
= CUDD_MEMORY_OUT
;
225 for (i
= 0; i
< manager
->size
; i
++) list
[i
] = 2;
226 ddPrintMintermAux(manager
,node
,list
);
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.]
245 SeeAlso [Cudd_PrintMinterm]
247 ******************************************************************************/
261 array
= ALLOC(int, Cudd_ReadSize(dd
));
262 if (array
== NULL
) return(0);
266 cover
= Cudd_ReadLogicZero(dd
);
269 while (lb
!= Cudd_ReadLogicZero(dd
)) {
270 DdNode
*implicant
, *prime
, *tmp
;
272 implicant
= Cudd_LargestCube(dd
,lb
,&length
);
273 if (implicant
== NULL
) {
274 Cudd_RecursiveDeref(dd
,lb
);
279 prime
= Cudd_bddMakePrime(dd
,implicant
,u
);
281 Cudd_RecursiveDeref(dd
,lb
);
282 Cudd_RecursiveDeref(dd
,implicant
);
287 Cudd_RecursiveDeref(dd
,implicant
);
288 tmp
= Cudd_bddAnd(dd
,lb
,Cudd_Not(prime
));
290 Cudd_RecursiveDeref(dd
,lb
);
291 Cudd_RecursiveDeref(dd
,prime
);
296 Cudd_RecursiveDeref(dd
,lb
);
298 result
= Cudd_BddToCubeArray(dd
,prime
,array
);
300 Cudd_RecursiveDeref(dd
,lb
);
301 Cudd_RecursiveDeref(dd
,prime
);
305 for (q
= 0; q
< dd
->size
; q
++) {
308 (void) fprintf(dd
->out
, "0");
311 (void) fprintf(dd
->out
, "1");
314 (void) fprintf(dd
->out
, "-");
317 (void) fprintf(dd
->out
, "?");
320 (void) fprintf(dd
->out
, " 1\n");
322 tmp
= Cudd_bddOr(dd
,prime
,cover
);
324 Cudd_RecursiveDeref(dd
,cover
);
325 Cudd_RecursiveDeref(dd
,lb
);
326 Cudd_RecursiveDeref(dd
,prime
);
331 Cudd_RecursiveDeref(dd
,cover
);
334 Cudd_RecursiveDeref(dd
,prime
);
336 (void) fprintf(dd
->out
, "\n");
337 Cudd_RecursiveDeref(dd
,lb
);
340 if (!Cudd_bddLeq(dd
,cover
,u
) || !Cudd_bddLeq(dd
,l
,cover
)) {
341 Cudd_RecursiveDeref(dd
,cover
);
344 Cudd_RecursiveDeref(dd
,cover
);
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 > 0. Specifically:
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 > 3 : prints counts + disjoint sum of product + list of nodes
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.]
373 SeeAlso [Cudd_DagSize Cudd_CountLeaves Cudd_CountMinterm
376 ******************************************************************************/
384 DdNode
*azero
, *bzero
;
391 (void) fprintf(dd
->out
,": is the NULL DD\n");
392 (void) fflush(dd
->out
);
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
);
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
);
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
);
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.]
434 SeeAlso [Cudd_SharingSize Cudd_PrintDebug]
436 ******************************************************************************/
443 i
= ddDagInt(Cudd_Regular(node
));
444 ddClearFlag(Cudd_Regular(node
));
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.]
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 */
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
);
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.]
509 SeeAlso [Cudd_DagSize]
511 ******************************************************************************/
513 Cudd_EstimateCofactorSimple(
519 val
= cuddEstimateCofactorSimple(Cudd_Regular(node
),i
);
520 ddClearFlag(Cudd_Regular(node
));
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.]
536 SeeAlso [Cudd_DagSize]
538 ******************************************************************************/
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
]));
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.]
570 SeeAlso [Cudd_PrintDebug Cudd_CountPath]
572 ******************************************************************************/
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);
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
);
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.]
615 SeeAlso [Cudd_CountMinterm]
617 ******************************************************************************/
626 table
= st_init_table(st_ptrcmp
,st_ptrhash
);
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
);
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.]
649 SeeAlso [Cudd_PrintDebug Cudd_CountPath]
651 ******************************************************************************/
653 Cudd_EpdCountMinterm(
663 background
= manager
->background
;
664 zero
= Cudd_Not(manager
->one
);
666 EpdPow2(nvars
, &max
);
667 table
= st_init_table(EpdCmp
, st_ptrhash
);
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
) {
677 return(CUDD_OUT_OF_MEM
);
679 if (Cudd_IsComplement(node
)) {
680 EpdSubtract3(&max
, epd
, &tmp
);
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.]
699 SeeAlso [Cudd_CountMinterm Cudd_CountPath]
701 ******************************************************************************/
703 Cudd_CountPathsToNonZero(
710 table
= st_init_table(st_ptrcmp
,st_ptrhash
);
712 return((double)CUDD_OUT_OF_MEM
);
714 i
= ddCountPathsToNonZero(node
,table
);
715 st_foreach(table
, cuddStCountfree
, NULL
);
716 st_free_table(table
);
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.]
732 SeeAlso [Cudd_VectorSupport Cudd_ClassifySupport]
734 ******************************************************************************/
737 DdManager
* dd
/* manager */,
738 DdNode
* f
/* DD whose support is sought */)
741 DdNode
*res
, *tmp
, *var
;
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
;
752 for (i
= 0; i
< size
; i
++) {
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. */
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
));
773 tmp
= cuddBddAndRecur(dd
,res
,var
);
775 Cudd_RecursiveDeref(dd
,res
);
776 Cudd_RecursiveDeref(dd
,var
);
781 Cudd_RecursiveDeref(dd
,res
);
782 Cudd_RecursiveDeref(dd
,var
);
786 } while (dd
->reordered
== 1);
789 if (res
!= NULL
) cuddDeref(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.]
807 SeeAlso [Cudd_Support Cudd_VectorSupport Cudd_ClassifySupport]
809 ******************************************************************************/
812 DdManager
* dd
/* manager */,
813 DdNode
* f
/* DD whose support is sought */)
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
;
826 for (i
= 0; i
< size
; i
++) {
830 /* Compute support and clean up markers. */
831 ddSupportStep(Cudd_Regular(f
),support
);
832 ddClearFlag(Cudd_Regular(f
));
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
849 SeeAlso [Cudd_Support]
851 ******************************************************************************/
854 DdManager
* dd
/* manager */,
855 DdNode
* f
/* DD whose support size is sought */)
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
++) {
873 /* Compute support and clean up markers. */
874 ddSupportStep(Cudd_Regular(f
),support
);
875 ddClearFlag(Cudd_Regular(f
));
877 /* Count support variables. */
879 for (i
= 0; i
< size
; i
++) {
880 if (support
[i
] == 1) 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.]
900 SeeAlso [Cudd_Support Cudd_ClassifySupport]
902 ******************************************************************************/
905 DdManager
* dd
/* manager */,
906 DdNode
** F
/* array of DDs whose support is sought */,
907 int n
/* size of the array */)
910 DdNode
*res
, *tmp
, *var
;
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
;
921 for (i
= 0; i
< size
; i
++) {
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. */
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
));
941 tmp
= Cudd_bddAnd(dd
,res
,var
);
943 Cudd_RecursiveDeref(dd
,res
);
944 Cudd_RecursiveDeref(dd
,var
);
949 Cudd_RecursiveDeref(dd
,res
);
950 Cudd_RecursiveDeref(dd
,var
);
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.]
972 SeeAlso [Cudd_SupportIndex Cudd_VectorSupport Cudd_ClassifySupport]
974 ******************************************************************************/
976 Cudd_VectorSupportIndex(
977 DdManager
* dd
/* manager */,
978 DdNode
** F
/* array of DDs whose support is sought */,
979 int n
/* size of the array */)
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
;
992 for (i
= 0; i
< size
; i
++) {
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
]));
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
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 */)
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
++) {
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. */
1055 for (i
= 0; i
< size
; i
++) {
1056 if (support
[i
] == 1) 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
;
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
;
1101 supportG
= ALLOC(int,size
);
1102 if (supportG
== NULL
) {
1103 dd
->errorCode
= CUDD_MEMORY_OUT
;
1107 for (i
= 0; i
< size
; i
++) {
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
));
1126 if (supportG
[i
] == 0) {
1127 tmp
= Cudd_bddAnd(dd
,*onlyF
,var
);
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
);
1137 Cudd_RecursiveDeref(dd
,*onlyF
);
1139 } else if (supportF
[i
] == 0) {
1140 tmp
= Cudd_bddAnd(dd
,*onlyG
,var
);
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
);
1150 Cudd_RecursiveDeref(dd
,*onlyG
);
1153 tmp
= Cudd_bddAnd(dd
,*common
,var
);
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
);
1163 Cudd_RecursiveDeref(dd
,*common
);
1166 Cudd_RecursiveDeref(dd
,var
);
1169 FREE(supportF
); FREE(supportG
);
1170 cuddDeref(*common
); cuddDeref(*onlyF
); cuddDeref(*onlyG
);
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
1186 SeeAlso [Cudd_PrintDebug]
1188 ******************************************************************************/
1195 i
= ddLeavesInt(Cudd_Regular(node
));
1196 ddClearFlag(Cudd_Regular(node
));
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.]
1213 SeeAlso [Cudd_bddPickOneMinterm]
1215 ******************************************************************************/
1217 Cudd_bddPickOneCube(
1223 DdNode
*one
, *bzero
;
1227 if (string
== NULL
|| node
== NULL
) return(0);
1229 /* The constant 0 function has no on-set cubes. */
1231 bzero
= Cudd_Not(one
);
1232 if (node
== bzero
) return(0);
1234 for (i
= 0; i
< ddm
->size
; i
++) string
[i
] = 2;
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
);
1247 string
[N
->index
] = 0;
1249 } else if (E
== bzero
) {
1250 string
[N
->index
] = 1;
1253 dir
= (char) ((Cudd_Random() & 0x2000) >> 13);
1254 string
[N
->index
] = dir
;
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
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>.
1283 SeeAlso [Cudd_bddPickOneCube]
1285 ******************************************************************************/
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> */)
1300 string
= ALLOC(char, size
);
1301 if (string
== NULL
) {
1302 dd
->errorCode
= CUDD_MEMORY_OUT
;
1305 indices
= ALLOC(int,n
);
1306 if (indices
== NULL
) {
1307 dd
->errorCode
= CUDD_MEMORY_OUT
;
1312 for (i
= 0; i
< n
; i
++) {
1313 indices
[i
] = vars
[i
]->index
;
1316 result
= Cudd_bddPickOneCube(dd
,f
,string
);
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
);
1333 for (i
= n
-1; i
>= 0; i
--) {
1334 neW
= Cudd_bddAnd(dd
,old
,Cudd_NotCond(vars
[i
],string
[indices
[i
]]==0));
1338 Cudd_RecursiveDeref(dd
,old
);
1342 Cudd_RecursiveDeref(dd
,old
);
1348 if (Cudd_bddLeq(dd
,old
,f
)) {
1351 Cudd_RecursiveDeref(dd
,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:
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>.
1385 SeeAlso [Cudd_bddPickOneMinterm Cudd_bddPickOneCube]
1387 ******************************************************************************/
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 */)
1403 int saveFlag
, savePoint
, isSame
;
1405 minterms
= Cudd_CountMinterm(dd
,f
,n
);
1406 if ((double)k
> minterms
) {
1411 string
= ALLOC(char *, k
);
1412 if (string
== NULL
) {
1413 dd
->errorCode
= CUDD_MEMORY_OUT
;
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
++)
1422 dd
->errorCode
= CUDD_MEMORY_OUT
;
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
++)
1437 for (i
= 0; i
< n
; i
++) {
1438 indices
[i
] = vars
[i
]->index
;
1441 result
= ddPickArbitraryMinterms(dd
,f
,n
,k
,string
);
1443 for (i
= 0; i
< k
; i
++)
1450 old
= ALLOC(DdNode
*, k
);
1452 dd
->errorCode
= CUDD_MEMORY_OUT
;
1453 for (i
= 0; i
< k
; i
++)
1459 saveString
= ALLOC(char, size
+ 1);
1460 if (saveString
== NULL
) {
1461 dd
->errorCode
= CUDD_MEMORY_OUT
;
1462 for (i
= 0; i
< k
; i
++)
1471 /* Build result BDD array. */
1472 for (i
= 0; i
< k
; i
++) {
1475 for (j
= i
+ 1; j
< k
; j
++) {
1476 if (strcmp(string
[i
], string
[j
]) == 0) {
1478 strcpy(saveString
, string
[i
]);
1484 if (strcmp(string
[i
], saveString
) == 0) {
1488 for (j
= i
+ 1; j
< k
; j
++) {
1489 if (strcmp(string
[i
], string
[j
]) == 0) {
1491 strcpy(saveString
, string
[i
]);
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');
1507 for (j
= savePoint
; j
< i
; j
++) {
1508 if (strcmp(string
[i
], string
[j
]) == 0) {
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
);
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
]));
1531 neW
= Cudd_bddAnd(dd
,old
[i
],vars
[j
]);
1535 for (l
= 0; l
< k
; l
++)
1539 for (l
= 0; l
<= i
; l
++)
1540 Cudd_RecursiveDeref(dd
,old
[l
]);
1545 Cudd_RecursiveDeref(dd
,old
[i
]);
1550 if (!Cudd_bddLeq(dd
,old
[i
],f
)) {
1552 for (l
= 0; l
< k
; l
++)
1556 for (l
= 0; l
<= i
; l
++)
1557 Cudd_RecursiveDeref(dd
,old
[l
]);
1564 for (i
= 0; i
< k
; i
++) {
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
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.]
1596 ******************************************************************************/
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> */)
1609 int *indices
, *mask
;
1611 DdNode
*zero
, *cube
, *newCube
, *subset
;
1615 support
= Cudd_Support(dd
,f
);
1617 Cudd_RecursiveDeref(dd
,support
);
1619 zero
= Cudd_Not(dd
->one
);
1622 weight
= ALLOC(double,size
);
1623 if (weight
== NULL
) {
1624 dd
->errorCode
= CUDD_MEMORY_OUT
;
1627 for (i
= 0; i
< size
; i
++) {
1630 for (i
= 0; i
< mvars
; i
++) {
1631 cof
= Cudd_Cofactor(dd
, f
, maskVars
[i
]);
1633 weight
[i
] = Cudd_CountMinterm(dd
, cof
, nvars
);
1634 Cudd_RecursiveDeref(dd
,cof
);
1636 cof
= Cudd_Cofactor(dd
, f
, Cudd_Not(maskVars
[i
]));
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
;
1648 mask
= ALLOC(int, size
);
1650 dd
->errorCode
= CUDD_MEMORY_OUT
;
1655 for (i
= 0; i
< size
; i
++) {
1659 string
[size
] = '\0';
1660 indices
= ALLOC(int,nvars
);
1661 if (indices
== NULL
) {
1662 dd
->errorCode
= CUDD_MEMORY_OUT
;
1668 for (i
= 0; i
< nvars
; i
++) {
1669 indices
[i
] = vars
[i
]->index
;
1672 result
= ddPickRepresentativeCube(dd
,f
,weight
,string
);
1681 cube
= Cudd_ReadOne(dd
);
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
);
1691 if (newCube
== NULL
) {
1696 Cudd_RecursiveDeref(dd
,cube
);
1700 Cudd_RecursiveDeref(dd
,cube
);
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';
1714 string
[indices
[i
]] = '0';
1717 string
[indices
[i
]] = '2';
1721 cube
= Cudd_ReadOne(dd
);
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
);
1733 if (newCube
== NULL
) {
1738 Cudd_RecursiveDeref(dd
,cube
);
1742 Cudd_RecursiveDeref(dd
,cube
);
1746 subset
= Cudd_bddAnd(dd
,f
,cube
);
1748 Cudd_RecursiveDeref(dd
,cube
);
1751 if (Cudd_bddLeq(dd
,subset
,f
)) {
1754 Cudd_RecursiveDeref(dd
,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
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
1792 ******************************************************************************/
1798 CUDD_VALUE_TYPE
* value
)
1801 DdNode
*top
, *treg
, *next
, *nreg
, *prev
, *preg
;
1806 if (dd
== NULL
|| f
== NULL
) return(NULL
);
1808 /* Allocate generator an initialize it. */
1809 gen
= ALLOC(DdGen
,1);
1811 dd
->errorCode
= CUDD_MEMORY_OUT
;
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
;
1821 gen
->stack
.stack
= NULL
;
1825 gen
->gen
.cubes
.cube
= ALLOC(int,nvars
);
1826 if (gen
->gen
.cubes
.cube
== NULL
) {
1827 dd
->errorCode
= CUDD_MEMORY_OUT
;
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
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
);
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
++;
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;
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
) {
1861 if (gen
->stack
.sp
== 1) {
1862 /* The current node has no predecessor. */
1863 gen
->status
= CUDD_GEN_EMPTY
;
1867 prev
= gen
->stack
.stack
[gen
->stack
.sp
-2];
1868 preg
= Cudd_Regular(prev
);
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
;
1876 /* Pop the stack and try again. */
1877 gen
->gen
.cubes
.cube
[preg
->index
] = 2;
1879 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
1880 treg
= Cudd_Regular(top
);
1883 gen
->status
= CUDD_GEN_NONEMPTY
;
1884 gen
->gen
.cubes
.value
= cuddV(top
);
1890 *cube
= gen
->gen
.cubes
.cube
;
1891 *value
= gen
->gen
.cubes
.value
;
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
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
1911 ******************************************************************************/
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. */
1923 if (gen
->stack
.sp
== 1) {
1924 /* The current node has no predecessor. */
1925 gen
->status
= CUDD_GEN_EMPTY
;
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
);
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
;
1940 /* Pop the stack and try again. */
1941 gen
->gen
.cubes
.cube
[preg
->index
] = 2;
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;
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
) {
1957 if (gen
->stack
.sp
== 1) {
1958 /* The current node has no predecessor. */
1959 gen
->status
= CUDD_GEN_EMPTY
;
1963 prev
= gen
->stack
.stack
[gen
->stack
.sp
-2];
1964 preg
= Cudd_Regular(prev
);
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
;
1972 /* Pop the stack and try again. */
1973 gen
->gen
.cubes
.cube
[preg
->index
] = 2;
1975 top
= gen
->stack
.stack
[gen
->stack
.sp
-1];
1976 treg
= Cudd_Regular(top
);
1979 gen
->status
= CUDD_GEN_NONEMPTY
;
1980 gen
->gen
.cubes
.value
= cuddV(top
);
1986 if (gen
->status
== CUDD_GEN_EMPTY
) return(0);
1987 *cube
= gen
->gen
.cubes
.cube
;
1988 *value
= gen
->gen
.cubes
.value
;
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 ******************************************************************************/
2031 DdNode
*implicant
, *prime
, *tmp
;
2035 if (dd
== NULL
|| l
== NULL
|| u
== NULL
) return(NULL
);
2037 /* Allocate generator an initialize it. */
2038 gen
= ALLOC(DdGen
,1);
2040 dd
->errorCode
= CUDD_MEMORY_OUT
;
2045 gen
->type
= CUDD_GEN_PRIMES
;
2046 gen
->status
= CUDD_GEN_EMPTY
;
2047 gen
->gen
.primes
.cube
= NULL
;
2048 gen
->gen
.primes
.ub
= u
;
2050 gen
->stack
.stack
= NULL
;
2054 gen
->gen
.primes
.cube
= ALLOC(int,dd
->size
);
2055 if (gen
->gen
.primes
.cube
== NULL
) {
2056 dd
->errorCode
= CUDD_MEMORY_OUT
;
2061 if (gen
->node
== Cudd_ReadLogicZero(dd
)) {
2062 gen
->status
= CUDD_GEN_EMPTY
;
2064 implicant
= Cudd_LargestCube(dd
,gen
->node
,&length
);
2065 if (implicant
== NULL
) {
2066 Cudd_RecursiveDeref(dd
,gen
->node
);
2067 FREE(gen
->gen
.primes
.cube
);
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
);
2081 Cudd_RecursiveDeref(dd
,implicant
);
2082 tmp
= Cudd_bddAnd(dd
,gen
->node
,Cudd_Not(prime
));
2084 Cudd_RecursiveDeref(dd
,gen
->node
);
2085 Cudd_RecursiveDeref(dd
,prime
);
2086 FREE(gen
->gen
.primes
.cube
);
2091 Cudd_RecursiveDeref(dd
,gen
->node
);
2093 result
= Cudd_BddToCubeArray(dd
,prime
,gen
->gen
.primes
.cube
);
2095 Cudd_RecursiveDeref(dd
,gen
->node
);
2096 Cudd_RecursiveDeref(dd
,prime
);
2097 FREE(gen
->gen
.primes
.cube
);
2101 Cudd_RecursiveDeref(dd
,prime
);
2102 gen
->status
= CUDD_GEN_NONEMPTY
;
2104 *cube
= gen
->gen
.primes
.cube
;
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
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 ******************************************************************************/
2130 DdNode
*implicant
, *prime
, *tmp
;
2131 DdManager
*dd
= gen
->manager
;
2134 if (gen
->node
== Cudd_ReadLogicZero(dd
)) {
2135 gen
->status
= CUDD_GEN_EMPTY
;
2137 implicant
= Cudd_LargestCube(dd
,gen
->node
,&length
);
2138 if (implicant
== NULL
) {
2139 gen
->status
= CUDD_GEN_EMPTY
;
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
;
2150 Cudd_RecursiveDeref(dd
,implicant
);
2151 tmp
= Cudd_bddAnd(dd
,gen
->node
,Cudd_Not(prime
));
2153 Cudd_RecursiveDeref(dd
,prime
);
2154 gen
->status
= CUDD_GEN_EMPTY
;
2158 Cudd_RecursiveDeref(dd
,gen
->node
);
2160 result
= Cudd_BddToCubeArray(dd
,prime
,gen
->gen
.primes
.cube
);
2162 Cudd_RecursiveDeref(dd
,prime
);
2163 gen
->status
= CUDD_GEN_EMPTY
;
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
;
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.]
2188 SeeAlso [Cudd_addComputeCube Cudd_IndicesToCube Cudd_CubeArrayToBdd]
2190 ******************************************************************************/
2192 Cudd_bddComputeCube(
2205 for (i
= n
- 1; i
>= 0; i
--) {
2206 if (phase
== NULL
|| phase
[i
] != 0) {
2207 fn
= Cudd_bddAnd(dd
,vars
[i
],cube
);
2209 fn
= Cudd_bddAnd(dd
,Cudd_Not(vars
[i
]),cube
);
2212 Cudd_RecursiveDeref(dd
,cube
);
2216 Cudd_RecursiveDeref(dd
,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.]
2238 SeeAlso [Cudd_bddComputeCube]
2240 ******************************************************************************/
2242 Cudd_addComputeCube(
2248 DdNode
*cube
, *zero
;
2256 for (i
= n
- 1; i
>= 0; i
--) {
2257 if (phase
== NULL
|| phase
[i
] != 0) {
2258 fn
= Cudd_addIte(dd
,vars
[i
],cube
,zero
);
2260 fn
= Cudd_addIte(dd
,vars
[i
],zero
,cube
);
2263 Cudd_RecursiveDeref(dd
,cube
);
2267 Cudd_RecursiveDeref(dd
,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.]
2290 SeeAlso [Cudd_bddComputeCube Cudd_IndicesToCube Cudd_BddToCubeArray]
2292 ******************************************************************************/
2294 Cudd_CubeArrayToBdd(
2298 DdNode
*cube
, *var
, *tmp
;
2300 int size
= Cudd_ReadSize(dd
);
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));
2309 Cudd_RecursiveDeref(dd
,cube
);
2313 Cudd_RecursiveDeref(dd
,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
2336 SideEffects [The result is in the array passed by reference.]
2338 SeeAlso [Cudd_CubeArrayToBdd]
2340 ******************************************************************************/
2342 Cudd_BddToCubeArray(
2347 DdNode
*scan
, *t
, *e
;
2349 int size
= Cudd_ReadSize(dd
);
2350 DdNode
*zero
= Cudd_Not(DD_ONE(dd
));
2352 for (i
= size
-1; i
>= 0; i
--) {
2356 while (!Cudd_IsConstant(scan
)) {
2357 int index
= Cudd_Regular(scan
)->index
;
2358 cuddGetBranches(scan
,&t
,&e
);
2362 } else if (e
== zero
) {
2366 return(0); /* cube is not a cube */
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
2389 SideEffects [The first node is returned as a side effect.]
2391 SeeAlso [Cudd_ForeachNode Cudd_NextNode Cudd_GenFree Cudd_IsGenEmpty
2394 ******************************************************************************/
2405 if (dd
== NULL
|| f
== NULL
) return(NULL
);
2407 /* Allocate generator an initialize it. */
2408 gen
= ALLOC(DdGen
,1);
2410 dd
->errorCode
= CUDD_MEMORY_OUT
;
2415 gen
->type
= CUDD_GEN_NODES
;
2416 gen
->status
= CUDD_GEN_EMPTY
;
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
) {
2424 dd
->errorCode
= CUDD_MEMORY_OUT
;
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
];
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
2453 ******************************************************************************/
2459 /* Find the next node. */
2461 if (gen
->stack
.sp
< gen
->gen
.nodes
.size
) {
2462 gen
->node
= gen
->stack
.stack
[gen
->stack
.sp
];
2466 gen
->status
= CUDD_GEN_EMPTY
;
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.]
2482 SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
2483 Cudd_FirstNode Cudd_NextNode Cudd_IsGenEmpty]
2485 ******************************************************************************/
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
);
2497 case CUDD_GEN_PRIMES
:
2498 FREE(gen
->gen
.primes
.cube
);
2499 Cudd_RecursiveDeref(gen
->manager
,gen
->node
);
2501 case CUDD_GEN_NODES
:
2502 FREE(gen
->stack
.stack
);
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.]
2522 SeeAlso [Cudd_ForeachCube Cudd_ForeachNode Cudd_FirstCube Cudd_NextCube
2523 Cudd_FirstNode Cudd_NextNode Cudd_GenFree]
2525 ******************************************************************************/
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.]
2545 SeeAlso [Cudd_bddComputeCube Cudd_CubeArrayToBdd]
2547 ******************************************************************************/
2559 for (i
= n
- 1; i
>= 0; i
--) {
2560 tmp
= Cudd_bddAnd(dd
,Cudd_bddIthVar(dd
,array
[i
]),cube
);
2562 Cudd_RecursiveDeref(dd
,cube
);
2566 Cudd_RecursiveDeref(dd
,cube
);
2573 } /* end of Cudd_IndicesToCube */
2576 /**Function********************************************************************
2578 Synopsis [Prints the package version number.]
2586 ******************************************************************************/
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.]
2608 ******************************************************************************/
2610 Cudd_AverageDistance(
2613 double tetotal
, nexttotal
;
2614 double tesubtotal
, nextsubtotal
;
2615 double temeasured
, nextmeasured
;
2620 DdNodePtr
*nodelist
;
2621 DdNode
*sentinel
= &(dd
->sentinel
);
2624 if (nvars
== 0) return(0.0);
2626 /* Initialize totals. */
2632 /* Scan the variable subtables. */
2633 for (i
= 0; i
< nvars
; i
++) {
2634 nodelist
= dd
->subtables
[i
].nodelist
;
2637 slots
= dd
->subtables
[i
].slots
;
2638 for (j
= 0; j
< slots
; 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
);
2646 if (scan
->next
!= sentinel
) {
2647 diff
= (long) scan
- (long) scan
->next
;
2648 nextsubtotal
+= (double) ddAbs(diff
);
2649 nextmeasured
+= 1.0;
2654 tetotal
+= tesubtotal
;
2655 nexttotal
+= nextsubtotal
;
2658 /* Scan the constant table. */
2659 nodelist
= dd
->constants
.nodelist
;
2661 slots
= dd
->constants
.slots
;
2662 for (j
= 0; j
< slots
; 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;
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
2694 SeeAlso [Cudd_Srandom]
2696 ******************************************************************************/
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
2756 SeeAlso [Cudd_Random]
2758 ******************************************************************************/
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
++) {
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.]
2794 SeeAlso [Cudd_CountMinterm Cudd_DagSize]
2796 ******************************************************************************/
2799 DdManager
* dd
/* manager */,
2800 DdNode
* f
/* function whose density is sought */,
2801 int nvars
/* size of the support of f */)
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
;
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.]
2831 ******************************************************************************/
2834 long size
/* size of the allocation that failed */)
2836 (void) fflush(stdout
);
2837 (void) fprintf(stderr
, "\nunable to allocate %ld bytes\n", size
);
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
2853 Description [Prints a DD to the standard output. One line per node is
2854 printed. Returns 1 if successful; 0 otherwise.]
2858 SeeAlso [Cudd_PrintDebug]
2860 ******************************************************************************/
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
);
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.]
2889 ******************************************************************************/
2898 d
= (double *)value
;
2900 return(ST_CONTINUE
);
2902 } /* end of cuddStCountfree */
2905 /**Function********************************************************************
2907 Synopsis [Recursively collects all the nodes of a DD in a symbol
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.]
2919 ******************************************************************************/
2929 assert(!Cudd_IsComplement(f
));
2932 /* If already visited, nothing to do. */
2933 if (st_is_member(visited
, (char *) f
) == 1)
2936 /* Check for abnormal condition that should never happen. */
2940 /* Mark node as visited. */
2941 if (st_add_direct(visited
, (char *) f
, NULL
) == ST_OUT_OF_MEM
)
2944 /* Check terminal case. */
2945 if (cuddIsConstant(f
))
2948 /* Recursive calls. */
2950 retval
= cuddCollectNodes(T
,visited
);
2951 if (retval
!= 1) return(retval
);
2952 E
= Cudd_Regular(cuddE(f
));
2953 retval
= cuddCollectNodes(E
,visited
);
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 ******************************************************************************/
2982 size
= ddDagInt(Cudd_Regular(f
));
2983 table
= ALLOC(DdNodePtr
, size
);
2984 if (table
== NULL
) {
2985 ddClearFlag(Cudd_Regular(f
));
2989 retval
= cuddNodeArrayRecur(f
, table
, 0);
2990 assert(retval
== size
);
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.]
3012 ******************************************************************************/
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
));
3031 (void) fprintf(dd
->out
,"ID = %c0x%x\tvalue = %-9g\n", bang(f
),
3032 (ptruint
) g
/ (ptruint
) sizeof(DdNode
),cuddV(g
));
3036 if (st_is_member(t
,(char *) g
) == 1) {
3039 if (st_add_direct(t
,(char *) g
,NULL
) == ST_OUT_OF_MEM
)
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
);
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
);
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
);
3054 (void) fprintf(dd
->out
,"ID = %c0x%x\tindex = %hu\t", bang(f
),
3055 (ptruint
) g
/ (ptruint
) sizeof(DdNode
),g
->index
);
3059 if (cuddIsConstant(n
)) {
3060 (void) fprintf(dd
->out
,"T = %-9g\t",cuddV(n
));
3063 #if SIZEOF_VOID_P == 8
3064 (void) fprintf(dd
->out
,"T = 0x%lx\t",(ptruint
) n
/ (ptruint
) sizeof(DdNode
));
3066 (void) fprintf(dd
->out
,"T = 0x%x\t",(ptruint
) n
/ (ptruint
) sizeof(DdNode
));
3072 N
= Cudd_Regular(n
);
3073 if (cuddIsConstant(N
)) {
3074 (void) fprintf(dd
->out
,"E = %c%-9g\n",bang(n
),cuddV(N
));
3077 #if SIZEOF_VOID_P == 8
3078 (void) fprintf(dd
->out
,"E = %c0x%lx\n", bang(n
), (ptruint
) N
/(ptruint
) sizeof(DdNode
));
3080 (void) fprintf(dd
->out
,"E = %c0x%x\n", bang(n
), (ptruint
) N
/(ptruint
) sizeof(DdNode
));
3085 if (dp2(dd
,N
,t
) == 0)
3089 if (dp2(dd
,cuddT(g
),t
) == 0)
3097 /**Function********************************************************************
3099 Synopsis [Performs the recursive step of Cudd_PrintMinterm.]
3105 ******************************************************************************/
3108 DdManager
* dd
/* manager */,
3109 DdNode
* node
/* current node */,
3110 int * list
/* current recursion path */)
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
++) {
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
));
3134 if (Cudd_IsComplement(node
)) {
3136 Nnv
= Cudd_Not(Nnv
);
3140 ddPrintMintermAux(dd
,Nnv
,list
);
3142 ddPrintMintermAux(dd
,Nv
,list
);
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.]
3159 ******************************************************************************/
3166 if (Cudd_IsComplement(n
->next
)) {
3169 n
->next
= Cudd_Not(n
->next
);
3170 if (cuddIsConstant(n
)) {
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.]
3194 ******************************************************************************/
3203 if (!Cudd_IsComplement(f
->next
)) {
3206 /* Clear visited flag. */
3207 f
->next
= Cudd_Regular(f
->next
);
3208 if (cuddIsConstant(f
)) {
3212 tindex
= cuddNodeArrayRecur(cuddT(f
), table
, index
);
3213 eindex
= cuddNodeArrayRecur(Cudd_Regular(cuddE(f
)), table
, tindex
);
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
3234 ******************************************************************************/
3236 cuddEstimateCofactor(
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
) ==
3251 return(CUDD_OUT_OF_MEM
);
3256 node
->next
= Cudd_Not(node
->next
);
3257 if (cuddIsConstant(node
)) {
3259 if (st_add_direct(table
,(char *)node
,(char *)node
) == ST_OUT_OF_MEM
)
3260 return(CUDD_OUT_OF_MEM
);
3263 if ((int) node
->index
== i
) {
3266 val
= ddDagInt(cuddT(node
));
3269 val
= ddDagInt(Cudd_Regular(cuddE(node
)));
3271 if (node
->ref
> 1) {
3272 if (st_add_direct(table
,(char *)node
,(char *)*ptr
) ==
3274 return(CUDD_OUT_OF_MEM
);
3278 if (dd
->perm
[node
->index
] > dd
->perm
[i
]) {
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
) ==
3285 return(CUDD_OUT_OF_MEM
);
3287 val
= 1 + tval
+ eval
;
3290 tval
= cuddEstimateCofactor(dd
,table
,cuddT(node
),i
,phase
,&ptrT
);
3291 eval
= cuddEstimateCofactor(dd
,table
,Cudd_Regular(cuddE(node
)),i
,
3293 ptrE
= Cudd_NotCond(ptrE
,Cudd_IsComplement(cuddE(node
)));
3294 if (ptrT
== ptrE
) { /* recombination */
3297 if (node
->ref
> 1) {
3298 if (st_add_direct(table
,(char *)node
,(char *)*ptr
) ==
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
)) {
3307 val
= 1 + tval
+ eval
;
3309 if (node
->ref
> 1) {
3310 if (st_add_direct(table
,(char *)node
,(char *)*ptr
) ==
3312 return(CUDD_OUT_OF_MEM
);
3316 val
= 1 + tval
+ eval
;
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.]
3332 SeeAlso [cuddUniqueInter]
3334 ******************************************************************************/
3344 DdNodePtr
*nodelist
;
3346 DdSubtable
*subtable
;
3348 if (index
>= unique
->size
) {
3352 level
= unique
->perm
[index
];
3353 subtable
= &(unique
->subtables
[level
]);
3356 assert(level
< (unsigned) cuddI(unique
,T
->index
));
3357 assert(level
< (unsigned) cuddI(unique
,Cudd_Regular(E
)->index
));
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
) {
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
3393 ******************************************************************************/
3395 cuddEstimateCofactorSimple(
3401 if (Cudd_IsComplement(node
->next
)) {
3404 node
->next
= Cudd_Not(node
->next
);
3405 if (cuddIsConstant(node
)) {
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:
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
3433 ******************************************************************************/
3438 DdHashTable
* table
)
3440 DdNode
*N
, *Nt
, *Ne
;
3441 double min
, minT
, minE
;
3444 N
= Cudd_Regular(node
);
3446 if (cuddIsConstant(N
)) {
3447 if (node
== background
|| node
== zero
) {
3453 if (N
->ref
!= 1 && (res
= cuddHashTableLookup1(table
,node
)) != NULL
) {
3455 if (res
->ref
== 0) {
3456 table
->manager
->dead
++;
3457 table
->manager
->constants
.dead
++;
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
);
3470 minE
= ddCountMintermAux(Ne
,max
,table
);
3471 if (minE
== (double)CUDD_OUT_OF_MEM
) return((double)CUDD_OUT_OF_MEM
);
3476 ptrint fanout
= (ptrint
) N
->ref
;
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
);
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:
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.]
3506 ******************************************************************************/
3514 double paths
, *ppaths
, paths1
, paths2
;
3518 if (cuddIsConstant(node
)) {
3521 if (st_lookup(table
, node
, &dummy
)) {
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
);
3541 if (st_add_direct(table
,(char *)node
, (char *)ppaths
) == ST_OUT_OF_MEM
) {
3543 return((double)CUDD_OUT_OF_MEM
);
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:
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
3567 ******************************************************************************/
3569 ddEpdCountMintermAux(
3576 EpDouble
*min
, minT
, minE
;
3580 /* node is assumed to be regular */
3581 if (cuddIsConstant(node
)) {
3582 if (node
== background
|| node
== zero
) {
3583 EpdMakeZero(epd
, 0);
3589 if (node
->ref
!= 1 && st_lookup(table
, node
, &res
)) {
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) {
3611 return(CUDD_OUT_OF_MEM
);
3613 if (st_insert(table
, (char *)node
, (char *)min
) == ST_OUT_OF_MEM
) {
3615 return(CUDD_OUT_OF_MEM
);
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:
3634 where f0 and f1 are the two cofactors of f. Returns the number of
3635 paths of the function rooted at node.]
3639 ******************************************************************************/
3641 ddCountPathsToNonZero(
3646 DdNode
*node
, *Nt
, *Ne
;
3647 double paths
, *ppaths
, paths1
, paths2
;
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
)) {
3659 Nt
= cuddT(node
); Ne
= cuddE(node
);
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
);
3677 if (st_add_direct(table
,(char *)N
, (char *)ppaths
) == ST_OUT_OF_MEM
) {
3679 return((double)CUDD_OUT_OF_MEM
);
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.]
3696 SeeAlso [ddClearFlag]
3698 ******************************************************************************/
3704 if (cuddIsConstant(f
) || Cudd_IsComplement(f
->next
)) {
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
);
3715 } /* end of ddSupportStep */
3718 /**Function********************************************************************
3720 Synopsis [Performs a DFS from f, clearing the LSB of the next
3727 SeeAlso [ddSupportStep ddDagInt]
3729 ******************************************************************************/
3734 if (!Cudd_IsComplement(f
->next
)) {
3737 /* Clear visited flag. */
3738 f
->next
= Cudd_Regular(f
->next
);
3739 if (cuddIsConstant(f
)) {
3742 ddClearFlag(cuddT(f
));
3743 ddClearFlag(Cudd_Regular(cuddE(f
)));
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.]
3758 SeeAlso [Cudd_CountLeaves]
3760 ******************************************************************************/
3767 if (Cudd_IsComplement(n
->next
)) {
3770 n
->next
= Cudd_Not(n
->next
);
3771 if (cuddIsConstant(n
)) {
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.]
3790 SeeAlso [Cudd_bddPickArbitraryMinterms]
3792 ******************************************************************************/
3794 ddPickArbitraryMinterms(
3802 DdNode
*one
, *bzero
;
3806 if (string
== NULL
|| node
== NULL
) return(0);
3808 /* The constant 0 function has no on-set cubes. */
3810 bzero
= Cudd_Not(one
);
3811 if (nminterms
== 0 || node
== bzero
) 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]);
3836 result
= ddPickArbitraryMinterms(dd
,E
,nvars
,nminterms
-t
,&string
[t
]);
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 ******************************************************************************/
3855 ddPickRepresentativeCube(
3862 DdNode
*one
, *bzero
;
3864 if (string
== NULL
|| node
== NULL
) return(0);
3866 /* The constant 0 function has no on-set cubes. */
3868 bzero
= Cudd_Not(one
);
3869 if (node
== bzero
) return(0);
3871 if (node
== DD_ONE(dd
)) return(1);
3874 N
= Cudd_Regular(node
);
3879 if (Cudd_IsComplement(node
)) {
3883 if (weight
[N
->index
] >= 0.0) {
3886 string
[N
->index
] = '0';
3889 string
[N
->index
] = '1';
3894 string
[N
->index
] = '1';
3897 string
[N
->index
] = '0';
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.]
3916 ******************************************************************************/
3917 static enum st_retval
3925 epd
= (EpDouble
*) value
;
3927 return(ST_CONTINUE
);
3929 } /* end of ddEpdFree */