1 /**CFile***********************************************************************
3 FileName [cuddAndAbs.c]
7 Synopsis [Combined AND and existential abstraction for BDDs]
9 Description [External procedures included in this module:
11 <li> Cudd_bddAndAbstract()
12 <li> Cudd_bddAndAbstractLimit()
14 Internal procedures included in this module:
16 <li> cuddBddAndAbstractRecur()
19 Author [Fabio Somenzi]
21 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
25 Redistribution and use in source and binary forms, with or without
26 modification, are permitted provided that the following conditions
29 Redistributions of source code must retain the above copyright
30 notice, this list of conditions and the following disclaimer.
32 Redistributions in binary form must reproduce the above copyright
33 notice, this list of conditions and the following disclaimer in the
34 documentation and/or other materials provided with the distribution.
36 Neither the name of the University of Colorado nor the names of its
37 contributors may be used to endorse or promote products derived from
38 this software without specific prior written permission.
40 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
41 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
42 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
43 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
44 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
45 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
46 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
48 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
50 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51 POSSIBILITY OF SUCH DAMAGE.]
53 ******************************************************************************/
59 /*---------------------------------------------------------------------------*/
60 /* Constant declarations */
61 /*---------------------------------------------------------------------------*/
64 /*---------------------------------------------------------------------------*/
65 /* Stucture declarations */
66 /*---------------------------------------------------------------------------*/
69 /*---------------------------------------------------------------------------*/
70 /* Type declarations */
71 /*---------------------------------------------------------------------------*/
74 /*---------------------------------------------------------------------------*/
75 /* Variable declarations */
76 /*---------------------------------------------------------------------------*/
79 static char rcsid
[] DD_UNUSED
= "$Id: cuddAndAbs.c,v 1.19 2004/08/13 18:04:46 fabio Exp $";
83 /*---------------------------------------------------------------------------*/
84 /* Macro declarations */
85 /*---------------------------------------------------------------------------*/
88 /**AutomaticStart*************************************************************/
90 /*---------------------------------------------------------------------------*/
91 /* Static function prototypes */
92 /*---------------------------------------------------------------------------*/
95 /**AutomaticEnd***************************************************************/
98 /*---------------------------------------------------------------------------*/
99 /* Definition of exported functions */
100 /*---------------------------------------------------------------------------*/
103 /**Function********************************************************************
105 Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
108 Description [Takes the AND of two BDDs and simultaneously abstracts
109 the variables in cube. The variables are existentially abstracted.
110 Returns a pointer to the result is successful; NULL otherwise.
111 Cudd_bddAndAbstract implements the semiring matrix multiplication
112 algorithm for the boolean semiring.]
116 SeeAlso [Cudd_addMatrixMultiply Cudd_addTriangle Cudd_bddAnd]
118 ******************************************************************************/
129 manager
->reordered
= 0;
130 res
= cuddBddAndAbstractRecur(manager
, f
, g
, cube
);
131 } while (manager
->reordered
== 1);
134 } /* end of Cudd_bddAndAbstract */
137 /**Function********************************************************************
139 Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
140 variables in cube. Returns NULL if too many nodes are required.]
142 Description [Takes the AND of two BDDs and simultaneously abstracts
143 the variables in cube. The variables are existentially abstracted.
144 Returns a pointer to the result is successful; NULL otherwise.
145 In particular, if the number of new nodes created exceeds
146 <code>limit</code>, this function returns NULL.]
150 SeeAlso [Cudd_bddAndAbstract]
152 ******************************************************************************/
154 Cudd_bddAndAbstractLimit(
162 unsigned int saveLimit
= manager
->maxLive
;
164 manager
->maxLive
= (manager
->keys
- manager
->dead
) +
165 (manager
->keysZ
- manager
->deadZ
) + limit
;
167 manager
->reordered
= 0;
168 res
= cuddBddAndAbstractRecur(manager
, f
, g
, cube
);
169 } while (manager
->reordered
== 1);
170 manager
->maxLive
= saveLimit
;
173 } /* end of Cudd_bddAndAbstractLimit */
176 /*---------------------------------------------------------------------------*/
177 /* Definition of internal functions */
178 /*---------------------------------------------------------------------------*/
181 /**Function********************************************************************
183 Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
186 Description [Takes the AND of two BDDs and simultaneously abstracts
187 the variables in cube. The variables are existentially abstracted.
188 Returns a pointer to the result is successful; NULL otherwise.]
192 SeeAlso [Cudd_bddAndAbstract]
194 ******************************************************************************/
196 cuddBddAndAbstractRecur(
202 DdNode
*F
, *ft
, *fe
, *G
, *gt
, *ge
;
203 DdNode
*one
, *zero
, *r
, *t
, *e
;
204 unsigned int topf
, topg
, topcube
, top
, index
;
207 one
= DD_ONE(manager
);
208 zero
= Cudd_Not(one
);
210 /* Terminal cases. */
211 if (f
== zero
|| g
== zero
|| f
== Cudd_Not(g
)) return(zero
);
212 if (f
== one
&& g
== one
) return(one
);
215 return(cuddBddAndRecur(manager
, f
, g
));
217 if (f
== one
|| f
== g
) {
218 return(cuddBddExistAbstractRecur(manager
, g
, cube
));
221 return(cuddBddExistAbstractRecur(manager
, f
, cube
));
223 /* At this point f, g, and cube are not constant. */
225 if (f
> g
) { /* Try to increase cache efficiency. */
231 /* Here we can skip the use of cuddI, because the operands are known
232 ** to be non-constant.
236 topf
= manager
->perm
[F
->index
];
237 topg
= manager
->perm
[G
->index
];
238 top
= ddMin(topf
, topg
);
239 topcube
= manager
->perm
[cube
->index
];
241 while (topcube
< top
) {
244 return(cuddBddAndRecur(manager
, f
, g
));
246 topcube
= manager
->perm
[cube
->index
];
248 /* Now, topcube >= top. */
251 if (F
->ref
!= 1 || G
->ref
!= 1) {
252 r
= cuddCacheLookup(manager
, DD_BDD_AND_ABSTRACT_TAG
, f
, g
, cube
);
262 if (Cudd_IsComplement(f
)) {
274 if (Cudd_IsComplement(g
)) {
282 if (topcube
== top
) { /* quantify */
283 DdNode
*Cube
= cuddT(cube
);
284 t
= cuddBddAndAbstractRecur(manager
, ft
, gt
, Cube
);
285 if (t
== NULL
) return(NULL
);
286 /* Special case: 1 OR anything = 1. Hence, no need to compute
287 ** the else branch if t is 1. Likewise t + t * anything == t.
288 ** Notice that t == fe implies that fe does not depend on the
289 ** variables in Cube. Likewise for t == ge.
291 if (t
== one
|| t
== fe
|| t
== ge
) {
292 if (F
->ref
!= 1 || G
->ref
!= 1)
293 cuddCacheInsert(manager
, DD_BDD_AND_ABSTRACT_TAG
,
298 /* Special case: t + !t * anything == t + anything. */
299 if (t
== Cudd_Not(fe
)) {
300 e
= cuddBddExistAbstractRecur(manager
, ge
, Cube
);
301 } else if (t
== Cudd_Not(ge
)) {
302 e
= cuddBddExistAbstractRecur(manager
, fe
, Cube
);
304 e
= cuddBddAndAbstractRecur(manager
, fe
, ge
, Cube
);
307 Cudd_IterDerefBdd(manager
, t
);
315 r
= cuddBddAndRecur(manager
, Cudd_Not(t
), Cudd_Not(e
));
317 Cudd_IterDerefBdd(manager
, t
);
318 Cudd_IterDerefBdd(manager
, e
);
323 Cudd_DelayedDerefBdd(manager
, t
);
324 Cudd_DelayedDerefBdd(manager
, e
);
328 t
= cuddBddAndAbstractRecur(manager
, ft
, gt
, cube
);
329 if (t
== NULL
) return(NULL
);
331 e
= cuddBddAndAbstractRecur(manager
, fe
, ge
, cube
);
333 Cudd_IterDerefBdd(manager
, t
);
341 if (Cudd_IsComplement(t
)) {
342 r
= cuddUniqueInter(manager
, (int) index
,
343 Cudd_Not(t
), Cudd_Not(e
));
345 Cudd_IterDerefBdd(manager
, t
);
346 Cudd_IterDerefBdd(manager
, e
);
351 r
= cuddUniqueInter(manager
,(int)index
,t
,e
);
353 Cudd_IterDerefBdd(manager
, t
);
354 Cudd_IterDerefBdd(manager
, e
);
363 if (F
->ref
!= 1 || G
->ref
!= 1)
364 cuddCacheInsert(manager
, DD_BDD_AND_ABSTRACT_TAG
, f
, g
, cube
, r
);
367 } /* end of cuddBddAndAbstractRecur */
370 /*---------------------------------------------------------------------------*/
371 /* Definition of static functions */
372 /*---------------------------------------------------------------------------*/