예제 #1
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddIsop.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddIsop]

******************************************************************************/
DdNode	*
cuddZddIsop(
  DdManager * dd,
  DdNode * L,
  DdNode * U,
  DdNode ** zdd_I)
{
    DdNode	*one = DD_ONE(dd);
    DdNode	*zero = Cudd_Not(one);
    DdNode	*zdd_one = DD_ONE(dd);
    DdNode	*zdd_zero = DD_ZERO(dd);
    int		v, top_l, top_u;
    DdNode	*Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud;
    DdNode	*Lsuper0, *Usuper0, *Lsuper1, *Usuper1;
    DdNode	*Isub0, *Isub1, *Id;
    DdNode	*zdd_Isub0, *zdd_Isub1, *zdd_Id;
    DdNode	*x;
    DdNode	*term0, *term1, *sum;
    DdNode	*Lv, *Uv, *Lnv, *Unv;
    DdNode	*r, *y, *z;
    int		index;
    DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *);

    statLine(dd);
    if (L == zero) {
	*zdd_I = zdd_zero;
    	return(zero);
    }
    if (U == one) {
	*zdd_I = zdd_one;
    	return(one);
    }

    if (U == zero || L == one) {
	printf("*** ERROR : illegal condition for ISOP (U < L).\n");
	exit(1);
    }

    /* Check the cache. We store two results for each recursive call.
    ** One is the BDD, and the other is the ZDD. Both are needed.
    ** Hence we need a double hit in the cache to terminate the
    ** recursion. Clearly, collisions may evict only one of the two
    ** results. */
    cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop;
    r = cuddCacheLookup2(dd, cuddBddIsop, L, U);
    if (r) {
	*zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U);
	if (*zdd_I)
	    return(r);
	else {
	    /* The BDD result may have been dead. In that case
	    ** cuddCacheLookup2 would have called cuddReclaim,
	    ** whose effects we now have to undo. */
	    cuddRef(r);
	    Cudd_RecursiveDeref(dd, r);
	}
    }

    top_l = dd->perm[Cudd_Regular(L)->index];
    top_u = dd->perm[Cudd_Regular(U)->index];
    v = ddMin(top_l, top_u);

    /* Compute cofactors. */
    if (top_l == v) {
	index = Cudd_Regular(L)->index;
    	Lv = Cudd_T(L);
    	Lnv = Cudd_E(L);
    	if (Cudd_IsComplement(L)) {
    	    Lv = Cudd_Not(Lv);
    	    Lnv = Cudd_Not(Lnv);
    	}
    }
    else {
	index = Cudd_Regular(U)->index;
        Lv = Lnv = L;
    }

    if (top_u == v) {
    	Uv = Cudd_T(U);
    	Unv = Cudd_E(U);
    	if (Cudd_IsComplement(U)) {
    	    Uv = Cudd_Not(Uv);
    	    Unv = Cudd_Not(Unv);
    	}
    }
    else {
        Uv = Unv = U;
    }

    Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv));
    if (Lsub0 == NULL)
	return(NULL);
    Cudd_Ref(Lsub0);
    Usub0 = Unv;
    Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv));
    if (Lsub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	return(NULL);
    }
    Cudd_Ref(Lsub1);
    Usub1 = Uv;

    Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0);
    if (Isub0 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Isub0))) &&
	(Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Isub0);
    Cudd_Ref(zdd_Isub0);
    Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1);
    if (Isub1 == NULL) {
	Cudd_RecursiveDeref(dd, Lsub0);
	Cudd_RecursiveDeref(dd, Lsub1);
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Isub1))) &&
	(Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Isub1);
    Cudd_Ref(zdd_Isub1);
    Cudd_RecursiveDeref(dd, Lsub0);
    Cudd_RecursiveDeref(dd, Lsub1);

    Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0));
    if (Lsuper0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	return(NULL);
    }
    Cudd_Ref(Lsuper0);
    Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1));
    if (Lsuper1 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	return(NULL);
    }
    Cudd_Ref(Lsuper1);
    Usuper0 = Unv;
    Usuper1 = Uv;

    /* Ld = Lsuper0 + Lsuper1 */
    Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1));
    if (Ld == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	return(NULL);
    }
    Ld = Cudd_Not(Ld);
    Cudd_Ref(Ld);
    /* Ud = Usuper0 * Usuper1 */
    Ud = cuddBddAndRecur(dd, Usuper0, Usuper1);
    if (Ud == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Lsuper0);
	Cudd_RecursiveDeref(dd, Lsuper1);
	Cudd_RecursiveDeref(dd, Ld);
	return(NULL);
    }
    Cudd_Ref(Ud);
    Cudd_RecursiveDeref(dd, Lsuper0);
    Cudd_RecursiveDeref(dd, Lsuper1);

    Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id);
    if (Id == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Ld);
	Cudd_RecursiveDeref(dd, Ud);
	return(NULL);
    }
    /*
    if ((!cuddIsConstant(Cudd_Regular(Id))) &&
	(Cudd_Regular(Id)->index != zdd_Id->index / 2 ||
	dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) {
	printf("*** ERROR : illegal permutation in ZDD. ***\n");
    }
    */
    Cudd_Ref(Id);
    Cudd_Ref(zdd_Id);
    Cudd_RecursiveDeref(dd, Ld);
    Cudd_RecursiveDeref(dd, Ud);

    x = cuddUniqueInter(dd, index, one, zero);
    if (x == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	return(NULL);
    }
    Cudd_Ref(x);
    /* term0 = x * Isub0 */
    term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0);
    if (term0 == NULL) {
	Cudd_RecursiveDeref(dd, Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, x);
	return(NULL);
    }
    Cudd_Ref(term0);
    Cudd_RecursiveDeref(dd, Isub0);
    /* term1 = x * Isub1 */
    term1 = cuddBddAndRecur(dd, x, Isub1);
    if (term1 == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDeref(dd, Isub1);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, x);
	Cudd_RecursiveDeref(dd, term0);
	return(NULL);
    }
    Cudd_Ref(term1);
    Cudd_RecursiveDeref(dd, x);
    Cudd_RecursiveDeref(dd, Isub1);
    /* sum = term0 + term1 */
    sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1));
    if (sum == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, term0);
	Cudd_RecursiveDeref(dd, term1);
	return(NULL);
    }
    sum = Cudd_Not(sum);
    Cudd_Ref(sum);
    Cudd_RecursiveDeref(dd, term0);
    Cudd_RecursiveDeref(dd, term1);
    /* r = sum + Id */
    r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id));
    r = Cudd_NotCond(r, r != NULL);
    if (r == NULL) {
	Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	Cudd_RecursiveDeref(dd, Id);
	Cudd_RecursiveDerefZdd(dd, zdd_Id);
	Cudd_RecursiveDeref(dd, sum);
	return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDeref(dd, sum);
    Cudd_RecursiveDeref(dd, Id);

    if (zdd_Isub0 != zdd_zero) {
	z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id);
	if (z == NULL) {
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
	    Cudd_RecursiveDeref(dd, r);
	    return(NULL);
	}
    }
    else {
	z = zdd_Id;
    }
    Cudd_Ref(z);
    if (zdd_Isub1 != zdd_zero) {
	y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z);
	if (y == NULL) {
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
	    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
	    Cudd_RecursiveDerefZdd(dd, zdd_Id);
	    Cudd_RecursiveDeref(dd, r);
	    Cudd_RecursiveDerefZdd(dd, z);
	    return(NULL);
	}
    }
    else
	y = z;
    Cudd_Ref(y);

    Cudd_RecursiveDerefZdd(dd, zdd_Isub0);
    Cudd_RecursiveDerefZdd(dd, zdd_Isub1);
    Cudd_RecursiveDerefZdd(dd, zdd_Id);
    Cudd_RecursiveDerefZdd(dd, z);

    cuddCacheInsert2(dd, cuddBddIsop, L, U, r);
    cuddCacheInsert2(dd, cacheOp, L, U, y);

    Cudd_Deref(r);
    Cudd_Deref(y);
    *zdd_I = y;
    /*
    if (Cudd_Regular(r)->index != y->index / 2) {
	printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n");
    }
    */
    return(r);

} /* end of cuddZddIsop */
예제 #2
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddWeakDivF.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddWeakDivF]

