示例#1
0
文件: cuddMatMult.c 项目: maeon/SBSAT
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addTriangle.]

  Description [Performs the recursive step of Cudd_addTriangle. Returns
  a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

******************************************************************************/
static DdNode *
addTriangleRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  int * vars,
  DdNode *cube)
{
    DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
    CUDD_VALUE_TYPE value;
    int top, topf, topg, index;

    statLine(dd);
    if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
	return(DD_PLUS_INFINITY(dd));
    }

    if (cuddIsConstant(f) && cuddIsConstant(g)) {
	value = cuddV(f) + cuddV(g);
	res = cuddUniqueConst(dd, value);
	return(res);
    }
    if (f < g) {
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    if (f->ref != 1 || g->ref != 1) {
	res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
	if (res != NULL) {
	    return(res);
	}
    }

    topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
    top = ddMin(topf,topg);

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

    t = addTriangleRecur(dd, fv, gv, vars, cube);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = addTriangleRecur(dd, fvn, gvn, vars, cube);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd, t);
	return(NULL);
    }
    cuddRef(e);

    index = dd->invperm[top];
    if (vars[index] < 0) {
	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddDeref(t);
	cuddDeref(e);
    } else {
	res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
	cuddDeref(res);
    }

    if (f->ref != 1 || g->ref != 1) {
	cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
    }

    return(res);

} /* end of addTriangleRecur */
示例#2
0
/**Function********************************************************************

  Synopsis [Takes the exclusive OR of two BDDs and simultaneously abstracts the
  variables in cube.]

  Description [Takes the exclusive OR of two BDDs and simultaneously abstracts
  the variables in cube. The variables are existentially abstracted.  Returns a
  pointer to the result is successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAndAbstract]

******************************************************************************/
DdNode *
cuddBddXorExistAbstractRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube)
{
    DdNode *F, *fv, *fnv, *G, *gv, *gnv;
    DdNode *one, *zero, *r, *t, *e, *Cube;
    unsigned int topf, topg, topcube, top, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == g) {
	return(zero);
    }
    if (f == Cudd_Not(g)) {
	return(one);
    }
    if (cube == one) {
	return(cuddBddXorRecur(manager, f, g));
    }
    if (f == one) {
	return(cuddBddExistAbstractRecur(manager, Cudd_Not(g), cube));
    }
    if (g == one) {
	return(cuddBddExistAbstractRecur(manager, Cudd_Not(f), cube));
    }
    if (f == zero) {
	return(cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == zero) {
	return(cuddBddExistAbstractRecur(manager, f, cube));
    }

    /* At this point f, g, and cube are not constant. */

    if (f > g) { /* Try to increase cache efficiency. */
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    /* Check cache. */
    r = cuddCacheLookup(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube);
    if (r != NULL) {
	return(r);
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    F = Cudd_Regular(f);
    topf = manager->perm[F->index];
    G = Cudd_Regular(g);
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    if (topcube < top) {
	return(cuddBddXorExistAbstractRecur(manager, f, g, cuddT(cube)));
    }
    /* Now, topcube >= top. */

    if (topf == top) {
	index = F->index;
	fv = cuddT(F);
	fnv = cuddE(F);
	if (Cudd_IsComplement(f)) {
	    fv = Cudd_Not(fv);
	    fnv = Cudd_Not(fnv);
	}
    } else {
	index = G->index;
	fv = fnv = f;
    }

    if (topg == top) {
	gv = cuddT(G);
	gnv = cuddE(G);
	if (Cudd_IsComplement(g)) {
	    gv = Cudd_Not(gv);
	    gnv = Cudd_Not(gnv);
	}
    } else {
	gv = gnv = g;
    }

    if (topcube == top) {
	Cube = cuddT(cube);
    } else {
	Cube = cube;
    }

    t = cuddBddXorExistAbstractRecur(manager, fv, gv, Cube);
    if (t == NULL) return(NULL);

    /* Special case: 1 OR anything = 1. Hence, no need to compute
    ** the else branch if t is 1.
    */
    if (t == one && topcube == top) {
	cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, one);
	return(one);
    }
    cuddRef(t);

    e = cuddBddXorExistAbstractRecur(manager, fnv, gnv, Cube);
    if (e == NULL) {
	Cudd_IterDerefBdd(manager, t);
	return(NULL);
    }
    cuddRef(e);

    if (topcube == top) {	/* abstract */
	r = cuddBddAndRecur(manager, Cudd_Not(t), Cudd_Not(e));
	if (r == NULL) {
	    Cudd_IterDerefBdd(manager, t);
	    Cudd_IterDerefBdd(manager, e);
	    return(NULL);
	}
	r = Cudd_Not(r);
	cuddRef(r);
	Cudd_IterDerefBdd(manager, t);
	Cudd_IterDerefBdd(manager, e);
	cuddDeref(r);
    } else if (t == e) {
	r = t;
	cuddDeref(t);
	cuddDeref(e);
    } else {
	if (Cudd_IsComplement(t)) {
	    r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	    r = Cudd_Not(r);
	} else {
	    r = cuddUniqueInter(manager,(int)index,t,e);
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	}
	cuddDeref(e);
	cuddDeref(t);
    }
    cuddCacheInsert(manager, DD_BDD_XOR_EXIST_ABSTRACT_TAG, f, g, cube, r);
    return (r);

} /* end of cuddBddXorExistAbstractRecur */
示例#3
0
/**Function********************************************************************

  Synopsis [Takes the AND of two BDDs and simultaneously abstracts the
  variables in cube.]

  Description [Takes the AND of two BDDs and simultaneously abstracts
  the variables in cube. The variables are existentially abstracted.
  Returns a pointer to the result is successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddAndAbstract]

******************************************************************************/
DdNode *
cuddBddAndAbstractRecurTime(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube,
  int * pRecCalls,
  int TimeOut)
{
    DdNode *F, *ft, *fe, *G, *gt, *ge;
    DdNode *one, *zero, *r, *t, *e;
    unsigned int topf, topg, topcube, top, index;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == one && g == one)	return(one);

    if (cube == one) {
	return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut));
    }
    if (f == one || f == g) {
	return(cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == one) {
	return(cuddBddExistAbstractRecur(manager, f, cube));
    }
    /* At this point f, g, and cube are not constant. */

    if (f > g) { /* Try to increase cache efficiency. */
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    while (topcube < top) {
	cube = cuddT(cube);
	if (cube == one) {
	    return(cuddBddAndRecurTime(manager, f, g, pRecCalls, TimeOut));
	}
	topcube = manager->perm[cube->index];
    }
    /* Now, topcube >= top. */

    /* Check cache. */
    if (F->ref != 1 || G->ref != 1) {
	r = cuddCacheLookup(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube);
	if (r != NULL) {
	    return(r);
	}
    }

//    if ( TimeOut && ((*pRecCalls)++ % CHECK_FACTOR) == 0 && TimeOut < clock() )
    if ( TimeOut && TimeOut < clock() )
        return NULL;

    if (topf == top) {
	index = F->index;
	ft = cuddT(F);
	fe = cuddE(F);
	if (Cudd_IsComplement(f)) {
	    ft = Cudd_Not(ft);
	    fe = Cudd_Not(fe);
	}
    } else {
	index = G->index;
	ft = fe = f;
    }

    if (topg == top) {
	gt = cuddT(G);
	ge = cuddE(G);
	if (Cudd_IsComplement(g)) {
	    gt = Cudd_Not(gt);
	    ge = Cudd_Not(ge);
	}
    } else {
	gt = ge = g;
    }

    if (topcube == top) {	/* quantify */
	DdNode *Cube = cuddT(cube);
	t = cuddBddAndAbstractRecurTime(manager, ft, gt, Cube, pRecCalls, TimeOut);
	if (t == NULL) return(NULL);
	/* Special case: 1 OR anything = 1. Hence, no need to compute
	** the else branch if t is 1. Likewise t + t * anything == t.
	** Notice that t == fe implies that fe does not depend on the
	** variables in Cube. Likewise for t == ge.
	*/
	if (t == one || t == fe || t == ge) {
	    if (F->ref != 1 || G->ref != 1)
		cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG,
				f, g, cube, t);
	    return(t);
	}
	cuddRef(t);
	/* Special case: t + !t * anything == t + anything. */
	if (t == Cudd_Not(fe)) {
	    e = cuddBddExistAbstractRecur(manager, ge, Cube);
	} else if (t == Cudd_Not(ge)) {
	    e = cuddBddExistAbstractRecur(manager, fe, Cube);
	} else {
	    e = cuddBddAndAbstractRecurTime(manager, fe, ge, Cube, pRecCalls, TimeOut);
	}
	if (e == NULL) {
	    Cudd_IterDerefBdd(manager, t);
	    return(NULL);
	}
	if (t == e) {
	    r = t;
	    cuddDeref(t);
	} else {
	    cuddRef(e);
	    r = cuddBddAndRecurTime(manager, Cudd_Not(t), Cudd_Not(e), pRecCalls, TimeOut);
	    if (r == NULL) {
		Cudd_IterDerefBdd(manager, t);
		Cudd_IterDerefBdd(manager, e);
		return(NULL);
	    }
	    r = Cudd_Not(r);
	    cuddRef(r);
	    Cudd_DelayedDerefBdd(manager, t);
	    Cudd_DelayedDerefBdd(manager, e);
	    cuddDeref(r);
	}
    } else {
	t = cuddBddAndAbstractRecurTime(manager, ft, gt, cube, pRecCalls, TimeOut);
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddBddAndAbstractRecurTime(manager, fe, ge, cube, pRecCalls, TimeOut);
	if (e == NULL) {
	    Cudd_IterDerefBdd(manager, t);
	    return(NULL);
	}
	if (t == e) {
	    r = t;
	    cuddDeref(t);
	} else {
	    cuddRef(e);
	    if (Cudd_IsComplement(t)) {
		r = cuddUniqueInter(manager, (int) index,
				    Cudd_Not(t), Cudd_Not(e));
		if (r == NULL) {
		    Cudd_IterDerefBdd(manager, t);
		    Cudd_IterDerefBdd(manager, e);
		    return(NULL);
		}
		r = Cudd_Not(r);
	    } else {
		r = cuddUniqueInter(manager,(int)index,t,e);
		if (r == NULL) {
		    Cudd_IterDerefBdd(manager, t);
		    Cudd_IterDerefBdd(manager, e);
		    return(NULL);
		}
	    }
	    cuddDeref(e);
	    cuddDeref(t);
	}
    }

    if (F->ref != 1 || G->ref != 1)
	cuddCacheInsert(manager, DD_BDD_AND_ABSTRACT_TAG, f, g, cube, r);
    return (r);

} /* end of cuddBddAndAbstractRecur */
示例#4
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addCompose.]

  Description [Performs the recursive step of Cudd_addCompose.
  Returns the composed BDD if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addCompose]

