cuddSat.c 39.3 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10
/**CFile***********************************************************************

  FileName    [cuddSat.c]

  PackageName [cudd]

  Synopsis    [Functions for the solution of satisfiability related
  problems.]

  Description [External procedures included in this file:
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
                <ul>
                <li> Cudd_Eval()
                <li> Cudd_ShortestPath()
                <li> Cudd_LargestCube()
                <li> Cudd_ShortestLength()
                <li> Cudd_Decreasing()
                <li> Cudd_Increasing()
                <li> Cudd_EquivDC()
                <li> Cudd_bddLeqUnless()
                <li> Cudd_EqualSupNorm()
                <li> Cudd_bddMakePrime()
                </ul>
        Internal procedures included in this module:
                <ul>
                <li> cuddBddMakePrime()
                </ul>
        Static procedures included in this module:
                <ul>
                <li> freePathPair()
                <li> getShortest()
                <li> getPath()
                <li> getLargest()
                <li> getCube()
                </ul>]
Alan Mishchenko committed
35 36 37

  Author      [Seh-Woong Jeong, Fabio Somenzi]

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
  Copyright   [Copyright (c) 1995-2004, Regents of the University of Colorado

  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions
  are met:

  Redistributions of source code must retain the above copyright
  notice, this list of conditions and the following disclaimer.

  Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

  Neither the name of the University of Colorado nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.]
Alan Mishchenko committed
69 70 71

******************************************************************************/

72
#include "misc/util/util_hack.h"
Alan Mishchenko committed
73 74
#include "cuddInt.h"

75 76 77
ABC_NAMESPACE_IMPL_START


78

Alan Mishchenko committed
79 80 81 82
/*---------------------------------------------------------------------------*/
/* Constant declarations                                                     */
/*---------------------------------------------------------------------------*/

83
#define DD_BIGGY        1000000
Alan Mishchenko committed
84 85 86 87 88 89 90 91 92 93

/*---------------------------------------------------------------------------*/
/* Stucture declarations                                                     */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/* Type declarations                                                         */
/*---------------------------------------------------------------------------*/

typedef struct cuddPathPair {
94 95
    int pos;
    int neg;
Alan Mishchenko committed
96 97 98 99 100 101 102
} cuddPathPair;

/*---------------------------------------------------------------------------*/
/* Variable declarations                                                     */
/*---------------------------------------------------------------------------*/

#ifndef lint
103
static char rcsid[] DD_UNUSED = "$Id: cuddSat.c,v 1.36 2009/03/08 02:49:02 fabio Exp $";
Alan Mishchenko committed
104 105
#endif

106
static  DdNode  *one, *zero;
Alan Mishchenko committed
107 108 109 110 111

/*---------------------------------------------------------------------------*/
/* Macro declarations                                                        */
/*---------------------------------------------------------------------------*/

112 113
#define WEIGHT(weight, col)     ((weight) == NULL ? 1 : weight[col])

Alan Mishchenko committed
114 115 116 117 118 119
/**AutomaticStart*************************************************************/

/*---------------------------------------------------------------------------*/
/* Static function prototypes                                                */
/*---------------------------------------------------------------------------*/

120 121 122 123 124
static enum st__retval freePathPair (char *key, char *value, char *arg);
static cuddPathPair getShortest (DdNode *root, int *cost, int *support, st__table *visited);
static DdNode * getPath (DdManager *manager, st__table *visited, DdNode *f, int *weight, int cost);
static cuddPathPair getLargest (DdNode *root, st__table *visited);
static DdNode * getCube (DdManager *manager, st__table *visited, DdNode *f, int cost);
Alan Mishchenko committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160

/**AutomaticEnd***************************************************************/

/*---------------------------------------------------------------------------*/
/* Definition of exported functions                                          */
/*---------------------------------------------------------------------------*/


/**Function********************************************************************

  Synopsis    [Returns the value of a DD for a given variable assignment.]

  Description [Finds the value of a DD for a given variable
  assignment. The variable assignment is passed in an array of int's,
  that should specify a zero or a one for each variable in the support
  of the function. Returns a pointer to a constant node. No new nodes
  are produced.]

  SideEffects [None]

  SeeAlso     [Cudd_bddLeq Cudd_addEvalConst]

******************************************************************************/
DdNode *
Cudd_Eval(
  DdManager * dd,
  DdNode * f,
  int * inputs)
{
    int comple;
    DdNode *ptr;

    comple = Cudd_IsComplement(f);
    ptr = Cudd_Regular(f);

    while (!cuddIsConstant(ptr)) {
161 162 163 164 165 166
        if (inputs[ptr->index] == 1) {
            ptr = cuddT(ptr);
        } else {
            comple ^= Cudd_IsComplement(cuddE(ptr));
            ptr = Cudd_Regular(cuddE(ptr));
        }
Alan Mishchenko committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    }
    return(Cudd_NotCond(ptr,comple));

} /* end of Cudd_Eval */