******************************************************************************/
DdNode  *
cuddZddWeakDivF(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v, top_f, top_g, vf, vg;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
    DdNode      *q, *tmp;
    DdNode      *r;
    DdNode      *term1, *term0, *termd;
    int         flag;
    int         pv, nv;

    statLine(dd);
    if (g == one)
        return(f);
    if (f == zero || f == one)
        return(zero);
    if (f == g)
        return(one);

    /* Check cache. */
    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g);
    if (r)
        return(r);

    top_f = dd->permZ[f->index];
    top_g = dd->permZ[g->index];
    vf = top_f >> 1;
    vg = top_g >> 1;
    v = ddMin(top_f, top_g);

    if (v == top_f && vf < vg) {
        v = f->index;
        flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
        if (flag == 1)
            return(NULL);
        Cudd_Ref(f1);
        Cudd_Ref(f0);
        Cudd_Ref(fd);

        pv = cuddZddGetPosVarIndex(dd, v);
        nv = cuddZddGetNegVarIndex(dd, v);

        term1 = cuddZddWeakDivF(dd, f1, g);
        if (term1 == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            return(NULL);
        }
        Cudd_Ref(term1);
        Cudd_RecursiveDerefZdd(dd, f1);
        term0 = cuddZddWeakDivF(dd, f0, g);
        if (term0 == NULL) {
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, term1);
            return(NULL);
        }
        Cudd_Ref(term0);
        Cudd_RecursiveDerefZdd(dd, f0);
        termd = cuddZddWeakDivF(dd, fd, g);
        if (termd == NULL) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, term1);
            Cudd_RecursiveDerefZdd(dd, term0);
            return(NULL);
        }
        Cudd_Ref(termd);
        Cudd_RecursiveDerefZdd(dd, fd);

        tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, term1);
            Cudd_RecursiveDerefZdd(dd, term0);
            Cudd_RecursiveDerefZdd(dd, termd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, term0);
        Cudd_RecursiveDerefZdd(dd, termd);
        q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, term1);
            Cudd_RecursiveDerefZdd(dd, tmp);
            return(NULL);
        }
        Cudd_Ref(q);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, tmp);

        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
        Cudd_Deref(q);
        return(q);
    }

    if (v == top_f)
        v = f->index;
    else
        v = g->index;

    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);
    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);
    Cudd_Ref(gd);

    q = g;

    if (g0 != zero) {
        q = cuddZddWeakDivF(dd, f0, g0);
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(q);
    }
    else
        Cudd_Ref(q);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g0);

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (g1 != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDivF(dd, f1, g1);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, fd);
                Cudd_RecursiveDerefZdd(dd, gd);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
    }

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (gd != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDivF(dd, fd, gd);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, tmp);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
    }

    cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q);
    Cudd_Deref(q);
    return(q);

} /* end of cuddZddWeakDivF */
예제 #3
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddDiff.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddZddDiff(
  DdManager * zdd,
  DdNode * P,
  DdNode * Q)
{
    int		p_top, q_top;
    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
    DdManager	*table = zdd;

    statLine(zdd);
    if (P == empty)
	return(empty);
    if (Q == empty)
	return(P);
    if (P == Q)
	return(empty);

    /* Check cache.  The cache is shared by Cudd_zddDiffConst(). */
    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
    if (res != NULL && res != DD_NON_CONSTANT)
	return(res);

    if (cuddIsConstant(P))
	p_top = P->index;
    else
	p_top = zdd->permZ[P->index];
    if (cuddIsConstant(Q))
	q_top = Q->index;
    else
	q_top = zdd->permZ[Q->index];
    if (p_top < q_top) {
	e = cuddZddDiff(zdd, cuddE(P), Q);
	if (e == NULL) return(NULL);
	cuddRef(e);
	res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
	if (res == NULL) {
	    Cudd_RecursiveDerefZdd(table, e);
	    return(NULL);
	}
	cuddDeref(e);
    } else if (p_top > q_top) {
	res = cuddZddDiff(zdd, P, cuddE(Q));
	if (res == NULL) return(NULL);
    } else {
	t = cuddZddDiff(zdd, cuddT(P), cuddT(Q));
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddZddDiff(zdd, cuddE(P), cuddE(Q));
	if (e == NULL) {
	    Cudd_RecursiveDerefZdd(table, t);
	    return(NULL);
	}
	cuddRef(e);
	res = cuddZddGetNode(zdd, P->index, t, e);
	if (res == NULL) {
	    Cudd_RecursiveDerefZdd(table, t);
	    Cudd_RecursiveDerefZdd(table, e);
	    return(NULL);
	}
	cuddDeref(t);
	cuddDeref(e);
    }

    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);

    return(res);

} /* end of cuddZddDiff */
예제 #4
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddUnateProduct.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddUnateProduct]