******************************************************************************/
DdNode *
cuddAddComposeRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * proj)
{
    DdNode *f1, *f0, *g1, *g0, *r, *t, *e;
    unsigned int v, topf, topg, topindex;

    statLine(dd);
    v = dd->perm[proj->index];
    topf = cuddI(dd,f->index);

    /* Terminal case. Subsumes the test for constant f. */
    if (topf > v) return(f);

    /* Check cache. */
    r = cuddCacheLookup(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj);
    if (r != NULL) {
	return(r);
    }

    if (topf == v) {
	/* Compose. */
	f1 = cuddT(f);
	f0 = cuddE(f);
	r = cuddAddIteRecur(dd, g, f1, f0);
	if (r == NULL) return(NULL);
    } else {
	/* Compute cofactors of f and g. Remember the index of the top
	** variable.
	*/
	topg = cuddI(dd,g->index);
	if (topf > topg) {
	    topindex = g->index;
	    f1 = f0 = f;
	} else {
	    topindex = f->index;
	    f1 = cuddT(f);
	    f0 = cuddE(f);
	}
	if (topg > topf) {
	    g1 = g0 = g;
	} else {
	    g1 = cuddT(g);
	    g0 = cuddE(g);
	}
	/* Recursive step. */
	t = cuddAddComposeRecur(dd, f1, g1, proj);
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddAddComposeRecur(dd, f0, g0, proj);
	if (e == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    return(NULL);
	}
	cuddRef(e);

	if (t == e) {
	    r = t;
	} else {
	    r = cuddUniqueInter(dd, (int) topindex, t, e);
	    if (r == NULL) {
		Cudd_RecursiveDeref(dd, t);
		Cudd_RecursiveDeref(dd, e);
		return(NULL);
	    }
	}
	cuddDeref(t);
	cuddDeref(e);
    }

    cuddCacheInsert(dd,DD_ADD_COMPOSE_RECUR_TAG,f,g,proj,r);

    return(r);

} /* end of cuddAddComposeRecur */
示例#5
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddIte.]

  Description [Implements the recursive step of Cudd_bddIte. Returns a
  pointer to the resulting BDD. NULL if the intermediate result blows
  up or if reordering occurs.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
DdNode *
cuddBddIteRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * h)
{
    DdNode	 *one, *zero, *res;
    DdNode	 *r, *Fv, *Fnv, *Gv, *Gnv, *H, *Hv, *Hnv, *t, *e;
    unsigned int topf, topg, toph, v;
    int		 index;
    int		 comple;

    statLine(dd);
    /* Terminal cases. */

    /* One variable cases. */
    if (f == (one = DD_ONE(dd))) 	/* ITE(1,G,H) = G */
	return(g);
    
    if (f == (zero = Cudd_Not(one))) 	/* ITE(0,G,H) = H */
	return(h);
    
    /* From now on, f is known not to be a constant. */
    if (g == one || f == g) {	/* ITE(F,F,H) = ITE(F,1,H) = F + H */
	if (h == zero) {	/* ITE(F,1,0) = F */
	    return(f);
	} else {
	    res = cuddBddAndRecur(dd,Cudd_Not(f),Cudd_Not(h));
	    return(Cudd_NotCond(res,res != NULL));
	}
    } else if (g == zero || f == Cudd_Not(g)) { /* ITE(F,!F,H) = ITE(F,0,H) = !F * H */
	if (h == one) {		/* ITE(F,0,1) = !F */
	    return(Cudd_Not(f));
	} else {
	    res = cuddBddAndRecur(dd,Cudd_Not(f),h);
	    return(res);
	}
    }
    if (h == zero || f == h) {    /* ITE(F,G,F) = ITE(F,G,0) = F * G */
	res = cuddBddAndRecur(dd,f,g);
	return(res);
    } else if (h == one || f == Cudd_Not(h)) { /* ITE(F,G,!F) = ITE(F,G,1) = !F + G */
	res = cuddBddAndRecur(dd,f,Cudd_Not(g));
	return(Cudd_NotCond(res,res != NULL));
    }

    /* Check remaining one variable case. */
    if (g == h) { 		/* ITE(F,G,G) = G */
	return(g);
    } else if (g == Cudd_Not(h)) { /* ITE(F,G,!G) = F <-> G */
	res = cuddBddXorRecur(dd,f,h);
	return(res);
    }
    
    /* From here, there are no constants. */
    comple = bddVarToCanonicalSimple(dd, &f, &g, &h, &topf, &topg, &toph);

    /* f & g are now regular pointers */

    v = ddMin(topg, toph);

    /* A shortcut: ITE(F,G,H) = (v,G,H) if F = (v,1,0), v < top(G,H). */
    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
	r = cuddUniqueInter(dd, (int) f->index, g, h);
	return(Cudd_NotCond(r,comple && r != NULL));
    }

    /* Check cache. */
    r = cuddCacheLookup(dd, DD_BDD_ITE_TAG, f, g, h);
    if (r != NULL) {
	return(Cudd_NotCond(r,comple));
    }

    /* Compute cofactors. */
    if (topf <= v) {
	v = ddMin(topf, v);	/* v = top_var(F,G,H) */
	index = f->index;
	Fv = cuddT(f); Fnv = cuddE(f);
    } else {
	Fv = Fnv = f;
    }
    if (topg == v) {
	index = g->index;
	Gv = cuddT(g); Gnv = cuddE(g);
    } else {
	Gv = Gnv = g;
    }
    if (toph == v) {
	H = Cudd_Regular(h);
	index = H->index;
	Hv = cuddT(H); Hnv = cuddE(H);
	if (Cudd_IsComplement(h)) {
	    Hv = Cudd_Not(Hv);
	    Hnv = Cudd_Not(Hnv);
	}
    } else {
	Hv = Hnv = h;
    }

    /* Recursive step. */
    t = cuddBddIteRecur(dd,Fv,Gv,Hv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddBddIteRecur(dd,Fnv,Gnv,Hnv);
    if (e == NULL) {
	Cudd_IterDerefBdd(dd,t);
	return(NULL);
    }
    cuddRef(e);

    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
    if (r == NULL) {
	Cudd_IterDerefBdd(dd,t);
	Cudd_IterDerefBdd(dd,e);
	return(NULL);
    }
    cuddDeref(t);
    cuddDeref(e);

    cuddCacheInsert(dd, DD_BDD_ITE_TAG, f, g, h, r);
    return(Cudd_NotCond(r,comple));

} /* end of cuddBddIteRecur */
示例#6
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addNonSimCompose.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddAddNonSimComposeRecur(
  DdManager * dd,
  DdNode * f,
  DdNode ** vector,
  DdNode * key,
  DdNode * cube,
  int  lastsub)
{
    DdNode *f1, *f0, *key1, *key0, *cube1, *var;
    DdNode *T,*E;
    DdNode *r;
    unsigned int top, topf, topk, topc;
    unsigned int index;
    int i;
    DdNode **vect1;
    DdNode **vect0;

    statLine(dd);
    /* If we are past the deepest substitution, return f. */
    if (cube == DD_ONE(dd) || cuddIsConstant(f)) {
	return(f);
    }

    /* If problem already solved, look up answer and return. */
    r = cuddCacheLookup(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube);
    if (r != NULL) {
	return(r);
    }

    /* Find top variable. we just need to look at f, key, and cube,
    ** because all the varibles in the gi are in key.
    */
    topf = cuddI(dd,f->index);
    topk = cuddI(dd,key->index);
    top = ddMin(topf,topk);
    topc = cuddI(dd,cube->index);
    top = ddMin(top,topc);
    index = dd->invperm[top];

    /* Compute the cofactors. */
    if (topf == top) {
	f1 = cuddT(f);
	f0 = cuddE(f);
    } else {
	f1 = f0 = f;
    }
    if (topc == top) {
	cube1 = cuddT(cube);
	/* We want to eliminate vector[index] from key. Otherwise
	** cache performance is severely affected. Hence we
	** existentially quantify the variable with index "index" from key.
	*/
	var = Cudd_addIthVar(dd, (int) index);
	if (var == NULL) {
	    return(NULL);
	}
	cuddRef(var);
	key1 = cuddAddExistAbstractRecur(dd, key, var);
	if (key1 == NULL) {
	    Cudd_RecursiveDeref(dd,var);
	    return(NULL);
	}
	cuddRef(key1);
	Cudd_RecursiveDeref(dd,var);
	key0 = key1;
    } else {
	cube1 = cube;
	if (topk == top) {
	    key1 = cuddT(key);
	    key0 = cuddE(key);
	} else {
	    key1 = key0 = key;
	}
	cuddRef(key1);
    }

    /* Allocate two new vectors for the cofactors of vector. */
    vect1 = ALLOC(DdNode *,lastsub);
    if (vect1 == NULL) {
	dd->errorCode = CUDD_MEMORY_OUT;
	Cudd_RecursiveDeref(dd,key1);
	return(NULL);
    }
    vect0 = ALLOC(DdNode *,lastsub);
    if (vect0 == NULL) {
	dd->errorCode = CUDD_MEMORY_OUT;
	Cudd_RecursiveDeref(dd,key1);
	FREE(vect1);
	return(NULL);
    }

    /* Cofactor the gi. Eliminate vect1[index] and vect0[index], because
    ** we do not need them.
    */
    for (i = 0; i < lastsub; i++) {
	DdNode *gi = vector[i];
	if (gi == NULL) {
	    vect1[i] = vect0[i] = NULL;
	} else if (gi->index == index) {
	    vect1[i] = cuddT(gi);
	    vect0[i] = cuddE(gi);
	} else {
	    vect1[i] = vect0[i] = gi;
	}
    }
    vect1[index] = vect0[index] = NULL;

    /* Recur on children. */
    T = cuddAddNonSimComposeRecur(dd,f1,vect1,key1,cube1,lastsub);
    FREE(vect1);
    if (T == NULL) {
	Cudd_RecursiveDeref(dd,key1);
	FREE(vect0);
	return(NULL);
    }
    cuddRef(T);
    E = cuddAddNonSimComposeRecur(dd,f0,vect0,key0,cube1,lastsub);
    FREE(vect0);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,key1);
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);
    Cudd_RecursiveDeref(dd,key1);

    /* Retrieve the 0-1 ADD for the current top variable from vector,
    ** and call cuddAddIteRecur with the T and E we just created.
    */
    r = cuddAddIteRecur(dd,vector[index],T,E);
    if (r == NULL) {
	Cudd_RecursiveDeref(dd,T);
	Cudd_RecursiveDeref(dd,E);
	return(NULL);
    }
    cuddRef(r);
    Cudd_RecursiveDeref(dd,T);
    Cudd_RecursiveDeref(dd,E);
    cuddDeref(r);

    /* Store answer to trim recursion. */
    cuddCacheInsert(dd,DD_ADD_NON_SIM_COMPOSE_TAG,f,key,cube,r);

    return(r);

} /* end of cuddAddNonSimComposeRecur */
示例#7
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddCompose.]

  Description [Performs the recursive step of Cudd_bddCompose.
  Exploits the fact that the composition of f' with g
  produces the complement of the composition of f with g to better
  utilize the cache.  Returns the composed BDD if successful; NULL
  otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddCompose]

