abc-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
cuddGenCof.c
Go to the documentation of this file.
1 /**CFile***********************************************************************
2 
3  FileName [cuddGenCof.c]
4 
5  PackageName [cudd]
6 
7  Synopsis [Generalized cofactors for BDDs and ADDs.]
8 
9  Description [External procedures included in this module:
10  <ul>
11  <li> Cudd_bddConstrain()
12  <li> Cudd_bddRestrict()
13  <li> Cudd_bddNPAnd()
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()
22  </ul>
23  Internal procedures included in this module:
24  <ul>
25  <li> cuddBddConstrainRecur()
26  <li> cuddBddRestrictRecur()
27  <li> cuddBddNPAndRecur()
28  <li> cuddAddConstrainRecur()
29  <li> cuddAddRestrictRecur()
30  <li> cuddBddLICompaction()
31  </ul>
32  Static procedures included in this module:
33  <ul>
34  <li> cuddBddConstrainDecomp()
35  <li> cuddBddCharToVect()
36  <li> cuddBddLICMarkEdges()
37  <li> cuddBddLICBuildResult()
38  <li> cuddBddSqueeze()
39  </ul>
40  ]
41 
42  Author [Fabio Somenzi]
43 
44  Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
45 
46  All rights reserved.
47 
48  Redistribution and use in source and binary forms, with or without
49  modification, are permitted provided that the following conditions
50  are met:
51 
52  Redistributions of source code must retain the above copyright
53  notice, this list of conditions and the following disclaimer.
54 
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.
58 
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.
62 
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.]
75 
76 ******************************************************************************/
77 
78 #include "misc/util/util_hack.h"
79 #include "cuddInt.h"
80 
82 
83 
84 
85 
86 /*---------------------------------------------------------------------------*/
87 /* Constant declarations */
88 /*---------------------------------------------------------------------------*/
89 
90 /* Codes for edge markings in Cudd_bddLICompaction. The codes are defined
91 ** so that they can be bitwise ORed to implement the code priority scheme.
92 */
93 #define DD_LIC_DC 0
94 #define DD_LIC_1 1
95 #define DD_LIC_0 2
96 #define DD_LIC_NL 3
97 
98 /*---------------------------------------------------------------------------*/
99 /* Stucture declarations */
100 /*---------------------------------------------------------------------------*/
101 
102 
103 /*---------------------------------------------------------------------------*/
104 /* Type declarations */
105 /*---------------------------------------------------------------------------*/
106 
107 /* Key for the cache used in the edge marking phase. */
108 typedef struct MarkCacheKey {
111 } MarkCacheKey;
112 
113 /*---------------------------------------------------------------------------*/
114 /* Variable declarations */
115 /*---------------------------------------------------------------------------*/
116 
117 #ifndef lint
118 static char rcsid[] DD_UNUSED = "$Id: cuddGenCof.c,v 1.38 2005/05/14 17:27:11 fabio Exp $";
119 #endif
120 
121 /*---------------------------------------------------------------------------*/
122 /* Macro declarations */
123 /*---------------------------------------------------------------------------*/
124 
125 #ifdef __cplusplus
126 extern "C" {
127 #endif
128 
129 /**AutomaticStart*************************************************************/
130 
131 /*---------------------------------------------------------------------------*/
132 /* Static function prototypes */
133 /*---------------------------------------------------------------------------*/
134 
135 static int cuddBddConstrainDecomp (DdManager *dd, DdNode *f, DdNode **decomp);
136 static DdNode * cuddBddCharToVect (DdManager *dd, DdNode *f, DdNode *x);
137 static int cuddBddLICMarkEdges (DdManager *dd, DdNode *f, DdNode *c, st__table *table, st__table *cache);
138 static DdNode * cuddBddLICBuildResult (DdManager *dd, DdNode *f, st__table *cache, st__table *table);
139 static int MarkCacheHash (const char *ptr, int modulus);
140 static int MarkCacheCompare (const char *ptr1, const char *ptr2);
141 static enum st__retval MarkCacheCleanUp (char *key, char *value, char *arg);
142 static DdNode * cuddBddSqueeze (DdManager *dd, DdNode *l, DdNode *u);
143 
144 /**AutomaticEnd***************************************************************/
145 
146 #ifdef __cplusplus
147 }
148 #endif
149 
150 /*---------------------------------------------------------------------------*/
151 /* Definition of exported functions */
152 /*---------------------------------------------------------------------------*/
153 
154 
155 /**Function********************************************************************
156 
157  Synopsis [Computes f constrain c.]
158 
159  Description [Computes f constrain c (f @ c).
160  Uses a canonical form: (f' @ c) = ( f @ c)'. (Note: this is not true
161  for c.) List of special cases:
162  <ul>
163  <li> f @ 0 = 0
164  <li> f @ 1 = f
165  <li> 0 @ c = 0
166  <li> 1 @ c = 1
167  <li> f @ f = 1
168  <li> f @ f'= 0
169  </ul>
170  Returns a pointer to the result if successful; NULL otherwise. Note that if
171  F=(f1,...,fn) and reordering takes place while computing F @ c, then the
172  image restriction property (Img(F,c) = Img(F @ c)) is lost.]
173 
174  SideEffects [None]
175 
176  SeeAlso [Cudd_bddRestrict Cudd_addConstrain]
177 
178 ******************************************************************************/
179 DdNode *
181  DdManager * dd,
182  DdNode * f,
183  DdNode * c)
184 {
185  DdNode *res;
186 
187  do {
188  dd->reordered = 0;
189  res = cuddBddConstrainRecur(dd,f,c);
190  } while (dd->reordered == 1);
191  return(res);
192 
193 } /* end of Cudd_bddConstrain */
194 
195 
196 /**Function********************************************************************
197 
198  Synopsis [BDD restrict according to Coudert and Madre's algorithm
199  (ICCAD90).]
200 
201  Description [BDD restrict according to Coudert and Madre's algorithm
202  (ICCAD90). Returns the restricted BDD if successful; otherwise NULL.
203  If application of restrict results in a BDD larger than the input
204  BDD, the input BDD is returned.]
205 
206  SideEffects [None]
207 
208  SeeAlso [Cudd_bddConstrain Cudd_addRestrict]
209 
210 ******************************************************************************/
211 DdNode *
213  DdManager * dd,
214  DdNode * f,
215  DdNode * c)
216 {
217  DdNode *suppF, *suppC, *commonSupport;
218  DdNode *cplus, *res;
219  int retval;
220  int sizeF, sizeRes;
221 
222  /* Check terminal cases here to avoid computing supports in trivial cases.
223  ** This also allows us notto check later for the case c == 0, in which
224  ** there is no common support. */
225  if (c == Cudd_Not(DD_ONE(dd))) return(Cudd_Not(DD_ONE(dd)));
226  if (Cudd_IsConstant(f)) return(f);
227  if (f == c) return(DD_ONE(dd));
228  if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
229 
230  /* Check if supports intersect. */
231  retval = Cudd_ClassifySupport(dd,f,c,&commonSupport,&suppF,&suppC);
232  if (retval == 0) {
233  return(NULL);
234  }
235  cuddRef(commonSupport); cuddRef(suppF); cuddRef(suppC);
236  Cudd_IterDerefBdd(dd,suppF);
237 
238  if (commonSupport == DD_ONE(dd)) {
239  Cudd_IterDerefBdd(dd,commonSupport);
240  Cudd_IterDerefBdd(dd,suppC);
241  return(f);
242  }
243  Cudd_IterDerefBdd(dd,commonSupport);
244 
245  /* Abstract from c the variables that do not appear in f. */
246  cplus = Cudd_bddExistAbstract(dd, c, suppC);
247  if (cplus == NULL) {
248  Cudd_IterDerefBdd(dd,suppC);
249  return(NULL);
250  }
251  cuddRef(cplus);
252  Cudd_IterDerefBdd(dd,suppC);
253 
254  do {
255  dd->reordered = 0;
256  res = cuddBddRestrictRecur(dd, f, cplus);
257  } while (dd->reordered == 1);
258  if (res == NULL) {
259  Cudd_IterDerefBdd(dd,cplus);
260  return(NULL);
261  }
262  cuddRef(res);
263  Cudd_IterDerefBdd(dd,cplus);
264  /* Make restric safe by returning the smaller of the input and the
265  ** result. */
266  sizeF = Cudd_DagSize(f);
267  sizeRes = Cudd_DagSize(res);
268  if (sizeF <= sizeRes) {
269  Cudd_IterDerefBdd(dd, res);
270  return(f);
271  } else {
272  cuddDeref(res);
273  return(res);
274  }
275 
276 } /* end of Cudd_bddRestrict */
277 
278 
279 /**Function********************************************************************
280 
281  Synopsis [Computes f non-polluting-and g.]
282 
283  Description [Computes f non-polluting-and g. The non-polluting AND
284  of f and g is a hybrid of AND and Restrict. From Restrict, this
285  operation takes the idea of existentially quantifying the top
286  variable of the second operand if it does not appear in the first.
287  Therefore, the variables that appear in the result also appear in f.
288  For the rest, the function behaves like AND. Since the two operands
289  play different roles, non-polluting AND is not commutative.
290 
291  Returns a pointer to the result if successful; NULL otherwise.]
292 
293  SideEffects [None]
294 
295  SeeAlso [Cudd_bddConstrain Cudd_bddRestrict]
296 
297 ******************************************************************************/
298 DdNode *
300  DdManager * dd,
301  DdNode * f,
302  DdNode * g)
303 {
304  DdNode *res;
305 
306  do {
307  dd->reordered = 0;
308  res = cuddBddNPAndRecur(dd,f,g);
309  } while (dd->reordered == 1);
310  return(res);
311 
312 } /* end of Cudd_bddNPAnd */
313 
314 
315 /**Function********************************************************************
316 
317  Synopsis [Computes f constrain c for ADDs.]
318 
319  Description [Computes f constrain c (f @ c), for f an ADD and c a 0-1
320  ADD. List of special cases:
321  <ul>
322  <li> F @ 0 = 0
323  <li> F @ 1 = F
324  <li> 0 @ c = 0
325  <li> 1 @ c = 1
326  <li> F @ F = 1
327  </ul>
328  Returns a pointer to the result if successful; NULL otherwise.]
329 
330  SideEffects [None]
331 
332  SeeAlso [Cudd_bddConstrain]
333 
334 ******************************************************************************/
335 DdNode *
337  DdManager * dd,
338  DdNode * f,
339  DdNode * c)
340 {
341  DdNode *res;
342 
343  do {
344  dd->reordered = 0;
345  res = cuddAddConstrainRecur(dd,f,c);
346  } while (dd->reordered == 1);
347  return(res);
348 
349 } /* end of Cudd_addConstrain */
350 
351 
352 /**Function********************************************************************
353 
354  Synopsis [BDD conjunctive decomposition as in McMillan's CAV96 paper.]
355 
356  Description [BDD conjunctive decomposition as in McMillan's CAV96
357  paper. The decomposition is canonical only for a given variable
358  order. If canonicity is required, variable ordering must be disabled
359  after the decomposition has been computed. Returns an array with one
360  entry for each BDD variable in the manager if successful; otherwise
361  NULL. The components of the solution have their reference counts
362  already incremented (unlike the results of most other functions in
363  the package.]
364 
365  SideEffects [None]
366 
367  SeeAlso [Cudd_bddConstrain Cudd_bddExistAbstract]
368 
369 ******************************************************************************/
370 DdNode **
372  DdManager * dd,
373  DdNode * f)
374 {
375  DdNode **decomp;
376  int res;
377  int i;
378 
379  /* Create an initialize decomposition array. */
380  decomp = ABC_ALLOC(DdNode *,dd->size);
381  if (decomp == NULL) {
383  return(NULL);
384  }
385  for (i = 0; i < dd->size; i++) {
386  decomp[i] = NULL;
387  }
388  do {
389  dd->reordered = 0;
390  /* Clean up the decomposition array in case reordering took place. */
391  for (i = 0; i < dd->size; i++) {
392  if (decomp[i] != NULL) {
393  Cudd_IterDerefBdd(dd, decomp[i]);
394  decomp[i] = NULL;
395  }
396  }
397  res = cuddBddConstrainDecomp(dd,f,decomp);
398  } while (dd->reordered == 1);
399  if (res == 0) {
400  ABC_FREE(decomp);
401  return(NULL);
402  }
403  /* Missing components are constant ones. */
404  for (i = 0; i < dd->size; i++) {
405  if (decomp[i] == NULL) {
406  decomp[i] = DD_ONE(dd);
407  cuddRef(decomp[i]);
408  }
409  }
410  return(decomp);
411 
412 } /* end of Cudd_bddConstrainDecomp */
413 
414 
415 /**Function********************************************************************
416 
417  Synopsis [ADD restrict according to Coudert and Madre's algorithm
418  (ICCAD90).]
419 
420  Description [ADD restrict according to Coudert and Madre's algorithm
421  (ICCAD90). Returns the restricted ADD if successful; otherwise NULL.
422  If application of restrict results in an ADD larger than the input
423  ADD, the input ADD is returned.]
424 
425  SideEffects [None]
426 
427  SeeAlso [Cudd_addConstrain Cudd_bddRestrict]
428 
429 ******************************************************************************/
430 DdNode *
432  DdManager * dd,
433  DdNode * f,
434  DdNode * c)
435 {
436  DdNode *supp_f, *supp_c;
437  DdNode *res, *commonSupport;
438  int intersection;
439  int sizeF, sizeRes;
440 
441  /* Check if supports intersect. */
442  supp_f = Cudd_Support(dd, f);
443  if (supp_f == NULL) {
444  return(NULL);
445  }
446  cuddRef(supp_f);
447  supp_c = Cudd_Support(dd, c);
448  if (supp_c == NULL) {
449  Cudd_RecursiveDeref(dd,supp_f);
450  return(NULL);
451  }
452  cuddRef(supp_c);
453  commonSupport = Cudd_bddLiteralSetIntersection(dd, supp_f, supp_c);
454  if (commonSupport == NULL) {
455  Cudd_RecursiveDeref(dd,supp_f);
456  Cudd_RecursiveDeref(dd,supp_c);
457  return(NULL);
458  }
459  cuddRef(commonSupport);
460  Cudd_RecursiveDeref(dd,supp_f);
461  Cudd_RecursiveDeref(dd,supp_c);
462  intersection = commonSupport != DD_ONE(dd);
463  Cudd_RecursiveDeref(dd,commonSupport);
464 
465  if (intersection) {
466  do {
467  dd->reordered = 0;
468  res = cuddAddRestrictRecur(dd, f, c);
469  } while (dd->reordered == 1);
470  sizeF = Cudd_DagSize(f);
471  sizeRes = Cudd_DagSize(res);
472  if (sizeF <= sizeRes) {
473  cuddRef(res);
474  Cudd_RecursiveDeref(dd, res);
475  return(f);
476  } else {
477  return(res);
478  }
479  } else {
480  return(f);
481  }
482 
483 } /* end of Cudd_addRestrict */
484 
485 
486 /**Function********************************************************************
487 
488  Synopsis [Computes a vector whose image equals a non-zero function.]
489 
490  Description [Computes a vector of BDDs whose image equals a non-zero
491  function.
492  The result depends on the variable order. The i-th component of the vector
493  depends only on the first i variables in the order. Each BDD in the vector
494  is not larger than the BDD of the given characteristic function. This
495  function is based on the description of char-to-vect in "Verification of
496  Sequential Machines Using Boolean Functional Vectors" by O. Coudert, C.
497  Berthet and J. C. Madre.
498  Returns a pointer to an array containing the result if successful; NULL
499  otherwise. The size of the array equals the number of variables in the
500  manager. The components of the solution have their reference counts
501  already incremented (unlike the results of most other functions in
502  the package).]
503 
504  SideEffects [None]
505 
506  SeeAlso [Cudd_bddConstrain]
507 
508 ******************************************************************************/
509 DdNode **
511  DdManager * dd,
512  DdNode * f)
513 {
514  int i, j;
515  DdNode **vect;
516  DdNode *res = NULL;
517 
518  if (f == Cudd_Not(DD_ONE(dd))) return(NULL);
519 
520  vect = ABC_ALLOC(DdNode *, dd->size);
521  if (vect == NULL) {
523  return(NULL);
524  }
525 
526  do {
527  dd->reordered = 0;
528  for (i = 0; i < dd->size; i++) {
529  res = cuddBddCharToVect(dd,f,dd->vars[dd->invperm[i]]);
530  if (res == NULL) {
531  /* Clean up the vector array in case reordering took place. */
532  for (j = 0; j < i; j++) {
533  Cudd_IterDerefBdd(dd, vect[dd->invperm[j]]);
534  }
535  break;
536  }
537  cuddRef(res);
538  vect[dd->invperm[i]] = res;
539  }
540  } while (dd->reordered == 1);
541  if (res == NULL) {
542  ABC_FREE(vect);
543  return(NULL);
544  }
545  return(vect);
546 
547 } /* end of Cudd_bddCharToVect */
548 
549 
550 /**Function********************************************************************
551 
552  Synopsis [Performs safe minimization of a BDD.]
553 
554  Description [Performs safe minimization of a BDD. Given the BDD
555  <code>f</code> of a function to be minimized and a BDD
556  <code>c</code> representing the care set, Cudd_bddLICompaction
557  produces the BDD of a function that agrees with <code>f</code>
558  wherever <code>c</code> is 1. Safe minimization means that the size
559  of the result is guaranteed not to exceed the size of
560  <code>f</code>. This function is based on the DAC97 paper by Hong et
561  al.. Returns a pointer to the result if successful; NULL
562  otherwise.]
563 
564  SideEffects [None]
565 
566  SeeAlso [Cudd_bddRestrict]
567 
568 ******************************************************************************/
569 DdNode *
571  DdManager * dd /* manager */,
572  DdNode * f /* function to be minimized */,
573  DdNode * c /* constraint (care set) */)
574 {
575  DdNode *res;
576 
577  do {
578  dd->reordered = 0;
579  res = cuddBddLICompaction(dd,f,c);
580  } while (dd->reordered == 1);
581  return(res);
582 
583 } /* end of Cudd_bddLICompaction */
584 
585 
586 /**Function********************************************************************
587 
588  Synopsis [Finds a small BDD in a function interval.]
589 
590  Description [Finds a small BDD in a function interval. Given BDDs
591  <code>l</code> and <code>u</code>, representing the lower bound and
592  upper bound of a function interval, Cudd_bddSqueeze produces the BDD
593  of a function within the interval with a small BDD. Returns a
594  pointer to the result if successful; NULL otherwise.]
595 
596  SideEffects [None]
597 
598  SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction]
599 
600 ******************************************************************************/
601 DdNode *
603  DdManager * dd /* manager */,
604  DdNode * l /* lower bound */,
605  DdNode * u /* upper bound */)
606 {
607  DdNode *res;
608  int sizeRes, sizeL, sizeU;
609 
610  do {
611  dd->reordered = 0;
612  res = cuddBddSqueeze(dd,l,u);
613  } while (dd->reordered == 1);
614  if (res == NULL) return(NULL);
615  /* We now compare the result with the bounds and return the smallest.
616  ** We first compare to u, so that in case l == 0 and u == 1, we return
617  ** 0 as in other minimization algorithms. */
618  sizeRes = Cudd_DagSize(res);
619  sizeU = Cudd_DagSize(u);
620  if (sizeU <= sizeRes) {
621  cuddRef(res);
622  Cudd_IterDerefBdd(dd,res);
623  res = u;
624  sizeRes = sizeU;
625  }
626  sizeL = Cudd_DagSize(l);
627  if (sizeL <= sizeRes) {
628  cuddRef(res);
629  Cudd_IterDerefBdd(dd,res);
630  res = l;
631  sizeRes = sizeL;
632  }
633  return(res);
634 
635 } /* end of Cudd_bddSqueeze */
636 
637 
638 /**Function********************************************************************
639 
640  Synopsis [Finds a small BDD that agrees with <code>f</code> over
641  <code>c</code>.]
642 
643  Description [Finds a small BDD that agrees with <code>f</code> over
644  <code>c</code>. Returns a pointer to the result if successful; NULL
645  otherwise.]
646 
647  SideEffects [None]
648 
649  SeeAlso [Cudd_bddRestrict Cudd_bddLICompaction Cudd_bddSqueeze]
650 
651 ******************************************************************************/
652 DdNode *
654  DdManager * dd,
655  DdNode * f,
656  DdNode * c)
657 {
658  DdNode *cplus, *res;
659 
660  if (c == Cudd_Not(DD_ONE(dd))) return(c);
661  if (Cudd_IsConstant(f)) return(f);
662  if (f == c) return(DD_ONE(dd));
663  if (f == Cudd_Not(c)) return(Cudd_Not(DD_ONE(dd)));
664 
665  cplus = Cudd_RemapOverApprox(dd,c,0,0,1.0);
666  if (cplus == NULL) return(NULL);
667  cuddRef(cplus);
668  res = Cudd_bddLICompaction(dd,f,cplus);
669  if (res == NULL) {
670  Cudd_IterDerefBdd(dd,cplus);
671  return(NULL);
672  }
673  cuddRef(res);
674  Cudd_IterDerefBdd(dd,cplus);
675  cuddDeref(res);
676  return(res);
677 
678 } /* end of Cudd_bddMinimize */
679 
680 
681 /**Function********************************************************************
682 
683  Synopsis [Find a dense subset of BDD <code>f</code>.]
684 
685  Description [Finds a dense subset of BDD <code>f</code>. Density is
686  the ratio of number of minterms to number of nodes. Uses several
687  techniques in series. It is more expensive than other subsetting
688  procedures, but often produces better results. See
689  Cudd_SubsetShortPaths for a description of the threshold and nvars
690  parameters. Returns a pointer to the result if successful; NULL
691  otherwise.]
692 
693  SideEffects [None]
694 
695  SeeAlso [Cudd_SubsetRemap Cudd_SubsetShortPaths Cudd_SubsetHeavyBranch
696  Cudd_bddSqueeze]
697 
698 ******************************************************************************/
699 DdNode *
701  DdManager * dd /* manager */,
702  DdNode * f /* BDD whose subset is sought */,
703  int nvars /* number of variables in the support of f */,
704  int threshold /* maximum number of nodes in the subset */)
705 {
706  DdNode *res, *tmp1, *tmp2;
707 
708  tmp1 = Cudd_SubsetShortPaths(dd, f, nvars, threshold, 0);
709  if (tmp1 == NULL) return(NULL);
710  cuddRef(tmp1);
711  tmp2 = Cudd_RemapUnderApprox(dd,tmp1,nvars,0,1.0);
712  if (tmp2 == NULL) {
713  Cudd_IterDerefBdd(dd,tmp1);
714  return(NULL);
715  }
716  cuddRef(tmp2);
717  Cudd_IterDerefBdd(dd,tmp1);
718  res = Cudd_bddSqueeze(dd,tmp2,f);
719  if (res == NULL) {
720  Cudd_IterDerefBdd(dd,tmp2);
721  return(NULL);
722  }
723  cuddRef(res);
724  Cudd_IterDerefBdd(dd,tmp2);
725  cuddDeref(res);
726  return(res);
727 
728 } /* end of Cudd_SubsetCompress */
729 
730 
731 /**Function********************************************************************
732 
733  Synopsis [Find a dense superset of BDD <code>f</code>.]
734 
735  Description [Finds a dense superset of BDD <code>f</code>. Density is
736  the ratio of number of minterms to number of nodes. Uses several
737  techniques in series. It is more expensive than other supersetting
738  procedures, but often produces better results. See
739  Cudd_SupersetShortPaths for a description of the threshold and nvars
740  parameters. Returns a pointer to the result if successful; NULL
741  otherwise.]
742 
743  SideEffects [None]
744 
745  SeeAlso [Cudd_SubsetCompress Cudd_SupersetRemap Cudd_SupersetShortPaths
746  Cudd_SupersetHeavyBranch Cudd_bddSqueeze]
747 
748 ******************************************************************************/
749 DdNode *
751  DdManager * dd /* manager */,
752  DdNode * f /* BDD whose superset is sought */,
753  int nvars /* number of variables in the support of f */,
754  int threshold /* maximum number of nodes in the superset */)
755 {
756  DdNode *subset;
757 
758  subset = Cudd_SubsetCompress(dd, Cudd_Not(f),nvars,threshold);
759 
760  return(Cudd_NotCond(subset, (subset != NULL)));
761 
762 } /* end of Cudd_SupersetCompress */
763 
764 
765 /*---------------------------------------------------------------------------*/
766 /* Definition of internal functions */
767 /*---------------------------------------------------------------------------*/
768 
769 
770 /**Function********************************************************************
771 
772  Synopsis [Performs the recursive step of Cudd_bddConstrain.]
773 
774  Description [Performs the recursive step of Cudd_bddConstrain.
775  Returns a pointer to the result if successful; NULL otherwise.]
776 
777  SideEffects [None]
778 
779  SeeAlso [Cudd_bddConstrain]
780 
781 ******************************************************************************/
782 DdNode *
784  DdManager * dd,
785  DdNode * f,
786  DdNode * c)
787 {
788  DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
789  DdNode *one, *zero;
790  unsigned int topf, topc;
791  int index;
792  int comple = 0;
793 
794  statLine(dd);
795  one = DD_ONE(dd);
796  zero = Cudd_Not(one);
797 
798  /* Trivial cases. */
799  if (c == one) return(f);
800  if (c == zero) return(zero);
801  if (Cudd_IsConstant(f)) return(f);
802  if (f == c) return(one);
803  if (f == Cudd_Not(c)) return(zero);
804 
805  /* Make canonical to increase the utilization of the cache. */
806  if (Cudd_IsComplement(f)) {
807  f = Cudd_Not(f);
808  comple = 1;
809  }
810  /* Now f is a regular pointer to a non-constant node; c is also
811  ** non-constant, but may be complemented.
812  */
813 
814  /* Check the cache. */
815  r = cuddCacheLookup2(dd, Cudd_bddConstrain, f, c);
816  if (r != NULL) {
817  return(Cudd_NotCond(r,comple));
818  }
819 
820  /* Recursive step. */
821  topf = dd->perm[f->index];
822  topc = dd->perm[Cudd_Regular(c)->index];
823  if (topf <= topc) {
824  index = f->index;
825  Fv = cuddT(f); Fnv = cuddE(f);
826  } else {
827  index = Cudd_Regular(c)->index;
828  Fv = Fnv = f;
829  }
830  if (topc <= topf) {
831  Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
832  if (Cudd_IsComplement(c)) {
833  Cv = Cudd_Not(Cv);
834  Cnv = Cudd_Not(Cnv);
835  }
836  } else {
837  Cv = Cnv = c;
838  }
839 
840  if (!Cudd_IsConstant(Cv)) {
841  t = cuddBddConstrainRecur(dd, Fv, Cv);
842  if (t == NULL)
843  return(NULL);
844  } else if (Cv == one) {
845  t = Fv;
846  } else { /* Cv == zero: return Fnv @ Cnv */
847  if (Cnv == one) {
848  r = Fnv;
849  } else {
850  r = cuddBddConstrainRecur(dd, Fnv, Cnv);
851  if (r == NULL)
852  return(NULL);
853  }
854  return(Cudd_NotCond(r,comple));
855  }
856  cuddRef(t);
857 
858  if (!Cudd_IsConstant(Cnv)) {
859  e = cuddBddConstrainRecur(dd, Fnv, Cnv);
860  if (e == NULL) {
861  Cudd_IterDerefBdd(dd, t);
862  return(NULL);
863  }
864  } else if (Cnv == one) {
865  e = Fnv;
866  } else { /* Cnv == zero: return Fv @ Cv previously computed */
867  cuddDeref(t);
868  return(Cudd_NotCond(t,comple));
869  }
870  cuddRef(e);
871 
872  if (Cudd_IsComplement(t)) {
873  t = Cudd_Not(t);
874  e = Cudd_Not(e);
875  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
876  if (r == NULL) {
877  Cudd_IterDerefBdd(dd, e);
878  Cudd_IterDerefBdd(dd, t);
879  return(NULL);
880  }
881  r = Cudd_Not(r);
882  } else {
883  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
884  if (r == NULL) {
885  Cudd_IterDerefBdd(dd, e);
886  Cudd_IterDerefBdd(dd, t);
887  return(NULL);
888  }
889  }
890  cuddDeref(t);
891  cuddDeref(e);
892 
893  cuddCacheInsert2(dd, Cudd_bddConstrain, f, c, r);
894  return(Cudd_NotCond(r,comple));
895 
896 } /* end of cuddBddConstrainRecur */
897 
898 
899 /**Function********************************************************************
900 
901  Synopsis [Performs the recursive step of Cudd_bddRestrict.]
902 
903  Description [Performs the recursive step of Cudd_bddRestrict.
904  Returns the restricted BDD if successful; otherwise NULL.]
905 
906  SideEffects [None]
907 
908  SeeAlso [Cudd_bddRestrict]
909 
910 ******************************************************************************/
911 DdNode *
913  DdManager * dd,
914  DdNode * f,
915  DdNode * c)
916 {
917  DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
918  unsigned int topf, topc;
919  int index;
920  int comple = 0;
921 
922  statLine(dd);
923  one = DD_ONE(dd);
924  zero = Cudd_Not(one);
925 
926  /* Trivial cases */
927  if (c == one) return(f);
928  if (c == zero) return(zero);
929  if (Cudd_IsConstant(f)) return(f);
930  if (f == c) return(one);
931  if (f == Cudd_Not(c)) return(zero);
932 
933  /* Make canonical to increase the utilization of the cache. */
934  if (Cudd_IsComplement(f)) {
935  f = Cudd_Not(f);
936  comple = 1;
937  }
938  /* Now f is a regular pointer to a non-constant node; c is also
939  ** non-constant, but may be complemented.
940  */
941 
942  /* Check the cache. */
943  r = cuddCacheLookup2(dd, Cudd_bddRestrict, f, c);
944  if (r != NULL) {
945  return(Cudd_NotCond(r,comple));
946  }
947 
948  topf = dd->perm[f->index];
949  topc = dd->perm[Cudd_Regular(c)->index];
950 
951  if (topc < topf) { /* abstract top variable from c */
952  DdNode *d, *s1, *s2;
953 
954  /* Find complements of cofactors of c. */
955  if (Cudd_IsComplement(c)) {
956  s1 = cuddT(Cudd_Regular(c));
957  s2 = cuddE(Cudd_Regular(c));
958  } else {
959  s1 = Cudd_Not(cuddT(c));
960  s2 = Cudd_Not(cuddE(c));
961  }
962  /* Take the OR by applying DeMorgan. */
963  d = cuddBddAndRecur(dd, s1, s2);
964  if (d == NULL) return(NULL);
965  d = Cudd_Not(d);
966  cuddRef(d);
967  r = cuddBddRestrictRecur(dd, f, d);
968  if (r == NULL) {
969  Cudd_IterDerefBdd(dd, d);
970  return(NULL);
971  }
972  cuddRef(r);
973  Cudd_IterDerefBdd(dd, d);
974  cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
975  cuddDeref(r);
976  return(Cudd_NotCond(r,comple));
977  }
978 
979  /* Recursive step. Here topf <= topc. */
980  index = f->index;
981  Fv = cuddT(f); Fnv = cuddE(f);
982  if (topc == topf) {
983  Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
984  if (Cudd_IsComplement(c)) {
985  Cv = Cudd_Not(Cv);
986  Cnv = Cudd_Not(Cnv);
987  }
988  } else {
989  Cv = Cnv = c;
990  }
991 
992  if (!Cudd_IsConstant(Cv)) {
993  t = cuddBddRestrictRecur(dd, Fv, Cv);
994  if (t == NULL) return(NULL);
995  } else if (Cv == one) {
996  t = Fv;
997  } else { /* Cv == zero: return(Fnv @ Cnv) */
998  if (Cnv == one) {
999  r = Fnv;
1000  } else {
1001  r = cuddBddRestrictRecur(dd, Fnv, Cnv);
1002  if (r == NULL) return(NULL);
1003  }
1004  return(Cudd_NotCond(r,comple));
1005  }
1006  cuddRef(t);
1007 
1008  if (!Cudd_IsConstant(Cnv)) {
1009  e = cuddBddRestrictRecur(dd, Fnv, Cnv);
1010  if (e == NULL) {
1011  Cudd_IterDerefBdd(dd, t);
1012  return(NULL);
1013  }
1014  } else if (Cnv == one) {
1015  e = Fnv;
1016  } else { /* Cnv == zero: return (Fv @ Cv) previously computed */
1017  cuddDeref(t);
1018  return(Cudd_NotCond(t,comple));
1019  }
1020  cuddRef(e);
1021 
1022  if (Cudd_IsComplement(t)) {
1023  t = Cudd_Not(t);
1024  e = Cudd_Not(e);
1025  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
1026  if (r == NULL) {
1027  Cudd_IterDerefBdd(dd, e);
1028  Cudd_IterDerefBdd(dd, t);
1029  return(NULL);
1030  }
1031  r = Cudd_Not(r);
1032  } else {
1033  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
1034  if (r == NULL) {
1035  Cudd_IterDerefBdd(dd, e);
1036  Cudd_IterDerefBdd(dd, t);
1037  return(NULL);
1038  }
1039  }
1040  cuddDeref(t);
1041  cuddDeref(e);
1042 
1043  cuddCacheInsert2(dd, Cudd_bddRestrict, f, c, r);
1044  return(Cudd_NotCond(r,comple));
1045 
1046 } /* end of cuddBddRestrictRecur */
1047 
1048 
1049 /**Function********************************************************************
1050 
1051  Synopsis [Implements the recursive step of Cudd_bddAnd.]
1052 
1053  Description [Implements the recursive step of Cudd_bddNPAnd.
1054  Returns a pointer to the result is successful; NULL otherwise.]
1055 
1056  SideEffects [None]
1057 
1058  SeeAlso [Cudd_bddNPAnd]
1059 
1060 ******************************************************************************/
1061 DdNode *
1063  DdManager * manager,
1064  DdNode * f,
1065  DdNode * g)
1066 {
1067  DdNode *F, *ft, *fe, *G, *gt, *ge;
1068  DdNode *one, *r, *t, *e;
1069  unsigned int topf, topg, index;
1070 
1071  statLine(manager);
1072  one = DD_ONE(manager);
1073 
1074  /* Terminal cases. */
1075  F = Cudd_Regular(f);
1076  G = Cudd_Regular(g);
1077  if (F == G) {
1078  if (f == g) return(one);
1079  else return(Cudd_Not(one));
1080  }
1081  if (G == one) {
1082  if (g == one) return(f);
1083  else return(g);
1084  }
1085  if (F == one) {
1086  return(f);
1087  }
1088 
1089  /* At this point f and g are not constant. */
1090  /* Check cache. */
1091  if (F->ref != 1 || G->ref != 1) {
1092  r = cuddCacheLookup2(manager, Cudd_bddNPAnd, f, g);
1093  if (r != NULL) return(r);
1094  }
1095 
1096  /* Here we can skip the use of cuddI, because the operands are known
1097  ** to be non-constant.
1098  */
1099  topf = manager->perm[F->index];
1100  topg = manager->perm[G->index];
1101 
1102  if (topg < topf) { /* abstract top variable from g */
1103  DdNode *d;
1104 
1105  /* Find complements of cofactors of g. */
1106  if (Cudd_IsComplement(g)) {
1107  gt = cuddT(G);
1108  ge = cuddE(G);
1109  } else {
1110  gt = Cudd_Not(cuddT(g));
1111  ge = Cudd_Not(cuddE(g));
1112  }
1113  /* Take the OR by applying DeMorgan. */
1114  d = cuddBddAndRecur(manager, gt, ge);
1115  if (d == NULL) return(NULL);
1116  d = Cudd_Not(d);
1117  cuddRef(d);
1118  r = cuddBddNPAndRecur(manager, f, d);
1119  if (r == NULL) {
1120  Cudd_IterDerefBdd(manager, d);
1121  return(NULL);
1122  }
1123  cuddRef(r);
1124  Cudd_IterDerefBdd(manager, d);
1125  cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
1126  cuddDeref(r);
1127  return(r);
1128  }
1129 
1130  /* Compute cofactors. */
1131  index = F->index;
1132  ft = cuddT(F);
1133  fe = cuddE(F);
1134  if (Cudd_IsComplement(f)) {
1135  ft = Cudd_Not(ft);
1136  fe = Cudd_Not(fe);
1137  }
1138 
1139  if (topg == topf) {
1140  gt = cuddT(G);
1141  ge = cuddE(G);
1142  if (Cudd_IsComplement(g)) {
1143  gt = Cudd_Not(gt);
1144  ge = Cudd_Not(ge);
1145  }
1146  } else {
1147  gt = ge = g;
1148  }
1149 
1150  t = cuddBddAndRecur(manager, ft, gt);
1151  if (t == NULL) return(NULL);
1152  cuddRef(t);
1153 
1154  e = cuddBddAndRecur(manager, fe, ge);
1155  if (e == NULL) {
1156  Cudd_IterDerefBdd(manager, t);
1157  return(NULL);
1158  }
1159  cuddRef(e);
1160 
1161  if (t == e) {
1162  r = t;
1163  } else {
1164  if (Cudd_IsComplement(t)) {
1165  r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
1166  if (r == NULL) {
1167  Cudd_IterDerefBdd(manager, t);
1168  Cudd_IterDerefBdd(manager, e);
1169  return(NULL);
1170  }
1171  r = Cudd_Not(r);
1172  } else {
1173  r = cuddUniqueInter(manager,(int)index,t,e);
1174  if (r == NULL) {
1175  Cudd_IterDerefBdd(manager, t);
1176  Cudd_IterDerefBdd(manager, e);
1177  return(NULL);
1178  }
1179  }
1180  }
1181  cuddDeref(e);
1182  cuddDeref(t);
1183  if (F->ref != 1 || G->ref != 1)
1184  cuddCacheInsert2(manager, Cudd_bddNPAnd, f, g, r);
1185  return(r);
1186 
1187 } /* end of cuddBddNPAndRecur */
1188 
1189 
1190 /**Function********************************************************************
1191 
1192  Synopsis [Performs the recursive step of Cudd_addConstrain.]
1193 
1194  Description [Performs the recursive step of Cudd_addConstrain.
1195  Returns a pointer to the result if successful; NULL otherwise.]
1196 
1197  SideEffects [None]
1198 
1199  SeeAlso [Cudd_addConstrain]
1200 
1201 ******************************************************************************/
1202 DdNode *
1204  DdManager * dd,
1205  DdNode * f,
1206  DdNode * c)
1207 {
1208  DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r;
1209  DdNode *one, *zero;
1210  unsigned int topf, topc;
1211  int index;
1212 
1213  statLine(dd);
1214  one = DD_ONE(dd);
1215  zero = DD_ZERO(dd);
1216 
1217  /* Trivial cases. */
1218  if (c == one) return(f);
1219  if (c == zero) return(zero);
1220  if (Cudd_IsConstant(f)) return(f);
1221  if (f == c) return(one);
1222 
1223  /* Now f and c are non-constant. */
1224 
1225  /* Check the cache. */
1226  r = cuddCacheLookup2(dd, Cudd_addConstrain, f, c);
1227  if (r != NULL) {
1228  return(r);
1229  }
1230 
1231  /* Recursive step. */
1232  topf = dd->perm[f->index];
1233  topc = dd->perm[c->index];
1234  if (topf <= topc) {
1235  index = f->index;
1236  Fv = cuddT(f); Fnv = cuddE(f);
1237  } else {
1238  index = c->index;
1239  Fv = Fnv = f;
1240  }
1241  if (topc <= topf) {
1242  Cv = cuddT(c); Cnv = cuddE(c);
1243  } else {
1244  Cv = Cnv = c;
1245  }
1246 
1247  if (!Cudd_IsConstant(Cv)) {
1248  t = cuddAddConstrainRecur(dd, Fv, Cv);
1249  if (t == NULL)
1250  return(NULL);
1251  } else if (Cv == one) {
1252  t = Fv;
1253  } else { /* Cv == zero: return Fnv @ Cnv */
1254  if (Cnv == one) {
1255  r = Fnv;
1256  } else {
1257  r = cuddAddConstrainRecur(dd, Fnv, Cnv);
1258  if (r == NULL)
1259  return(NULL);
1260  }
1261  return(r);
1262  }
1263  cuddRef(t);
1264 
1265  if (!Cudd_IsConstant(Cnv)) {
1266  e = cuddAddConstrainRecur(dd, Fnv, Cnv);
1267  if (e == NULL) {
1268  Cudd_RecursiveDeref(dd, t);
1269  return(NULL);
1270  }
1271  } else if (Cnv == one) {
1272  e = Fnv;
1273  } else { /* Cnv == zero: return Fv @ Cv previously computed */
1274  cuddDeref(t);
1275  return(t);
1276  }
1277  cuddRef(e);
1278 
1279  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
1280  if (r == NULL) {
1281  Cudd_RecursiveDeref(dd, e);
1282  Cudd_RecursiveDeref(dd, t);
1283  return(NULL);
1284  }
1285  cuddDeref(t);
1286  cuddDeref(e);
1287 
1288  cuddCacheInsert2(dd, Cudd_addConstrain, f, c, r);
1289  return(r);
1290 
1291 } /* end of cuddAddConstrainRecur */
1292 
1293 
1294 /**Function********************************************************************
1295 
1296  Synopsis [Performs the recursive step of Cudd_addRestrict.]
1297 
1298  Description [Performs the recursive step of Cudd_addRestrict.
1299  Returns the restricted ADD if successful; otherwise NULL.]
1300 
1301  SideEffects [None]
1302 
1303  SeeAlso [Cudd_addRestrict]
1304 
1305 ******************************************************************************/
1306 DdNode *
1308  DdManager * dd,
1309  DdNode * f,
1310  DdNode * c)
1311 {
1312  DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *r, *one, *zero;
1313  unsigned int topf, topc;
1314  int index;
1315 
1316  statLine(dd);
1317  one = DD_ONE(dd);
1318  zero = DD_ZERO(dd);
1319 
1320  /* Trivial cases */
1321  if (c == one) return(f);
1322  if (c == zero) return(zero);
1323  if (Cudd_IsConstant(f)) return(f);
1324  if (f == c) return(one);
1325 
1326  /* Now f and c are non-constant. */
1327 
1328  /* Check the cache. */
1329  r = cuddCacheLookup2(dd, Cudd_addRestrict, f, c);
1330  if (r != NULL) {
1331  return(r);
1332  }
1333 
1334  topf = dd->perm[f->index];
1335  topc = dd->perm[c->index];
1336 
1337  if (topc < topf) { /* abstract top variable from c */
1338  DdNode *d, *s1, *s2;
1339 
1340  /* Find cofactors of c. */
1341  s1 = cuddT(c);
1342  s2 = cuddE(c);
1343  /* Take the OR by applying DeMorgan. */
1344  d = cuddAddApplyRecur(dd, Cudd_addOr, s1, s2);
1345  if (d == NULL) return(NULL);
1346  cuddRef(d);
1347  r = cuddAddRestrictRecur(dd, f, d);
1348  if (r == NULL) {
1349  Cudd_RecursiveDeref(dd, d);
1350  return(NULL);
1351  }
1352  cuddRef(r);
1353  Cudd_RecursiveDeref(dd, d);
1354  cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
1355  cuddDeref(r);
1356  return(r);
1357  }
1358 
1359  /* Recursive step. Here topf <= topc. */
1360  index = f->index;
1361  Fv = cuddT(f); Fnv = cuddE(f);
1362  if (topc == topf) {
1363  Cv = cuddT(c); Cnv = cuddE(c);
1364  } else {
1365  Cv = Cnv = c;
1366  }
1367 
1368  if (!Cudd_IsConstant(Cv)) {
1369  t = cuddAddRestrictRecur(dd, Fv, Cv);
1370  if (t == NULL) return(NULL);
1371  } else if (Cv == one) {
1372  t = Fv;
1373  } else { /* Cv == zero: return(Fnv @ Cnv) */
1374  if (Cnv == one) {
1375  r = Fnv;
1376  } else {
1377  r = cuddAddRestrictRecur(dd, Fnv, Cnv);
1378  if (r == NULL) return(NULL);
1379  }
1380  return(r);
1381  }
1382  cuddRef(t);
1383 
1384  if (!Cudd_IsConstant(Cnv)) {
1385  e = cuddAddRestrictRecur(dd, Fnv, Cnv);
1386  if (e == NULL) {
1387  Cudd_RecursiveDeref(dd, t);
1388  return(NULL);
1389  }
1390  } else if (Cnv == one) {
1391  e = Fnv;
1392  } else { /* Cnv == zero: return (Fv @ Cv) previously computed */
1393  cuddDeref(t);
1394  return(t);
1395  }
1396  cuddRef(e);
1397 
1398  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
1399  if (r == NULL) {
1400  Cudd_RecursiveDeref(dd, e);
1401  Cudd_RecursiveDeref(dd, t);
1402  return(NULL);
1403  }
1404  cuddDeref(t);
1405  cuddDeref(e);
1406 
1407  cuddCacheInsert2(dd, Cudd_addRestrict, f, c, r);
1408  return(r);
1409 
1410 } /* end of cuddAddRestrictRecur */
1411 
1412 
1413 
1414 /**Function********************************************************************
1415 
1416  Synopsis [Performs safe minimization of a BDD.]
1417 
1418  Description [Performs safe minimization of a BDD. Given the BDD
1419  <code>f</code> of a function to be minimized and a BDD
1420  <code>c</code> representing the care set, Cudd_bddLICompaction
1421  produces the BDD of a function that agrees with <code>f</code>
1422  wherever <code>c</code> is 1. Safe minimization means that the size
1423  of the result is guaranteed not to exceed the size of
1424  <code>f</code>. This function is based on the DAC97 paper by Hong et
1425  al.. Returns a pointer to the result if successful; NULL
1426  otherwise.]
1427 
1428  SideEffects [None]
1429 
1430  SeeAlso [Cudd_bddLICompaction]
1431 
1432 ******************************************************************************/
1433 DdNode *
1435  DdManager * dd /* manager */,
1436  DdNode * f /* function to be minimized */,
1437  DdNode * c /* constraint (care set) */)
1438 {
1439  st__table *marktable, *markcache, *buildcache;
1440  DdNode *res, *zero;
1441 
1442  zero = Cudd_Not(DD_ONE(dd));
1443  if (c == zero) return(zero);
1444 
1445  /* We need to use local caches for both steps of this operation.
1446  ** The results of the edge marking step are only valid as long as the
1447  ** edge markings themselves are available. However, the edge markings
1448  ** are lost at the end of one invocation of Cudd_bddLICompaction.
1449  ** Hence, the cache entries for the edge marking step must be
1450  ** invalidated at the end of this function.
1451  ** For the result of the building step we argue as follows. The result
1452  ** for a node and a given constrain depends on the BDD in which the node
1453  ** appears. Hence, the same node and constrain may give different results
1454  ** in successive invocations.
1455  */
1456  marktable = st__init_table( st__ptrcmp, st__ptrhash);
1457  if (marktable == NULL) {
1458  return(NULL);
1459  }
1461  if (markcache == NULL) {
1462  st__free_table(marktable);
1463  return(NULL);
1464  }
1465  if (cuddBddLICMarkEdges(dd,f,c,marktable,markcache) == CUDD_OUT_OF_MEM) {
1466  st__foreach(markcache, MarkCacheCleanUp, NULL);
1467  st__free_table(marktable);
1468  st__free_table(markcache);
1469  return(NULL);
1470  }
1471  st__foreach(markcache, MarkCacheCleanUp, NULL);
1472  st__free_table(markcache);
1473  buildcache = st__init_table( st__ptrcmp, st__ptrhash);
1474  if (buildcache == NULL) {
1475  st__free_table(marktable);
1476  return(NULL);
1477  }
1478  res = cuddBddLICBuildResult(dd,f,buildcache,marktable);
1479  st__free_table(buildcache);
1480  st__free_table(marktable);
1481  return(res);
1482 
1483 } /* end of cuddBddLICompaction */
1484 
1485 
1486 /*---------------------------------------------------------------------------*/
1487 /* Definition of static functions */
1488 /*---------------------------------------------------------------------------*/
1489 
1490 
1491 /**Function********************************************************************
1492 
1493  Synopsis [Performs the recursive step of Cudd_bddConstrainDecomp.]
1494 
1495  Description [Performs the recursive step of Cudd_bddConstrainDecomp.
1496  Returns f super (i) if successful; otherwise NULL.]
1497 
1498  SideEffects [None]
1499 
1500  SeeAlso [Cudd_bddConstrainDecomp]
1501 
1502 ******************************************************************************/
1503 static int
1505  DdManager * dd,
1506  DdNode * f,
1507  DdNode ** decomp)
1508 {
1509  DdNode *F, *fv, *fvn;
1510  DdNode *fAbs;
1511  DdNode *result;
1512  int ok;
1513 
1514  if (Cudd_IsConstant(f)) return(1);
1515  /* Compute complements of cofactors. */
1516  F = Cudd_Regular(f);
1517  fv = cuddT(F);
1518  fvn = cuddE(F);
1519  if (F == f) {
1520  fv = Cudd_Not(fv);
1521  fvn = Cudd_Not(fvn);
1522  }
1523  /* Compute abstraction of top variable. */
1524  fAbs = cuddBddAndRecur(dd, fv, fvn);
1525  if (fAbs == NULL) {
1526  return(0);
1527  }
1528  cuddRef(fAbs);
1529  fAbs = Cudd_Not(fAbs);
1530  /* Recursively find the next abstraction and the components of the
1531  ** decomposition. */
1532  ok = cuddBddConstrainDecomp(dd, fAbs, decomp);
1533  if (ok == 0) {
1534  Cudd_IterDerefBdd(dd,fAbs);
1535  return(0);
1536  }
1537  /* Compute the component of the decomposition corresponding to the
1538  ** top variable and store it in the decomposition array. */
1539  result = cuddBddConstrainRecur(dd, f, fAbs);
1540  if (result == NULL) {
1541  Cudd_IterDerefBdd(dd,fAbs);
1542  return(0);
1543  }
1544  cuddRef(result);
1545  decomp[F->index] = result;
1546  Cudd_IterDerefBdd(dd, fAbs);
1547  return(1);
1548 
1549 } /* end of cuddBddConstrainDecomp */
1550 
1551 
1552 /**Function********************************************************************
1553 
1554  Synopsis [Performs the recursive step of Cudd_bddCharToVect.]
1555 
1556  Description [Performs the recursive step of Cudd_bddCharToVect.
1557  This function maintains the invariant that f is non-zero.
1558  Returns the i-th component of the vector if successful; otherwise NULL.]
1559 
1560  SideEffects [None]
1561 
1562  SeeAlso [Cudd_bddCharToVect]
1563 
1564 ******************************************************************************/
1565 static DdNode *
1567  DdManager * dd,
1568  DdNode * f,
1569  DdNode * x)
1570 {
1571  unsigned int topf;
1572  unsigned int level;
1573  int comple;
1574 
1575  DdNode *one, *zero, *res, *F, *fT, *fE, *T, *E;
1576 
1577  statLine(dd);
1578  /* Check the cache. */
1579  res = cuddCacheLookup2(dd, cuddBddCharToVect, f, x);
1580  if (res != NULL) {
1581  return(res);
1582  }
1583 
1584  F = Cudd_Regular(f);
1585 
1586  topf = cuddI(dd,F->index);
1587  level = dd->perm[x->index];
1588 
1589  if (topf > level) return(x);
1590 
1591  one = DD_ONE(dd);
1592  zero = Cudd_Not(one);
1593 
1594  comple = F != f;
1595  fT = Cudd_NotCond(cuddT(F),comple);
1596  fE = Cudd_NotCond(cuddE(F),comple);
1597 
1598  if (topf == level) {
1599  if (fT == zero) return(zero);
1600  if (fE == zero) return(one);
1601  return(x);
1602  }
1603 
1604  /* Here topf < level. */
1605  if (fT == zero) return(cuddBddCharToVect(dd, fE, x));
1606  if (fE == zero) return(cuddBddCharToVect(dd, fT, x));
1607 
1608  T = cuddBddCharToVect(dd, fT, x);
1609  if (T == NULL) {
1610  return(NULL);
1611  }
1612  cuddRef(T);
1613  E = cuddBddCharToVect(dd, fE, x);
1614  if (E == NULL) {
1615  Cudd_IterDerefBdd(dd,T);
1616  return(NULL);
1617  }
1618  cuddRef(E);
1619  res = cuddBddIteRecur(dd, dd->vars[F->index], T, E);
1620  if (res == NULL) {
1621  Cudd_IterDerefBdd(dd,T);
1622  Cudd_IterDerefBdd(dd,E);
1623  return(NULL);
1624  }
1625  cuddDeref(T);
1626  cuddDeref(E);
1627  cuddCacheInsert2(dd, cuddBddCharToVect, f, x, res);
1628  return(res);
1629 
1630 } /* end of cuddBddCharToVect */
1631 
1632 
1633 /**Function********************************************************************
1634 
1635  Synopsis [Performs the edge marking step of Cudd_bddLICompaction.]
1636 
1637  Description [Performs the edge marking step of Cudd_bddLICompaction.
1638  Returns the LUB of the markings of the two outgoing edges of <code>f</code>
1639  if successful; otherwise CUDD_OUT_OF_MEM.]
1640 
1641  SideEffects [None]
1642 
1643  SeeAlso [Cudd_bddLICompaction cuddBddLICBuildResult]
1644 
1645 ******************************************************************************/
1646 static int
1648  DdManager * dd,
1649  DdNode * f,
1650  DdNode * c,
1651  st__table * table,
1652  st__table * cache)
1653 {
1654  DdNode *Fv, *Fnv, *Cv, *Cnv;
1655  DdNode *one, *zero;
1656  unsigned int topf, topc;
1657  int comple;
1658  int resT, resE, res, retval;
1659  char **slot;
1660  MarkCacheKey *key;
1661 
1662  one = DD_ONE(dd);
1663  zero = Cudd_Not(one);
1664 
1665  /* Terminal cases. */
1666  if (c == zero) return(DD_LIC_DC);
1667  if (f == one) return(DD_LIC_1);
1668  if (f == zero) return(DD_LIC_0);
1669 
1670  /* Make canonical to increase the utilization of the cache. */
1671  comple = Cudd_IsComplement(f);
1672  f = Cudd_Regular(f);
1673  /* Now f is a regular pointer to a non-constant node; c may be
1674  ** constant, or it may be complemented.
1675  */
1676 
1677  /* Check the cache. */
1678  key = ABC_ALLOC(MarkCacheKey, 1);
1679  if (key == NULL) {
1680  dd->errorCode = CUDD_MEMORY_OUT;
1681  return(CUDD_OUT_OF_MEM);
1682  }
1683  key->f = f; key->c = c;
1684  if ( st__lookup_int(cache, (char *)key, &res)) {
1685  ABC_FREE(key);
1686  if (comple) {
1687  if (res == DD_LIC_0) res = DD_LIC_1;
1688  else if (res == DD_LIC_1) res = DD_LIC_0;
1689  }
1690  return(res);
1691  }
1692 
1693  /* Recursive step. */
1694  topf = dd->perm[f->index];
1695  topc = cuddI(dd,Cudd_Regular(c)->index);
1696  if (topf <= topc) {
1697  Fv = cuddT(f); Fnv = cuddE(f);
1698  } else {
1699  Fv = Fnv = f;
1700  }
1701  if (topc <= topf) {
1702  /* We know that c is not constant because f is not. */
1703  Cv = cuddT(Cudd_Regular(c)); Cnv = cuddE(Cudd_Regular(c));
1704  if (Cudd_IsComplement(c)) {
1705  Cv = Cudd_Not(Cv);
1706  Cnv = Cudd_Not(Cnv);
1707  }
1708  } else {
1709  Cv = Cnv = c;
1710  }
1711 
1712  resT = cuddBddLICMarkEdges(dd, Fv, Cv, table, cache);
1713  if (resT == CUDD_OUT_OF_MEM) {
1714  ABC_FREE(key);
1715  return(CUDD_OUT_OF_MEM);
1716  }
1717  resE = cuddBddLICMarkEdges(dd, Fnv, Cnv, table, cache);
1718  if (resE == CUDD_OUT_OF_MEM) {
1719  ABC_FREE(key);
1720  return(CUDD_OUT_OF_MEM);
1721  }
1722 
1723  /* Update edge markings. */
1724  if (topf <= topc) {
1725  retval = st__find_or_add(table, (char *)f, (char ***)&slot);
1726  if (retval == 0) {
1727  *slot = (char *) (ptrint)((resT << 2) | resE);
1728  } else if (retval == 1) {
1729  *slot = (char *) (ptrint)((int)((ptrint) *slot) | (resT << 2) | resE);
1730  } else {
1731  ABC_FREE(key);
1732  return(CUDD_OUT_OF_MEM);
1733  }
1734  }
1735 
1736  /* Cache result. */
1737  res = resT | resE;
1738  if ( st__insert(cache, (char *)key, (char *)(ptrint)res) == st__OUT_OF_MEM) {
1739  ABC_FREE(key);
1740  return(CUDD_OUT_OF_MEM);
1741  }
1742 
1743  /* Take into account possible complementation. */
1744  if (comple) {
1745  if (res == DD_LIC_0) res = DD_LIC_1;
1746  else if (res == DD_LIC_1) res = DD_LIC_0;
1747  }
1748  return(res);
1749 
1750 } /* end of cuddBddLICMarkEdges */
1751 
1752 
1753 /**Function********************************************************************
1754 
1755  Synopsis [Builds the result of Cudd_bddLICompaction.]
1756 
1757  Description [Builds the results of Cudd_bddLICompaction.
1758  Returns a pointer to the minimized BDD if successful; otherwise NULL.]
1759 
1760  SideEffects [None]
1761 
1762  SeeAlso [Cudd_bddLICompaction cuddBddLICMarkEdges]
1763 
1764 ******************************************************************************/
1765 static DdNode *
1767  DdManager * dd,
1768  DdNode * f,
1769  st__table * cache,
1770  st__table * table)
1771 {
1772  DdNode *Fv, *Fnv, *r, *t, *e;
1773  DdNode *one, *zero;
1774  int index;
1775  int comple;
1776  int markT, markE, markings;
1777 
1778  one = DD_ONE(dd);
1779  zero = Cudd_Not(one);
1780 
1781  if (Cudd_IsConstant(f)) return(f);
1782  /* Make canonical to increase the utilization of the cache. */
1783  comple = Cudd_IsComplement(f);
1784  f = Cudd_Regular(f);
1785 
1786  /* Check the cache. */
1787  if ( st__lookup(cache, (const char *)f, (char **)&r)) {
1788  return(Cudd_NotCond(r,comple));
1789  }
1790 
1791  /* Retrieve the edge markings. */
1792  if ( st__lookup_int(table, (char *)f, &markings) == 0)
1793  return(NULL);
1794  markT = markings >> 2;
1795  markE = markings & 3;
1796 
1797  index = f->index;
1798  Fv = cuddT(f); Fnv = cuddE(f);
1799 
1800  if (markT == DD_LIC_NL) {
1801  t = cuddBddLICBuildResult(dd,Fv,cache,table);
1802  if (t == NULL) {
1803  return(NULL);
1804  }
1805  } else if (markT == DD_LIC_1) {
1806  t = one;
1807  } else {
1808  t = zero;
1809  }
1810  cuddRef(t);
1811  if (markE == DD_LIC_NL) {
1812  e = cuddBddLICBuildResult(dd,Fnv,cache,table);
1813  if (e == NULL) {
1814  Cudd_IterDerefBdd(dd,t);
1815  return(NULL);
1816  }
1817  } else if (markE == DD_LIC_1) {
1818  e = one;
1819  } else {
1820  e = zero;
1821  }
1822  cuddRef(e);
1823 
1824  if (markT == DD_LIC_DC && markE != DD_LIC_DC) {
1825  r = e;
1826  } else if (markT != DD_LIC_DC && markE == DD_LIC_DC) {
1827  r = t;
1828  } else {
1829  if (Cudd_IsComplement(t)) {
1830  t = Cudd_Not(t);
1831  e = Cudd_Not(e);
1832  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
1833  if (r == NULL) {
1834  Cudd_IterDerefBdd(dd, e);
1835  Cudd_IterDerefBdd(dd, t);
1836  return(NULL);
1837  }
1838  r = Cudd_Not(r);
1839  } else {
1840  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
1841  if (r == NULL) {
1842  Cudd_IterDerefBdd(dd, e);
1843  Cudd_IterDerefBdd(dd, t);
1844  return(NULL);
1845  }
1846  }
1847  }
1848  cuddDeref(t);
1849  cuddDeref(e);
1850 
1851  if ( st__insert(cache, (char *)f, (char *)r) == st__OUT_OF_MEM) {
1852  cuddRef(r);
1853  Cudd_IterDerefBdd(dd,r);
1854  return(NULL);
1855  }
1856 
1857  return(Cudd_NotCond(r,comple));
1858 
1859 } /* end of cuddBddLICBuildResult */
1860 
1861 
1862 /**Function********************************************************************
1863 
1864  Synopsis [Hash function for the computed table of cuddBddLICMarkEdges.]
1865 
1866  Description [Hash function for the computed table of
1867  cuddBddLICMarkEdges. Returns the bucket number.]
1868 
1869  SideEffects [None]
1870 
1871  SeeAlso [Cudd_bddLICompaction]
1872 
1873 ******************************************************************************/
1874 static int
1876  const char * ptr,
1877  int modulus)
1878 {
1879  int val = 0;
1881 
1882  entry = (MarkCacheKey *) ptr;
1883 
1884  val = (int) (ptrint) entry->f;
1885  val = val * 997 + (int) (ptrint) entry->c;
1886 
1887  return ((val < 0) ? -val : val) % modulus;
1888 
1889 } /* end of MarkCacheHash */
1890 
1891 
1892 /**Function********************************************************************
1893 
1894  Synopsis [Comparison function for the computed table of
1895  cuddBddLICMarkEdges.]
1896 
1897  Description [Comparison function for the computed table of
1898  cuddBddLICMarkEdges. Returns 0 if the two nodes of the key are equal; 1
1899  otherwise.]
1900 
1901  SideEffects [None]
1902 
1903  SeeAlso [Cudd_bddLICompaction]
1904 
1905 ******************************************************************************/
1906 static int
1908  const char * ptr1,
1909  const char * ptr2)
1910 {
1911  MarkCacheKey *entry1, *entry2;
1912 
1913  entry1 = (MarkCacheKey *) ptr1;
1914  entry2 = (MarkCacheKey *) ptr2;
1915 
1916  return((entry1->f != entry2->f) || (entry1->c != entry2->c));
1917 
1918 } /* end of MarkCacheCompare */
1919 
1920 
1921 
1922 /**Function********************************************************************
1923 
1924  Synopsis [Frees memory associated with computed table of
1925  cuddBddLICMarkEdges.]
1926 
1927  Description [Frees memory associated with computed table of
1928  cuddBddLICMarkEdges. Returns st__CONTINUE.]
1929 
1930  SideEffects [None]
1931 
1932  SeeAlso [Cudd_bddLICompaction]
1933 
1934 ******************************************************************************/
1935 static enum st__retval
1937  char * key,
1938  char * value,
1939  char * arg)
1940 {
1942 
1943  entry = (MarkCacheKey *) key;
1944  ABC_FREE(entry);
1945  return st__CONTINUE;
1946 
1947 } /* end of MarkCacheCleanUp */
1948 
1949 
1950 /**Function********************************************************************
1951 
1952  Synopsis [Performs the recursive step of Cudd_bddSqueeze.]
1953 
1954  Description [Performs the recursive step of Cudd_bddSqueeze. This
1955  procedure exploits the fact that if we complement and swap the
1956  bounds of the interval we obtain a valid solution by taking the
1957  complement of the solution to the original problem. Therefore, we
1958  can enforce the condition that the upper bound is always regular.
1959  Returns a pointer to the result if successful; NULL otherwise.]
1960 
1961  SideEffects [None]
1962 
1963  SeeAlso [Cudd_bddSqueeze]
1964 
1965 ******************************************************************************/
1966 static DdNode *
1968  DdManager * dd,
1969  DdNode * l,
1970  DdNode * u)
1971 {
1972  DdNode *one, *zero, *r, *lt, *le, *ut, *ue, *t, *e;
1973 #if 0
1974  DdNode *ar;
1975 #endif
1976  int comple = 0;
1977  unsigned int topu, topl;
1978  int index;
1979 
1980  statLine(dd);
1981  if (l == u) {
1982  return(l);
1983  }
1984  one = DD_ONE(dd);
1985  zero = Cudd_Not(one);
1986  /* The only case when l == zero && u == one is at the top level,
1987  ** where returning either one or zero is OK. In all other cases
1988  ** the procedure will detect such a case and will perform
1989  ** remapping. Therefore the order in which we test l and u at this
1990  ** point is immaterial. */
1991  if (l == zero) return(l);
1992  if (u == one) return(u);
1993 
1994  /* Make canonical to increase the utilization of the cache. */
1995  if (Cudd_IsComplement(u)) {
1996  DdNode *temp;
1997  temp = Cudd_Not(l);
1998  l = Cudd_Not(u);
1999  u = temp;
2000  comple = 1;
2001  }
2002  /* At this point u is regular and non-constant; l is non-constant, but
2003  ** may be complemented. */
2004 
2005  /* Here we could check the relative sizes. */
2006 
2007  /* Check the cache. */
2008  r = cuddCacheLookup2(dd, Cudd_bddSqueeze, l, u);
2009  if (r != NULL) {
2010  return(Cudd_NotCond(r,comple));
2011  }
2012 
2013  /* Recursive step. */
2014  topu = dd->perm[u->index];
2015  topl = dd->perm[Cudd_Regular(l)->index];
2016  if (topu <= topl) {
2017  index = u->index;
2018  ut = cuddT(u); ue = cuddE(u);
2019  } else {
2020  index = Cudd_Regular(l)->index;
2021  ut = ue = u;
2022  }
2023  if (topl <= topu) {
2024  lt = cuddT(Cudd_Regular(l)); le = cuddE(Cudd_Regular(l));
2025  if (Cudd_IsComplement(l)) {
2026  lt = Cudd_Not(lt);
2027  le = Cudd_Not(le);
2028  }
2029  } else {
2030  lt = le = l;
2031  }
2032 
2033  /* If one interval is contained in the other, use the smaller
2034  ** interval. This corresponds to one-sided matching. */
2035  if ((lt == zero || Cudd_bddLeq(dd,lt,le)) &&
2036  (ut == one || Cudd_bddLeq(dd,ue,ut))) { /* remap */
2037  r = cuddBddSqueeze(dd, le, ue);
2038  if (r == NULL)
2039  return(NULL);
2040  return(Cudd_NotCond(r,comple));
2041  } else if ((le == zero || Cudd_bddLeq(dd,le,lt)) &&
2042  (ue == one || Cudd_bddLeq(dd,ut,ue))) { /* remap */
2043  r = cuddBddSqueeze(dd, lt, ut);
2044  if (r == NULL)
2045  return(NULL);
2046  return(Cudd_NotCond(r,comple));
2047  } else if ((le == zero || Cudd_bddLeq(dd,le,Cudd_Not(ut))) &&
2048  (ue == one || Cudd_bddLeq(dd,Cudd_Not(lt),ue))) { /* c-remap */
2049  t = cuddBddSqueeze(dd, lt, ut);
2050  cuddRef(t);
2051  if (Cudd_IsComplement(t)) {
2052  r = cuddUniqueInter(dd, index, Cudd_Not(t), t);
2053  if (r == NULL) {
2054  Cudd_IterDerefBdd(dd, t);
2055  return(NULL);
2056  }
2057  r = Cudd_Not(r);
2058  } else {
2059  r = cuddUniqueInter(dd, index, t, Cudd_Not(t));
2060  if (r == NULL) {
2061  Cudd_IterDerefBdd(dd, t);
2062  return(NULL);
2063  }
2064  }
2065  cuddDeref(t);
2066  if (r == NULL)
2067  return(NULL);
2068  cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
2069  return(Cudd_NotCond(r,comple));
2070  } else if ((lt == zero || Cudd_bddLeq(dd,lt,Cudd_Not(ue))) &&
2071  (ut == one || Cudd_bddLeq(dd,Cudd_Not(le),ut))) { /* c-remap */
2072  e = cuddBddSqueeze(dd, le, ue);
2073  cuddRef(e);
2074  if (Cudd_IsComplement(e)) {
2075  r = cuddUniqueInter(dd, index, Cudd_Not(e), e);
2076  if (r == NULL) {
2077  Cudd_IterDerefBdd(dd, e);
2078  return(NULL);
2079  }
2080  } else {
2081  r = cuddUniqueInter(dd, index, e, Cudd_Not(e));
2082  if (r == NULL) {
2083  Cudd_IterDerefBdd(dd, e);
2084  return(NULL);
2085  }
2086  r = Cudd_Not(r);
2087  }
2088  cuddDeref(e);
2089  if (r == NULL)
2090  return(NULL);
2091  cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
2092  return(Cudd_NotCond(r,comple));
2093  }
2094 
2095 #if 0
2096  /* If the two intervals intersect, take a solution from
2097  ** the intersection of the intervals. This guarantees that the
2098  ** splitting variable will not appear in the result.
2099  ** This approach corresponds to two-sided matching, and is very
2100  ** expensive. */
2101  if (Cudd_bddLeq(dd,lt,ue) && Cudd_bddLeq(dd,le,ut)) {
2102  DdNode *au, *al;
2103  au = cuddBddAndRecur(dd,ut,ue);
2104  if (au == NULL)
2105  return(NULL);
2106  cuddRef(au);
2107  al = cuddBddAndRecur(dd,Cudd_Not(lt),Cudd_Not(le));
2108  if (al == NULL) {
2109  Cudd_IterDerefBdd(dd,au);
2110  return(NULL);
2111  }
2112  cuddRef(al);
2113  al = Cudd_Not(al);
2114  ar = cuddBddSqueeze(dd, al, au);
2115  if (ar == NULL) {
2116  Cudd_IterDerefBdd(dd,au);
2117  Cudd_IterDerefBdd(dd,al);
2118  return(NULL);
2119  }
2120  cuddRef(ar);
2121  Cudd_IterDerefBdd(dd,au);
2122  Cudd_IterDerefBdd(dd,al);
2123  } else {
2124  ar = NULL;
2125  }
2126 #endif
2127 
2128  t = cuddBddSqueeze(dd, lt, ut);
2129  if (t == NULL) {
2130  return(NULL);
2131  }
2132  cuddRef(t);
2133  e = cuddBddSqueeze(dd, le, ue);
2134  if (e == NULL) {
2135  Cudd_IterDerefBdd(dd,t);
2136  return(NULL);
2137  }
2138  cuddRef(e);
2139 
2140  if (Cudd_IsComplement(t)) {
2141  t = Cudd_Not(t);
2142  e = Cudd_Not(e);
2143  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
2144  if (r == NULL) {
2145  Cudd_IterDerefBdd(dd, e);
2146  Cudd_IterDerefBdd(dd, t);
2147  return(NULL);
2148  }
2149  r = Cudd_Not(r);
2150  } else {
2151  r = (t == e) ? t : cuddUniqueInter(dd, index, t, e);
2152  if (r == NULL) {
2153  Cudd_IterDerefBdd(dd, e);
2154  Cudd_IterDerefBdd(dd, t);
2155  return(NULL);
2156  }
2157  }
2158  cuddDeref(t);
2159  cuddDeref(e);
2160 
2161 #if 0
2162  /* Check whether there is a result obtained by abstraction and whether
2163  ** it is better than the one obtained by recursion. */
2164  cuddRef(r);
2165  if (ar != NULL) {
2166  if (Cudd_DagSize(ar) <= Cudd_DagSize(r)) {
2167  Cudd_IterDerefBdd(dd, r);
2168  r = ar;
2169  } else {
2170  Cudd_IterDerefBdd(dd, ar);
2171  }
2172  }
2173  cuddDeref(r);
2174 #endif
2175 
2176  cuddCacheInsert2(dd, Cudd_bddSqueeze, l, u, r);
2177  return(Cudd_NotCond(r,comple));
2178 
2179 } /* end of cuddBddSqueeze */
2180 
2181 
2183 
void Cudd_IterDerefBdd(DdManager *table, DdNode *n)
Definition: cuddRef.c:217
DdHalfWord ref
Definition: cudd.h:280
DdNode * Cudd_addConstrain(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:336
void st__free_table(st__table *table)
Definition: st.c:81
#define cuddRef(n)
Definition: cuddInt.h:584
#define CUDD_OUT_OF_MEM
Definition: cudd.h:95
DdNode * cuddBddConstrainRecur(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:783
#define cuddDeref(n)
Definition: cuddInt.h:604
void Cudd_RecursiveDeref(DdManager *table, DdNode *n)
Definition: cuddRef.c:154
Definition: cudd.h:278
DdNode * Cudd_bddLICompaction(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:570
#define Cudd_Not(node)
Definition: cudd.h:367
void cuddCacheInsert2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g, DdNode *data)
Definition: cuddCache.c:277
DdNode * Cudd_addOr(DdManager *dd, DdNode **f, DdNode **g)
Definition: cuddAddApply.c:581
int st__insert(st__table *table, const char *key, char *value)
Definition: st.c:171
DdNode * Cudd_Support(DdManager *dd, DdNode *f)
Definition: cuddUtil.c:740
int size
Definition: cuddInt.h:361
#define Cudd_IsConstant(node)
Definition: cudd.h:352
DdNode * c
Definition: cuddGenCof.c:110
DdNode * Cudd_RemapOverApprox(DdManager *dd, DdNode *f, int numVars, int threshold, double quality)
Definition: cuddApprox.c:366
#define Cudd_Regular(node)
Definition: cudd.h:397
DdNode * cuddAddApplyRecur(DdManager *dd, DD_AOP op, DdNode *f, DdNode *g)
Definition: cuddAddApply.c:809
DdNode * Cudd_bddExistAbstract(DdManager *manager, DdNode *f, DdNode *cube)
Definition: cuddBddAbs.c:130
DdNode * Cudd_SubsetCompress(DdManager *dd, DdNode *f, int nvars, int threshold)
Definition: cuddGenCof.c:700
int st__ptrcmp(const char *, const char *)
Definition: st.c:480
#define ABC_ALLOC(type, num)
Definition: abc_global.h:229
DdNode * Cudd_bddRestrict(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:212
int st__lookup_int(st__table *table, char *key, int *value)
Definition: st.c:134
static DdNode * cuddBddCharToVect(DdManager *dd, DdNode *f, DdNode *x)
Definition: cuddGenCof.c:1566
static enum st__retval MarkCacheCleanUp(char *key, char *value, char *arg)
Definition: cuddGenCof.c:1936
static DdNode * cuddBddSqueeze(DdManager *dd, DdNode *l, DdNode *u)
Definition: cuddGenCof.c:1967
DdNode * Cudd_bddSqueeze(DdManager *dd, DdNode *l, DdNode *u)
Definition: cuddGenCof.c:602
#define statLine(dd)
Definition: cuddInt.h:1037
static int * entry
Definition: cuddGroup.c:122
static int cuddBddConstrainDecomp(DdManager *dd, DdNode *f, DdNode **decomp)
Definition: cuddGenCof.c:1504
DdNode ** Cudd_bddCharToVect(DdManager *dd, DdNode *f)
Definition: cuddGenCof.c:510
DdNode * cuddCacheLookup2(DdManager *table, DD_CTFP op, DdNode *f, DdNode *g)
Definition: cuddCache.c:502
st__retval
Definition: st.h:73
st__table * st__init_table(st__compare_func_type compare, st__hash_func_type hash)
Definition: st.c:72
int reordered
Definition: cuddInt.h:409
DdNode * Cudd_bddLiteralSetIntersection(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddLiteral.c:118
static DdNode * cuddBddLICBuildResult(DdManager *dd, DdNode *f, st__table *cache, st__table *table)
Definition: cuddGenCof.c:1766
#define Cudd_IsComplement(node)
Definition: cudd.h:425
int st__find_or_add(st__table *table, char *key, char ***slot)
Definition: st.c:230
static DdNode * one
Definition: cuddDecomp.c:112
ABC_PTRINT_T ptrint
Definition: cuddInt.h:260
Definition: st.h:52
DdNode * Cudd_SupersetCompress(DdManager *dd, DdNode *f, int nvars, int threshold)
Definition: cuddGenCof.c:750
#define DD_LIC_DC
Definition: cuddGenCof.c:93
DdNode * cuddBddLICompaction(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:1434
#define ABC_NAMESPACE_IMPL_END
Definition: abc_global.h:108
DdNode * Cudd_RemapUnderApprox(DdManager *dd, DdNode *f, int numVars, int threshold, double quality)
Definition: cuddApprox.c:320
static int MarkCacheHash(const char *ptr, int modulus)
Definition: cuddGenCof.c:1875
DdNode * f
Definition: cuddGenCof.c:109
int Cudd_ClassifySupport(DdManager *dd, DdNode *f, DdNode *g, DdNode **common, DdNode **onlyF, DdNode **onlyG)
Definition: cuddUtil.c:1085
DdNode * cuddAddConstrainRecur(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:1203
int st__foreach(st__table *table, enum st__retval(*func)(char *, char *, char *), char *arg)
Definition: st.c:421
static char s1[largest_string]
Definition: set.c:514
#define cuddT(node)
Definition: cuddInt.h:636
DdNode * cuddBddNPAndRecur(DdManager *manager, DdNode *f, DdNode *g)
Definition: cuddGenCof.c:1062
#define st__OUT_OF_MEM
Definition: st.h:113
#define DD_LIC_NL
Definition: cuddGenCof.c:96
#define ABC_NAMESPACE_IMPL_START
Definition: abc_global.h:107
#define cuddI(dd, index)
Definition: cuddInt.h:686
int Cudd_bddLeq(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddBddIte.c:536
int st__lookup(st__table *table, const char *key, char **value)
Definition: st.c:114
DdNode ** Cudd_bddConstrainDecomp(DdManager *dd, DdNode *f)
Definition: cuddGenCof.c:371
DdNode * Cudd_bddConstrain(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:180
DdNode * Cudd_addRestrict(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:431
DdNode * Cudd_bddNPAnd(DdManager *dd, DdNode *f, DdNode *g)
Definition: cuddGenCof.c:299
#define DD_LIC_0
Definition: cuddGenCof.c:95
DdNode * Cudd_SubsetShortPaths(DdManager *dd, DdNode *f, int numVars, int threshold, int hardlimit)
Definition: cuddSubsetSP.c:220
DdHalfWord index
Definition: cudd.h:279
#define ABC_FREE(obj)
Definition: abc_global.h:232
DdNode ** vars
Definition: cuddInt.h:390
enum keys key
#define cuddE(node)
Definition: cuddInt.h:652
#define Cudd_NotCond(node, c)
Definition: cudd.h:383
static int cuddBddLICMarkEdges(DdManager *dd, DdNode *f, DdNode *c, st__table *table, st__table *cache)
Definition: cuddGenCof.c:1647
int value
static char rcsid[] DD_UNUSED
Definition: cuddGenCof.c:118
DdNode * cuddAddRestrictRecur(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:1307
int * invperm
Definition: cuddInt.h:388
static int result
Definition: cuddGenetic.c:125
#define DD_ONE(dd)
Definition: cuddInt.h:911
DdNode * cuddBddAndRecur(DdManager *manager, DdNode *f, DdNode *g)
Definition: cuddBddIte.c:886
#define DD_LIC_1
Definition: cuddGenCof.c:94
int * perm
Definition: cuddInt.h:386
Cudd_ErrorType errorCode
Definition: cuddInt.h:447
int st__ptrhash(const char *, int)
Definition: st.c:468
DdNode * cuddUniqueInter(DdManager *unique, int index, DdNode *T, DdNode *E)
Definition: cuddTable.c:1128
DdNode * cuddBddRestrictRecur(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:912
static DdNode * zero
Definition: cuddApa.c:100
int Cudd_DagSize(DdNode *node)
Definition: cuddUtil.c:442
struct MarkCacheKey MarkCacheKey
static int MarkCacheCompare(const char *ptr1, const char *ptr2)
Definition: cuddGenCof.c:1907
DdNode * Cudd_bddMinimize(DdManager *dd, DdNode *f, DdNode *c)
Definition: cuddGenCof.c:653
#define DD_ZERO(dd)
Definition: cuddInt.h:927
DdNode * cuddBddIteRecur(DdManager *dd, DdNode *f, DdNode *g, DdNode *h)
Definition: cuddBddIte.c:633