******************************************************************************/
DdNode  *
cuddZddUnateProduct(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v, top_f, top_g;
    DdNode      *term1, *term2, *term3, *term4;
    DdNode      *sum1, *sum2;
    DdNode      *f0, *f1, *g0, *g1;
    DdNode      *r;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    int         flag;

    statLine(dd);
    if (f == zero || g == zero)
        return(zero);
    if (f == one)
        return(g);
    if (g == one)
        return(f);

    top_f = dd->permZ[f->index];
    top_g = dd->permZ[g->index];

    if (top_f > top_g)
        return(cuddZddUnateProduct(dd, g, f));

    /* Check cache */
    r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g);
    if (r)
        return(r);

    v = f->index;       /* either yi or zi */
    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);

    term1 = cuddZddUnateProduct(dd, f1, g1);
    if (term1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        return(NULL);
    }
    Cudd_Ref(term1);
    term2 = cuddZddUnateProduct(dd, f1, g0);
    if (term2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, term1);
        return(NULL);
    }
    Cudd_Ref(term2);
    term3 = cuddZddUnateProduct(dd, f0, g1);
    if (term3 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        return(NULL);
    }
    Cudd_Ref(term3);
    term4 = cuddZddUnateProduct(dd, f0, g0);
    if (term4 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        return(NULL);
    }
    Cudd_Ref(term4);
    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g1);
    Cudd_RecursiveDerefZdd(dd, g0);
    sum1 = cuddZddUnion(dd, term1, term2);
    if (sum1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, term4);
        return(NULL);
    }
    Cudd_Ref(sum1);
    Cudd_RecursiveDerefZdd(dd, term1);
    Cudd_RecursiveDerefZdd(dd, term2);
    sum2 = cuddZddUnion(dd, sum1, term3);
    if (sum2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, term4);
        Cudd_RecursiveDerefZdd(dd, sum1);
        return(NULL);
    }
    Cudd_Ref(sum2);
    Cudd_RecursiveDerefZdd(dd, sum1);
    Cudd_RecursiveDerefZdd(dd, term3);
    r = cuddZddGetNode(dd, v, sum2, term4);
    if (r == NULL) {
        Cudd_RecursiveDerefZdd(dd, term4);
        Cudd_RecursiveDerefZdd(dd, sum2);
        return(NULL);
    }
    Cudd_Ref(r);
    Cudd_RecursiveDerefZdd(dd, sum2);
    Cudd_RecursiveDerefZdd(dd, term4);

    cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r);
    Cudd_Deref(r);
    return(r);

} /* end of cuddZddUnateProduct */
예제 #5
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddWeakDiv.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddWeakDiv]