******************************************************************************/
DdNode *
cuddBddComposeRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * proj)
{
    DdNode	*F, *G, *f1, *f0, *g1, *g0, *r, *t, *e;
    unsigned int v, topf, topg, topindex;
    int		comple;

    statLine(dd);
    v = dd->perm[proj->index];
    F = Cudd_Regular(f);
    topf = cuddI(dd,F->index);

    /* Terminal case. Subsumes the test for constant f. */
    if (topf > v) return(f);

    /* We solve the problem for a regular pointer, and then complement
    ** the result if the pointer was originally complemented.
    */
    comple = Cudd_IsComplement(f);

    /* Check cache. */
    r = cuddCacheLookup(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj);
    if (r != NULL) {
	return(Cudd_NotCond(r,comple));
    }

    if (topf == v) {
	/* Compose. */
	f1 = cuddT(F);
	f0 = cuddE(F);
	r = cuddBddIteRecur(dd, g, f1, f0);
	if (r == NULL) return(NULL);
    } else {
	/* Compute cofactors of f and g. Remember the index of the top
	** variable.
	*/
	G = Cudd_Regular(g);
	topg = cuddI(dd,G->index);
	if (topf > topg) {
	    topindex = G->index;
	    f1 = f0 = F;
	} else {
	    topindex = F->index;
	    f1 = cuddT(F);
	    f0 = cuddE(F);
	}
	if (topg > topf) {
	    g1 = g0 = g;
	} else {
	    g1 = cuddT(G);
	    g0 = cuddE(G);
	    if (g != G) {
		g1 = Cudd_Not(g1);
		g0 = Cudd_Not(g0);
	    }
	}
	/* Recursive step. */
	t = cuddBddComposeRecur(dd, f1, g1, proj);
	if (t == NULL) return(NULL);
	cuddRef(t);
	e = cuddBddComposeRecur(dd, f0, g0, proj);
	if (e == NULL) {
	    Cudd_IterDerefBdd(dd, t);
	    return(NULL);
	}
	cuddRef(e);

	r = cuddBddIteRecur(dd, dd->vars[topindex], t, e);
	if (r == NULL) {
	    Cudd_IterDerefBdd(dd, t);
	    Cudd_IterDerefBdd(dd, e);
	    return(NULL);
	}
	cuddRef(r);
	Cudd_IterDerefBdd(dd, t); /* t & e not necessarily part of r */
	Cudd_IterDerefBdd(dd, e);
	cuddDeref(r);
    }

    cuddCacheInsert(dd,DD_BDD_COMPOSE_RECUR_TAG,F,g,proj,r);

    return(Cudd_NotCond(r,comple));

} /* end of cuddBddComposeRecur */
示例#8
0
文件: cuddAddIte.c 项目: maeon/SBSAT
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_addIte(f,g,h).]

  Description [Implements the recursive step of Cudd_addIte(f,g,h).
  Returns a pointer to the resulting ADD if successful; NULL
  otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addIte]