/**Function********************************************************************

  Synopsis    [Finds a shortest path in a DD.]

  Description [Finds a shortest path in a DD. f is the DD we want to
  get the shortest path for; weight\[i\] is the weight of the THEN arc
  coming from the node whose index is i. If weight is NULL, then unit
  weights are assumed for all THEN arcs. All ELSE arcs have 0 weight.
  If non-NULL, both weight and support should point to arrays with at
  least as many entries as there are variables in the manager.
  Returns the shortest path as the BDD of a cube.]

  SideEffects [support contains on return the true support of f.
  If support is NULL on entry, then Cudd_ShortestPath does not compute
  the true support info. length contains the length of the path.]

  SeeAlso     [Cudd_ShortestLength Cudd_LargestCube]

******************************************************************************/
DdNode *
Cudd_ShortestPath(
  DdManager * manager,
  DdNode * f,
  int * weight,
  int * support,
  int * length)
{
200
    DdNode      *F;
201
    st__table    *visited;
202
    DdNode      *sol;
Alan Mishchenko committed
203
    cuddPathPair *rootPair;
204 205
    int         complement, cost;
    int         i;
Alan Mishchenko committed
206 207 208 209

    one = DD_ONE(manager);
    zero = DD_ZERO(manager);

210 211 212
    /* Initialize support. Support does not depend on variable order.
    ** Hence, it does not need to be reinitialized if reordering occurs.
    */
Alan Mishchenko committed
213
    if (support) {
214
      for (i = 0; i < manager->size; i++) {
Alan Mishchenko committed
215
        support[i] = 0;
216
      }
Alan Mishchenko committed
217 218 219
    }

    if (f == Cudd_Not(one) || f == zero) {
220 221
      *length = DD_BIGGY;
      return(Cudd_Not(one));
Alan Mishchenko committed
222 223 224
    }
    /* From this point on, a path exists. */

225 226
    do {
        manager->reordered = 0;
Alan Mishchenko committed
227

228
        /* Initialize visited table. */
229
        visited = st__init_table( st__ptrcmp, st__ptrhash);
Alan Mishchenko committed
230

231 232
        /* Now get the length of the shortest path(s) from f to 1. */
        (void) getShortest(f, weight, support, visited);
Alan Mishchenko committed
233

234
        complement = Cudd_IsComplement(f);
Alan Mishchenko committed
235

236
        F = Cudd_Regular(f);
Alan Mishchenko committed
237

238
        if (! st__lookup(visited, (const char *)F, (char **)&rootPair)) return(NULL);
Alan Mishchenko committed
239

240 241 242 243 244 245 246 247 248
        if (complement) {
          cost = rootPair->neg;
        } else {
          cost = rootPair->pos;
        }

        /* Recover an actual shortest path. */
        sol = getPath(manager,visited,f,weight,cost);

249 250
        st__foreach(visited, freePathPair, NULL);
        st__free_table(visited);
251 252

    } while (manager->reordered == 1);
Alan Mishchenko committed
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281

    *length = cost;
    return(sol);

} /* end of Cudd_ShortestPath */


/**Function********************************************************************

  Synopsis    [Finds a largest cube in a DD.]

  Description [Finds a largest cube in a DD. f is the DD we want to
  get the largest cube for. The problem is translated into the one of
  finding a shortest path in f, when both THEN and ELSE arcs are assumed to
  have unit length. This yields a largest cube in the disjoint cover
  corresponding to the DD. Therefore, it is not necessarily the largest
  implicant of f.  Returns the largest cube as a BDD.]

  SideEffects [The number of literals of the cube is returned in length.]

  SeeAlso     [Cudd_ShortestPath]

******************************************************************************/
DdNode *
Cudd_LargestCube(
  DdManager * manager,
  DdNode * f,
  int * length)
{
282
    register    DdNode  *F;
283
    st__table    *visited;
284
    DdNode      *sol;
Alan Mishchenko committed
285
    cuddPathPair *rootPair;
286
    int         complement, cost;
Alan Mishchenko committed
287 288 289 290 291

    one = DD_ONE(manager);
    zero = DD_ZERO(manager);

    if (f == Cudd_Not(one) || f == zero) {
292 293
        *length = DD_BIGGY;
        return(Cudd_Not(one));
Alan Mishchenko committed
294 295 296
    }
    /* From this point on, a path exists. */

297 298
    do {
        manager->reordered = 0;
Alan Mishchenko committed
299

300
        /* Initialize visited table. */
301
        visited = st__init_table( st__ptrcmp, st__ptrhash);
Alan Mishchenko committed
302

303 304
        /* Now get the length of the shortest path(s) from f to 1. */
        (void) getLargest(f, visited);
Alan Mishchenko committed
305

306
        complement = Cudd_IsComplement(f);
Alan Mishchenko committed
307

308
        F = Cudd_Regular(f);
Alan Mishchenko committed
309

310
        if (! st__lookup(visited, (const char *)F, (char **)&rootPair)) return(NULL);
Alan Mishchenko committed
311

312 313 314 315 316 317 318 319 320
        if (complement) {
          cost = rootPair->neg;
        } else {
          cost = rootPair->pos;
        }

        /* Recover an actual shortest path. */
        sol = getCube(manager,visited,f,cost);

321 322
        st__foreach(visited, freePathPair, NULL);
        st__free_table(visited);
323 324

    } while (manager->reordered == 1);
Alan Mishchenko committed
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339

    *length = cost;
    return(sol);

} /* end of Cudd_LargestCube */