******************************************************************************/
DdNode  *
cuddZddWeakDiv(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
    DdNode      *q, *tmp;
    DdNode      *r;
    int         flag;

    statLine(dd);
    if (g == one)
        return(f);
    if (f == zero || f == one)
        return(zero);
    if (f == g)
        return(one);

    /* Check cache. */
    r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g);
    if (r)
        return(r);

    v = g->index;

    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);
    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);
    Cudd_Ref(gd);

    q = g;

    if (g0 != zero) {
        q = cuddZddWeakDiv(dd, f0, g0);
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(q);
    }
    else
        Cudd_Ref(q);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g0);

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (g1 != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDiv(dd, f1, g1);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, fd);
                Cudd_RecursiveDerefZdd(dd, gd);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, g1);
    }

    if (q == zero) {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero);
        Cudd_Deref(q);
        return(zero);
    }

    if (gd != zero) {
        Cudd_RecursiveDerefZdd(dd, q);
        tmp = cuddZddWeakDiv(dd, fd, gd);
        if (tmp == NULL) {
            Cudd_RecursiveDerefZdd(dd, fd);
            Cudd_RecursiveDerefZdd(dd, gd);
            return(NULL);
        }
        Cudd_Ref(tmp);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
        if (q == g)
            q = tmp;
        else {
            q = cuddZddIntersect(dd, q, tmp);
            if (q == NULL) {
                Cudd_RecursiveDerefZdd(dd, tmp);
                return(NULL);
            }
            Cudd_Ref(q);
            Cudd_RecursiveDerefZdd(dd, tmp);
        }
    }
    else {
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, gd);
    }

    cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q);
    Cudd_Deref(q);
    return(q);

} /* end of cuddZddWeakDiv */
예제 #6
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddProduct.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddProduct]

