source: vis_dev/glu-2.1/src/cuBdd/cuddSat.c @ 13

Last change on this file since 13 was 8, checked in by cecile, 13 years ago

src glu

File size: 35.7 KB
Line 
1/**CFile***********************************************************************
2
3  FileName    [cuddSat.c]
4
5  PackageName [cudd]
6
7  Synopsis    [Functions for the solution of satisfiability related
8  problems.]
9
10  Description [External procedures included in this file:
11                <ul>
12                <li> Cudd_Eval()
13                <li> Cudd_ShortestPath()
14                <li> Cudd_LargestCube()
15                <li> Cudd_ShortestLength()
16                <li> Cudd_Decreasing()
17                <li> Cudd_Increasing()
18                <li> Cudd_EquivDC()
19                <li> Cudd_bddLeqUnless()
20                <li> Cudd_EqualSupNorm()
21                <li> Cudd_bddMakePrime()
22                </ul>
23        Internal procedures included in this module:
24                <ul>
25                <li> cuddBddMakePrime()
26                </ul>
27        Static procedures included in this module:
28                <ul>
29                <li> freePathPair()
30                <li> getShortest()
31                <li> getPath()
32                <li> getLargest()
33                <li> getCube()
34                </ul>]
35
36  Author      [Seh-Woong Jeong, Fabio Somenzi]
37
38  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado
39
40  All rights reserved.
41
42  Redistribution and use in source and binary forms, with or without
43  modification, are permitted provided that the following conditions
44  are met:
45
46  Redistributions of source code must retain the above copyright
47  notice, this list of conditions and the following disclaimer.
48
49  Redistributions in binary form must reproduce the above copyright
50  notice, this list of conditions and the following disclaimer in the
51  documentation and/or other materials provided with the distribution.
52
53  Neither the name of the University of Colorado nor the names of its
54  contributors may be used to endorse or promote products derived from
55  this software without specific prior written permission.
56
57  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
58  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
59  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
60  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
61  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
62  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
63  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
64  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
65  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
67  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68  POSSIBILITY OF SUCH DAMAGE.]
69
70******************************************************************************/
71
72#include "util.h"
73#include "cuddInt.h"
74
75/*---------------------------------------------------------------------------*/
76/* Constant declarations                                                     */
77/*---------------------------------------------------------------------------*/
78
79#define DD_BIGGY        1000000
80
81/*---------------------------------------------------------------------------*/
82/* Stucture declarations                                                     */
83/*---------------------------------------------------------------------------*/
84
85/*---------------------------------------------------------------------------*/
86/* Type declarations                                                         */
87/*---------------------------------------------------------------------------*/
88
89typedef struct cuddPathPair {
90    int pos;
91    int neg;
92} cuddPathPair;
93
94/*---------------------------------------------------------------------------*/
95/* Variable declarations                                                     */
96/*---------------------------------------------------------------------------*/
97
98#ifndef lint
99static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.34 2004/08/13 18:04:50 fabio Exp $";
100#endif
101
102static  DdNode  *one, *zero;
103
104/*---------------------------------------------------------------------------*/
105/* Macro declarations                                                        */
106/*---------------------------------------------------------------------------*/
107
108#define WEIGHT(weight, col)     ((weight) == NULL ? 1 : weight[col])
109
110#ifdef __cplusplus
111extern "C" {
112#endif
113
114/**AutomaticStart*************************************************************/
115
116/*---------------------------------------------------------------------------*/
117/* Static function prototypes                                                */
118/*---------------------------------------------------------------------------*/
119
120static enum st_retval freePathPair (char *key, char *value, char *arg);
121static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st_table *visited);
122static DdNode * getPath (DdManager *manager, st_table *visited, DdNode *f, int *weight, int cost);
123static cuddPathPair getLargest (DdNode *root, st_table *visited);
124static DdNode * getCube (DdManager *manager, st_table *visited, DdNode *f, int cost);
125
126/**AutomaticEnd***************************************************************/
127
128#ifdef __cplusplus
129}
130#endif
131
132/*---------------------------------------------------------------------------*/
133/* Definition of exported functions                                          */
134/*---------------------------------------------------------------------------*/
135
136
137/**Function********************************************************************
138
139  Synopsis    [Returns the value of a DD for a given variable assignment.]
140
141  Description [Finds the value of a DD for a given variable
142  assignment. The variable assignment is passed in an array of int's,
143  that should specify a zero or a one for each variable in the support
144  of the function. Returns a pointer to a constant node. No new nodes
145  are produced.]
146
147  SideEffects [None]
148
149  SeeAlso     [Cudd_bddLeq Cudd_addEvalConst]
150
151******************************************************************************/
152DdNode *
153Cudd_Eval(
154  DdManager * dd,
155  DdNode * f,
156  int * inputs)
157{
158    int comple;
159    DdNode *ptr;
160
161    comple = Cudd_IsComplement(f);
162    ptr = Cudd_Regular(f);
163
164    while (!cuddIsConstant(ptr)) {
165        if (inputs[ptr->index] == 1) {
166            ptr = cuddT(ptr);
167        } else {
168            comple ^= Cudd_IsComplement(cuddE(ptr));
169            ptr = Cudd_Regular(cuddE(ptr));
170        }
171    }
172    return(Cudd_NotCond(ptr,comple));
173
174} /* end of Cudd_Eval */
175
176
177/**Function********************************************************************
178
179  Synopsis    [Finds a shortest path in a DD.]
180
181  Description [Finds a shortest path in a DD. f is the DD we want to
182  get the shortest path for; weight\[i\] is the weight of the THEN arc
183  coming from the node whose index is i. If weight is NULL, then unit
184  weights are assumed for all THEN arcs. All ELSE arcs have 0 weight.
185  If non-NULL, both weight and support should point to arrays with at
186  least as many entries as there are variables in the manager.
187  Returns the shortest path as the BDD of a cube.]
188
189  SideEffects [support contains on return the true support of f.
190  If support is NULL on entry, then Cudd_ShortestPath does not compute
191  the true support info. length contains the length of the path.]
192
193  SeeAlso     [Cudd_ShortestLength Cudd_LargestCube]
194
195******************************************************************************/
196DdNode *
197Cudd_ShortestPath(
198  DdManager * manager,
199  DdNode * f,
200  int * weight,
201  int * support,
202  int * length)
203{
204    DdNode      *F;
205    st_table    *visited;
206    DdNode      *sol;
207    cuddPathPair *rootPair;
208    int         complement, cost;
209    int         i;
210
211    one = DD_ONE(manager);
212    zero = DD_ZERO(manager);
213
214    /* Initialize support. Support does not depend on variable order.
215    ** Hence, it does not need to be reinitialized if reordering occurs.
216    */
217    if (support) {
218      for (i = 0; i < manager->size; i++) {
219        support[i] = 0;
220      }
221    }
222
223    if (f == Cudd_Not(one) || f == zero) {
224      *length = DD_BIGGY;
225      return(Cudd_Not(one));
226    }
227    /* From this point on, a path exists. */
228
229    do {
230        manager->reordered = 0;
231
232        /* Initialize visited table. */
233        visited = st_init_table(st_ptrcmp, st_ptrhash);
234
235        /* Now get the length of the shortest path(s) from f to 1. */
236        (void) getShortest(f, weight, support, visited);
237
238        complement = Cudd_IsComplement(f);
239
240        F = Cudd_Regular(f);
241
242        st_lookup(visited, F, &rootPair);
243
244        if (complement) {
245          cost = rootPair->neg;
246        } else {
247          cost = rootPair->pos;
248        }
249
250        /* Recover an actual shortest path. */
251        sol = getPath(manager,visited,f,weight,cost);
252
253        st_foreach(visited, freePathPair, NULL);
254        st_free_table(visited);
255
256    } while (manager->reordered == 1);
257
258    *length = cost;
259    return(sol);
260
261} /* end of Cudd_ShortestPath */
262
263
264/**Function********************************************************************
265
266  Synopsis    [Finds a largest cube in a DD.]
267
268  Description [Finds a largest cube in a DD. f is the DD we want to
269  get the largest cube for. The problem is translated into the one of
270  finding a shortest path in f, when both THEN and ELSE arcs are assumed to
271  have unit length. This yields a largest cube in the disjoint cover
272  corresponding to the DD. Therefore, it is not necessarily the largest
273  implicant of f.  Returns the largest cube as a BDD.]
274
275  SideEffects [The number of literals of the cube is returned in length.]
276
277  SeeAlso     [Cudd_ShortestPath]
278
279******************************************************************************/
280DdNode *
281Cudd_LargestCube(
282  DdManager * manager,
283  DdNode * f,
284  int * length)
285{
286    register    DdNode  *F;
287    st_table    *visited;
288    DdNode      *sol;
289    cuddPathPair *rootPair;
290    int         complement, cost;
291
292    one = DD_ONE(manager);
293    zero = DD_ZERO(manager);
294
295    if (f == Cudd_Not(one) || f == zero) {
296        *length = DD_BIGGY;
297        return(Cudd_Not(one));
298    }
299    /* From this point on, a path exists. */
300
301    do {
302        manager->reordered = 0;
303
304        /* Initialize visited table. */
305        visited = st_init_table(st_ptrcmp, st_ptrhash);
306
307        /* Now get the length of the shortest path(s) from f to 1. */
308        (void) getLargest(f, visited);
309
310        complement = Cudd_IsComplement(f);
311
312        F = Cudd_Regular(f);
313
314        st_lookup(visited, F, &rootPair);
315
316        if (complement) {
317          cost = rootPair->neg;
318        } else {
319          cost = rootPair->pos;
320        }
321
322        /* Recover an actual shortest path. */
323        sol = getCube(manager,visited,f,cost);
324
325        st_foreach(visited, freePathPair, NULL);
326        st_free_table(visited);
327
328    } while (manager->reordered == 1);
329
330    *length = cost;
331    return(sol);
332
333} /* end of Cudd_LargestCube */
334
335
336/**Function********************************************************************
337
338  Synopsis    [Find the length of the shortest path(s) in a DD.]
339
340  Description [Find the length of the shortest path(s) in a DD. f is
341  the DD we want to get the shortest path for; weight\[i\] is the
342  weight of the THEN edge coming from the node whose index is i. All
343  ELSE edges have 0 weight. Returns the length of the shortest
344  path(s) if successful; CUDD_OUT_OF_MEM otherwise.]
345
346  SideEffects [None]
347
348  SeeAlso     [Cudd_ShortestPath]
349
350******************************************************************************/
351int
352Cudd_ShortestLength(
353  DdManager * manager,
354  DdNode * f,
355  int * weight)
356{
357    register    DdNode  *F;
358    st_table    *visited;
359    cuddPathPair *my_pair;
360    int         complement, cost;
361
362    one = DD_ONE(manager);
363    zero = DD_ZERO(manager);
364
365    if (f == Cudd_Not(one) || f == zero) {
366        return(DD_BIGGY);
367    }
368
369    /* From this point on, a path exists. */
370    /* Initialize visited table and support. */
371    visited = st_init_table(st_ptrcmp, st_ptrhash);
372
373    /* Now get the length of the shortest path(s) from f to 1. */
374    (void) getShortest(f, weight, NULL, visited);
375
376    complement = Cudd_IsComplement(f);
377
378    F = Cudd_Regular(f);
379
380    st_lookup(visited, F, &my_pair);
381   
382    if (complement) {
383        cost = my_pair->neg;
384    } else {
385        cost = my_pair->pos;
386    }
387
388    st_foreach(visited, freePathPair, NULL);
389    st_free_table(visited);
390
391    return(cost);
392
393} /* end of Cudd_ShortestLength */
394
395
396/**Function********************************************************************
397
398  Synopsis    [Determines whether a BDD is negative unate in a
399  variable.]
400
401  Description [Determines whether the function represented by BDD f is
402  negative unate (monotonic decreasing) in variable i. Returns the
403  constant one is f is unate and the (logical) constant zero if it is not.
404  This function does not generate any new nodes.]
405
406  SideEffects [None]
407
408  SeeAlso     [Cudd_Increasing]
409
410******************************************************************************/
411DdNode *
412Cudd_Decreasing(
413  DdManager * dd,
414  DdNode * f,
415  int  i)
416{
417    unsigned int topf, level;
418    DdNode *F, *fv, *fvn, *res;
419    DD_CTFP cacheOp;
420
421    statLine(dd);
422#ifdef DD_DEBUG
423    assert(0 <= i && i < dd->size);
424#endif
425
426    F = Cudd_Regular(f);
427    topf = cuddI(dd,F->index);
428
429    /* Check terminal case. If topf > i, f does not depend on var.
430    ** Therefore, f is unate in i.
431    */
432    level = (unsigned) dd->perm[i];
433    if (topf > level) {
434        return(DD_ONE(dd));
435    }
436
437    /* From now on, f is not constant. */
438
439    /* Check cache. */
440    cacheOp = (DD_CTFP) Cudd_Decreasing;
441    res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
442    if (res != NULL) {
443        return(res);
444    }
445
446    /* Compute cofactors. */
447    fv = cuddT(F); fvn = cuddE(F);
448    if (F != f) {
449        fv = Cudd_Not(fv);
450        fvn = Cudd_Not(fvn);
451    }
452
453    if (topf == (unsigned) level) {
454        /* Special case: if fv is regular, fv(1,...,1) = 1;
455        ** If in addition fvn is complemented, fvn(1,...,1) = 0.
456        ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not
457        ** monotonic decreasing in i.
458        */
459        if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
460            return(Cudd_Not(DD_ONE(dd)));
461        }
462        res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
463    } else {
464        res = Cudd_Decreasing(dd,fv,i);
465        if (res == DD_ONE(dd)) {
466            res = Cudd_Decreasing(dd,fvn,i);
467        }
468    }
469
470    cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
471    return(res);
472
473} /* end of Cudd_Decreasing */
474
475
476/**Function********************************************************************
477
478  Synopsis    [Determines whether a BDD is positive unate in a
479  variable.]
480
481  Description [Determines whether the function represented by BDD f is
482  positive unate (monotonic increasing) in variable i. It is based on
483  Cudd_Decreasing and the fact that f is monotonic increasing in i if
484  and only if its complement is monotonic decreasing in i.]
485
486  SideEffects [None]
487
488  SeeAlso     [Cudd_Decreasing]
489
490******************************************************************************/
491DdNode *
492Cudd_Increasing(
493  DdManager * dd,
494  DdNode * f,
495  int  i)
496{
497    return(Cudd_Decreasing(dd,Cudd_Not(f),i));
498
499} /* end of Cudd_Increasing */
500
501
502/**Function********************************************************************
503
504  Synopsis    [Tells whether F and G are identical wherever D is 0.]
505
506  Description [Tells whether F and G are identical wherever D is 0.  F
507  and G are either two ADDs or two BDDs.  D is either a 0-1 ADD or a
508  BDD.  The function returns 1 if F and G are equivalent, and 0
509  otherwise.  No new nodes are created.]
510
511  SideEffects [None]
512
513  SeeAlso     [Cudd_bddLeqUnless]
514
515******************************************************************************/
516int
517Cudd_EquivDC(
518  DdManager * dd,
519  DdNode * F,
520  DdNode * G,
521  DdNode * D)
522{
523    DdNode *tmp, *One, *Gr, *Dr;
524    DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
525    int res;
526    unsigned int flevel, glevel, dlevel, top;
527
528    One = DD_ONE(dd);
529
530    statLine(dd);
531    /* Check terminal cases. */
532    if (D == One || F == G) return(1);
533    if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);
534
535    /* From now on, D is non-constant. */
536
537    /* Normalize call to increase cache efficiency. */
538    if (F > G) {
539        tmp = F;
540        F = G;
541        G = tmp;
542    }
543    if (Cudd_IsComplement(F)) {
544        F = Cudd_Not(F);
545        G = Cudd_Not(G);
546    }
547
548    /* From now on, F is regular. */
549
550    /* Check cache. */
551    tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
552    if (tmp != NULL) return(tmp == One);
553
554    /* Find splitting variable. */
555    flevel = cuddI(dd,F->index);
556    Gr = Cudd_Regular(G);
557    glevel = cuddI(dd,Gr->index);
558    top = ddMin(flevel,glevel);
559    Dr = Cudd_Regular(D);
560    dlevel = dd->perm[Dr->index];
561    top = ddMin(top,dlevel);
562
563    /* Compute cofactors. */
564    if (top == flevel) {
565        Fv = cuddT(F);
566        Fvn = cuddE(F);
567    } else {
568        Fv = Fvn = F;
569    }
570    if (top == glevel) {
571        Gv = cuddT(Gr);
572        Gvn = cuddE(Gr);
573        if (G != Gr) {
574            Gv = Cudd_Not(Gv);
575            Gvn = Cudd_Not(Gvn);
576        }
577    } else {
578        Gv = Gvn = G;
579    }
580    if (top == dlevel) {
581        Dv = cuddT(Dr);
582        Dvn = cuddE(Dr);
583        if (D != Dr) {
584            Dv = Cudd_Not(Dv);
585            Dvn = Cudd_Not(Dvn);
586        }
587    } else {
588        Dv = Dvn = D;
589    }
590
591    /* Solve recursively. */
592    res = Cudd_EquivDC(dd,Fv,Gv,Dv);
593    if (res != 0) {
594        res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
595    }
596    cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));
597
598    return(res);
599
600} /* end of Cudd_EquivDC */
601
602
603/**Function********************************************************************
604
605  Synopsis    [Tells whether f is less than of equal to G unless D is 1.]
606
607  Description [Tells whether f is less than of equal to G unless D is
608  1.  f, g, and D are BDDs.  The function returns 1 if f is less than
609  of equal to G, and 0 otherwise.  No new nodes are created.]
610
611  SideEffects [None]
612
613  SeeAlso     [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant]
614
615******************************************************************************/
616int
617Cudd_bddLeqUnless(
618  DdManager *dd,
619  DdNode *f,
620  DdNode *g,
621  DdNode *D)
622{
623    DdNode *tmp, *One, *F, *G;
624    DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
625    int res;
626    unsigned int flevel, glevel, dlevel, top;
627
628    statLine(dd);
629
630    One = DD_ONE(dd);
631
632    /* Check terminal cases. */
633    if (f == g || g == One || f == Cudd_Not(One) || D == One ||
634        D == f || D == Cudd_Not(g)) return(1);
635    /* Check for two-operand cases. */
636    if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
637        return(Cudd_bddLeq(dd,f,g));
638    if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
639    if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));
640
641    /* From now on, f, g, and D are non-constant, distinct, and
642    ** non-complementary. */
643
644    /* Normalize call to increase cache efficiency.  We rely on the
645    ** fact that f <= g unless D is equivalent to not(g) <= not(f)
646    ** unless D and to f <= D unless g.  We make sure that D is
647    ** regular, and that at most one of f and g is complemented.  We also
648    ** ensure that when two operands can be swapped, the one with the
649    ** lowest address comes first. */
650
651    if (Cudd_IsComplement(D)) {
652        if (Cudd_IsComplement(g)) {
653            /* Special case: if f is regular and g is complemented,
654            ** f(1,...,1) = 1 > 0 = g(1,...,1).  If D(1,...,1) = 0, return 0.
655            */
656            if (!Cudd_IsComplement(f)) return(0);
657            /* !g <= D unless !f  or  !D <= g unless !f */
658            tmp = D;
659            D = Cudd_Not(f);
660            if (g < tmp) {
661                f = Cudd_Not(g);
662                g = tmp;
663            } else {
664                f = Cudd_Not(tmp);
665            }
666        } else {
667            if (Cudd_IsComplement(f)) {
668                /* !D <= !f unless g  or  !D <= g unless !f */
669                tmp = f;
670                f = Cudd_Not(D);
671                if (tmp < g) {
672                    D = g;
673                    g = Cudd_Not(tmp);
674                } else {
675                    D = Cudd_Not(tmp);
676                }
677            } else {
678                /* f <= D unless g  or  !D <= !f unless g */
679                tmp = D;
680                D = g;
681                if (tmp < f) {
682                    g = Cudd_Not(f);
683                    f = Cudd_Not(tmp);
684                } else {
685                    g = tmp;
686                }
687            }
688        }
689    } else {
690        if (Cudd_IsComplement(g)) {
691            if (Cudd_IsComplement(f)) {
692                /* !g <= !f unless D  or  !g <= D unless !f */
693                tmp = f;
694                f = Cudd_Not(g);
695                if (D < tmp) {
696                    g = D;
697                    D = Cudd_Not(tmp);
698                } else {
699                    g = Cudd_Not(tmp);
700                }
701            } else {
702                /* f <= g unless D  or  !g <= !f unless D */
703                if (g < f) {
704                    tmp = g;
705                    g = Cudd_Not(f);
706                    f = Cudd_Not(tmp);
707                }
708            }
709        } else {
710            /* f <= g unless D  or  f <= D unless g */
711            if (D < g) {
712                tmp = D;
713                D = g;
714                g = tmp;
715            }
716        }
717    }
718
719    /* From now on, D is regular. */
720
721    /* Check cache. */
722    tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
723    if (tmp != NULL) return(tmp == One);
724
725    /* Find splitting variable. */
726    F = Cudd_Regular(f);
727    flevel = dd->perm[F->index];
728    G = Cudd_Regular(g);
729    glevel = dd->perm[G->index];
730    top = ddMin(flevel,glevel);
731    dlevel = dd->perm[D->index];
732    top = ddMin(top,dlevel);
733
734    /* Compute cofactors. */
735    if (top == flevel) {
736        Ft = cuddT(F);
737        Fe = cuddE(F);
738        if (F != f) {
739            Ft = Cudd_Not(Ft);
740            Fe = Cudd_Not(Fe);
741        }
742    } else {
743        Ft = Fe = f;
744    }
745    if (top == glevel) {
746        Gt = cuddT(G);
747        Ge = cuddE(G);
748        if (G != g) {
749            Gt = Cudd_Not(Gt);
750            Ge = Cudd_Not(Ge);
751        }
752    } else {
753        Gt = Ge = g;
754    }
755    if (top == dlevel) {
756        Dt = cuddT(D);
757        De = cuddE(D);
758    } else {
759        Dt = De = D;
760    }
761
762    /* Solve recursively. */
763    res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
764    if (res != 0) {
765        res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
766    }
767    cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));
768
769    return(res);
770
771} /* end of Cudd_bddLeqUnless */
772
773
774/**Function********************************************************************
775
776  Synopsis    [Compares two ADDs for equality within tolerance.]
777
778  Description [Compares two ADDs for equality within tolerance. Two
779  ADDs are reported to be equal if the maximum difference between them
780  (the sup norm of their difference) is less than or equal to the
781  tolerance parameter. Returns 1 if the two ADDs are equal (within
782  tolerance); 0 otherwise. If parameter <code>pr</code> is positive
783  the first failure is reported to the standard output.]
784
785  SideEffects [None]
786
787  SeeAlso     []
788
789******************************************************************************/
790int
791Cudd_EqualSupNorm(
792  DdManager * dd /* manager */,
793  DdNode * f /* first ADD */,
794  DdNode * g /* second ADD */,
795  CUDD_VALUE_TYPE  tolerance /* maximum allowed difference */,
796  int  pr /* verbosity level */)
797{
798    DdNode *fv, *fvn, *gv, *gvn, *r;
799    unsigned int topf, topg;
800
801    statLine(dd);
802    /* Check terminal cases. */
803    if (f == g) return(1);
804    if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
805        if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
806            return(1);
807        } else {
808            if (pr>0) {
809                (void) fprintf(dd->out,"Offending nodes:\n");
810#if SIZEOF_VOID_P == 8
811                (void) fprintf(dd->out,
812                               "f: address = %lx\t value = %40.30f\n",
813                               (unsigned long) f, cuddV(f));
814                (void) fprintf(dd->out,
815                               "g: address = %lx\t value = %40.30f\n",
816                               (unsigned long) g, cuddV(g));
817#else
818                (void) fprintf(dd->out,
819                               "f: address = %x\t value = %40.30f\n",
820                               (unsigned) f, cuddV(f));
821                (void) fprintf(dd->out,
822                               "g: address = %x\t value = %40.30f\n",
823                               (unsigned) g, cuddV(g));
824#endif
825            }
826            return(0);
827        }
828    }
829
830    /* We only insert the result in the cache if the comparison is
831    ** successful. Therefore, if we hit we return 1. */
832    r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g);
833    if (r != NULL) {
834        return(1);
835    }
836
837    /* Compute the cofactors and solve the recursive subproblems. */
838    topf = cuddI(dd,f->index);
839    topg = cuddI(dd,g->index);
840
841    if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
842    if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}
843
844    if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
845    if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);
846
847    cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd));
848
849    return(1);
850
851} /* end of Cudd_EqualSupNorm */
852
853
854/**Function********************************************************************
855
856  Synopsis    [Expands cube to a prime implicant of f.]
857
858  Description [Expands cube to a prime implicant of f. Returns the prime
859  if successful; NULL otherwise.  In particular, NULL is returned if cube
860  is not a real cube or is not an implicant of f.]
861
862  SideEffects [None]
863
864  SeeAlso     []
865
866******************************************************************************/
867DdNode *
868Cudd_bddMakePrime(
869  DdManager *dd /* manager */,
870  DdNode *cube /* cube to be expanded */,
871  DdNode *f /* function of which the cube is to be made a prime */)
872{
873    DdNode *res;
874
875    if (!Cudd_bddLeq(dd,cube,f)) return(NULL);
876
877    do {
878        dd->reordered = 0;
879        res = cuddBddMakePrime(dd,cube,f);
880    } while (dd->reordered == 1);
881    return(res);
882
883} /* end of Cudd_bddMakePrime */
884
885
886/*---------------------------------------------------------------------------*/
887/* Definition of internal functions                                          */
888/*---------------------------------------------------------------------------*/
889
890
891/**Function********************************************************************
892
893  Synopsis    [Performs the recursive step of Cudd_bddMakePrime.]
894
895  Description [Performs the recursive step of Cudd_bddMakePrime.
896  Returns the prime if successful; NULL otherwise.]
897
898  SideEffects [None]
899
900  SeeAlso     []
901
902******************************************************************************/
903DdNode *
904cuddBddMakePrime(
905  DdManager *dd /* manager */,
906  DdNode *cube /* cube to be expanded */,
907  DdNode *f /* function of which the cube is to be made a prime */)
908{
909    DdNode *scan;
910    DdNode *t, *e;
911    DdNode *res = cube;
912    DdNode *zero = Cudd_Not(DD_ONE(dd));
913
914    Cudd_Ref(res);
915    scan = cube;
916    while (!Cudd_IsConstant(scan)) {
917        DdNode *reg = Cudd_Regular(scan);
918        DdNode *var = dd->vars[reg->index];
919        DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
920        if (expanded == NULL) {
921            return(NULL);
922        }
923        Cudd_Ref(expanded);
924        if (Cudd_bddLeq(dd,expanded,f)) {
925            Cudd_RecursiveDeref(dd,res);
926            res = expanded;
927        } else {
928            Cudd_RecursiveDeref(dd,expanded);
929        }
930        cuddGetBranches(scan,&t,&e);
931        if (t == zero) {
932            scan = e;
933        } else if (e == zero) {
934            scan = t;
935        } else {
936            Cudd_RecursiveDeref(dd,res);
937            return(NULL);       /* cube is not a cube */
938        }
939    }
940
941    if (scan == DD_ONE(dd)) {
942        Cudd_Deref(res);
943        return(res);
944    } else {
945        Cudd_RecursiveDeref(dd,res);
946        return(NULL);
947    }
948
949} /* end of cuddBddMakePrime */
950
951
952/*---------------------------------------------------------------------------*/
953/* Definition of static functions                                            */
954/*---------------------------------------------------------------------------*/
955
956
957/**Function********************************************************************
958
959  Synopsis    [Frees the entries of the visited symbol table.]
960
961  Description [Frees the entries of the visited symbol table. Returns
962  ST_CONTINUE.]
963
964  SideEffects [None]
965
966******************************************************************************/
967static enum st_retval
968freePathPair(
969  char * key,
970  char * value,
971  char * arg)
972{
973    cuddPathPair *pair;
974
975    pair = (cuddPathPair *) value;
976        FREE(pair);
977    return(ST_CONTINUE);
978
979} /* end of freePathPair */
980
981
982/**Function********************************************************************
983
984  Synopsis    [Finds the length of the shortest path(s) in a DD.]
985
986  Description [Finds the length of the shortest path(s) in a DD.
987  Uses a local symbol table to store the lengths for each
988  node. Only the lengths for the regular nodes are entered in the table,
989  because those for the complement nodes are simply obtained by swapping
990  the two lenghts.
991  Returns a pair of lengths: the length of the shortest path to 1;
992  and the length of the shortest path to 0. This is done so as to take
993  complement arcs into account.]
994
995  SideEffects [Accumulates the support of the DD in support.]
996
997  SeeAlso     []
998
999******************************************************************************/
1000static cuddPathPair
1001getShortest(
1002  DdNode * root,
1003  int * cost,
1004  int * support,
1005  st_table * visited)
1006{
1007    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
1008    DdNode      *my_root, *T, *E;
1009    int         weight;
1010
1011    my_root = Cudd_Regular(root);
1012
1013    if (st_lookup(visited, my_root, &my_pair)) {
1014        if (Cudd_IsComplement(root)) {
1015            res_pair.pos = my_pair->neg;
1016            res_pair.neg = my_pair->pos;
1017        } else {
1018            res_pair.pos = my_pair->pos;
1019            res_pair.neg = my_pair->neg;
1020        }
1021        return(res_pair);
1022    }
1023
1024    /* In the case of a BDD the following test is equivalent to
1025    ** testing whether the BDD is the constant 1. This formulation,
1026    ** however, works for ADDs as well, by assuming the usual
1027    ** dichotomy of 0 and != 0.
1028    */
1029    if (cuddIsConstant(my_root)) {
1030        if (my_root != zero) {
1031            res_pair.pos = 0;
1032            res_pair.neg = DD_BIGGY;
1033        } else {
1034            res_pair.pos = DD_BIGGY;
1035            res_pair.neg = 0;
1036        }
1037    } else {
1038        T = cuddT(my_root);
1039        E = cuddE(my_root);
1040
1041        pair_T = getShortest(T, cost, support, visited);
1042        pair_E = getShortest(E, cost, support, visited);
1043        weight = WEIGHT(cost, my_root->index);
1044        res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
1045        res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);
1046
1047        /* Update support. */
1048        if (support != NULL) {
1049            support[my_root->index] = 1;
1050        }
1051    }
1052
1053    my_pair = ALLOC(cuddPathPair, 1);
1054    if (my_pair == NULL) {
1055        if (Cudd_IsComplement(root)) {
1056            int tmp = res_pair.pos;
1057            res_pair.pos = res_pair.neg;
1058            res_pair.neg = tmp;
1059        }
1060        return(res_pair);
1061    }
1062    my_pair->pos = res_pair.pos;
1063    my_pair->neg = res_pair.neg;
1064
1065    st_insert(visited, (char *)my_root, (char *)my_pair);
1066    if (Cudd_IsComplement(root)) {
1067        res_pair.pos = my_pair->neg;
1068        res_pair.neg = my_pair->pos;
1069    } else {
1070        res_pair.pos = my_pair->pos;
1071        res_pair.neg = my_pair->neg;
1072    }
1073    return(res_pair);
1074
1075} /* end of getShortest */
1076
1077
1078/**Function********************************************************************
1079
1080  Synopsis    [Build a BDD for a shortest path of f.]
1081
1082  Description [Build a BDD for a shortest path of f.
1083  Given the minimum length from the root, and the minimum
1084  lengths for each node (in visited), apply triangulation at each node.
1085  Of the two children of each node on a shortest path, at least one is
1086  on a shortest path. In case of ties the procedure chooses the THEN
1087  children.
1088  Returns a pointer to the cube BDD representing the path if
1089  successful; NULL otherwise.]
1090
1091  SideEffects [None]
1092
1093  SeeAlso     []
1094
1095******************************************************************************/
1096static DdNode *
1097getPath(
1098  DdManager * manager,
1099  st_table * visited,
1100  DdNode * f,
1101  int * weight,
1102  int  cost)
1103{
1104    DdNode      *sol, *tmp;
1105    DdNode      *my_dd, *T, *E;
1106    cuddPathPair *T_pair, *E_pair;
1107    int         Tcost, Ecost;
1108    int         complement;
1109
1110    my_dd = Cudd_Regular(f);
1111    complement = Cudd_IsComplement(f);
1112
1113    sol = one;
1114    cuddRef(sol);
1115
1116    while (!cuddIsConstant(my_dd)) {
1117        Tcost = cost - WEIGHT(weight, my_dd->index);
1118        Ecost = cost;
1119
1120        T = cuddT(my_dd);
1121        E = cuddE(my_dd);
1122
1123        if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
1124
1125        st_lookup(visited, Cudd_Regular(T), &T_pair);
1126        if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
1127        (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
1128            tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
1129            if (tmp == NULL) {
1130                Cudd_RecursiveDeref(manager,sol);
1131                return(NULL);
1132            }
1133            cuddRef(tmp);
1134            Cudd_RecursiveDeref(manager,sol);
1135            sol = tmp;
1136
1137            complement =  Cudd_IsComplement(T);
1138            my_dd = Cudd_Regular(T);
1139            cost = Tcost;
1140            continue;
1141        }
1142        st_lookup(visited, Cudd_Regular(E), &E_pair);
1143        if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
1144        (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
1145            tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
1146            if (tmp == NULL) {
1147                Cudd_RecursiveDeref(manager,sol);
1148                return(NULL);
1149            }
1150            cuddRef(tmp);
1151            Cudd_RecursiveDeref(manager,sol);
1152            sol = tmp;
1153            complement = Cudd_IsComplement(E);
1154            my_dd = Cudd_Regular(E);
1155            cost = Ecost;
1156            continue;
1157        }
1158        (void) fprintf(manager->err,"We shouldn't be here!!\n");
1159        manager->errorCode = CUDD_INTERNAL_ERROR;
1160        return(NULL);
1161    }
1162
1163    cuddDeref(sol);
1164    return(sol);
1165
1166} /* end of getPath */
1167
1168
1169/**Function********************************************************************
1170
1171  Synopsis    [Finds the size of the largest cube(s) in a DD.]
1172
1173  Description [Finds the size of the largest cube(s) in a DD.
1174  This problem is translated into finding the shortest paths from a node
1175  when both THEN and ELSE arcs have unit lengths.
1176  Uses a local symbol table to store the lengths for each
1177  node. Only the lengths for the regular nodes are entered in the table,
1178  because those for the complement nodes are simply obtained by swapping
1179  the two lenghts.
1180  Returns a pair of lengths: the length of the shortest path to 1;
1181  and the length of the shortest path to 0. This is done so as to take
1182  complement arcs into account.]
1183
1184  SideEffects [none]
1185
1186  SeeAlso     []
1187
1188******************************************************************************/
1189static cuddPathPair
1190getLargest(
1191  DdNode * root,
1192  st_table * visited)
1193{
1194    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
1195    DdNode      *my_root, *T, *E;
1196
1197    my_root = Cudd_Regular(root);
1198
1199    if (st_lookup(visited, my_root, &my_pair)) {
1200        if (Cudd_IsComplement(root)) {
1201            res_pair.pos = my_pair->neg;
1202            res_pair.neg = my_pair->pos;
1203        } else {
1204            res_pair.pos = my_pair->pos;
1205            res_pair.neg = my_pair->neg;
1206        }
1207        return(res_pair);
1208    }
1209
1210    /* In the case of a BDD the following test is equivalent to
1211    ** testing whether the BDD is the constant 1. This formulation,
1212    ** however, works for ADDs as well, by assuming the usual
1213    ** dichotomy of 0 and != 0.
1214    */
1215    if (cuddIsConstant(my_root)) {
1216        if (my_root != zero) {
1217            res_pair.pos = 0;
1218            res_pair.neg = DD_BIGGY;
1219        } else {
1220            res_pair.pos = DD_BIGGY;
1221            res_pair.neg = 0;
1222        }
1223    } else {
1224        T = cuddT(my_root);
1225        E = cuddE(my_root);
1226
1227        pair_T = getLargest(T, visited);
1228        pair_E = getLargest(E, visited);
1229        res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
1230        res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
1231    }
1232
1233    my_pair = ALLOC(cuddPathPair, 1);
1234    if (my_pair == NULL) {      /* simply do not cache this result */
1235        if (Cudd_IsComplement(root)) {
1236            int tmp = res_pair.pos;
1237            res_pair.pos = res_pair.neg;
1238            res_pair.neg = tmp;
1239        }
1240        return(res_pair);
1241    }
1242    my_pair->pos = res_pair.pos;
1243    my_pair->neg = res_pair.neg;
1244
1245    st_insert(visited, (char *)my_root, (char *)my_pair);
1246    if (Cudd_IsComplement(root)) {
1247        res_pair.pos = my_pair->neg;
1248        res_pair.neg = my_pair->pos;
1249    } else {
1250        res_pair.pos = my_pair->pos;
1251        res_pair.neg = my_pair->neg;
1252    }
1253    return(res_pair);
1254
1255} /* end of getLargest */
1256
1257
1258/**Function********************************************************************
1259
1260  Synopsis    [Build a BDD for a largest cube of f.]
1261
1262  Description [Build a BDD for a largest cube of f.
1263  Given the minimum length from the root, and the minimum
1264  lengths for each node (in visited), apply triangulation at each node.
1265  Of the two children of each node on a shortest path, at least one is
1266  on a shortest path. In case of ties the procedure chooses the THEN
1267  children.
1268  Returns a pointer to the cube BDD representing the path if
1269  successful; NULL otherwise.]
1270
1271  SideEffects [None]
1272
1273  SeeAlso     []
1274
1275******************************************************************************/
1276static DdNode *
1277getCube(
1278  DdManager * manager,
1279  st_table * visited,
1280  DdNode * f,
1281  int  cost)
1282{
1283    DdNode      *sol, *tmp;
1284    DdNode      *my_dd, *T, *E;
1285    cuddPathPair *T_pair, *E_pair;
1286    int         Tcost, Ecost;
1287    int         complement;
1288
1289    my_dd = Cudd_Regular(f);
1290    complement = Cudd_IsComplement(f);
1291
1292    sol = one;
1293    cuddRef(sol);
1294
1295    while (!cuddIsConstant(my_dd)) {
1296        Tcost = cost - 1;
1297        Ecost = cost - 1;
1298
1299        T = cuddT(my_dd);
1300        E = cuddE(my_dd);
1301
1302        if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}
1303
1304        st_lookup(visited, Cudd_Regular(T), &T_pair);
1305        if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
1306        (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
1307            tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
1308            if (tmp == NULL) {
1309                Cudd_RecursiveDeref(manager,sol);
1310                return(NULL);
1311            }
1312            cuddRef(tmp);
1313            Cudd_RecursiveDeref(manager,sol);
1314            sol = tmp;
1315
1316            complement =  Cudd_IsComplement(T);
1317            my_dd = Cudd_Regular(T);
1318            cost = Tcost;
1319            continue;
1320        }
1321        st_lookup(visited, Cudd_Regular(E), &E_pair);
1322        if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
1323        (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
1324            tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
1325            if (tmp == NULL) {
1326                Cudd_RecursiveDeref(manager,sol);
1327                return(NULL);
1328            }
1329            cuddRef(tmp);
1330            Cudd_RecursiveDeref(manager,sol);
1331            sol = tmp;
1332            complement = Cudd_IsComplement(E);
1333            my_dd = Cudd_Regular(E);
1334            cost = Ecost;
1335            continue;
1336        }
1337        (void) fprintf(manager->err,"We shouldn't be here!\n");
1338        manager->errorCode = CUDD_INTERNAL_ERROR;
1339        return(NULL);
1340    }
1341
1342    cuddDeref(sol);
1343    return(sol);
1344
1345} /* end of getCube */
Note: See TracBrowser for help on using the repository browser.