/**Function********************************************************************

  Synopsis    [Find the length of the shortest path(s) in a DD.]

  Description [Find the length of the shortest path(s) in a DD. f is
  the DD we want to get the shortest path for; weight\[i\] is the
  weight of the THEN edge coming from the node whose index is i. All
  ELSE edges have 0 weight. Returns the length of the shortest
340 341
  path(s) if such a path is found; a large number if the function is
  identically 0, and CUDD_OUT_OF_MEM in case of failure.]
Alan Mishchenko committed
342 343 344 345 346 347 348 349 350 351 352 353

  SideEffects [None]

  SeeAlso     [Cudd_ShortestPath]

******************************************************************************/
int
Cudd_ShortestLength(
  DdManager * manager,
  DdNode * f,
  int * weight)
{
354
    register    DdNode  *F;
355
    st__table    *visited;
Alan Mishchenko committed
356
    cuddPathPair *my_pair;
357
    int         complement, cost;
Alan Mishchenko committed
358 359 360 361 362

    one = DD_ONE(manager);
    zero = DD_ZERO(manager);

    if (f == Cudd_Not(one) || f == zero) {
363
        return(DD_BIGGY);
Alan Mishchenko committed
364 365 366 367
    }

    /* From this point on, a path exists. */
    /* Initialize visited table and support. */
368
    visited = st__init_table( st__ptrcmp, st__ptrhash);
Alan Mishchenko committed
369 370 371 372 373 374 375 376

    /* Now get the length of the shortest path(s) from f to 1. */
    (void) getShortest(f, weight, NULL, visited);

    complement = Cudd_IsComplement(f);

    F = Cudd_Regular(f);

377
    if (! st__lookup(visited, (const char *)F, (char **)&my_pair)) return(CUDD_OUT_OF_MEM);
Alan Mishchenko committed
378 379
    
    if (complement) {
380
        cost = my_pair->neg;
Alan Mishchenko committed
381
    } else {
382
        cost = my_pair->pos;
Alan Mishchenko committed
383 384
    }

385 386
    st__foreach(visited, freePathPair, NULL);
    st__free_table(visited);
Alan Mishchenko committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415

    return(cost);

} /* end of Cudd_ShortestLength */


/**Function********************************************************************

  Synopsis    [Determines whether a BDD is negative unate in a
  variable.]

  Description [Determines whether the function represented by BDD f is
  negative unate (monotonic decreasing) in variable i. Returns the
  constant one is f is unate and the (logical) constant zero if it is not.
  This function does not generate any new nodes.]

  SideEffects [None]

  SeeAlso     [Cudd_Increasing]

******************************************************************************/
DdNode *
Cudd_Decreasing(
  DdManager * dd,
  DdNode * f,
  int  i)
{
    unsigned int topf, level;
    DdNode *F, *fv, *fvn, *res;
416
    DD_CTFP cacheOp;
Alan Mishchenko committed
417 418 419 420 421 422 423 424 425 426 427 428 429 430

    statLine(dd);
#ifdef DD_DEBUG
    assert(0 <= i && i < dd->size);
#endif

    F = Cudd_Regular(f);
    topf = cuddI(dd,F->index);

    /* Check terminal case. If topf > i, f does not depend on var.
    ** Therefore, f is unate in i.
    */
    level = (unsigned) dd->perm[i];
    if (topf > level) {
431
        return(DD_ONE(dd));
Alan Mishchenko committed
432 433 434 435 436
    }

    /* From now on, f is not constant. */

    /* Check cache. */
437
    cacheOp = (DD_CTFP) Cudd_Decreasing;
Alan Mishchenko committed
438 439
    res = cuddCacheLookup2(dd,cacheOp,f,dd->vars[i]);
    if (res != NULL) {
440
        return(res);
Alan Mishchenko committed
441 442 443 444 445
    }

    /* Compute cofactors. */
    fv = cuddT(F); fvn = cuddE(F);
    if (F != f) {
446 447
        fv = Cudd_Not(fv);
        fvn = Cudd_Not(fvn);
Alan Mishchenko committed
448 449 450
    }

    if (topf == (unsigned) level) {
451 452 453 454 455 456 457 458 459
        /* Special case: if fv is regular, fv(1,...,1) = 1;
        ** If in addition fvn is complemented, fvn(1,...,1) = 0.
        ** But then f(1,1,...,1) > f(0,1,...,1). Hence f is not
        ** monotonic decreasing in i.
        */
        if (!Cudd_IsComplement(fv) && Cudd_IsComplement(fvn)) {
            return(Cudd_Not(DD_ONE(dd)));
        }
        res = Cudd_bddLeq(dd,fv,fvn) ? DD_ONE(dd) : Cudd_Not(DD_ONE(dd));
Alan Mishchenko committed
460
    } else {
461 462 463 464
        res = Cudd_Decreasing(dd,fv,i);
        if (res == DD_ONE(dd)) {
            res = Cudd_Decreasing(dd,fvn,i);
        }
Alan Mishchenko committed
465 466 467 468 469 470 471 472 473 474 475 476 477 478
    }

    cuddCacheInsert2(dd,cacheOp,f,dd->vars[i],res);
    return(res);

} /* end of Cudd_Decreasing */


/**Function********************************************************************

  Synopsis    [Determines whether a BDD is positive unate in a
  variable.]

  Description [Determines whether the function represented by BDD f is
479
  positive unate (monotonic increasing) in variable i. It is based on
Alan Mishchenko committed
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
  Cudd_Decreasing and the fact that f is monotonic increasing in i if
  and only if its complement is monotonic decreasing in i.]

  SideEffects [None]

  SeeAlso     [Cudd_Decreasing]

******************************************************************************/
DdNode *
Cudd_Increasing(
  DdManager * dd,
  DdNode * f,
  int  i)
{
    return(Cudd_Decreasing(dd,Cudd_Not(f),i));

} /* end of Cudd_Increasing */


