1 /**CFile***********************************************************************
3 FileName [cuddAddAbs.c]
7 Synopsis [Quantification functions for ADDs.]
9 Description [External procedures included in this module:
11 <li> Cudd_addExistAbstract()
12 <li> Cudd_addUnivAbstract()
13 <li> Cudd_addOrAbstract()
15 Internal procedures included in this module:
17 <li> cuddAddExistAbstractRecur()
18 <li> cuddAddUnivAbstractRecur()
19 <li> cuddAddOrAbstractRecur()
21 Static procedures included in this module:
23 <li> addCheckPositiveCube()
26 Author [Fabio Somenzi]
28 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
32 Redistribution and use in source and binary forms, with or without
33 modification, are permitted provided that the following conditions
36 Redistributions of source code must retain the above copyright
37 notice, this list of conditions and the following disclaimer.
39 Redistributions in binary form must reproduce the above copyright
40 notice, this list of conditions and the following disclaimer in the
41 documentation and/or other materials provided with the distribution.
43 Neither the name of the University of Colorado nor the names of its
44 contributors may be used to endorse or promote products derived from
45 this software without specific prior written permission.
47 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
50 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
51 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
52 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
53 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
55 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
57 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58 POSSIBILITY OF SUCH DAMAGE.]
60 ******************************************************************************/
65 /*---------------------------------------------------------------------------*/
66 /* Constant declarations */
67 /*---------------------------------------------------------------------------*/
70 /*---------------------------------------------------------------------------*/
71 /* Stucture declarations */
72 /*---------------------------------------------------------------------------*/
75 /*---------------------------------------------------------------------------*/
76 /* Type declarations */
77 /*---------------------------------------------------------------------------*/
80 /*---------------------------------------------------------------------------*/
81 /* Variable declarations */
82 /*---------------------------------------------------------------------------*/
85 static char rcsid
[] DD_UNUSED
= "$Id: cuddAddAbs.c,v 1.15 2004/08/13 18:04:45 fabio Exp $";
90 /*---------------------------------------------------------------------------*/
91 /* Macro declarations */
92 /*---------------------------------------------------------------------------*/
95 /**AutomaticStart*************************************************************/
97 /*---------------------------------------------------------------------------*/
98 /* Static function prototypes */
99 /*---------------------------------------------------------------------------*/
101 static int addCheckPositiveCube (DdManager
*manager
, DdNode
*cube
);
103 /**AutomaticEnd***************************************************************/
106 /*---------------------------------------------------------------------------*/
107 /* Definition of exported functions */
108 /*---------------------------------------------------------------------------*/
110 /**Function********************************************************************
112 Synopsis [Existentially Abstracts all the variables in cube from f.]
114 Description [Abstracts all the variables in cube from f by summing
115 over all possible values taken by the variables. Returns the
120 SeeAlso [Cudd_addUnivAbstract Cudd_bddExistAbstract
123 ******************************************************************************/
125 Cudd_addExistAbstract(
132 two
= cuddUniqueConst(manager
,(CUDD_VALUE_TYPE
) 2);
133 if (two
== NULL
) return(NULL
);
136 if (addCheckPositiveCube(manager
, cube
) == 0) {
137 (void) fprintf(manager
->err
,"Error: Can only abstract cubes");
142 manager
->reordered
= 0;
143 res
= cuddAddExistAbstractRecur(manager
, f
, cube
);
144 } while (manager
->reordered
== 1);
147 Cudd_RecursiveDeref(manager
,two
);
151 Cudd_RecursiveDeref(manager
,two
);
156 } /* end of Cudd_addExistAbstract */
159 /**Function********************************************************************
161 Synopsis [Universally Abstracts all the variables in cube from f.]
163 Description [Abstracts all the variables in cube from f by taking
164 the product over all possible values taken by the variable. Returns
165 the abstracted ADD if successful; NULL otherwise.]
169 SeeAlso [Cudd_addExistAbstract Cudd_bddUnivAbstract
172 ******************************************************************************/
174 Cudd_addUnivAbstract(
181 if (addCheckPositiveCube(manager
, cube
) == 0) {
182 (void) fprintf(manager
->err
,"Error: Can only abstract cubes");
187 manager
->reordered
= 0;
188 res
= cuddAddUnivAbstractRecur(manager
, f
, cube
);
189 } while (manager
->reordered
== 1);
193 } /* end of Cudd_addUnivAbstract */
196 /**Function********************************************************************
198 Synopsis [Disjunctively abstracts all the variables in cube from the
201 Description [Abstracts all the variables in cube from the 0-1 ADD f
202 by taking the disjunction over all possible values taken by the
203 variables. Returns the abstracted ADD if successful; NULL
208 SeeAlso [Cudd_addUnivAbstract Cudd_addExistAbstract]
210 ******************************************************************************/
219 if (addCheckPositiveCube(manager
, cube
) == 0) {
220 (void) fprintf(manager
->err
,"Error: Can only abstract cubes");
225 manager
->reordered
= 0;
226 res
= cuddAddOrAbstractRecur(manager
, f
, cube
);
227 } while (manager
->reordered
== 1);
230 } /* end of Cudd_addOrAbstract */
233 /*---------------------------------------------------------------------------*/
234 /* Definition of internal functions */
235 /*---------------------------------------------------------------------------*/
238 /**Function********************************************************************
240 Synopsis [Performs the recursive step of Cudd_addExistAbstract.]
242 Description [Performs the recursive step of Cudd_addExistAbstract.
243 Returns the ADD obtained by abstracting the variables of cube from f,
244 if successful; NULL otherwise.]
250 ******************************************************************************/
252 cuddAddExistAbstractRecur(
257 DdNode
*T
, *E
, *res
, *res1
, *res2
, *zero
;
260 zero
= DD_ZERO(manager
);
262 /* Cube is guaranteed to be a cube at this point. */
263 if (f
== zero
|| cuddIsConstant(cube
)) {
267 /* Abstract a variable that does not appear in f => multiply by 2. */
268 if (cuddI(manager
,f
->index
) > cuddI(manager
,cube
->index
)) {
269 res1
= cuddAddExistAbstractRecur(manager
, f
, cuddT(cube
));
270 if (res1
== NULL
) return(NULL
);
272 /* Use the "internal" procedure to be alerted in case of
273 ** dynamic reordering. If dynamic reordering occurs, we
274 ** have to abort the entire abstraction.
276 res
= cuddAddApplyRecur(manager
,Cudd_addTimes
,res1
,two
);
278 Cudd_RecursiveDeref(manager
,res1
);
282 Cudd_RecursiveDeref(manager
,res1
);
287 if ((res
= cuddCacheLookup2(manager
, Cudd_addExistAbstract
, f
, cube
)) != NULL
) {
294 /* If the two indices are the same, so are their levels. */
295 if (f
->index
== cube
->index
) {
296 res1
= cuddAddExistAbstractRecur(manager
, T
, cuddT(cube
));
297 if (res1
== NULL
) return(NULL
);
299 res2
= cuddAddExistAbstractRecur(manager
, E
, cuddT(cube
));
301 Cudd_RecursiveDeref(manager
,res1
);
305 res
= cuddAddApplyRecur(manager
, Cudd_addPlus
, res1
, res2
);
307 Cudd_RecursiveDeref(manager
,res1
);
308 Cudd_RecursiveDeref(manager
,res2
);
312 Cudd_RecursiveDeref(manager
,res1
);
313 Cudd_RecursiveDeref(manager
,res2
);
314 cuddCacheInsert2(manager
, Cudd_addExistAbstract
, f
, cube
, res
);
317 } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
318 res1
= cuddAddExistAbstractRecur(manager
, T
, cube
);
319 if (res1
== NULL
) return(NULL
);
321 res2
= cuddAddExistAbstractRecur(manager
, E
, cube
);
323 Cudd_RecursiveDeref(manager
,res1
);
327 res
= (res1
== res2
) ? res1
:
328 cuddUniqueInter(manager
, (int) f
->index
, res1
, res2
);
330 Cudd_RecursiveDeref(manager
,res1
);
331 Cudd_RecursiveDeref(manager
,res2
);
336 cuddCacheInsert2(manager
, Cudd_addExistAbstract
, f
, cube
, res
);
340 } /* end of cuddAddExistAbstractRecur */
343 /**Function********************************************************************
345 Synopsis [Performs the recursive step of Cudd_addUnivAbstract.]
347 Description [Performs the recursive step of Cudd_addUnivAbstract.
348 Returns the ADD obtained by abstracting the variables of cube from f,
349 if successful; NULL otherwise.]
355 ******************************************************************************/
357 cuddAddUnivAbstractRecur(
362 DdNode
*T
, *E
, *res
, *res1
, *res2
, *one
, *zero
;
365 one
= DD_ONE(manager
);
366 zero
= DD_ZERO(manager
);
368 /* Cube is guaranteed to be a cube at this point.
369 ** zero and one are the only constatnts c such that c*c=c.
371 if (f
== zero
|| f
== one
|| cube
== one
) {
375 /* Abstract a variable that does not appear in f. */
376 if (cuddI(manager
,f
->index
) > cuddI(manager
,cube
->index
)) {
377 res1
= cuddAddUnivAbstractRecur(manager
, f
, cuddT(cube
));
378 if (res1
== NULL
) return(NULL
);
380 /* Use the "internal" procedure to be alerted in case of
381 ** dynamic reordering. If dynamic reordering occurs, we
382 ** have to abort the entire abstraction.
384 res
= cuddAddApplyRecur(manager
, Cudd_addTimes
, res1
, res1
);
386 Cudd_RecursiveDeref(manager
,res1
);
390 Cudd_RecursiveDeref(manager
,res1
);
395 if ((res
= cuddCacheLookup2(manager
, Cudd_addUnivAbstract
, f
, cube
)) != NULL
) {
402 /* If the two indices are the same, so are their levels. */
403 if (f
->index
== cube
->index
) {
404 res1
= cuddAddUnivAbstractRecur(manager
, T
, cuddT(cube
));
405 if (res1
== NULL
) return(NULL
);
407 res2
= cuddAddUnivAbstractRecur(manager
, E
, cuddT(cube
));
409 Cudd_RecursiveDeref(manager
,res1
);
413 res
= cuddAddApplyRecur(manager
, Cudd_addTimes
, res1
, res2
);
415 Cudd_RecursiveDeref(manager
,res1
);
416 Cudd_RecursiveDeref(manager
,res2
);
420 Cudd_RecursiveDeref(manager
,res1
);
421 Cudd_RecursiveDeref(manager
,res2
);
422 cuddCacheInsert2(manager
, Cudd_addUnivAbstract
, f
, cube
, res
);
425 } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
426 res1
= cuddAddUnivAbstractRecur(manager
, T
, cube
);
427 if (res1
== NULL
) return(NULL
);
429 res2
= cuddAddUnivAbstractRecur(manager
, E
, cube
);
431 Cudd_RecursiveDeref(manager
,res1
);
435 res
= (res1
== res2
) ? res1
:
436 cuddUniqueInter(manager
, (int) f
->index
, res1
, res2
);
438 Cudd_RecursiveDeref(manager
,res1
);
439 Cudd_RecursiveDeref(manager
,res2
);
444 cuddCacheInsert2(manager
, Cudd_addUnivAbstract
, f
, cube
, res
);
448 } /* end of cuddAddUnivAbstractRecur */
451 /**Function********************************************************************
453 Synopsis [Performs the recursive step of Cudd_addOrAbstract.]
455 Description [Performs the recursive step of Cudd_addOrAbstract.
456 Returns the ADD obtained by abstracting the variables of cube from f,
457 if successful; NULL otherwise.]
463 ******************************************************************************/
465 cuddAddOrAbstractRecur(
470 DdNode
*T
, *E
, *res
, *res1
, *res2
, *one
;
473 one
= DD_ONE(manager
);
475 /* Cube is guaranteed to be a cube at this point. */
476 if (cuddIsConstant(f
) || cube
== one
) {
480 /* Abstract a variable that does not appear in f. */
481 if (cuddI(manager
,f
->index
) > cuddI(manager
,cube
->index
)) {
482 res
= cuddAddOrAbstractRecur(manager
, f
, cuddT(cube
));
486 if ((res
= cuddCacheLookup2(manager
, Cudd_addOrAbstract
, f
, cube
)) != NULL
) {
493 /* If the two indices are the same, so are their levels. */
494 if (f
->index
== cube
->index
) {
495 res1
= cuddAddOrAbstractRecur(manager
, T
, cuddT(cube
));
496 if (res1
== NULL
) return(NULL
);
499 res2
= cuddAddOrAbstractRecur(manager
, E
, cuddT(cube
));
501 Cudd_RecursiveDeref(manager
,res1
);
505 res
= cuddAddApplyRecur(manager
, Cudd_addOr
, res1
, res2
);
507 Cudd_RecursiveDeref(manager
,res1
);
508 Cudd_RecursiveDeref(manager
,res2
);
512 Cudd_RecursiveDeref(manager
,res1
);
513 Cudd_RecursiveDeref(manager
,res2
);
517 cuddCacheInsert2(manager
, Cudd_addOrAbstract
, f
, cube
, res
);
520 } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */
521 res1
= cuddAddOrAbstractRecur(manager
, T
, cube
);
522 if (res1
== NULL
) return(NULL
);
524 res2
= cuddAddOrAbstractRecur(manager
, E
, cube
);
526 Cudd_RecursiveDeref(manager
,res1
);
530 res
= (res1
== res2
) ? res1
:
531 cuddUniqueInter(manager
, (int) f
->index
, res1
, res2
);
533 Cudd_RecursiveDeref(manager
,res1
);
534 Cudd_RecursiveDeref(manager
,res2
);
539 cuddCacheInsert2(manager
, Cudd_addOrAbstract
, f
, cube
, res
);
543 } /* end of cuddAddOrAbstractRecur */
547 /*---------------------------------------------------------------------------*/
548 /* Definition of static functions */
549 /*---------------------------------------------------------------------------*/
552 /**Function********************************************************************
554 Synopsis [Checks whether cube is an ADD representing the product
555 of positive literals.]
557 Description [Checks whether cube is an ADD representing the product of
558 positive literals. Returns 1 in case of success; 0 otherwise.]
564 ******************************************************************************/
566 addCheckPositiveCube(
570 if (Cudd_IsComplement(cube
)) return(0);
571 if (cube
== DD_ONE(manager
)) return(1);
572 if (cuddIsConstant(cube
)) return(0);
573 if (cuddE(cube
) == DD_ZERO(manager
)) {
574 return(addCheckPositiveCube(manager
, cuddT(cube
)));
578 } /* end of addCheckPositiveCube */