******************************************************************************/
DdNode *
cuddAddIteRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  DdNode * h)
{
    DdNode *one,*zero;
    DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
    unsigned int topf,topg,toph,v;
    int index;

    statLine(dd);
    /* Trivial cases. */

    /* One variable cases. */
    if (f == (one = DD_ONE(dd))) {	/* ITE(1,G,H) = G */
        return(g);
    }
    if (f == (zero = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
        return(h);
    }

    /* From now on, f is known to not be a constant. */
    addVarToConst(f,&g,&h,one,zero);

    /* Check remaining one variable cases. */
    if (g == h) {			/* ITE(F,G,G) = G */
        return(g);
    }

    if (g == one) {			/* ITE(F,1,0) = F */
        if (h == zero) return(f);
    }

    topf = cuddI(dd,f->index);
    topg = cuddI(dd,g->index);
    toph = cuddI(dd,h->index);
    v = ddMin(topg,toph);

    /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
	r = cuddUniqueInter(dd,(int)f->index,g,h);
	return(r);
    }
    if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
	r = cuddUniqueInter(dd,(int)f->index,h,g);
	return(r);
    }

    /* Check cache. */
    r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
    if (r != NULL) {
        return(r);
    }

    /* Compute cofactors. */
    if (topf <= v) {
	v = ddMin(topf,v);	/* v = top_var(F,G,H) */
	index = f->index;
        Fv = cuddT(f); Fnv = cuddE(f);
    } else {
        Fv = Fnv = f;
    }
    if (topg == v) {
	index = g->index;
        Gv = cuddT(g); Gnv = cuddE(g);
    } else {
        Gv = Gnv = g;
    }
    if (toph == v) {
	index = h->index;
        Hv = cuddT(h); Hnv = cuddE(h);
    } else {
        Hv = Hnv = h;
    }
    
    /* Recursive step. */
    t = cuddAddIteRecur(dd,Fv,Gv,Hv);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd,t);
	return(NULL);
    }
    cuddRef(e);

    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
    if (r == NULL) {
	Cudd_RecursiveDeref(dd,t);
	Cudd_RecursiveDeref(dd,e);
	return(NULL);
    }
    cuddDeref(t);
    cuddDeref(e);

    cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);

    return(r);

} /* end of cuddAddIteRecur */
示例#9
0
/**Function********************************************************************

  Synopsis [Approximates the AND of two BDDs and simultaneously abstracts the
  variables in cube.]

  Description [Approximates the AND of two BDDs and simultaneously
  abstracts the variables in cube. The variables are existentially
  abstracted.  Returns a pointer to the result is successful; NULL
  otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_bddClippingAndAbstract]

******************************************************************************/
static DdNode *
cuddBddClipAndAbsRecur(
  DdManager * manager,
  DdNode * f,
  DdNode * g,
  DdNode * cube,
  int  distance,
  int  direction)
{
    DdNode *F, *ft, *fe, *G, *gt, *ge;
    DdNode *one, *zero, *r, *t, *e, *Cube;
    unsigned int topf, topg, topcube, top, index;
    ptruint cacheTag;

    statLine(manager);
    one = DD_ONE(manager);
    zero = Cudd_Not(one);

    /* Terminal cases. */
    if (f == zero || g == zero || f == Cudd_Not(g)) return(zero);
    if (f == one && g == one)   return(one);
    if (cube == one) {
        return(cuddBddClippingAndRecur(manager, f, g, distance, direction));
    }
    if (f == one || f == g) {
        return (cuddBddExistAbstractRecur(manager, g, cube));
    }
    if (g == one) {
        return (cuddBddExistAbstractRecur(manager, f, cube));
    }
    if (distance == 0) return(Cudd_NotCond(one,(direction == 0)));

    /* At this point f, g, and cube are not constant. */
    distance--;

    /* Check cache. */
    if (f > g) { /* Try to increase cache efficiency. */
        DdNode *tmp = f;
        f = g; g = tmp;
    }
    F = Cudd_Regular(f);
    G = Cudd_Regular(g);
    cacheTag = direction ? DD_BDD_CLIPPING_AND_ABSTRACT_UP_TAG :
        DD_BDD_CLIPPING_AND_ABSTRACT_DOWN_TAG;
    if (F->ref != 1 || G->ref != 1) {
        r = cuddCacheLookup(manager, cacheTag,
                            f, g, cube);
        if (r != NULL) {
            return(r);
        }
    }

    /* Here we can skip the use of cuddI, because the operands are known
    ** to be non-constant.
    */
    topf = manager->perm[F->index];
    topg = manager->perm[G->index];
    top = ddMin(topf, topg);
    topcube = manager->perm[cube->index];

    if (topcube < top) {
        return(cuddBddClipAndAbsRecur(manager, f, g, cuddT(cube),
                                      distance, direction));
    }
    /* Now, topcube >= top. */

    if (topf == top) {
        index = F->index;
        ft = cuddT(F);
        fe = cuddE(F);
        if (Cudd_IsComplement(f)) {
            ft = Cudd_Not(ft);
            fe = Cudd_Not(fe);
        }
    } else {
        index = G->index;
        ft = fe = f;
    }

    if (topg == top) {
        gt = cuddT(G);
        ge = cuddE(G);
        if (Cudd_IsComplement(g)) {
            gt = Cudd_Not(gt);
            ge = Cudd_Not(ge);
        }
    } else {
        gt = ge = g;
    }

    if (topcube == top) {
        Cube = cuddT(cube);
    } else {
        Cube = cube;
    }

    t = cuddBddClipAndAbsRecur(manager, ft, gt, Cube, distance, direction);
    if (t == NULL) return(NULL);

    /* Special case: 1 OR anything = 1. Hence, no need to compute
    ** the else branch if t is 1.
    */
    if (t == one && topcube == top) {
        if (F->ref != 1 || G->ref != 1)
            cuddCacheInsert(manager, cacheTag, f, g, cube, one);
        return(one);
    }
    cuddRef(t);

    e = cuddBddClipAndAbsRecur(manager, fe, ge, Cube, distance, direction);
    if (e == NULL) {
        Cudd_RecursiveDeref(manager, t);
        return(NULL);
    }
    cuddRef(e);

    if (topcube == top) {       /* abstract */
        r = cuddBddClippingAndRecur(manager, Cudd_Not(t), Cudd_Not(e),
                                    distance, (direction == 0));
        if (r == NULL) {
            Cudd_RecursiveDeref(manager, t);
            Cudd_RecursiveDeref(manager, e);
            return(NULL);
        }
        r = Cudd_Not(r);
        cuddRef(r);
        Cudd_RecursiveDeref(manager, t);
        Cudd_RecursiveDeref(manager, e);
        cuddDeref(r);
    } else if (t == e) {
        r = t;
        cuddDeref(t);
        cuddDeref(e);
    } else {
        if (Cudd_IsComplement(t)) {
            r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e));
            if (r == NULL) {
                Cudd_RecursiveDeref(manager, t);
                Cudd_RecursiveDeref(manager, e);
                return(NULL);
            }
            r = Cudd_Not(r);
        } else {
            r = cuddUniqueInter(manager,(int)index,t,e);
            if (r == NULL) {
                Cudd_RecursiveDeref(manager, t);
                Cudd_RecursiveDeref(manager, e);
                return(NULL);
            }
        }
        cuddDeref(e);
        cuddDeref(t);
    }
    if (F->ref != 1 || G->ref != 1)
        cuddCacheInsert(manager, cacheTag, f, g, cube, r);
    return (r);

} /* end of cuddBddClipAndAbsRecur */
示例#10
0
DdNode *
cuddAddTernaryApplyWithDataRecur(
  DdManager * dd,
  DD_TAOPD op,
  DdNode * f,
  DdNode * g,
  DdNode * h,
  void * data)
{
    DdNode *res,
	   *fv, *fvn, *gv, *gvn, *hv, *hvn,
	   *T, *E;
    unsigned int ford, gord, hord;
    unsigned int index;
    ptruint cacheOp;

    /* Check terminal cases. Op may swap f and g to increase the
     * cache hit rate.
     */
    statLine(dd);
    res = (*op)(dd,&f,&g,&h, data);
    if (res != NULL) return(res);

    /* Check cache. */
    cacheOp = (ptruint)global_bloody_counter_ternary;
    res = cuddCacheLookup(dd,cacheOp,f,g,h);
    if (res != NULL) return(res);

    /* Recursive step. */
    ford = cuddI(dd,f->index);
    gord = cuddI(dd,g->index);
    hord = cuddI(dd,h->index);

    if ((ford <= gord) && (ford <= hord)) {
	index = f->index;
	fv = cuddT(f);
	fvn = cuddE(f);
    } else {
	fv = fvn = f;
    }

    if ((gord <= ford) && (gord <= hord)) {
	index = g->index;
	gv = cuddT(g);
	gvn = cuddE(g);
    } else {
	gv = gvn = g;
    }

    if ((hord <= ford) && (hord <= gord)) {
	index = h->index;
	hv = cuddT(h);
	hvn = cuddE(h);
    } else {
	hv = hvn = h;
    }

    T = cuddAddTernaryApplyWithDataRecur(dd,op,fv,gv,hv, data);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = cuddAddTernaryApplyWithDataRecur(dd,op,fvn,gvn,hvn, data);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);

    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd, T);
	Cudd_RecursiveDeref(dd, E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert(dd,cacheOp,f,g,h,res);

    return(res);

} /* end of cuddAddTernaryApplyWithDataRecur */
示例#11
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addOuterSum.]

  Description [Performs the recursive step of Cudd_addOuterSum.
  Returns a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddAddOuterSumRecur(
    DdManager *dd,
    DdNode *M,
    DdNode *r,
    DdNode *c)
{
    DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
    int topM, topc, topr;
    int v, index;

    statLine(dd);
    /* Check special cases. */
    if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M);

    if (cuddIsConstant(c) && cuddIsConstant(r)) {
        R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
        cuddRef(R);
        if (cuddIsConstant(M)) {
            if (cuddV(R) <= cuddV(M)) {
                cuddDeref(R);
                return(R);
            } else {
                Cudd_RecursiveDeref(dd,R);
                return(M);
            }
        } else {
            P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
            cuddRef(P);
            Cudd_RecursiveDeref(dd,R);
            cuddDeref(P);
            return(P);
        }
    }

    /* Check the cache. */
    R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
    if (R != NULL) return(R);

    topM = cuddI(dd,M->index);
    topr = cuddI(dd,r->index);
    topc = cuddI(dd,c->index);
    v = ddMin(topM,ddMin(topr,topc));

    /* Compute cofactors. */
    if (topM == v) {
        Mt = cuddT(M);
        Me = cuddE(M);
    }
    else {
        Mt = Me = M;
    }
    if (topr == v) {
        rt = cuddT(r);
        re = cuddE(r);
    }
    else {
        rt = re = r;
    }
    if (topc == v) {
        ct = cuddT(c);
        ce = cuddE(c);
    }
    else {
        ct = ce = c;
    }

    /* Recursively solve. */
    Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
    if (Rt == NULL) return(NULL);
    cuddRef(Rt);
    Re = cuddAddOuterSumRecur(dd,Me,re,ce);
    if (Re == NULL) {
        Cudd_RecursiveDeref(dd, Rt);
        return(NULL);
    }
    cuddRef(Re);
    index = dd->invperm[v];
    R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
    if (R == NULL) {
        Cudd_RecursiveDeref(dd, Rt);
        Cudd_RecursiveDeref(dd, Re);
        return(NULL);
    }
    cuddDeref(Rt);
    cuddDeref(Re);

    /* Store the result in the cache. */
    cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R);

    return(R);

} /* end of cuddAddOuterSumRecur */
示例#12
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_addIteGeneral(f,g,h).]

  Description [Implements the recursive step of Cudd_addIteGeneral(f,g,h),
  meaning that g and h are not supposed to be 0-1 ADDs but may have more terminals.
  Applying arithmetic addition in the terminal case. Returns a pointer to the 
  resulting ADD if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addIte]

