1 /**CFile***********************************************************************
3 FileName [cuddGenCof.c]
7 Synopsis [Generalized cofactors for BDDs and ADDs.]
9 Description [External procedures included in this module:
11 <li> Cudd_bddConstrain()
12 <li> Cudd_bddRestrict()
14 <li> Cudd_addConstrain()
15 <li> Cudd_bddConstrainDecomp()
16 <li> Cudd_addRestrict()
17 <li> Cudd_bddCharToVect()
18 <li> Cudd_bddLICompaction()
19 <li> Cudd_bddSqueeze()
20 <li> Cudd_SubsetCompress()
21 <li> Cudd_SupersetCompress()
23 Internal procedures included in this module:
25 <li> cuddBddConstrainRecur()
26 <li> cuddBddRestrictRecur()
27 <li> cuddBddNPAndRecur()
28 <li> cuddAddConstrainRecur()
29 <li> cuddAddRestrictRecur()
30 <li> cuddBddLICompaction()
32 Static procedures included in this module:
34 <li> cuddBddConstrainDecomp()
35 <li> cuddBddCharToVect()
36 <li> cuddBddLICMarkEdges()
37 <li> cuddBddLICBuildResult()
42 Author [Fabio Somenzi]
44 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
48 Redistribution and use in source and binary forms, with or without
49 modification, are permitted provided that the following conditions
52 Redistributions of source code must retain the above copyright
53 notice, this list of conditions and the following disclaimer.
55 Redistributions in binary form must reproduce the above copyright
56 notice, this list of conditions and the following disclaimer in the
57 documentation and/or other materials provided with the distribution.
59 Neither the name of the University of Colorado nor the names of its
60 contributors may be used to endorse or promote products derived from
61 this software without specific prior written permission.
63 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
64 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
65 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
66 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
67 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
68 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
69 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
70 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
71 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
72 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
73 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
74 POSSIBILITY OF SUCH DAMAGE.]
76 ******************************************************************************/
82 /*---------------------------------------------------------------------------*/
83 /* Constant declarations */
84 /*---------------------------------------------------------------------------*/
86 /* Codes for edge markings in Cudd_bddLICompaction. The codes are defined
87 ** so that they can be bitwise ORed to implement the code priority scheme.
94 /*---------------------------------------------------------------------------*/
95 /* Stucture declarations */
96 /*---------------------------------------------------------------------------*/
99 /*---------------------------------------------------------------------------*/
100 /* Type declarations */
101 /*---------------------------------------------------------------------------*/
103 /* Key for the cache used in the edge marking phase. */
104 typedef struct MarkCacheKey
{
109 /*---------------------------------------------------------------------------*/
110 /* Variable declarations */
111 /*---------------------------------------------------------------------------*/
114 static char rcsid
[] DD_UNUSED
= "$Id: cuddGenCof.c,v 1.38 2005/05/14 17:27:11 fabio Exp $";
117 /*---------------------------------------------------------------------------*/
118 /* Macro declarations */
119 /*---------------------------------------------------------------------------*/
125 /**AutomaticStart*************************************************************/
127 /*---------------------------------------------------------------------------*/
128 /* Static function prototypes */
129 /*---------------------------------------------------------------------------*/
131 static int cuddBddConstrainDecomp (DdManager
*dd
, DdNode
*f
, DdNode
**decomp
);
132 static DdNode
* cuddBddCharToVect (DdManager
*dd
, DdNode
*f
, DdNode
*x
);
133 static int cuddBddLICMarkEdges (DdManager
*dd
, DdNode
*f
, DdNode
*c
, st_table
*table
, st_table
*cache
);
134 static DdNode
* cuddBddLICBuildResult (DdManager
*dd
, DdNode
*f
, st_table
*cache
, st_table
*table
);
135 static int MarkCacheHash (char *ptr
, int modulus
);
136 static int MarkCacheCompare (const char *ptr1
, const char *ptr2
);
137 static enum st_retval
MarkCacheCleanUp (char *key
, char *value
, char *arg
);
138 static DdNode
* cuddBddSqueeze (DdManager
*dd
, DdNode
*l
, DdNode
*u
);
140 /**AutomaticEnd***************************************************************/
146 /*---------------------------------------------------------------------------*/
147 /* Definition of exported functions */
148 /*---------------------------------------------------------------------------*/
151 /**Function********************************************************************
153 Synopsis [Computes f constrain c.]
155 Description [Computes f constrain c (f @ c).
156 Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true
157 for c.) List of special cases:
166 Returns a pointer to the result if successful; NULL otherwise. Note that if
167 F=(f1,...,fn) and reordering takes place while computing F @ c, then the
168 image restriction property (Img(F,c) = Img(F @ c)) is lost.]
172 SeeAlso [Cudd_bddRestrict Cudd_addConstrain]
174 ******************************************************************************/
185 res
= cuddBddConstrainRecur(dd
,f
,c
);
186 } while (dd
->reordered
== 1);
189 } /* end of Cudd_bddConstrain */
192 /**Function********************************************************************
194 Synopsis [BDD restrict according to Coudert and Madre's algorithm
197 Description [BDD restrict according to Coudert and Madre's algorithm
198 (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.
199 If application of restrict results in a BDD larger than the input
200 BDD, the input BDD is returned.]
204 SeeAlso [Cudd_bddConstrain Cudd_addRestrict]
206 ******************************************************************************/
213 DdNode
*suppF
, *suppC
, *commonSupport
;
218 /* Check terminal cases here to avoid computing supports in trivial cases.
219 ** This also allows us notto check later for the case c == 0, in which
220 ** there is no common support. */
221 if (c
== Cudd_Not(DD_ONE(dd
))) return(Cudd_Not(DD_ONE(dd
)));
222 if (Cudd_IsConstant(f
)) return(f
);
223 if (f
== c
) return(DD_ONE(dd
));
224 if (f
== Cudd_Not(c
)) return(Cudd_Not(DD_ONE(dd
)));
226 /* Check if supports intersect. */
227 retval
= Cudd_ClassifySupport(dd
,f
,c
,&commonSupport
,&suppF
,&suppC
);
231 cuddRef(commonSupport
); cuddRef(suppF
); cuddRef(suppC
);
232 Cudd_IterDerefBdd(dd
,suppF
);
234 if (commonSupport
== DD_ONE(dd
)) {
235 Cudd_IterDerefBdd(dd
,commonSupport
);
236 Cudd_IterDerefBdd(dd
,suppC
);
239 Cudd_IterDerefBdd(dd
,commonSupport
);
241 /* Abstract from c the variables that do not appear in f. */
242 cplus
= Cudd_bddExistAbstract(dd
, c
, suppC
);
244 Cudd_IterDerefBdd(dd
,suppC
);
248 Cudd_IterDerefBdd(dd
,suppC
);
252 res
= cuddBddRestrictRecur(dd
, f
, cplus
);
253 } while (dd
->reordered
== 1);
255 Cudd_IterDerefBdd(dd
,cplus
);
259 Cudd_IterDerefBdd(dd
,cplus
);
260 /* Make restric safe by returning the smaller of the input and the
262 sizeF
= Cudd_DagSize(f
);
263 sizeRes
= Cudd_DagSize(res
);
264 if (sizeF
<= sizeRes
) {
265 Cudd_IterDerefBdd(dd
, res
);
272 } /* end of Cudd_bddRestrict */
275 /**Function********************************************************************
277 Synopsis [Computes f non-polluting-and g.]
279 Description [Computes f non-polluting-and g. The non-polluting AND
280 of f and g is a hybrid of AND and Restrict. From Restrict, this
281 operation takes the idea of existentially quantifying the top
282 variable of the second operand if it does not appear in the first.
283 Therefore, the variables that appear in the result also appear in f.
284 For the rest, the function behaves like AND. Since the two operands
285 play different roles, non-polluting AND is not commutative.
287 Returns a pointer to the result if successful; NULL otherwise.]
291 SeeAlso [Cudd_bddConstrain Cudd_bddRestrict]
293 ******************************************************************************/
304 res
= cuddBddNPAndRecur(dd
,f
,g
);
305 } while (dd
->reordered
== 1);
308 } /* end of Cudd_bddNPAnd */
311 /**Function********************************************************************
313 Synopsis [Computes f constrain c for ADDs.]
315 Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1
316 ADD. List of special cases:
324 Returns a pointer to the result if successful; NULL otherwise.]
328 SeeAlso [Cudd_bddConstrain]
330 ******************************************************************************/
341 res
= cuddAddConstrainRecur(dd
,f
,c
);
342 } while (dd
->reordered
== 1);
345 } /* end of Cudd_addConstrain */
348 /**Function********************************************************************
350 Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.]
352 Description [BDD conjunctive decomposition as in McMillan's CAV96
353 paper. The decomposition is canonical only for a given variable
354 order. If canonicity is required, variable ordering must be disabled
355 after the decomposition has been computed. Returns an array with one
356 entry for each BDD variable in the manager if successful; otherwise
357 NULL. The components of the solution have their reference counts
358 already incremented (unlike the results of most other functions in
363 SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract]
365 ******************************************************************************/
367 Cudd_bddConstrainDecomp(
375 /* Create an initialize decomposition array. */
376 decomp
= ALLOC(DdNode
*,dd
->size
);
377 if (decomp
== NULL
) {
378 dd
->errorCode
= CUDD_MEMORY_OUT
;
381 for (i
= 0; i
< dd
->size
; i
++) {
386 /* Clean up the decomposition array in case reordering took place. */
387 for (i
= 0; i
< dd
->size
; i
++) {
388 if (decomp
[i
] != NULL
) {
389 Cudd_IterDerefBdd(dd
, decomp
[i
]);
393 res
= cuddBddConstrainDecomp(dd
,f
,decomp
);
394 } while (dd
->reordered
== 1);
399 /* Missing components are constant ones. */
400 for (i
= 0; i
< dd
->size
; i
++) {
401 if (decomp
[i
] == NULL
) {
402 decomp
[i
] = DD_ONE(dd
);
408 } /* end of Cudd_bddConstrainDecomp */
411 /**Function********************************************************************
413 Synopsis [ADD restrict according to Coudert and Madre's algorithm
416 Description [ADD restrict according to Coudert and Madre's algorithm
417 (ICCAD90). Returns the restricted ADD if successful; otherwise NULL.
418 If application of restrict results in an ADD larger than the input
419 ADD, the input ADD is returned.]
423 SeeAlso [Cudd_addConstrain Cudd_bddRestrict]
425 ******************************************************************************/
432 DdNode
*supp_f
, *supp_c
;
433 DdNode
*res
, *commonSupport
;
437 /* Check if supports intersect. */
438 supp_f
= Cudd_Support(dd
, f
);
439 if (supp_f
== NULL
) {
443 supp_c
= Cudd_Support(dd
, c
);
444 if (supp_c
== NULL
) {
445 Cudd_RecursiveDeref(dd
,supp_f
);
449 commonSupport
= Cudd_bddLiteralSetIntersection(dd
, supp_f
, supp_c
);
450 if (commonSupport
== NULL
) {
451 Cudd_RecursiveDeref(dd
,supp_f
);
452 Cudd_RecursiveDeref(dd
,supp_c
);
455 cuddRef(commonSupport
);
456 Cudd_RecursiveDeref(dd
,supp_f
);
457 Cudd_RecursiveDeref(dd
,supp_c
);
458 intersection
= commonSupport
!= DD_ONE(dd
);
459 Cudd_RecursiveDeref(dd
,commonSupport
);
464 res
= cuddAddRestrictRecur(dd
, f
, c
);
465 } while (dd
->reordered
== 1);
466 sizeF
= Cudd_DagSize(f
);
467 sizeRes
= Cudd_DagSize(res
);
468 if (sizeF
<= sizeRes
) {
470 Cudd_RecursiveDeref(dd
, res
);
479 } /* end of Cudd_addRestrict */
482 /**Function********************************************************************
484 Synopsis [Computes a vector whose image equals a non-zero function.]
486 Description [Computes a vector of BDDs whose image equals a non-zero
488 The result depends on the variable order. The i-th component of the vector
489 depends only on the first i variables in the order. Each BDD in the vector
490 is not larger than the BDD of the given characteristic function. This
491 function is based on the description of char-to-vect in "Verification of
492 Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C.
493 Berthet and J. C. Madre.
494 Returns a pointer to an array containing the result if successful; NULL
495 otherwise. The size of the array equals the number of variables in the
496 manager. The components of the solution have their reference counts
497 already incremented (unlike the results of most other functions in
502 SeeAlso [Cudd_bddConstrain]
504 ******************************************************************************/
514 if (f
== Cudd_Not(DD_ONE(dd
))) return(NULL
);
516 vect
= ALLOC(DdNode
*, dd
->size
);
518 dd
->errorCode
= CUDD_MEMORY_OUT
;
524 for (i
= 0; i
< dd
->size
; i
++) {
525 res
= cuddBddCharToVect(dd
,f
,dd
->vars
[dd
->invperm
[i
]]);
527 /* Clean up the vector array in case reordering took place. */
528 for (j
= 0; j
< i
; j
++) {
529 Cudd_IterDerefBdd(dd
, vect
[dd
->invperm
[j
]]);
534 vect
[dd
->invperm
[i
]] = res
;
536 } while (dd
->reordered
== 1);
543 } /* end of Cudd_bddCharToVect */
546 /**Function********************************************************************
548 Synopsis [Performs safe minimization of a BDD.]
550 Description [Performs safe minimization of a BDD. Given the BDD
551 <code>f</code> of a function to be minimized and a BDD
552 <code>c</code> representing the care set, Cudd_bddLICompaction
553 produces the BDD of a function that agrees with <code>f</code>
554 wherever <code>c</code> is 1. Safe minimization means that the size
555 of the result is guaranteed not to exceed the size of
556 <code>f</code>. This function is based on the DAC97 paper by Hong et
557 al.. Returns a pointer to the result if successful; NULL
562 SeeAlso [Cudd_bddRestrict]
564 ******************************************************************************/
566 Cudd_bddLICompaction(
567 DdManager
* dd
/* manager */,
568 DdNode
* f
/* function to be minimized */,
569 DdNode
* c
/* constraint (care set) */)
575 res
= cuddBddLICompaction(dd
,f
,c
);
576 } while (dd
->reordered
== 1);
579 } /* end of Cudd_bddLICompaction */
582 /**Function********************************************************************
584 Synopsis [Finds a small BDD in a function interval.]
586 Description [Finds a small BDD in a function interval. Given BDDs
587 <code>l</code> and <code>u</code>, representing the lower bound and
588 upper bound of a function interval, Cudd_bddSqueeze produces the BDD
589 of a function within the interval with a small BDD. Returns a
590 pointer to the result if successful; NULL otherwise.]
594 SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction]
596 ******************************************************************************/
599 DdManager
* dd
/* manager */,
600 DdNode
* l
/* lower bound */,
601 DdNode
* u
/* upper bound */)
604 int sizeRes
, sizeL
, sizeU
;
608 res
= cuddBddSqueeze(dd
,l
,u
);
609 } while (dd
->reordered
== 1);
610 if (res
== NULL
) return(NULL
);
611 /* We now compare the result with the bounds and return the smallest.
612 ** We first compare to u, so that in case l == 0 and u == 1, we return
613 ** 0 as in other minimization algorithms. */
614 sizeRes
= Cudd_DagSize(res
);
615 sizeU
= Cudd_DagSize(u
);
616 if (sizeU
<= sizeRes
) {
618 Cudd_IterDerefBdd(dd
,res
);
622 sizeL
= Cudd_DagSize(l
);
623 if (sizeL
<= sizeRes
) {
625 Cudd_IterDerefBdd(dd
,res
);
631 } /* end of Cudd_bddSqueeze */
634 /**Function********************************************************************
636 Synopsis [Finds a small BDD that agrees with <code>f</code> over
639 Description [Finds a small BDD that agrees with <code>f</code> over
640 <code>c</code>. Returns a pointer to the result if successful; NULL
645 SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze]
647 ******************************************************************************/
656 if (c
== Cudd_Not(DD_ONE(dd
))) return(c
);
657 if (Cudd_IsConstant(f
)) return(f
);
658 if (f
== c
) return(DD_ONE(dd
));
659 if (f
== Cudd_Not(c
)) return(Cudd_Not(DD_ONE(dd
)));
661 cplus
= Cudd_RemapOverApprox(dd
,c
,0,0,1.0);
662 if (cplus
== NULL
) return(NULL
);
664 res
= Cudd_bddLICompaction(dd
,f
,cplus
);
666 Cudd_IterDerefBdd(dd
,cplus
);
670 Cudd_IterDerefBdd(dd
,cplus
);
674 } /* end of Cudd_bddMinimize */
677 /**Function********************************************************************
679 Synopsis [Find a dense subset of BDD <code>f</code>.]
681 Description [Finds a dense subset of BDD <code>f</code>. Density is
682 the ratio of number of minterms to number of nodes. Uses several
683 techniques in series. It is more expensive than other subsetting
684 procedures, but often produces better results. See
685 Cudd_SubsetShortPaths for a description of the threshold and nvars
686 parameters. Returns a pointer to the result if successful; NULL
691 SeeAlso [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch
694 ******************************************************************************/
697 DdManager
* dd
/* manager */,
698 DdNode
* f
/* BDD whose subset is sought */,
699 int nvars
/* number of variables in the support of f */,
700 int threshold
/* maximum number of nodes in the subset */)
702 DdNode
*res
, *tmp1
, *tmp2
;
704 tmp1
= Cudd_SubsetShortPaths(dd
, f
, nvars
, threshold
, 0);
705 if (tmp1
== NULL
) return(NULL
);
707 tmp2
= Cudd_RemapUnderApprox(dd
,tmp1
,nvars
,0,1.0);
709 Cudd_IterDerefBdd(dd
,tmp1
);
713 Cudd_IterDerefBdd(dd
,tmp1
);
714 res
= Cudd_bddSqueeze(dd
,tmp2
,f
);
716 Cudd_IterDerefBdd(dd
,tmp2
);
720 Cudd_IterDerefBdd(dd
,tmp2
);
724 } /* end of Cudd_SubsetCompress */
727 /**Function********************************************************************
729 Synopsis [Find a dense superset of BDD <code>f</code>.]
731 Description [Finds a dense superset of BDD <code>f</code>. Density is
732 the ratio of number of minterms to number of nodes. Uses several
733 techniques in series. It is more expensive than other supersetting
734 procedures, but often produces better results. See
735 Cudd_SupersetShortPaths for a description of the threshold and nvars
736 parameters. Returns a pointer to the result if successful; NULL
741 SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths
742 Cudd_SupersetHeavyBranch Cudd_bddSqueeze]
744 ******************************************************************************/
746 Cudd_SupersetCompress(
747 DdManager
* dd
/* manager */,
748 DdNode
* f
/* BDD whose superset is sought */,
749 int nvars
/* number of variables in the support of f */,
750 int threshold
/* maximum number of nodes in the superset */)
754 subset
= Cudd_SubsetCompress(dd
, Cudd_Not(f
),nvars
,threshold
);
756 return(Cudd_NotCond(subset
, (subset
!= NULL
)));
758 } /* end of Cudd_SupersetCompress */
761 /*---------------------------------------------------------------------------*/
762 /* Definition of internal functions */
763 /*---------------------------------------------------------------------------*/
766 /**Function********************************************************************
768 Synopsis [Performs the recursive step of Cudd_bddConstrain.]
770 Description [Performs the recursive step of Cudd_bddConstrain.
771 Returns a pointer to the result if successful; NULL otherwise.]
775 SeeAlso [Cudd_bddConstrain]
777 ******************************************************************************/
779 cuddBddConstrainRecur(
784 DdNode
*Fv
, *Fnv
, *Cv
, *Cnv
, *t
, *e
, *r
;
786 unsigned int topf
, topc
;
792 zero
= Cudd_Not(one
);
795 if (c
== one
) return(f
);
796 if (c
== zero
) return(zero
);
797 if (Cudd_IsConstant(f
)) return(f
);
798 if (f
== c
) return(one
);
799 if (f
== Cudd_Not(c
)) return(zero
);
801 /* Make canonical to increase the utilization of the cache. */
802 if (Cudd_IsComplement(f
)) {
806 /* Now f is a regular pointer to a non-constant node; c is also
807 ** non-constant, but may be complemented.
810 /* Check the cache. */
811 r
= cuddCacheLookup2(dd
, Cudd_bddConstrain
, f
, c
);
813 return(Cudd_NotCond(r
,comple
));
816 /* Recursive step. */
817 topf
= dd
->perm
[f
->index
];
818 topc
= dd
->perm
[Cudd_Regular(c
)->index
];
821 Fv
= cuddT(f
); Fnv
= cuddE(f
);
823 index
= Cudd_Regular(c
)->index
;
827 Cv
= cuddT(Cudd_Regular(c
)); Cnv
= cuddE(Cudd_Regular(c
));
828 if (Cudd_IsComplement(c
)) {
836 if (!Cudd_IsConstant(Cv
)) {
837 t
= cuddBddConstrainRecur(dd
, Fv
, Cv
);
840 } else if (Cv
== one
) {
842 } else { /* Cv == zero: return Fnv @ Cnv */
846 r
= cuddBddConstrainRecur(dd
, Fnv
, Cnv
);
850 return(Cudd_NotCond(r
,comple
));
854 if (!Cudd_IsConstant(Cnv
)) {
855 e
= cuddBddConstrainRecur(dd
, Fnv
, Cnv
);
857 Cudd_IterDerefBdd(dd
, t
);
860 } else if (Cnv
== one
) {
862 } else { /* Cnv == zero: return Fv @ Cv previously computed */
864 return(Cudd_NotCond(t
,comple
));
868 if (Cudd_IsComplement(t
)) {
871 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
873 Cudd_IterDerefBdd(dd
, e
);
874 Cudd_IterDerefBdd(dd
, t
);
879 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
881 Cudd_IterDerefBdd(dd
, e
);
882 Cudd_IterDerefBdd(dd
, t
);
889 cuddCacheInsert2(dd
, Cudd_bddConstrain
, f
, c
, r
);
890 return(Cudd_NotCond(r
,comple
));
892 } /* end of cuddBddConstrainRecur */
895 /**Function********************************************************************
897 Synopsis [Performs the recursive step of Cudd_bddRestrict.]
899 Description [Performs the recursive step of Cudd_bddRestrict.
900 Returns the restricted BDD if successful; otherwise NULL.]
904 SeeAlso [Cudd_bddRestrict]
906 ******************************************************************************/
908 cuddBddRestrictRecur(
913 DdNode
*Fv
, *Fnv
, *Cv
, *Cnv
, *t
, *e
, *r
, *one
, *zero
;
914 unsigned int topf
, topc
;
920 zero
= Cudd_Not(one
);
923 if (c
== one
) return(f
);
924 if (c
== zero
) return(zero
);
925 if (Cudd_IsConstant(f
)) return(f
);
926 if (f
== c
) return(one
);
927 if (f
== Cudd_Not(c
)) return(zero
);
929 /* Make canonical to increase the utilization of the cache. */
930 if (Cudd_IsComplement(f
)) {
934 /* Now f is a regular pointer to a non-constant node; c is also
935 ** non-constant, but may be complemented.
938 /* Check the cache. */
939 r
= cuddCacheLookup2(dd
, Cudd_bddRestrict
, f
, c
);
941 return(Cudd_NotCond(r
,comple
));
944 topf
= dd
->perm
[f
->index
];
945 topc
= dd
->perm
[Cudd_Regular(c
)->index
];
947 if (topc
< topf
) { /* abstract top variable from c */
950 /* Find complements of cofactors of c. */
951 if (Cudd_IsComplement(c
)) {
952 s1
= cuddT(Cudd_Regular(c
));
953 s2
= cuddE(Cudd_Regular(c
));
955 s1
= Cudd_Not(cuddT(c
));
956 s2
= Cudd_Not(cuddE(c
));
958 /* Take the OR by applying DeMorgan. */
959 d
= cuddBddAndRecur(dd
, s1
, s2
);
960 if (d
== NULL
) return(NULL
);
963 r
= cuddBddRestrictRecur(dd
, f
, d
);
965 Cudd_IterDerefBdd(dd
, d
);
969 Cudd_IterDerefBdd(dd
, d
);
970 cuddCacheInsert2(dd
, Cudd_bddRestrict
, f
, c
, r
);
972 return(Cudd_NotCond(r
,comple
));
975 /* Recursive step. Here topf <= topc. */
977 Fv
= cuddT(f
); Fnv
= cuddE(f
);
979 Cv
= cuddT(Cudd_Regular(c
)); Cnv
= cuddE(Cudd_Regular(c
));
980 if (Cudd_IsComplement(c
)) {
988 if (!Cudd_IsConstant(Cv
)) {
989 t
= cuddBddRestrictRecur(dd
, Fv
, Cv
);
990 if (t
== NULL
) return(NULL
);
991 } else if (Cv
== one
) {
993 } else { /* Cv == zero: return(Fnv @ Cnv) */
997 r
= cuddBddRestrictRecur(dd
, Fnv
, Cnv
);
998 if (r
== NULL
) return(NULL
);
1000 return(Cudd_NotCond(r
,comple
));
1004 if (!Cudd_IsConstant(Cnv
)) {
1005 e
= cuddBddRestrictRecur(dd
, Fnv
, Cnv
);
1007 Cudd_IterDerefBdd(dd
, t
);
1010 } else if (Cnv
== one
) {
1012 } else { /* Cnv == zero: return (Fv @ Cv) previously computed */
1014 return(Cudd_NotCond(t
,comple
));
1018 if (Cudd_IsComplement(t
)) {
1021 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
1023 Cudd_IterDerefBdd(dd
, e
);
1024 Cudd_IterDerefBdd(dd
, t
);
1029 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
1031 Cudd_IterDerefBdd(dd
, e
);
1032 Cudd_IterDerefBdd(dd
, t
);
1039 cuddCacheInsert2(dd
, Cudd_bddRestrict
, f
, c
, r
);
1040 return(Cudd_NotCond(r
,comple
));
1042 } /* end of cuddBddRestrictRecur */
1045 /**Function********************************************************************
1047 Synopsis [Implements the recursive step of Cudd_bddAnd.]
1049 Description [Implements the recursive step of Cudd_bddNPAnd.
1050 Returns a pointer to the result is successful; NULL otherwise.]
1054 SeeAlso [Cudd_bddNPAnd]
1056 ******************************************************************************/
1059 DdManager
* manager
,
1063 DdNode
*F
, *ft
, *fe
, *G
, *gt
, *ge
;
1064 DdNode
*one
, *r
, *t
, *e
;
1065 unsigned int topf
, topg
, index
;
1068 one
= DD_ONE(manager
);
1070 /* Terminal cases. */
1071 F
= Cudd_Regular(f
);
1072 G
= Cudd_Regular(g
);
1074 if (f
== g
) return(one
);
1075 else return(Cudd_Not(one
));
1078 if (g
== one
) return(f
);
1085 /* At this point f and g are not constant. */
1087 if (F
->ref
!= 1 || G
->ref
!= 1) {
1088 r
= cuddCacheLookup2(manager
, Cudd_bddNPAnd
, f
, g
);
1089 if (r
!= NULL
) return(r
);
1092 /* Here we can skip the use of cuddI, because the operands are known
1093 ** to be non-constant.
1095 topf
= manager
->perm
[F
->index
];
1096 topg
= manager
->perm
[G
->index
];
1098 if (topg
< topf
) { /* abstract top variable from g */
1101 /* Find complements of cofactors of g. */
1102 if (Cudd_IsComplement(g
)) {
1106 gt
= Cudd_Not(cuddT(g
));
1107 ge
= Cudd_Not(cuddE(g
));
1109 /* Take the OR by applying DeMorgan. */
1110 d
= cuddBddAndRecur(manager
, gt
, ge
);
1111 if (d
== NULL
) return(NULL
);
1114 r
= cuddBddNPAndRecur(manager
, f
, d
);
1116 Cudd_IterDerefBdd(manager
, d
);
1120 Cudd_IterDerefBdd(manager
, d
);
1121 cuddCacheInsert2(manager
, Cudd_bddNPAnd
, f
, g
, r
);
1126 /* Compute cofactors. */
1130 if (Cudd_IsComplement(f
)) {
1138 if (Cudd_IsComplement(g
)) {
1146 t
= cuddBddAndRecur(manager
, ft
, gt
);
1147 if (t
== NULL
) return(NULL
);
1150 e
= cuddBddAndRecur(manager
, fe
, ge
);
1152 Cudd_IterDerefBdd(manager
, t
);
1160 if (Cudd_IsComplement(t
)) {
1161 r
= cuddUniqueInter(manager
,(int)index
,Cudd_Not(t
),Cudd_Not(e
));
1163 Cudd_IterDerefBdd(manager
, t
);
1164 Cudd_IterDerefBdd(manager
, e
);
1169 r
= cuddUniqueInter(manager
,(int)index
,t
,e
);
1171 Cudd_IterDerefBdd(manager
, t
);
1172 Cudd_IterDerefBdd(manager
, e
);
1179 if (F
->ref
!= 1 || G
->ref
!= 1)
1180 cuddCacheInsert2(manager
, Cudd_bddNPAnd
, f
, g
, r
);
1183 } /* end of cuddBddNPAndRecur */
1186 /**Function********************************************************************
1188 Synopsis [Performs the recursive step of Cudd_addConstrain.]
1190 Description [Performs the recursive step of Cudd_addConstrain.
1191 Returns a pointer to the result if successful; NULL otherwise.]
1195 SeeAlso [Cudd_addConstrain]
1197 ******************************************************************************/
1199 cuddAddConstrainRecur(
1204 DdNode
*Fv
, *Fnv
, *Cv
, *Cnv
, *t
, *e
, *r
;
1206 unsigned int topf
, topc
;
1213 /* Trivial cases. */
1214 if (c
== one
) return(f
);
1215 if (c
== zero
) return(zero
);
1216 if (Cudd_IsConstant(f
)) return(f
);
1217 if (f
== c
) return(one
);
1219 /* Now f and c are non-constant. */
1221 /* Check the cache. */
1222 r
= cuddCacheLookup2(dd
, Cudd_addConstrain
, f
, c
);
1227 /* Recursive step. */
1228 topf
= dd
->perm
[f
->index
];
1229 topc
= dd
->perm
[c
->index
];
1232 Fv
= cuddT(f
); Fnv
= cuddE(f
);
1238 Cv
= cuddT(c
); Cnv
= cuddE(c
);
1243 if (!Cudd_IsConstant(Cv
)) {
1244 t
= cuddAddConstrainRecur(dd
, Fv
, Cv
);
1247 } else if (Cv
== one
) {
1249 } else { /* Cv == zero: return Fnv @ Cnv */
1253 r
= cuddAddConstrainRecur(dd
, Fnv
, Cnv
);
1261 if (!Cudd_IsConstant(Cnv
)) {
1262 e
= cuddAddConstrainRecur(dd
, Fnv
, Cnv
);
1264 Cudd_RecursiveDeref(dd
, t
);
1267 } else if (Cnv
== one
) {
1269 } else { /* Cnv == zero: return Fv @ Cv previously computed */
1275 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
1277 Cudd_RecursiveDeref(dd
, e
);
1278 Cudd_RecursiveDeref(dd
, t
);
1284 cuddCacheInsert2(dd
, Cudd_addConstrain
, f
, c
, r
);
1287 } /* end of cuddAddConstrainRecur */
1290 /**Function********************************************************************
1292 Synopsis [Performs the recursive step of Cudd_addRestrict.]
1294 Description [Performs the recursive step of Cudd_addRestrict.
1295 Returns the restricted ADD if successful; otherwise NULL.]
1299 SeeAlso [Cudd_addRestrict]
1301 ******************************************************************************/
1303 cuddAddRestrictRecur(
1308 DdNode
*Fv
, *Fnv
, *Cv
, *Cnv
, *t
, *e
, *r
, *one
, *zero
;
1309 unsigned int topf
, topc
;
1317 if (c
== one
) return(f
);
1318 if (c
== zero
) return(zero
);
1319 if (Cudd_IsConstant(f
)) return(f
);
1320 if (f
== c
) return(one
);
1322 /* Now f and c are non-constant. */
1324 /* Check the cache. */
1325 r
= cuddCacheLookup2(dd
, Cudd_addRestrict
, f
, c
);
1330 topf
= dd
->perm
[f
->index
];
1331 topc
= dd
->perm
[c
->index
];
1333 if (topc
< topf
) { /* abstract top variable from c */
1334 DdNode
*d
, *s1
, *s2
;
1336 /* Find cofactors of c. */
1339 /* Take the OR by applying DeMorgan. */
1340 d
= cuddAddApplyRecur(dd
, Cudd_addOr
, s1
, s2
);
1341 if (d
== NULL
) return(NULL
);
1343 r
= cuddAddRestrictRecur(dd
, f
, d
);
1345 Cudd_RecursiveDeref(dd
, d
);
1349 Cudd_RecursiveDeref(dd
, d
);
1350 cuddCacheInsert2(dd
, Cudd_addRestrict
, f
, c
, r
);
1355 /* Recursive step. Here topf <= topc. */
1357 Fv
= cuddT(f
); Fnv
= cuddE(f
);
1359 Cv
= cuddT(c
); Cnv
= cuddE(c
);
1364 if (!Cudd_IsConstant(Cv
)) {
1365 t
= cuddAddRestrictRecur(dd
, Fv
, Cv
);
1366 if (t
== NULL
) return(NULL
);
1367 } else if (Cv
== one
) {
1369 } else { /* Cv == zero: return(Fnv @ Cnv) */
1373 r
= cuddAddRestrictRecur(dd
, Fnv
, Cnv
);
1374 if (r
== NULL
) return(NULL
);
1380 if (!Cudd_IsConstant(Cnv
)) {
1381 e
= cuddAddRestrictRecur(dd
, Fnv
, Cnv
);
1383 Cudd_RecursiveDeref(dd
, t
);
1386 } else if (Cnv
== one
) {
1388 } else { /* Cnv == zero: return (Fv @ Cv) previously computed */
1394 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
1396 Cudd_RecursiveDeref(dd
, e
);
1397 Cudd_RecursiveDeref(dd
, t
);
1403 cuddCacheInsert2(dd
, Cudd_addRestrict
, f
, c
, r
);
1406 } /* end of cuddAddRestrictRecur */
1410 /**Function********************************************************************
1412 Synopsis [Performs safe minimization of a BDD.]
1414 Description [Performs safe minimization of a BDD. Given the BDD
1415 <code>f</code> of a function to be minimized and a BDD
1416 <code>c</code> representing the care set, Cudd_bddLICompaction
1417 produces the BDD of a function that agrees with <code>f</code>
1418 wherever <code>c</code> is 1. Safe minimization means that the size
1419 of the result is guaranteed not to exceed the size of
1420 <code>f</code>. This function is based on the DAC97 paper by Hong et
1421 al.. Returns a pointer to the result if successful; NULL
1426 SeeAlso [Cudd_bddLICompaction]
1428 ******************************************************************************/
1430 cuddBddLICompaction(
1431 DdManager
* dd
/* manager */,
1432 DdNode
* f
/* function to be minimized */,
1433 DdNode
* c
/* constraint (care set) */)
1435 st_table
*marktable
, *markcache
, *buildcache
;
1438 zero
= Cudd_Not(DD_ONE(dd
));
1439 if (c
== zero
) return(zero
);
1441 /* We need to use local caches for both steps of this operation.
1442 ** The results of the edge marking step are only valid as long as the
1443 ** edge markings themselves are available. However, the edge markings
1444 ** are lost at the end of one invocation of Cudd_bddLICompaction.
1445 ** Hence, the cache entries for the edge marking step must be
1446 ** invalidated at the end of this function.
1447 ** For the result of the building step we argue as follows. The result
1448 ** for a node and a given constrain depends on the BDD in which the node
1449 ** appears. Hence, the same node and constrain may give different results
1450 ** in successive invocations.
1452 marktable
= st_init_table(st_ptrcmp
,st_ptrhash
);
1453 if (marktable
== NULL
) {
1456 markcache
= st_init_table(MarkCacheCompare
,MarkCacheHash
);
1457 if (markcache
== NULL
) {
1458 st_free_table(marktable
);
1461 if (cuddBddLICMarkEdges(dd
,f
,c
,marktable
,markcache
) == CUDD_OUT_OF_MEM
) {
1462 st_foreach(markcache
, MarkCacheCleanUp
, NULL
);
1463 st_free_table(marktable
);
1464 st_free_table(markcache
);
1467 st_foreach(markcache
, MarkCacheCleanUp
, NULL
);
1468 st_free_table(markcache
);
1469 buildcache
= st_init_table(st_ptrcmp
,st_ptrhash
);
1470 if (buildcache
== NULL
) {
1471 st_free_table(marktable
);
1474 res
= cuddBddLICBuildResult(dd
,f
,buildcache
,marktable
);
1475 st_free_table(buildcache
);
1476 st_free_table(marktable
);
1479 } /* end of cuddBddLICompaction */
1482 /*---------------------------------------------------------------------------*/
1483 /* Definition of static functions */
1484 /*---------------------------------------------------------------------------*/
1487 /**Function********************************************************************
1489 Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.]
1491 Description [Performs the recursive step of Cudd_bddConstrainDecomp.
1492 Returns f super (i) if successful; otherwise NULL.]
1496 SeeAlso [Cudd_bddConstrainDecomp]
1498 ******************************************************************************/
1500 cuddBddConstrainDecomp(
1505 DdNode
*F
, *fv
, *fvn
;
1510 if (Cudd_IsConstant(f
)) return(1);
1511 /* Compute complements of cofactors. */
1512 F
= Cudd_Regular(f
);
1517 fvn
= Cudd_Not(fvn
);
1519 /* Compute abstraction of top variable. */
1520 fAbs
= cuddBddAndRecur(dd
, fv
, fvn
);
1525 fAbs
= Cudd_Not(fAbs
);
1526 /* Recursively find the next abstraction and the components of the
1527 ** decomposition. */
1528 ok
= cuddBddConstrainDecomp(dd
, fAbs
, decomp
);
1530 Cudd_IterDerefBdd(dd
,fAbs
);
1533 /* Compute the component of the decomposition corresponding to the
1534 ** top variable and store it in the decomposition array. */
1535 result
= cuddBddConstrainRecur(dd
, f
, fAbs
);
1536 if (result
== NULL
) {
1537 Cudd_IterDerefBdd(dd
,fAbs
);
1541 decomp
[F
->index
] = result
;
1542 Cudd_IterDerefBdd(dd
, fAbs
);
1545 } /* end of cuddBddConstrainDecomp */
1548 /**Function********************************************************************
1550 Synopsis [Performs the recursive step of Cudd_bddCharToVect.]
1552 Description [Performs the recursive step of Cudd_bddCharToVect.
1553 This function maintains the invariant that f is non-zero.
1554 Returns the i-th component of the vector if successful; otherwise NULL.]
1558 SeeAlso [Cudd_bddCharToVect]
1560 ******************************************************************************/
1571 DdNode
*one
, *zero
, *res
, *F
, *fT
, *fE
, *T
, *E
;
1574 /* Check the cache. */
1575 res
= cuddCacheLookup2(dd
, cuddBddCharToVect
, f
, x
);
1580 F
= Cudd_Regular(f
);
1582 topf
= cuddI(dd
,F
->index
);
1583 level
= dd
->perm
[x
->index
];
1585 if (topf
> level
) return(x
);
1588 zero
= Cudd_Not(one
);
1591 fT
= Cudd_NotCond(cuddT(F
),comple
);
1592 fE
= Cudd_NotCond(cuddE(F
),comple
);
1594 if (topf
== level
) {
1595 if (fT
== zero
) return(zero
);
1596 if (fE
== zero
) return(one
);
1600 /* Here topf < level. */
1601 if (fT
== zero
) return(cuddBddCharToVect(dd
, fE
, x
));
1602 if (fE
== zero
) return(cuddBddCharToVect(dd
, fT
, x
));
1604 T
= cuddBddCharToVect(dd
, fT
, x
);
1609 E
= cuddBddCharToVect(dd
, fE
, x
);
1611 Cudd_IterDerefBdd(dd
,T
);
1615 res
= cuddBddIteRecur(dd
, dd
->vars
[F
->index
], T
, E
);
1617 Cudd_IterDerefBdd(dd
,T
);
1618 Cudd_IterDerefBdd(dd
,E
);
1623 cuddCacheInsert2(dd
, cuddBddCharToVect
, f
, x
, res
);
1626 } /* end of cuddBddCharToVect */
1629 /**Function********************************************************************
1631 Synopsis [Performs the edge marking step of Cudd_bddLICompaction.]
1633 Description [Performs the edge marking step of Cudd_bddLICompaction.
1634 Returns the LUB of the markings of the two outgoing edges of <code>f</code>
1635 if successful; otherwise CUDD_OUT_OF_MEM.]
1639 SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult]
1641 ******************************************************************************/
1643 cuddBddLICMarkEdges(
1650 DdNode
*Fv
, *Fnv
, *Cv
, *Cnv
;
1652 unsigned int topf
, topc
;
1654 int resT
, resE
, res
, retval
;
1659 zero
= Cudd_Not(one
);
1661 /* Terminal cases. */
1662 if (c
== zero
) return(DD_LIC_DC
);
1663 if (f
== one
) return(DD_LIC_1
);
1664 if (f
== zero
) return(DD_LIC_0
);
1666 /* Make canonical to increase the utilization of the cache. */
1667 comple
= Cudd_IsComplement(f
);
1668 f
= Cudd_Regular(f
);
1669 /* Now f is a regular pointer to a non-constant node; c may be
1670 ** constant, or it may be complemented.
1673 /* Check the cache. */
1674 key
= ALLOC(MarkCacheKey
, 1);
1676 dd
->errorCode
= CUDD_MEMORY_OUT
;
1677 return(CUDD_OUT_OF_MEM
);
1679 key
->f
= f
; key
->c
= c
;
1680 if (st_lookup_int(cache
, (char *)key
, &res
)) {
1683 if (res
== DD_LIC_0
) res
= DD_LIC_1
;
1684 else if (res
== DD_LIC_1
) res
= DD_LIC_0
;
1689 /* Recursive step. */
1690 topf
= dd
->perm
[f
->index
];
1691 topc
= cuddI(dd
,Cudd_Regular(c
)->index
);
1693 Fv
= cuddT(f
); Fnv
= cuddE(f
);
1698 /* We know that c is not constant because f is not. */
1699 Cv
= cuddT(Cudd_Regular(c
)); Cnv
= cuddE(Cudd_Regular(c
));
1700 if (Cudd_IsComplement(c
)) {
1702 Cnv
= Cudd_Not(Cnv
);
1708 resT
= cuddBddLICMarkEdges(dd
, Fv
, Cv
, table
, cache
);
1709 if (resT
== CUDD_OUT_OF_MEM
) {
1711 return(CUDD_OUT_OF_MEM
);
1713 resE
= cuddBddLICMarkEdges(dd
, Fnv
, Cnv
, table
, cache
);
1714 if (resE
== CUDD_OUT_OF_MEM
) {
1716 return(CUDD_OUT_OF_MEM
);
1719 /* Update edge markings. */
1721 retval
= st_find_or_add(table
, (char *)f
, (char ***)&slot
);
1723 *slot
= (char *) (ptrint
)((resT
<< 2) | resE
);
1724 } else if (retval
== 1) {
1725 *slot
= (char *) (ptrint
)((int)((ptrint
) *slot
) | (resT
<< 2) | resE
);
1728 return(CUDD_OUT_OF_MEM
);
1734 if (st_insert(cache
, (char *)key
, (char *)(ptrint
)res
) == ST_OUT_OF_MEM
) {
1736 return(CUDD_OUT_OF_MEM
);
1739 /* Take into account possible complementation. */
1741 if (res
== DD_LIC_0
) res
= DD_LIC_1
;
1742 else if (res
== DD_LIC_1
) res
= DD_LIC_0
;
1746 } /* end of cuddBddLICMarkEdges */
1749 /**Function********************************************************************
1751 Synopsis [Builds the result of Cudd_bddLICompaction.]
1753 Description [Builds the results of Cudd_bddLICompaction.
1754 Returns a pointer to the minimized BDD if successful; otherwise NULL.]
1758 SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges]
1760 ******************************************************************************/
1762 cuddBddLICBuildResult(
1768 DdNode
*Fv
, *Fnv
, *r
, *t
, *e
;
1772 int markT
, markE
, markings
;
1775 zero
= Cudd_Not(one
);
1777 if (Cudd_IsConstant(f
)) return(f
);
1778 /* Make canonical to increase the utilization of the cache. */
1779 comple
= Cudd_IsComplement(f
);
1780 f
= Cudd_Regular(f
);
1782 /* Check the cache. */
1783 if (st_lookup(cache
, f
, &r
)) {
1784 return(Cudd_NotCond(r
,comple
));
1787 /* Retrieve the edge markings. */
1788 if (st_lookup_int(table
, (char *)f
, &markings
) == 0)
1790 markT
= markings
>> 2;
1791 markE
= markings
& 3;
1794 Fv
= cuddT(f
); Fnv
= cuddE(f
);
1796 if (markT
== DD_LIC_NL
) {
1797 t
= cuddBddLICBuildResult(dd
,Fv
,cache
,table
);
1801 } else if (markT
== DD_LIC_1
) {
1807 if (markE
== DD_LIC_NL
) {
1808 e
= cuddBddLICBuildResult(dd
,Fnv
,cache
,table
);
1810 Cudd_IterDerefBdd(dd
,t
);
1813 } else if (markE
== DD_LIC_1
) {
1820 if (markT
== DD_LIC_DC
&& markE
!= DD_LIC_DC
) {
1822 } else if (markT
!= DD_LIC_DC
&& markE
== DD_LIC_DC
) {
1825 if (Cudd_IsComplement(t
)) {
1828 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
1830 Cudd_IterDerefBdd(dd
, e
);
1831 Cudd_IterDerefBdd(dd
, t
);
1836 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
1838 Cudd_IterDerefBdd(dd
, e
);
1839 Cudd_IterDerefBdd(dd
, t
);
1847 if (st_insert(cache
, (char *)f
, (char *)r
) == ST_OUT_OF_MEM
) {
1849 Cudd_IterDerefBdd(dd
,r
);
1853 return(Cudd_NotCond(r
,comple
));
1855 } /* end of cuddBddLICBuildResult */
1858 /**Function********************************************************************
1860 Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.]
1862 Description [Hash function for the computed table of
1863 cuddBddLICMarkEdges. Returns the bucket number.]
1867 SeeAlso [Cudd_bddLICompaction]
1869 ******************************************************************************/
1876 MarkCacheKey
*entry
;
1878 entry
= (MarkCacheKey
*) ptr
;
1880 val
= (int) (ptrint
) entry
->f
;
1881 val
= val
* 997 + (int) (ptrint
) entry
->c
;
1883 return ((val
< 0) ? -val
: val
) % modulus
;
1885 } /* end of MarkCacheHash */
1888 /**Function********************************************************************
1890 Synopsis [Comparison function for the computed table of
1891 cuddBddLICMarkEdges.]
1893 Description [Comparison function for the computed table of
1894 cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1
1899 SeeAlso [Cudd_bddLICompaction]
1901 ******************************************************************************/
1907 MarkCacheKey
*entry1
, *entry2
;
1909 entry1
= (MarkCacheKey
*) ptr1
;
1910 entry2
= (MarkCacheKey
*) ptr2
;
1912 return((entry1
->f
!= entry2
->f
) || (entry1
->c
!= entry2
->c
));
1914 } /* end of MarkCacheCompare */
1918 /**Function********************************************************************
1920 Synopsis [Frees memory associated with computed table of
1921 cuddBddLICMarkEdges.]
1923 Description [Frees memory associated with computed table of
1924 cuddBddLICMarkEdges. Returns ST_CONTINUE.]
1928 SeeAlso [Cudd_bddLICompaction]
1930 ******************************************************************************/
1931 static enum st_retval
1937 MarkCacheKey
*entry
;
1939 entry
= (MarkCacheKey
*) key
;
1943 } /* end of MarkCacheCleanUp */
1946 /**Function********************************************************************
1948 Synopsis [Performs the recursive step of Cudd_bddSqueeze.]
1950 Description [Performs the recursive step of Cudd_bddSqueeze. This
1951 procedure exploits the fact that if we complement and swap the
1952 bounds of the interval we obtain a valid solution by taking the
1953 complement of the solution to the original problem. Therefore, we
1954 can enforce the condition that the upper bound is always regular.
1955 Returns a pointer to the result if successful; NULL otherwise.]
1959 SeeAlso [Cudd_bddSqueeze]
1961 ******************************************************************************/
1968 DdNode
*one
, *zero
, *r
, *lt
, *le
, *ut
, *ue
, *t
, *e
;
1973 unsigned int topu
, topl
;
1981 zero
= Cudd_Not(one
);
1982 /* The only case when l == zero && u == one is at the top level,
1983 ** where returning either one or zero is OK. In all other cases
1984 ** the procedure will detect such a case and will perform
1985 ** remapping. Therefore the order in which we test l and u at this
1986 ** point is immaterial. */
1987 if (l
== zero
) return(l
);
1988 if (u
== one
) return(u
);
1990 /* Make canonical to increase the utilization of the cache. */
1991 if (Cudd_IsComplement(u
)) {
1998 /* At this point u is regular and non-constant; l is non-constant, but
1999 ** may be complemented. */
2001 /* Here we could check the relative sizes. */
2003 /* Check the cache. */
2004 r
= cuddCacheLookup2(dd
, Cudd_bddSqueeze
, l
, u
);
2006 return(Cudd_NotCond(r
,comple
));
2009 /* Recursive step. */
2010 topu
= dd
->perm
[u
->index
];
2011 topl
= dd
->perm
[Cudd_Regular(l
)->index
];
2014 ut
= cuddT(u
); ue
= cuddE(u
);
2016 index
= Cudd_Regular(l
)->index
;
2020 lt
= cuddT(Cudd_Regular(l
)); le
= cuddE(Cudd_Regular(l
));
2021 if (Cudd_IsComplement(l
)) {
2029 /* If one interval is contained in the other, use the smaller
2030 ** interval. This corresponds to one-sided matching. */
2031 if ((lt
== zero
|| Cudd_bddLeq(dd
,lt
,le
)) &&
2032 (ut
== one
|| Cudd_bddLeq(dd
,ue
,ut
))) { /* remap */
2033 r
= cuddBddSqueeze(dd
, le
, ue
);
2036 return(Cudd_NotCond(r
,comple
));
2037 } else if ((le
== zero
|| Cudd_bddLeq(dd
,le
,lt
)) &&
2038 (ue
== one
|| Cudd_bddLeq(dd
,ut
,ue
))) { /* remap */
2039 r
= cuddBddSqueeze(dd
, lt
, ut
);
2042 return(Cudd_NotCond(r
,comple
));
2043 } else if ((le
== zero
|| Cudd_bddLeq(dd
,le
,Cudd_Not(ut
))) &&
2044 (ue
== one
|| Cudd_bddLeq(dd
,Cudd_Not(lt
),ue
))) { /* c-remap */
2045 t
= cuddBddSqueeze(dd
, lt
, ut
);
2047 if (Cudd_IsComplement(t
)) {
2048 r
= cuddUniqueInter(dd
, index
, Cudd_Not(t
), t
);
2050 Cudd_IterDerefBdd(dd
, t
);
2055 r
= cuddUniqueInter(dd
, index
, t
, Cudd_Not(t
));
2057 Cudd_IterDerefBdd(dd
, t
);
2064 cuddCacheInsert2(dd
, Cudd_bddSqueeze
, l
, u
, r
);
2065 return(Cudd_NotCond(r
,comple
));
2066 } else if ((lt
== zero
|| Cudd_bddLeq(dd
,lt
,Cudd_Not(ue
))) &&
2067 (ut
== one
|| Cudd_bddLeq(dd
,Cudd_Not(le
),ut
))) { /* c-remap */
2068 e
= cuddBddSqueeze(dd
, le
, ue
);
2070 if (Cudd_IsComplement(e
)) {
2071 r
= cuddUniqueInter(dd
, index
, Cudd_Not(e
), e
);
2073 Cudd_IterDerefBdd(dd
, e
);
2077 r
= cuddUniqueInter(dd
, index
, e
, Cudd_Not(e
));
2079 Cudd_IterDerefBdd(dd
, e
);
2087 cuddCacheInsert2(dd
, Cudd_bddSqueeze
, l
, u
, r
);
2088 return(Cudd_NotCond(r
,comple
));
2092 /* If the two intervals intersect, take a solution from
2093 ** the intersection of the intervals. This guarantees that the
2094 ** splitting variable will not appear in the result.
2095 ** This approach corresponds to two-sided matching, and is very
2097 if (Cudd_bddLeq(dd
,lt
,ue
) && Cudd_bddLeq(dd
,le
,ut
)) {
2099 au
= cuddBddAndRecur(dd
,ut
,ue
);
2103 al
= cuddBddAndRecur(dd
,Cudd_Not(lt
),Cudd_Not(le
));
2105 Cudd_IterDerefBdd(dd
,au
);
2110 ar
= cuddBddSqueeze(dd
, al
, au
);
2112 Cudd_IterDerefBdd(dd
,au
);
2113 Cudd_IterDerefBdd(dd
,al
);
2117 Cudd_IterDerefBdd(dd
,au
);
2118 Cudd_IterDerefBdd(dd
,al
);
2124 t
= cuddBddSqueeze(dd
, lt
, ut
);
2129 e
= cuddBddSqueeze(dd
, le
, ue
);
2131 Cudd_IterDerefBdd(dd
,t
);
2136 if (Cudd_IsComplement(t
)) {
2139 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
2141 Cudd_IterDerefBdd(dd
, e
);
2142 Cudd_IterDerefBdd(dd
, t
);
2147 r
= (t
== e
) ? t
: cuddUniqueInter(dd
, index
, t
, e
);
2149 Cudd_IterDerefBdd(dd
, e
);
2150 Cudd_IterDerefBdd(dd
, t
);
2158 /* Check whether there is a result obtained by abstraction and whether
2159 ** it is better than the one obtained by recursion. */
2162 if (Cudd_DagSize(ar
) <= Cudd_DagSize(r
)) {
2163 Cudd_IterDerefBdd(dd
, r
);
2166 Cudd_IterDerefBdd(dd
, ar
);
2172 cuddCacheInsert2(dd
, Cudd_bddSqueeze
, l
, u
, r
);
2173 return(Cudd_NotCond(r
,comple
));
2175 } /* end of cuddBddSqueeze */