/**Function********************************************************************

  Synopsis    [Tells whether F and G are identical wherever D is 0.]

  Description [Tells whether F and G are identical wherever D is 0.  F
  and G are either two ADDs or two BDDs.  D is either a 0-1 ADD or a
  BDD.  The function returns 1 if F and G are equivalent, and 0
  otherwise.  No new nodes are created.]

  SideEffects [None]

  SeeAlso     [Cudd_bddLeqUnless]

******************************************************************************/
int
Cudd_EquivDC(
  DdManager * dd,
  DdNode * F,
  DdNode * G,
  DdNode * D)
{
    DdNode *tmp, *One, *Gr, *Dr;
    DdNode *Fv, *Fvn, *Gv, *Gvn, *Dv, *Dvn;
    int res;
    unsigned int flevel, glevel, dlevel, top;

    One = DD_ONE(dd);

    statLine(dd);
    /* Check terminal cases. */
    if (D == One || F == G) return(1);
    if (D == Cudd_Not(One) || D == DD_ZERO(dd) || F == Cudd_Not(G)) return(0);

    /* From now on, D is non-constant. */

    /* Normalize call to increase cache efficiency. */
    if (F > G) {
536 537 538
        tmp = F;
        F = G;
        G = tmp;
Alan Mishchenko committed
539 540
    }
    if (Cudd_IsComplement(F)) {
541 542
        F = Cudd_Not(F);
        G = Cudd_Not(G);
Alan Mishchenko committed
543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561
    }

    /* From now on, F is regular. */

    /* Check cache. */
    tmp = cuddCacheLookup(dd,DD_EQUIV_DC_TAG,F,G,D);
    if (tmp != NULL) return(tmp == One);

    /* Find splitting variable. */
    flevel = cuddI(dd,F->index);
    Gr = Cudd_Regular(G);
    glevel = cuddI(dd,Gr->index);
    top = ddMin(flevel,glevel);
    Dr = Cudd_Regular(D);
    dlevel = dd->perm[Dr->index];
    top = ddMin(top,dlevel);

    /* Compute cofactors. */
    if (top == flevel) {
562 563
        Fv = cuddT(F);
        Fvn = cuddE(F);
Alan Mishchenko committed
564
    } else {
565
        Fv = Fvn = F;
Alan Mishchenko committed
566 567
    }
    if (top == glevel) {
568 569 570 571 572 573
        Gv = cuddT(Gr);
        Gvn = cuddE(Gr);
        if (G != Gr) {
            Gv = Cudd_Not(Gv);
            Gvn = Cudd_Not(Gvn);
        }
Alan Mishchenko committed
574
    } else {
575
        Gv = Gvn = G;
Alan Mishchenko committed
576 577
    }
    if (top == dlevel) {
578 579 580 581 582 583
        Dv = cuddT(Dr);
        Dvn = cuddE(Dr);
        if (D != Dr) {
            Dv = Cudd_Not(Dv);
            Dvn = Cudd_Not(Dvn);
        }
Alan Mishchenko committed
584
    } else {
585
        Dv = Dvn = D;
Alan Mishchenko committed
586 587 588 589 590
    }

    /* Solve recursively. */
    res = Cudd_EquivDC(dd,Fv,Gv,Dv);
    if (res != 0) {
591
        res = Cudd_EquivDC(dd,Fvn,Gvn,Dvn);
Alan Mishchenko committed
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630
    }
    cuddCacheInsert(dd,DD_EQUIV_DC_TAG,F,G,D,(res) ? One : Cudd_Not(One));

    return(res);

} /* end of Cudd_EquivDC */


