emergency commit
[cl-cudd.git] / distr / cudd / cuddClip.c
blob30111b07c766667c9aa0f0c3bbcabb306c55e743
1 /**CFile***********************************************************************
3 FileName [cuddClip.c]
5 PackageName [cudd]
7 Synopsis [Clipping functions.]
9 Description [External procedures included in this module:
10 <ul>
11 <li> Cudd_bddClippingAnd()
12 <li> Cudd_bddClippingAndAbstract()
13 </ul>
14 Internal procedures included in this module:
15 <ul>
16 <li> cuddBddClippingAnd()
17 <li> cuddBddClippingAndAbstract()
18 </ul>
19 Static procedures included in this module:
20 <ul>
21 <li> cuddBddClippingAndRecur()
22 <li> cuddBddClipAndAbsRecur()
23 </ul>
25 SeeAlso []
27 Author [Fabio Somenzi]
29 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
31 All rights reserved.
33 Redistribution and use in source and binary forms, with or without
34 modification, are permitted provided that the following conditions
35 are met:
37 Redistributions of source code must retain the above copyright
38 notice, this list of conditions and the following disclaimer.
40 Redistributions in binary form must reproduce the above copyright
41 notice, this list of conditions and the following disclaimer in the
42 documentation and/or other materials provided with the distribution.
44 Neither the name of the University of Colorado nor the names of its
45 contributors may be used to endorse or promote products derived from
46 this software without specific prior written permission.
48 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
49 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
50 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
51 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
52 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
53 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
54 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
55 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
56 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
58 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 POSSIBILITY OF SUCH DAMAGE.]
61 ******************************************************************************/
63 #include "util.h"
64 #include "cuddInt.h"
67 /*---------------------------------------------------------------------------*/
68 /* Constant declarations */
69 /*---------------------------------------------------------------------------*/
72 /*---------------------------------------------------------------------------*/
73 /* Stucture declarations */
74 /*---------------------------------------------------------------------------*/
77 /*---------------------------------------------------------------------------*/
78 /* Type declarations */
79 /*---------------------------------------------------------------------------*/
81 /*---------------------------------------------------------------------------*/
82 /* Variable declarations */
83 /*---------------------------------------------------------------------------*/
85 #ifndef lint
86 static char rcsid[] DD_UNUSED = "$Id: cuddClip.c,v 1.8 2004/08/13 18:04:47 fabio Exp $";
87 #endif
89 /*---------------------------------------------------------------------------*/
90 /* Macro declarations */
91 /*---------------------------------------------------------------------------*/
94 /**AutomaticStart*************************************************************/
96 /*---------------------------------------------------------------------------*/
97 /* Static function prototypes */
98 /*---------------------------------------------------------------------------*/
100 static DdNode * cuddBddClippingAndRecur (DdManager *manager, DdNode *f, DdNode *g, int distance, int direction);
101 static DdNode * cuddBddClipAndAbsRecur (DdManager *manager, DdNode *f, DdNode *g, DdNode *cube, int distance, int direction);
103 /**AutomaticEnd***************************************************************/
106 /*---------------------------------------------------------------------------*/
107 /* Definition of exported functions */
108 /*---------------------------------------------------------------------------*/
111 /**Function********************************************************************
113 Synopsis [Approximates the conjunction of two BDDs f and g.]
115 Description [Approximates the conjunction of two BDDs f and g. Returns a
116 pointer to the resulting BDD if successful; NULL if the intermediate
117 result blows up.]
119 SideEffects [None]
121 SeeAlso [Cudd_bddAnd]
123 ******************************************************************************/
124 DdNode *
125 Cudd_bddClippingAnd(
126 DdManager * dd /* manager */,
127 DdNode * f /* first conjunct */,
128 DdNode * g /* second conjunct */,
129 int maxDepth /* maximum recursion depth */,
130 int direction /* under (0) or over (1) approximation */)
132 DdNode *res;
134 do {
135 dd->reordered = 0;
136 res = cuddBddClippingAnd(dd,f,g,maxDepth,direction);
137 } while (dd->reordered == 1);
138 return(res);
140 } /* end of Cudd_bddClippingAnd */
143 /**Function********************************************************************
145 Synopsis [Approximates the conjunction of two BDDs f and g and
146 simultaneously abstracts the variables in cube.]
148 Description [Approximates the conjunction of two BDDs f and g and
149 simultaneously abstracts the variables in cube. The variables are
150 existentially abstracted. Returns a pointer to the resulting BDD if
151 successful; NULL if the intermediate result blows up.]
153 SideEffects [None]
155 SeeAlso [Cudd_bddAndAbstract Cudd_bddClippingAnd]
157 ******************************************************************************/
158 DdNode *
159 Cudd_bddClippingAndAbstract(
160 DdManager * dd /* manager */,
161 DdNode * f /* first conjunct */,
162 DdNode * g /* second conjunct */,
163 DdNode * cube /* cube of variables to be abstracted */,
164 int maxDepth /* maximum recursion depth */,
165 int direction /* under (0) or over (1) approximation */)
167 DdNode *res;
169 do {
170 dd->reordered = 0;
171 res = cuddBddClippingAndAbstract(dd,f,g,cube,maxDepth,direction);
172 } while (dd->reordered == 1);
173 return(res);
175 } /* end of Cudd_bddClippingAndAbstract */
178 /*---------------------------------------------------------------------------*/
179 /* Definition of internal functions */
180 /*---------------------------------------------------------------------------*/
183 /**Function********************************************************************
185 Synopsis [Approximates the conjunction of two BDDs f and g.]
187 Description [Approximates the conjunction of two BDDs f and g. Returns a
188 pointer to the resulting BDD if successful; NULL if the intermediate
189 result blows up.]
191 SideEffects [None]
193 SeeAlso [Cudd_bddClippingAnd]
195 ******************************************************************************/
196 DdNode *
197 cuddBddClippingAnd(
198 DdManager * dd /* manager */,
199 DdNode * f /* first conjunct */,
200 DdNode * g /* second conjunct */,
201 int maxDepth /* maximum recursion depth */,
202 int direction /* under (0) or over (1) approximation */)
204 DdNode *res;
206 res = cuddBddClippingAndRecur(dd,f,g,maxDepth,direction);
208 return(res);
210 } /* end of cuddBddClippingAnd */
213 /**Function********************************************************************
215 Synopsis [Approximates the conjunction of two BDDs f and g and
216 simultaneously abstracts the variables in cube.]
218 Description [Approximates the conjunction of two BDDs f and g and
219 simultaneously abstracts the variables in cube. Returns a
220 pointer to the resulting BDD if successful; NULL if the intermediate
221 result blows up.]
223 SideEffects [None]
225 SeeAlso [Cudd_bddClippingAndAbstract]
227 ******************************************************************************/
228 DdNode *
229 cuddBddClippingAndAbstract(
230 DdManager * dd /* manager */,
231 DdNode * f /* first conjunct */,
232 DdNode * g /* second conjunct */,
233 DdNode * cube /* cube of variables to be abstracted */,
234 int maxDepth /* maximum recursion depth */,
235 int direction /* under (0) or over (1) approximation */)
237 DdNode *res;
239 res = cuddBddClipAndAbsRecur(dd,f,g,cube,maxDepth,direction);
241 return(res);
243 } /* end of cuddBddClippingAndAbstract */
246 /*---------------------------------------------------------------------------*/
247 /* Definition of static functions */
248 /*---------------------------------------------------------------------------*/
251 /**Function********************************************************************
253 Synopsis [Implements the recursive step of Cudd_bddClippingAnd.]
255 Description [Implements the recursive step of Cudd_bddClippingAnd by taking
256 the conjunction of two BDDs. Returns a pointer to the result is
257 successful; NULL otherwise.]
259 SideEffects [None]
261 SeeAlso [cuddBddClippingAnd]
263 ******************************************************************************/
264 static DdNode *
265 cuddBddClippingAndRecur(
266 DdManager * manager,
267 DdNode * f,
268 DdNode * g,
269 int distance,
270 int direction)
272 DdNode *F, *ft, *fe, *G, *gt, *ge;
273 DdNode *one, *zero, *r, *t, *e;
274 unsigned int topf, topg, index;
275 DD_CTFP cacheOp;
277 statLine(manager);
278 one = DD_ONE(manager);
279 zero = Cudd_Not(one);
281 /* Terminal cases. */
282 if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
283 if (f == g || g == one) return(f);
284 if (f == one) return(g);
285 if (distance == 0) {
286 /* One last attempt at returning the right result. We sort of
287 ** cheat by calling Cudd_bddLeq. */
288 if (Cudd_bddLeq(manager,f,g)) return(f);
289 if (Cudd_bddLeq(manager,g,f)) return(g);
290 if (direction == 1) {
291 if (Cudd_bddLeq(manager,f,Cudd_Not(g)) ||
292 Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero);
294 return(Cudd_NotCond(one,(direction == 0)));
297 /* At this point f and g are not constant. */
298 distance--;
300 /* Check cache. Try to increase cache efficiency by sorting the
301 ** pointers. */
302 if (f > g) {
303 DdNode *tmp = f;
304 f = g; g = tmp;
306 F = Cudd_Regular(f);
307 G = Cudd_Regular(g);
308 cacheOp = (DD_CTFP)
309 (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd);
310 if (F->ref != 1 || G->ref != 1) {
311 r = cuddCacheLookup2(manager, cacheOp, f, g);
312 if (r != NULL) return(r);
315 /* Here we can skip the use of cuddI, because the operands are known
316 ** to be non-constant.
318 topf = manager->perm[F->index];
319 topg = manager->perm[G->index];
321 /* Compute cofactors. */
322 if (topf <= topg) {
323 index = F->index;
324 ft = cuddT(F);
325 fe = cuddE(F);
326 if (Cudd_IsComplement(f)) {
327 ft = Cudd_Not(ft);
328 fe = Cudd_Not(fe);
330 } else {
331 index = G->index;
332 ft = fe = f;
335 if (topg <= topf) {
336 gt = cuddT(G);
337 ge = cuddE(G);
338 if (Cudd_IsComplement(g)) {
339 gt = Cudd_Not(gt);
340 ge = Cudd_Not(ge);
342 } else {
343 gt = ge = g;
346 t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction);
347 if (t == NULL) return(NULL);
348 cuddRef(t);
349 e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction);
350 if (e == NULL) {
351 Cudd_RecursiveDeref(manager, t);
352 return(NULL);
354 cuddRef(e);
356 if (t == e) {
357 r = t;
358 } else {
359 if (Cudd_IsComplement(t)) {
360 r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
361 if (r == NULL) {
362 Cudd_RecursiveDeref(manager, t);
363 Cudd_RecursiveDeref(manager, e);
364 return(NULL);
366 r = Cudd_Not(r);
367 } else {
368 r = cuddUniqueInter(manager,(int)index,t,e);
369 if (r == NULL) {
370 Cudd_RecursiveDeref(manager, t);
371 Cudd_RecursiveDeref(manager, e);
372 return(NULL);
376 cuddDeref(e);
377 cuddDeref(t);
378 if (F->ref != 1 || G->ref != 1)
379 cuddCacheInsert2(manager, cacheOp, f, g, r);
380 return(r);
382 } /* end of cuddBddClippingAndRecur */
385 /**Function********************************************************************
387 Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the
388 variables in cube.]
390 Description [Approximates the AND of two BDDs and simultaneously
391 abstracts the variables in cube. The variables are existentially
392 abstracted. Returns a pointer to the result is successful; NULL
393 otherwise.]
395 SideEffects [None]
397 SeeAlso [Cudd_bddClippingAndAbstract]
399 ******************************************************************************/
400 static DdNode *
401 cuddBddClipAndAbsRecur(
402 DdManager * manager,
403 DdNode * f,
404 DdNode * g,
405 DdNode * cube,
406 int distance,
407 int direction)
409 DdNode *F, *ft, *fe, *G, *gt, *ge;
410 DdNode *one, *zero, *r, *t, *e, *Cube;
411 unsigned int topf, topg, topcube, top, index;
412 ptruint cacheTag;
414 statLine(manager);
415 one = DD_ONE(manager);
416 zero = Cudd_Not(one);
418 /* Terminal cases. */
419 if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
420 if (f == one && g == one) return(one);
421 if (cube == one) {
422 return(cuddBddClippingAndRecur(manager, f, g, distance, direction));
424 if (f == one || f == g) {
425 return (cuddBddExistAbstractRecur(manager, g, cube));
427 if (g == one) {
428 return (cuddBddExistAbstractRecur(manager, f, cube));
430 if (distance == 0) return(Cudd_NotCond(one,(direction == 0)));
432 /* At this point f, g, and cube are not constant. */
433 distance--;
435 /* Check cache. */
436 if (f > g) { /* Try to increase cache efficiency. */
437 DdNode *tmp = f;
438 f = g; g = tmp;
440 F = Cudd_Regular(f);
441 G = Cudd_Regular(g);
442 cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG :
443 DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG;
444 if (F->ref != 1 || G->ref != 1) {
445 r = cuddCacheLookup(manager, cacheTag,
446 f, g, cube);
447 if (r != NULL) {
448 return(r);
452 /* Here we can skip the use of cuddI, because the operands are known
453 ** to be non-constant.
455 topf = manager->perm[F->index];
456 topg = manager->perm[G->index];
457 top = ddMin(topf, topg);
458 topcube = manager->perm[cube->index];
460 if (topcube < top) {
461 return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube),
462 distance, direction));
464 /* Now, topcube >= top. */
466 if (topf == top) {
467 index = F->index;
468 ft = cuddT(F);
469 fe = cuddE(F);
470 if (Cudd_IsComplement(f)) {
471 ft = Cudd_Not(ft);
472 fe = Cudd_Not(fe);
474 } else {
475 index = G->index;
476 ft = fe = f;
479 if (topg == top) {
480 gt = cuddT(G);
481 ge = cuddE(G);
482 if (Cudd_IsComplement(g)) {
483 gt = Cudd_Not(gt);
484 ge = Cudd_Not(ge);
486 } else {
487 gt = ge = g;
490 if (topcube == top) {
491 Cube = cuddT(cube);
492 } else {
493 Cube = cube;
496 t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction);
497 if (t == NULL) return(NULL);
499 /* Special case: 1 OR anything = 1. Hence, no need to compute
500 ** the else branch if t is 1.
502 if (t == one && topcube == top) {
503 if (F->ref != 1 || G->ref != 1)
504 cuddCacheInsert(manager, cacheTag, f, g, cube, one);
505 return(one);
507 cuddRef(t);
509 e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction);
510 if (e == NULL) {
511 Cudd_RecursiveDeref(manager, t);
512 return(NULL);
514 cuddRef(e);
516 if (topcube == top) { /* abstract */
517 r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e),
518 distance, (direction == 0));
519 if (r == NULL) {
520 Cudd_RecursiveDeref(manager, t);
521 Cudd_RecursiveDeref(manager, e);
522 return(NULL);
524 r = Cudd_Not(r);
525 cuddRef(r);
526 Cudd_RecursiveDeref(manager, t);
527 Cudd_RecursiveDeref(manager, e);
528 cuddDeref(r);
529 } else if (t == e) {
530 r = t;
531 cuddDeref(t);
532 cuddDeref(e);
533 } else {
534 if (Cudd_IsComplement(t)) {
535 r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
536 if (r == NULL) {
537 Cudd_RecursiveDeref(manager, t);
538 Cudd_RecursiveDeref(manager, e);
539 return(NULL);
541 r = Cudd_Not(r);
542 } else {
543 r = cuddUniqueInter(manager,(int)index,t,e);
544 if (r == NULL) {
545 Cudd_RecursiveDeref(manager, t);
546 Cudd_RecursiveDeref(manager, e);
547 return(NULL);
550 cuddDeref(e);
551 cuddDeref(t);
553 if (F->ref != 1 || G->ref != 1)
554 cuddCacheInsert(manager, cacheTag, f, g, cube, r);
555 return (r);
557 } /* end of cuddBddClipAndAbsRecur */