******************************************************************************/
DdNode  *
cuddZddProduct(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v, top_f, top_g;
    DdNode      *tmp, *term1, *term2, *term3;
    DdNode      *f0, *f1, *fd, *g0, *g1, *gd;
    DdNode      *R0, *R1, *Rd, *N0, *N1;
    DdNode      *r;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    int         flag;
    int         pv, nv;

    statLine(dd);
    if (f == zero || g == zero)
        return(zero);
    if (f == one)
        return(g);
    if (g == one)
        return(f);

    top_f = dd->permZ[f->index];
    top_g = dd->permZ[g->index];

    if (top_f > top_g)
        return(cuddZddProduct(dd, g, f));

    /* Check cache */
    r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g);
    if (r)
        return(r);

    v = f->index;       /* either yi or zi */
    flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    Cudd_Ref(fd);
    flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd);
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);
    Cudd_Ref(gd);
    pv = cuddZddGetPosVarIndex(dd, v);
    nv = cuddZddGetNegVarIndex(dd, v);

    Rd = cuddZddProduct(dd, fd, gd);
    if (Rd == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        return(NULL);
    }
    Cudd_Ref(Rd);

    term1 = cuddZddProduct(dd, f0, g0);
    if (term1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        return(NULL);
    }
    Cudd_Ref(term1);
    term2 = cuddZddProduct(dd, f0, gd);
    if (term2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term1);
        return(NULL);
    }
    Cudd_Ref(term2);
    term3 = cuddZddProduct(dd, fd, g0);
    if (term3 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        return(NULL);
    }
    Cudd_Ref(term3);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g0);
    tmp = cuddZddUnion(dd, term1, term2);
    if (tmp == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        return(NULL);
    }
    Cudd_Ref(tmp);
    Cudd_RecursiveDerefZdd(dd, term1);
    Cudd_RecursiveDerefZdd(dd, term2);
    R0 = cuddZddUnion(dd, tmp, term3);
    if (R0 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, tmp);
        return(NULL);
    }
    Cudd_Ref(R0);
    Cudd_RecursiveDerefZdd(dd, tmp);
    Cudd_RecursiveDerefZdd(dd, term3);
    N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */
    if (N0 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, Rd);
        Cudd_RecursiveDerefZdd(dd, R0);
        return(NULL);
    }
    Cudd_Ref(N0);
    Cudd_RecursiveDerefZdd(dd, R0);
    Cudd_RecursiveDerefZdd(dd, Rd);

    term1 = cuddZddProduct(dd, f1, g1);
    if (term1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, N0);
        return(NULL);
    }
    Cudd_Ref(term1);
    term2 = cuddZddProduct(dd, f1, gd);
    if (term2 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term1);
        return(NULL);
    }
    Cudd_Ref(term2);
    term3 = cuddZddProduct(dd, fd, g1);
    if (term3 == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, fd);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, gd);
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        return(NULL);
    }
    Cudd_Ref(term3);
    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, g1);
    Cudd_RecursiveDerefZdd(dd, fd);
    Cudd_RecursiveDerefZdd(dd, gd);
    tmp = cuddZddUnion(dd, term1, term2);
    if (tmp == NULL) {
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term1);
        Cudd_RecursiveDerefZdd(dd, term2);
        Cudd_RecursiveDerefZdd(dd, term3);
        return(NULL);
    }
    Cudd_Ref(tmp);
    Cudd_RecursiveDerefZdd(dd, term1);
    Cudd_RecursiveDerefZdd(dd, term2);
    R1 = cuddZddUnion(dd, tmp, term3);
    if (R1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, term3);
        Cudd_RecursiveDerefZdd(dd, tmp);
        return(NULL);
    }
    Cudd_Ref(R1);
    Cudd_RecursiveDerefZdd(dd, tmp);
    Cudd_RecursiveDerefZdd(dd, term3);
    N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */
    if (N1 == NULL) {
        Cudd_RecursiveDerefZdd(dd, N0);
        Cudd_RecursiveDerefZdd(dd, R1);
        return(NULL);
    }
    Cudd_Ref(N1);
    Cudd_RecursiveDerefZdd(dd, R1);
    Cudd_RecursiveDerefZdd(dd, N0);

    cuddCacheInsert2(dd, cuddZddProduct, f, g, N1);
    Cudd_Deref(N1);
    return(N1);

} /* end of cuddZddProduct */
예제 #7
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_zddDivideF.]

  Description []

  SideEffects [None]

  SeeAlso     [Cudd_zddDivideF]