/**Function********************************************************************

  Synopsis    [Tells whether f is less than of equal to G unless D is 1.]

  Description [Tells whether f is less than of equal to G unless D is
  1.  f, g, and D are BDDs.  The function returns 1 if f is less than
  of equal to G, and 0 otherwise.  No new nodes are created.]

  SideEffects [None]

  SeeAlso     [Cudd_EquivDC Cudd_bddLeq Cudd_bddIteConstant]

******************************************************************************/
int
Cudd_bddLeqUnless(
  DdManager *dd,
  DdNode *f,
  DdNode *g,
  DdNode *D)
{
    DdNode *tmp, *One, *F, *G;
    DdNode *Ft, *Fe, *Gt, *Ge, *Dt, *De;
    int res;
    unsigned int flevel, glevel, dlevel, top;

    statLine(dd);

    One = DD_ONE(dd);

    /* Check terminal cases. */
    if (f == g || g == One || f == Cudd_Not(One) || D == One ||
631
        D == f || D == Cudd_Not(g)) return(1);
Alan Mishchenko committed
632 633
    /* Check for two-operand cases. */
    if (D == Cudd_Not(One) || D == g || D == Cudd_Not(f))
634
        return(Cudd_bddLeq(dd,f,g));
Alan Mishchenko committed
635 636 637 638 639 640 641 642 643 644 645 646 647 648
    if (g == Cudd_Not(One) || g == Cudd_Not(f)) return(Cudd_bddLeq(dd,f,D));
    if (f == One) return(Cudd_bddLeq(dd,Cudd_Not(g),D));

    /* From now on, f, g, and D are non-constant, distinct, and
    ** non-complementary. */

    /* Normalize call to increase cache efficiency.  We rely on the
    ** fact that f <= g unless D is equivalent to not(g) <= not(f)
    ** unless D and to f <= D unless g.  We make sure that D is
    ** regular, and that at most one of f and g is complemented.  We also
    ** ensure that when two operands can be swapped, the one with the
    ** lowest address comes first. */

    if (Cudd_IsComplement(D)) {
649 650 651 652 653 654 655 656 657 658 659 660 661 662
        if (Cudd_IsComplement(g)) {
            /* Special case: if f is regular and g is complemented,
            ** f(1,...,1) = 1 > 0 = g(1,...,1).  If D(1,...,1) = 0, return 0.
            */
            if (!Cudd_IsComplement(f)) return(0);
            /* !g <= D unless !f  or  !D <= g unless !f */
            tmp = D;
            D = Cudd_Not(f);
            if (g < tmp) {
                f = Cudd_Not(g);
                g = tmp;
            } else {
                f = Cudd_Not(tmp);
            }
Alan Mishchenko committed
663
        } else {
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
            if (Cudd_IsComplement(f)) {
                /* !D <= !f unless g  or  !D <= g unless !f */
                tmp = f;
                f = Cudd_Not(D);
                if (tmp < g) {
                    D = g;
                    g = Cudd_Not(tmp);
                } else {
                    D = Cudd_Not(tmp);
                }
            } else {
                /* f <= D unless g  or  !D <= !f unless g */
                tmp = D;
                D = g;
                if (tmp < f) {
                    g = Cudd_Not(f);
                    f = Cudd_Not(tmp);
                } else {
                    g = tmp;
                }
            }
Alan Mishchenko committed
685 686
        }
    } else {
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
        if (Cudd_IsComplement(g)) {
            if (Cudd_IsComplement(f)) {
                /* !g <= !f unless D  or  !g <= D unless !f */
                tmp = f;
                f = Cudd_Not(g);
                if (D < tmp) {
                    g = D;
                    D = Cudd_Not(tmp);
                } else {
                    g = Cudd_Not(tmp);
                }
            } else {
                /* f <= g unless D  or  !g <= !f unless D */
                if (g < f) {
                    tmp = g;
                    g = Cudd_Not(f);
                    f = Cudd_Not(tmp);
                }
            }
Alan Mishchenko committed
706
        } else {
707 708 709 710 711 712
            /* f <= g unless D  or  f <= D unless g */
            if (D < g) {
                tmp = D;
                D = g;
                g = tmp;
            }
Alan Mishchenko committed
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732
        }
    }

    /* From now on, D is regular. */

    /* Check cache. */
    tmp = cuddCacheLookup(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D);
    if (tmp != NULL) return(tmp == One);

    /* Find splitting variable. */
    F = Cudd_Regular(f);
    flevel = dd->perm[F->index];
    G = Cudd_Regular(g);
    glevel = dd->perm[G->index];
    top = ddMin(flevel,glevel);
    dlevel = dd->perm[D->index];
    top = ddMin(top,dlevel);

    /* Compute cofactors. */
    if (top == flevel) {
733 734 735 736 737 738
        Ft = cuddT(F);
        Fe = cuddE(F);
        if (F != f) {
            Ft = Cudd_Not(Ft);
            Fe = Cudd_Not(Fe);
        }
Alan Mishchenko committed
739
    } else {
740
        Ft = Fe = f;
Alan Mishchenko committed
741 742
    }
    if (top == glevel) {
743 744 745 746 747 748
        Gt = cuddT(G);
        Ge = cuddE(G);
        if (G != g) {
            Gt = Cudd_Not(Gt);
            Ge = Cudd_Not(Ge);
        }
Alan Mishchenko committed
749
    } else {
750
        Gt = Ge = g;
Alan Mishchenko committed
751 752
    }
    if (top == dlevel) {
753 754
        Dt = cuddT(D);
        De = cuddE(D);
Alan Mishchenko committed
755
    } else {
756
        Dt = De = D;
Alan Mishchenko committed
757 758 759 760 761
    }

    /* Solve recursively. */
    res = Cudd_bddLeqUnless(dd,Ft,Gt,Dt);
    if (res != 0) {
762
        res = Cudd_bddLeqUnless(dd,Fe,Ge,De);
Alan Mishchenko committed
763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801
    }
    cuddCacheInsert(dd,DD_BDD_LEQ_UNLESS_TAG,f,g,D,Cudd_NotCond(One,!res));

    return(res);

} /* end of Cudd_bddLeqUnless */


/**Function********************************************************************

  Synopsis    [Compares two ADDs for equality within tolerance.]

  Description [Compares two ADDs for equality within tolerance. Two
  ADDs are reported to be equal if the maximum difference between them
  (the sup norm of their difference) is less than or equal to the
  tolerance parameter. Returns 1 if the two ADDs are equal (within
  tolerance); 0 otherwise. If parameter <code>pr</code> is positive
  the first failure is reported to the standard output.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
Cudd_EqualSupNorm(
  DdManager * dd /* manager */,
  DdNode * f /* first ADD */,
  DdNode * g /* second ADD */,
  CUDD_VALUE_TYPE  tolerance /* maximum allowed difference */,
  int  pr /* verbosity level */)
{
    DdNode *fv, *fvn, *gv, *gvn, *r;
    unsigned int topf, topg;

    statLine(dd);
    /* Check terminal cases. */
    if (f == g) return(1);
    if (Cudd_IsConstant(f) && Cudd_IsConstant(g)) {
802 803 804 805 806 807 808 809 810 811 812 813 814
        if (ddEqualVal(cuddV(f),cuddV(g),tolerance)) {
            return(1);
        } else {
            if (pr>0) {
                (void) fprintf(dd->out,"Offending nodes:\n");
                (void) fprintf(dd->out,
                               "f: address = %p\t value = %40.30f\n",
                               (void *) f, cuddV(f));
                (void) fprintf(dd->out,
                               "g: address = %p\t value = %40.30f\n",
                               (void *) g, cuddV(g));
            }
            return(0);
Alan Mishchenko committed
815 816 817 818 819
        }
    }

    /* We only insert the result in the cache if the comparison is
    ** successful. Therefore, if we hit we return 1. */
820
    r = cuddCacheLookup2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g);
Alan Mishchenko committed
821
    if (r != NULL) {
822
        return(1);
Alan Mishchenko committed
823 824 825 826 827 828 829 830 831 832 833 834
    }

    /* Compute the cofactors and solve the recursive subproblems. */
    topf = cuddI(dd,f->index);
    topg = cuddI(dd,g->index);

    if (topf <= topg) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
    if (topg <= topf) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}

    if (!Cudd_EqualSupNorm(dd,fv,gv,tolerance,pr)) return(0);
    if (!Cudd_EqualSupNorm(dd,fvn,gvn,tolerance,pr)) return(0);

835
    cuddCacheInsert2(dd,(DD_CTFP)Cudd_EqualSupNorm,f,g,DD_ONE(dd));