******************************************************************************/
DdNode * extraAddIteRecurGeneral( DdManager * dd, DdNode * bX, DdNode * aF, DdNode * aG )
{
	DdNode * aRes;
	statLine( dd );

	assert( !Cudd_IsConstant(bX) );
	assert(  cuddE(bX) == b0 && cuddT(bX) == b1 ); /* the elementary variable */

    /* check cache */
    if ( aRes = cuddCacheLookup(dd, DD_ADD_ITE_GENERAL_TAG, bX, aF, aG) )
    	return aRes;
	else
	{
		DdNode * aF0, * aF1, * aG0, * aG1;
		int LevelF, LevelG, LevelX, LevelTop;

		LevelF = cuddI(dd,aF->index);
		LevelG = cuddI(dd,aG->index);
		LevelX = dd->perm[bX->index];
		LevelTop = ddMin(LevelF, LevelG);
		LevelTop = ddMin(LevelX, LevelTop);

		if ( LevelF == LevelTop )
		{
			aF0 = cuddE(aF);
			aF1 = cuddT(aF);
		}
		else
			aF0 = aF1 = aF;

		if ( LevelG == LevelTop )
		{
			aG0 = cuddE(aG);
			aG1 = cuddT(aG);
		}
		else
			aG0 = aG1 = aG;

		if ( LevelX == LevelTop )
		{
			assert( LevelX < LevelF );
			assert( LevelX < LevelG );

			/* consider the case when Res0 and Res1 are the same node */
			aRes = (aF == aG) ? aF : cuddUniqueInter( dd, bX->index, aF, aG );
			if (aRes == NULL) 
				return NULL;
		}
		else
		{
			DdNode * aRes0,  * aRes1;     /* partial results to be composed by ITE */

			aRes0  = extraAddIteRecurGeneral( dd, bX, aF0, aG0 );
			if ( aRes0 == NULL )
				return NULL;
			cuddRef( aRes0 );

			aRes1  = extraAddIteRecurGeneral( dd, bX, aF1, aG1 );
			if ( aRes1 == NULL )
			{
				Cudd_RecursiveDeref(dd, aRes0);
				return NULL;
			}
			cuddRef( aRes1 );

			/* only aRes0 and aRes1 are referenced at this point */

			/* consider the case when Res0 and Res1 are the same node */
			aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, dd->invperm[LevelTop], aRes1, aRes0 );
			if (aRes == NULL) 
			{
				Cudd_RecursiveDeref(dd, aRes1);
				Cudd_RecursiveDeref(dd, aRes0);
				return NULL;
			}
			cuddDeref(aRes1);
			cuddDeref(aRes0);
		}

		cuddCacheInsert( dd, DD_ADD_ITE_GENERAL_TAG, bX, aF, aG, aRes );
		return aRes;
	}
}	/* end of extraAddIteRecurGeneral */
示例#13
0
/**Function********************************************************************

  Synopsis    [Replaces the negative variable assignment node in the ADD by the given value.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode * extraAddUpdateZeroCubeValue(
  DdManager * dd, 
  DdNode * aFunc,    /* the ADD to be updated */
  DdNode * bVars,
  DdNode * aNode )  /* the terminal node representing the required value */
{
	DdNode * aRes;
    statLine(dd); 

	/* terminal cases */
	if ( bVars == b1 )
	{
		assert( Cudd_IsConstant(aFunc) );
		return aNode;
	}

    /* check cache */
    if ( aRes = cuddCacheLookup(dd, DD_ADD_UPDATE_ZERO_CUBE_TAG, aFunc, bVars, aNode) )
	{ 
		s_CacheHit++;
   		return aRes;
	}
	else
	{
		DdNode * aFunc0, * aFunc1;    /* cofactors */
		DdNode * aRes0,  * aRes1;     /* partial results to be composed by ITE */

		s_CacheMiss++;

		if ( aFunc->index == bVars->index )
		{
			aFunc0 = cuddE( aFunc );
			aFunc1 = cuddT( aFunc );
		}
		else
			aFunc0 = aFunc1 = aFunc;


		aRes0  = extraAddUpdateZeroCubeValue( dd, aFunc0, cuddT(bVars), aNode );
		if ( aRes0 == NULL )
			return NULL;
		cuddRef( aRes0 );

		aRes1 = aFunc1;
//		cuddRef( aRes1 );

		/* only aRes0 and aRes1 are referenced at this point */

		/* consider the case when Res0 and Res1 are the same node */
		aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, bVars->index, aRes1, aRes0 );
		if (aRes == NULL) 
		{
//			Cudd_RecursiveDeref(dd, aRes1);
			Cudd_RecursiveDeref(dd, aRes0);
			return NULL;
		}
//		cuddDeref(aRes1);
		cuddDeref(aRes0);

		/* insert the result into cache */
		cuddCacheInsert(dd, DD_ADD_UPDATE_ZERO_CUBE_TAG, aFunc, bVars, aNode, aRes);
		return aRes;
	}
} /* end of extraAddUpdateZeroCubeValue */
示例#14
0
/**Function********************************************************************

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

  Description [Generates in a bottom-up fashion an ADD for the inverse Haar.]

  SideEffects [The third cached argument (bSteps) is the BDD of the elementary variable
  whose index equal to the number of lazy steps made thus far plus one. On the top-most
  level it is 0, next it is 1, etc.]

  SeeAlso     []

******************************************************************************/
DdNode * extraBddHaarInverse( 
  DdManager * dd,    /* the manager */
  DdNode * aFunc,    /* the function whose spectrum is being computed */
  DdNode * aSteps,   /* the index of this variable indicates the number of previous lazy recursive calls */
  DdNode * bVars,    /* the variables, on which the function depends */
  DdNode * bVarsAll, /* the set of all variables, which will never change through the calls */
  int      nVarsAll, /* the number of vars in the set */
  int    * InverseMap ) /* the variable map mapping the var index into its inverse var index */
{
	DdNode * aRes;
	DdNode * bCacheCube;
    statLine(dd); 

	/* terminal cases */
	if ( bVars == b1 )
	{ // return a terminal node with a value equal to cuddV(aFunc) * 2^(nSteps-1)
		if ( cuddV(aSteps) == 0.0 )
			return cuddUniqueConst( dd, cuddV(aFunc) ); 
		else
			return cuddUniqueConst( dd, cuddV(aFunc) * Extra_Power2( (int)(cuddV(aSteps)-1) ) ); 
	}

    /* check cache */
    /* the last two arguments are derivitives, therefore there are useless for caching */
	/* the other two arguments (bVars and bVarsAll) can be combined into one argument */
	bCacheCube = extraCachingCube( dd, bVarsAll, bVars );  Cudd_Ref( bCacheCube );
    if ( aRes = cuddCacheLookup(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube) )
	{
		Cudd_RecursiveDeref( dd, bCacheCube );
   		return aRes;
	}
	else
	{
		DdNode * aFunc0, * aFunc1;   /* cofactors of the function */
		DdNode * aInvH0, * aInvH1;   /* partial solutions of the problem */
		DdNode * aRes0,  * aRes1;    /* partial results to be composed by ITE */
		DdNode * aStepNext;

		/* aFunc cannot depend on a variable that is not in bVars */
		assert( cuddI(dd,aFunc->index) >= cuddI(dd,bVars->index) );

		/* cofactor the ADD */
		if ( aFunc->index == bVars->index )
		{
			aFunc0 = cuddE(aFunc);
			aFunc1 = cuddT(aFunc);
		}
		else /* bVars is higher in the variable order */
			aFunc0 = aFunc1 = aFunc;


		if ( cuddV(aSteps) > 0.0 ) /* meaning that it is a lazy call */
		{
			/* solve subproblems */
			aStepNext = cuddUniqueConst( dd, cuddV(aSteps)+1 );
			if ( aStepNext == NULL )
				return NULL;
			cuddRef( aStepNext );

			aInvH0 = extraBddHaarInverse( dd, aFunc0, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH0 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				return NULL;
			}
			cuddRef( aInvH0 );

			aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aInvH1 );
			Cudd_RecursiveDeref( dd, aStepNext );

			aRes0 = aInvH0;
			aRes1 = aInvH1;
		}
		else // if ( cuddV(aSteps) == 0.0 )
		{
			/* solve subproblems */
			aInvH0 = extraBddHaarInverse( dd, aFunc0, aSteps, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH0 == NULL )
				return NULL;
			cuddRef( aInvH0 );

			aStepNext = cuddUniqueConst( dd, 1.0 );
			if ( aStepNext == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aStepNext );

			aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aInvH1 );
			Cudd_RecursiveDeref( dd, aStepNext );


			/* compute  aRes0 = aWalsh0 + aWalsh1 */
			aRes0 = cuddAddApplyRecur( dd, Cudd_addPlus, aInvH0, aInvH1 );
			if ( aRes0 == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				Cudd_RecursiveDeref( dd, aInvH1 );
				return NULL;
			}
			cuddRef( aRes0 );

			/* compute  aRes1 = aWalsh0 - aWalsh1 */
			aRes1 = cuddAddApplyRecur( dd, Cudd_addMinus, aInvH0, aInvH1 );
			if ( aRes1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				Cudd_RecursiveDeref( dd, aInvH1 );
				Cudd_RecursiveDeref( dd, aRes0 );
				return NULL;
			}
			cuddRef( aRes1 );

			Cudd_RecursiveDeref(dd, aInvH0);
			Cudd_RecursiveDeref(dd, aInvH1);
		}

		/* only aRes0 and aRes1 are referenced at this point */

		/* consider the case when Res0 and Res1 are the same node */
		aRes = extraAddIteRecurGeneral( dd, dd->vars[ InverseMap[bVars->index] ], aRes1, aRes0 );
		if (aRes == NULL) 
		{
			Cudd_RecursiveDeref(dd, aRes1);
			Cudd_RecursiveDeref(dd, aRes0);
			return NULL;
		}
		cuddRef( aRes );
		Cudd_RecursiveDeref(dd, aRes1);
		Cudd_RecursiveDeref(dd, aRes0);
		cuddDeref( aRes );

		/* insert the result into cache */
		cuddCacheInsert(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube, aRes);
		Cudd_RecursiveDeref( dd, bCacheCube );
		return aRes;
	}
} /* end of extraBddHaarInverse */