******************************************************************************/
DdNode  *
cuddZddDivideF(
  DdManager * dd,
  DdNode * f,
  DdNode * g)
{
    int         v;
    DdNode      *one = DD_ONE(dd);
    DdNode      *zero = DD_ZERO(dd);
    DdNode      *f0, *f1, *g0, *g1;
    DdNode      *q, *r, *tmp;
    int         flag;

    statLine(dd);
    if (g == one)
        return(f);
    if (f == zero || f == one)
        return(zero);
    if (f == g)
        return(one);

    /* Check cache. */
    r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g);
    if (r)
        return(r);

    v = g->index;

    flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0);
    if (flag == 1)
        return(NULL);
    Cudd_Ref(f1);
    Cudd_Ref(f0);
    flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);    /* g1 != zero */
    if (flag == 1) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        return(NULL);
    }
    Cudd_Ref(g1);
    Cudd_Ref(g0);

    r = cuddZddDivideF(dd, f1, g1);
    if (r == NULL) {
        Cudd_RecursiveDerefZdd(dd, f1);
        Cudd_RecursiveDerefZdd(dd, f0);
        Cudd_RecursiveDerefZdd(dd, g1);
        Cudd_RecursiveDerefZdd(dd, g0);
        return(NULL);
    }
    Cudd_Ref(r);

    if (r != zero && g0 != zero) {
        tmp = r;
        q = cuddZddDivideF(dd, f0, g0);
        if (q == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            return(NULL);
        }
        Cudd_Ref(q);
        r = cuddZddIntersect(dd, r, q);
        if (r == NULL) {
            Cudd_RecursiveDerefZdd(dd, f1);
            Cudd_RecursiveDerefZdd(dd, f0);
            Cudd_RecursiveDerefZdd(dd, g1);
            Cudd_RecursiveDerefZdd(dd, g0);
            Cudd_RecursiveDerefZdd(dd, q);
            return(NULL);
        }
        Cudd_Ref(r);
        Cudd_RecursiveDerefZdd(dd, q);
        Cudd_RecursiveDerefZdd(dd, tmp);
    }

    Cudd_RecursiveDerefZdd(dd, f1);
    Cudd_RecursiveDerefZdd(dd, f0);
    Cudd_RecursiveDerefZdd(dd, g1);
    Cudd_RecursiveDerefZdd(dd, g0);
    
    cuddCacheInsert2(dd, cuddZddDivideF, f, g, r);
    Cudd_Deref(r);
    return(r);

} /* end of cuddZddDivideF */
예제 #8
0
/**Function********************************************************************

  Synopsis    [Performs a recursive step of Extra_SymmPairsCompute.]

  Description [Returns the set of symmetric variable pairs represented as a set 
  of two-literal ZDD cubes. Both variables always appear in the positive polarity
  in the cubes. This function works without building new BDD nodes. Some relatively 
  small number of ZDD nodes may be built to ensure proper bookkeeping of the 
  symmetry information.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode * 
extraZddSymmPairsCompute( 
  DdManager * dd,   /* the manager */
  DdNode * bFunc,   /* the function whose symmetries are computed */
  DdNode * bVars )  /* the set of variables on which this function depends */
{
    DdNode * zRes;
    DdNode * bFR = Cudd_Regular(bFunc); 

    if ( cuddIsConstant(bFR) )
    {
        int nVars, i;

        // determine how many vars are in the bVars
        nVars = Extra_bddSuppSize( dd, bVars );
        if ( nVars < 2 )
            return z0;
        else
        {
            DdNode * bVarsK;

            // create the BDD bVarsK corresponding to K = 2;
            bVarsK = bVars;
            for ( i = 0; i < nVars-2; i++ )
                bVarsK = cuddT( bVarsK );
            return extraZddTuplesFromBdd( dd, bVarsK, bVars );
        }
    }
    assert( bVars != b1 );

    if ( (zRes = cuddCacheLookup2Zdd(dd, extraZddSymmPairsCompute, bFunc, bVars)) )
        return zRes;
    else
    {
        DdNode * zRes0, * zRes1;
        DdNode * zTemp, * zPlus, * zSymmVars;             
        DdNode * bF0, * bF1;             
        DdNode * bVarsNew;
        int nVarsExtra;
        int LevelF;

        // every variable in bF should be also in bVars, therefore LevelF cannot be above LevelV
        // if LevelF is below LevelV, scroll through the vars in bVars to the same level as F
        // count how many extra vars are there in bVars
        nVarsExtra = 0;
        LevelF = dd->perm[bFR->index];
        for ( bVarsNew = bVars; LevelF > dd->perm[bVarsNew->index]; bVarsNew = cuddT(bVarsNew) )
            nVarsExtra++; 
        // the indexes (level) of variables should be synchronized now
        assert( bFR->index == bVarsNew->index );

        // cofactor the function
        if ( bFR != bFunc ) // bFunc is complemented 
        {
            bF0 = Cudd_Not( cuddE(bFR) );
            bF1 = Cudd_Not( cuddT(bFR) );
        }
        else
        {
            bF0 = cuddE(bFR);
            bF1 = cuddT(bFR);
        }

        // solve subproblems
        zRes0 = extraZddSymmPairsCompute( dd, bF0, cuddT(bVarsNew) );
        if ( zRes0 == NULL )
            return NULL;
        cuddRef( zRes0 );

        // if there is no symmetries in the negative cofactor
        // there is no need to test the positive cofactor
        if ( zRes0 == z0 )
            zRes = zRes0;  // zRes takes reference
        else
        {
            zRes1 = extraZddSymmPairsCompute( dd, bF1, cuddT(bVarsNew) );
            if ( zRes1 == NULL )
            {
                Cudd_RecursiveDerefZdd( dd, zRes0 );
                return NULL;
            }
            cuddRef( zRes1 );

            // only those variables are pair-wise symmetric 
            // that are pair-wise symmetric in both cofactors
            // therefore, intersect the solutions
            zRes = cuddZddIntersect( dd, zRes0, zRes1 );
            if ( zRes == NULL )
            {
                Cudd_RecursiveDerefZdd( dd, zRes0 );
                Cudd_RecursiveDerefZdd( dd, zRes1 );
                return NULL;
            }
            cuddRef( zRes );
            Cudd_RecursiveDerefZdd( dd, zRes0 );
            Cudd_RecursiveDerefZdd( dd, zRes1 );
        }

        // consider the current top-most variable and find all the vars
        // that are pairwise symmetric with it
        // these variables are returned as a set of ZDD singletons
        zSymmVars = extraZddGetSymmetricVars( dd, bF1, bF0, cuddT(bVarsNew) );
        if ( zSymmVars == NULL )
        {
            Cudd_RecursiveDerefZdd( dd, zRes );
            return NULL;
        }
        cuddRef( zSymmVars );

        // attach the topmost variable to the set, to get the variable pairs
        // use the positive polarity ZDD variable for the purpose

        // there is no need to do so, if zSymmVars is empty
        if ( zSymmVars == z0 )
            Cudd_RecursiveDerefZdd( dd, zSymmVars );
        else
        {
            zPlus = cuddZddGetNode( dd, 2*bFR->index, zSymmVars, z0 );
            if ( zPlus == NULL ) 
            {
                Cudd_RecursiveDerefZdd( dd, zRes );
                Cudd_RecursiveDerefZdd( dd, zSymmVars );
                return NULL;
            }
            cuddRef( zPlus );
            cuddDeref( zSymmVars );

            // add these variable pairs to the result
            zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
            if ( zRes == NULL )
            {
                Cudd_RecursiveDerefZdd( dd, zTemp );
                Cudd_RecursiveDerefZdd( dd, zPlus );
                return NULL;
            }
            cuddRef( zRes );
            Cudd_RecursiveDerefZdd( dd, zTemp );
            Cudd_RecursiveDerefZdd( dd, zPlus );
        }

        // only zRes is referenced at this point

        // if we skipped some variables, these variables cannot be symmetric with
        // any variables that are currently in the support of bF, but they can be 
        // symmetric with the variables that are in bVars but not in the support of bF
        if ( nVarsExtra )
        {
            // it is possible to improve this step:
            // (1) there is no need to enter here, if nVarsExtra < 2

            // create the set of topmost nVarsExtra in bVars
            DdNode * bVarsExtra;
            int nVars;

            // remove from bVars all the variable that are in the support of bFunc
            bVarsExtra = extraBddReduceVarSet( dd, bVars, bFunc );  
            if ( bVarsExtra == NULL )
            {
                Cudd_RecursiveDerefZdd( dd, zRes );
                return NULL;
            }
            cuddRef( bVarsExtra );

            // determine how many vars are in the bVarsExtra
            nVars = Extra_bddSuppSize( dd, bVarsExtra );
            if ( nVars < 2 )
            {
                Cudd_RecursiveDeref( dd, bVarsExtra );
            }
            else
            {
                int i;
                DdNode * bVarsK;

                // create the BDD bVarsK corresponding to K = 2;
                bVarsK = bVarsExtra;
                for ( i = 0; i < nVars-2; i++ )
                    bVarsK = cuddT( bVarsK );

                // create the 2 variable tuples
                zPlus = extraZddTuplesFromBdd( dd, bVarsK, bVarsExtra );
                if ( zPlus == NULL )
                {
                    Cudd_RecursiveDeref( dd, bVarsExtra );
                    Cudd_RecursiveDerefZdd( dd, zRes );
                    return NULL;
                }
                cuddRef( zPlus );
                Cudd_RecursiveDeref( dd, bVarsExtra );

                // add these to the result
                zRes = cuddZddUnion( dd, zTemp = zRes, zPlus );
                if ( zRes == NULL )
                {
                    Cudd_RecursiveDerefZdd( dd, zTemp );
                    Cudd_RecursiveDerefZdd( dd, zPlus );
                    return NULL;
                }
                cuddRef( zRes );
                Cudd_RecursiveDerefZdd( dd, zTemp );
                Cudd_RecursiveDerefZdd( dd, zPlus );
            }
        }
        cuddDeref( zRes );


        /* insert the result into cache */
        cuddCacheInsert2(dd, extraZddSymmPairsCompute, bFunc, bVars, zRes);
        return zRes;
    }
} /* end of extraZddSymmPairsCompute */
예제 #9
0
/**Function********************************************************************

  Synopsis    [Performs the reordering-sensitive step of Extra_zddTupleFromBdd().]

  Description [Generates in a bottom-up fashion ZDD for all combinations
               composed of k variables out of variables belonging to Support.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode* extraZddTuplesFromBdd( 
  DdManager * dd,   /* the DD manager */
  DdNode * bVarsK,   /* the number of variables in tuples */
  DdNode * bVarsN)   /* the set of all variables */
{
    DdNode *zRes, *zRes0, *zRes1;
    statLine(dd); 

    /* terminal cases */
/*  if ( k < 0 || k > n )
 *      return dd->zero;
 *  if ( n == 0 )
 *      return dd->one; 
 */
    if ( cuddI( dd, bVarsK->index ) < cuddI( dd, bVarsN->index ) )
        return z0;
    if ( bVarsN == b1 )
        return z1;

    /* check cache */
    zRes = cuddCacheLookup2Zdd(dd, extraZddTuplesFromBdd, bVarsK, bVarsN);
    if (zRes)
        return(zRes);

    /* ZDD in which this variable is 0 */
/*  zRes0 = extraZddTuplesFromBdd( dd, k,     n-1 ); */
    zRes0 = extraZddTuplesFromBdd( dd, bVarsK, cuddT(bVarsN) );
    if ( zRes0 == NULL ) 
        return NULL;
    cuddRef( zRes0 );

    /* ZDD in which this variable is 1 */
/*  zRes1 = extraZddTuplesFromBdd( dd, k-1,          n-1 ); */
    if ( bVarsK == b1 )
    {
        zRes1 = z0;
        cuddRef( zRes1 );
    }
    else
    {
        zRes1 = extraZddTuplesFromBdd( dd, cuddT(bVarsK), cuddT(bVarsN) );
        if ( zRes1 == NULL ) 
        {
            Cudd_RecursiveDerefZdd( dd, zRes0 );
            return NULL;
        }
        cuddRef( zRes1 );
    }

    /* compose Res0 and Res1 with the given ZDD variable */
    zRes = cuddZddGetNode( dd, 2*bVarsN->index, zRes1, zRes0 );
    if ( zRes == NULL ) 
    {
        Cudd_RecursiveDerefZdd( dd, zRes0 );
        Cudd_RecursiveDerefZdd( dd, zRes1 );
        return NULL;
    }
    cuddDeref( zRes0 );
    cuddDeref( zRes1 );

    /* insert the result into cache */
    cuddCacheInsert2(dd, extraZddTuplesFromBdd, bVarsK, bVarsN, zRes);
    return zRes;

} /* end of extraZddTuplesFromBdd */
예제 #10
0
/**Function********************************************************************

  Synopsis [Performs the recursive step of Cudd_zddUnion.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddZddUnion(
  DdManager * zdd,
  DdNode * P,
  DdNode * Q)
{
    int		p_top, q_top;
    DdNode	*empty = DD_FALSE(zdd), *t, *e, *res;
    DdManager	*table = zdd;

    statLine(zdd);
    if (P == empty)
	return(Q);
    if (Q == empty)
	return(P);
    if (P == Q)
	return(P);

    /* Check cache */
    res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q);
    if (res != NULL)
	return(res);

    if (cuddIsConstant(P))
	p_top = P->index;
    else
	p_top = zdd->permZ[P->index];
    if (cuddIsConstant(Q))
	q_top = Q->index;
    else
	q_top = zdd->permZ[Q->index];
    if (p_top < q_top) {
	e = cuddZddUnion(zdd, cuddE(P), Q);
	if (e == NULL) return (NULL);
	cuddRef(e);
	res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
	if (res == NULL) {
	    Cudd_RecursiveDerefZdd(table, e);
	    return(NULL);
	}
	cuddDeref(e);
    } else if (p_top > q_top) {
	e = cuddZddUnion(zdd, P, cuddE(Q));
	if (e == NULL) return(NULL);
	cuddRef(e);
	res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e);
	if (res == NULL) {
	    Cudd_RecursiveDerefZdd(table, e);
	    return(NULL);
	}
	cuddDeref(e);
    } else {
	t = cuddZddUnion(zdd, cuddT(P), cuddT(Q));
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddZddUnion(zdd, cuddE(P), cuddE(Q));
	if (e == NULL) {
	    Cudd_RecursiveDerefZdd(table, t);
	    return(NULL);
	}
	cuddRef(e);
	res = cuddZddGetNode(zdd, P->index, t, e);
	if (res == NULL) {
	    Cudd_RecursiveDerefZdd(table, t);
	    Cudd_RecursiveDerefZdd(table, e);
	    return(NULL);
	}
	cuddDeref(t);
	cuddDeref(e);
    }

    cuddCacheInsert2(table, cuddZddUnion, P, Q, res);

    return(res);

} /* end of cuddZddUnion */