Alan Mishchenko committed
836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865

    return(1);

} /* end of Cudd_EqualSupNorm */


/**Function********************************************************************

  Synopsis    [Expands cube to a prime implicant of f.]

  Description [Expands cube to a prime implicant of f. Returns the prime
  if successful; NULL otherwise.  In particular, NULL is returned if cube
  is not a real cube or is not an implicant of f.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
Cudd_bddMakePrime(
  DdManager *dd /* manager */,
  DdNode *cube /* cube to be expanded */,
  DdNode *f /* function of which the cube is to be made a prime */)
{
    DdNode *res;

    if (!Cudd_bddLeq(dd,cube,f)) return(NULL);

    do {
866 867
        dd->reordered = 0;
        res = cuddBddMakePrime(dd,cube,f);
Alan Mishchenko committed
868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
    } while (dd->reordered == 1);
    return(res);

} /* end of Cudd_bddMakePrime */


/*---------------------------------------------------------------------------*/
/* Definition of internal functions                                          */
/*---------------------------------------------------------------------------*/


/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddMakePrime.]

  Description [Performs the recursive step of Cudd_bddMakePrime.
  Returns the prime if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddBddMakePrime(
  DdManager *dd /* manager */,
  DdNode *cube /* cube to be expanded */,
  DdNode *f /* function of which the cube is to be made a prime */)
{
    DdNode *scan;
    DdNode *t, *e;
    DdNode *res = cube;
    DdNode *zero = Cudd_Not(DD_ONE(dd));

    Cudd_Ref(res);
    scan = cube;
    while (!Cudd_IsConstant(scan)) {
905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926
        DdNode *reg = Cudd_Regular(scan);
        DdNode *var = dd->vars[reg->index];
        DdNode *expanded = Cudd_bddExistAbstract(dd,res,var);
        if (expanded == NULL) {
            return(NULL);
        }
        Cudd_Ref(expanded);
        if (Cudd_bddLeq(dd,expanded,f)) {
            Cudd_RecursiveDeref(dd,res);
            res = expanded;
        } else {
            Cudd_RecursiveDeref(dd,expanded);
        }
        cuddGetBranches(scan,&t,&e);
        if (t == zero) {
            scan = e;
        } else if (e == zero) {
            scan = t;
        } else {
            Cudd_RecursiveDeref(dd,res);
            return(NULL);       /* cube is not a cube */
        }
Alan Mishchenko committed
927 928 929
    }

    if (scan == DD_ONE(dd)) {
930 931
        Cudd_Deref(res);
        return(res);
Alan Mishchenko committed
932
    } else {
933 934
        Cudd_RecursiveDeref(dd,res);
        return(NULL);
Alan Mishchenko committed
935 936 937 938 939 940 941 942 943 944 945 946 947 948 949
    }

} /* end of cuddBddMakePrime */


/*---------------------------------------------------------------------------*/
/* Definition of static functions                                            */
/*---------------------------------------------------------------------------*/


/**Function********************************************************************

  Synopsis    [Frees the entries of the visited symbol table.]

  Description [Frees the entries of the visited symbol table. Returns
950
  st__CONTINUE.]
Alan Mishchenko committed
951 952 953 954

  SideEffects [None]

******************************************************************************/
955
static enum st__retval
Alan Mishchenko committed
956 957 958 959 960 961 962 963
freePathPair(
  char * key,
  char * value,
  char * arg)
{
    cuddPathPair *pair;

    pair = (cuddPathPair *) value;
964
        ABC_FREE(pair);
965
    return( st__CONTINUE);
Alan Mishchenko committed
966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992

} /* end of freePathPair */


/**Function********************************************************************

  Synopsis    [Finds the length of the shortest path(s) in a DD.]

  Description [Finds the length of the shortest path(s) in a DD.
  Uses a local symbol table to store the lengths for each
  node. Only the lengths for the regular nodes are entered in the table,
  because those for the complement nodes are simply obtained by swapping
  the two lenghts.
  Returns a pair of lengths: the length of the shortest path to 1;
  and the length of the shortest path to 0. This is done so as to take
  complement arcs into account.]

  SideEffects [Accumulates the support of the DD in support.]

  SeeAlso     []

******************************************************************************/
static cuddPathPair
getShortest(
  DdNode * root,
  int * cost,
  int * support,
993
  st__table * visited)
Alan Mishchenko committed
994 995
{
    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
996 997
    DdNode      *my_root, *T, *E;
    int         weight;
Alan Mishchenko committed
998 999 1000

    my_root = Cudd_Regular(root);

1001
    if ( st__lookup(visited, (const char *)my_root, (char **)&my_pair)) {
1002 1003 1004 1005 1006 1007 1008 1009
        if (Cudd_IsComplement(root)) {
            res_pair.pos = my_pair->neg;
            res_pair.neg = my_pair->pos;
        } else {
            res_pair.pos = my_pair->pos;
            res_pair.neg = my_pair->neg;
        }
        return(res_pair);
Alan Mishchenko committed
1010 1011 1012 1013 1014 1015 1016 1017
    }

    /* In the case of a BDD the following test is equivalent to
    ** testing whether the BDD is the constant 1. This formulation,
    ** however, works for ADDs as well, by assuming the usual
    ** dichotomy of 0 and != 0.
    */
    if (cuddIsConstant(my_root)) {
1018 1019 1020 1021 1022 1023 1024
        if (my_root != zero) {
            res_pair.pos = 0;
            res_pair.neg = DD_BIGGY;
        } else {
            res_pair.pos = DD_BIGGY;
            res_pair.neg = 0;
        }
Alan Mishchenko committed
1025
    } else {
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
        T = cuddT(my_root);
        E = cuddE(my_root);

        pair_T = getShortest(T, cost, support, visited);
        pair_E = getShortest(E, cost, support, visited);
        weight = WEIGHT(cost, my_root->index);
        res_pair.pos = ddMin(pair_T.pos+weight, pair_E.pos);
        res_pair.neg = ddMin(pair_T.neg+weight, pair_E.neg);

        /* Update support. */
        if (support != NULL) {
            support[my_root->index] = 1;
        }
Alan Mishchenko committed
1039 1040
    }

Alan Mishchenko committed
1041
    my_pair = ABC_ALLOC(cuddPathPair, 1);
Alan Mishchenko committed
1042
    if (my_pair == NULL) {
1043 1044 1045 1046 1047 1048
        if (Cudd_IsComplement(root)) {
            int tmp = res_pair.pos;
            res_pair.pos = res_pair.neg;
            res_pair.neg = tmp;
        }
        return(res_pair);
Alan Mishchenko committed
1049 1050 1051 1052
    }
    my_pair->pos = res_pair.pos;
    my_pair->neg = res_pair.neg;

1053
    st__insert(visited, (char *)my_root, (char *)my_pair);
Alan Mishchenko committed
1054
    if (Cudd_IsComplement(root)) {
1055 1056
        res_pair.pos = my_pair->neg;
        res_pair.neg = my_pair->pos;
Alan Mishchenko committed
1057
    } else {
1058 1059
        res_pair.pos = my_pair->pos;
        res_pair.neg = my_pair->neg;
Alan Mishchenko committed
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086
    }
    return(res_pair);

} /* end of getShortest */


/**Function********************************************************************

  Synopsis    [Build a BDD for a shortest path of f.]

  Description [Build a BDD for a shortest path of f.
  Given the minimum length from the root, and the minimum
  lengths for each node (in visited), apply triangulation at each node.
  Of the two children of each node on a shortest path, at least one is
  on a shortest path. In case of ties the procedure chooses the THEN
  children.
  Returns a pointer to the cube BDD representing the path if
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
getPath(
  DdManager * manager,
1087
  st__table * visited,
Alan Mishchenko committed
1088 1089 1090 1091
  DdNode * f,
  int * weight,
  int  cost)
{
1092 1093
    DdNode      *sol, *tmp;
    DdNode      *my_dd, *T, *E;
Alan Mishchenko committed
1094
    cuddPathPair *T_pair, *E_pair;
1095 1096
    int         Tcost, Ecost;
    int         complement;
Alan Mishchenko committed
1097 1098 1099 1100 1101 1102 1103 1104

    my_dd = Cudd_Regular(f);
    complement = Cudd_IsComplement(f);

    sol = one;
    cuddRef(sol);

    while (!cuddIsConstant(my_dd)) {
1105 1106 1107 1108 1109 1110 1111 1112
        Tcost = cost - WEIGHT(weight, my_dd->index);
        Ecost = cost;

        T = cuddT(my_dd);
        E = cuddE(my_dd);

        if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}

1113
        st__lookup(visited, (const char *)Cudd_Regular(T), (char **)&T_pair);
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
        if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
        (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
            tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
            if (tmp == NULL) {
                Cudd_RecursiveDeref(manager,sol);
                return(NULL);
            }
            cuddRef(tmp);
            Cudd_RecursiveDeref(manager,sol);
            sol = tmp;

            complement =  Cudd_IsComplement(T);
            my_dd = Cudd_Regular(T);
            cost = Tcost;
            continue;
Alan Mishchenko committed
1129
        }
1130
        st__lookup(visited, (const char *)Cudd_Regular(E), (char **)&E_pair);
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
        if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
        (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
            tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
            if (tmp == NULL) {
                Cudd_RecursiveDeref(manager,sol);
                return(NULL);
            }
            cuddRef(tmp);
            Cudd_RecursiveDeref(manager,sol);
            sol = tmp;
            complement = Cudd_IsComplement(E);
            my_dd = Cudd_Regular(E);
            cost = Ecost;
            continue;
Alan Mishchenko committed
1145
        }
1146 1147 1148
        (void) fprintf(manager->err,"We shouldn't be here!!\n");
        manager->errorCode = CUDD_INTERNAL_ERROR;
        return(NULL);
Alan Mishchenko committed
1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
    }

    cuddDeref(sol);
    return(sol);

} /* end of getPath */


/**Function********************************************************************

  Synopsis    [Finds the size of the largest cube(s) in a DD.]

  Description [Finds the size of the largest cube(s) in a DD.
  This problem is translated into finding the shortest paths from a node
  when both THEN and ELSE arcs have unit lengths.
  Uses a local symbol table to store the lengths for each
  node. Only the lengths for the regular nodes are entered in the table,
  because those for the complement nodes are simply obtained by swapping
  the two lenghts.
  Returns a pair of lengths: the length of the shortest path to 1;
  and the length of the shortest path to 0. This is done so as to take
  complement arcs into account.]

  SideEffects [none]

  SeeAlso     []

******************************************************************************/
static cuddPathPair
getLargest(
  DdNode * root,
1180
  st__table * visited)
Alan Mishchenko committed
1181 1182
{
    cuddPathPair *my_pair, res_pair, pair_T, pair_E;
1183
    DdNode      *my_root, *T, *E;
Alan Mishchenko committed
1184 1185 1186

    my_root = Cudd_Regular(root);

1187
    if ( st__lookup(visited, (const char *)my_root, (char **)&my_pair)) {
1188 1189 1190 1191 1192 1193 1194 1195
        if (Cudd_IsComplement(root)) {
            res_pair.pos = my_pair->neg;
            res_pair.neg = my_pair->pos;
        } else {
            res_pair.pos = my_pair->pos;
            res_pair.neg = my_pair->neg;
        }
        return(res_pair);
Alan Mishchenko committed
1196 1197 1198 1199 1200 1201 1202 1203
    }

    /* In the case of a BDD the following test is equivalent to
    ** testing whether the BDD is the constant 1. This formulation,
    ** however, works for ADDs as well, by assuming the usual
    ** dichotomy of 0 and != 0.
    */
    if (cuddIsConstant(my_root)) {
1204 1205 1206 1207 1208 1209 1210
        if (my_root != zero) {
            res_pair.pos = 0;
            res_pair.neg = DD_BIGGY;
        } else {
            res_pair.pos = DD_BIGGY;
            res_pair.neg = 0;
        }
Alan Mishchenko committed
1211
    } else {
1212 1213
        T = cuddT(my_root);
        E = cuddE(my_root);
Alan Mishchenko committed
1214

1215 1216 1217 1218
        pair_T = getLargest(T, visited);
        pair_E = getLargest(E, visited);
        res_pair.pos = ddMin(pair_T.pos, pair_E.pos) + 1;
        res_pair.neg = ddMin(pair_T.neg, pair_E.neg) + 1;
Alan Mishchenko committed
1219 1220
    }

Alan Mishchenko committed
1221
    my_pair = ABC_ALLOC(cuddPathPair, 1);
1222 1223 1224 1225 1226 1227 1228
    if (my_pair == NULL) {      /* simply do not cache this result */
        if (Cudd_IsComplement(root)) {
            int tmp = res_pair.pos;
            res_pair.pos = res_pair.neg;
            res_pair.neg = tmp;
        }
        return(res_pair);
Alan Mishchenko committed
1229 1230 1231 1232
    }
    my_pair->pos = res_pair.pos;
    my_pair->neg = res_pair.neg;

1233
    /* Caching may fail without affecting correctness. */
1234
    st__insert(visited, (char *)my_root, (char *)my_pair);
Alan Mishchenko committed
1235
    if (Cudd_IsComplement(root)) {
1236 1237
        res_pair.pos = my_pair->neg;
        res_pair.neg = my_pair->pos;
Alan Mishchenko committed
1238
    } else {
1239 1240
        res_pair.pos = my_pair->pos;
        res_pair.neg = my_pair->neg;
Alan Mishchenko committed
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
    }
    return(res_pair);

} /* end of getLargest */


/**Function********************************************************************

  Synopsis    [Build a BDD for a largest cube of f.]

  Description [Build a BDD for a largest cube of f.
  Given the minimum length from the root, and the minimum
  lengths for each node (in visited), apply triangulation at each node.
  Of the two children of each node on a shortest path, at least one is
  on a shortest path. In case of ties the procedure chooses the THEN
  children.
  Returns a pointer to the cube BDD representing the path if
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
getCube(
  DdManager * manager,
1268
  st__table * visited,
Alan Mishchenko committed
1269 1270 1271
  DdNode * f,
  int  cost)
{
1272 1273
    DdNode      *sol, *tmp;
    DdNode      *my_dd, *T, *E;
Alan Mishchenko committed
1274
    cuddPathPair *T_pair, *E_pair;
1275 1276
    int         Tcost, Ecost;
    int         complement;
Alan Mishchenko committed
1277 1278 1279 1280 1281 1282 1283 1284

    my_dd = Cudd_Regular(f);
    complement = Cudd_IsComplement(f);

    sol = one;
    cuddRef(sol);

    while (!cuddIsConstant(my_dd)) {
1285 1286 1287 1288 1289 1290 1291 1292
        Tcost = cost - 1;
        Ecost = cost - 1;

        T = cuddT(my_dd);
        E = cuddE(my_dd);

        if (complement) {T = Cudd_Not(T); E = Cudd_Not(E);}

1293
        if (! st__lookup(visited, (const char *)Cudd_Regular(T), (char **)&T_pair)) return(NULL);
1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308
        if ((Cudd_IsComplement(T) && T_pair->neg == Tcost) ||
        (!Cudd_IsComplement(T) && T_pair->pos == Tcost)) {
            tmp = cuddBddAndRecur(manager,manager->vars[my_dd->index],sol);
            if (tmp == NULL) {
                Cudd_RecursiveDeref(manager,sol);
                return(NULL);
            }
            cuddRef(tmp);
            Cudd_RecursiveDeref(manager,sol);
            sol = tmp;

            complement =  Cudd_IsComplement(T);
            my_dd = Cudd_Regular(T);
            cost = Tcost;
            continue;
Alan Mishchenko committed
1309
        }
1310
        if (! st__lookup(visited, (const char *)Cudd_Regular(E), (char **)&E_pair)) return(NULL);
1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
        if ((Cudd_IsComplement(E) && E_pair->neg == Ecost) ||
        (!Cudd_IsComplement(E) && E_pair->pos == Ecost)) {
            tmp = cuddBddAndRecur(manager,Cudd_Not(manager->vars[my_dd->index]),sol);
            if (tmp == NULL) {
                Cudd_RecursiveDeref(manager,sol);
                return(NULL);
            }
            cuddRef(tmp);
            Cudd_RecursiveDeref(manager,sol);
            sol = tmp;
            complement = Cudd_IsComplement(E);
            my_dd = Cudd_Regular(E);
            cost = Ecost;
            continue;
Alan Mishchenko committed
1325
        }
1326 1327 1328
        (void) fprintf(manager->err,"We shouldn't be here!\n");
        manager->errorCode = CUDD_INTERNAL_ERROR;
        return(NULL);
Alan Mishchenko committed
1329 1330 1331 1332 1333 1334
    }

    cuddDeref(sol);
    return(sol);

} /* end of getCube */
1335 1336


1337 1338
ABC_NAMESPACE_IMPL_END