//.........这里部分代码省略.........
for (i = 0; i < dd->size; i++) {
if (vars[i]) {
if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
scale *= 2;
}
}
}
if (scale > 1.0) {
cuddRef(res);
add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
if (add_scale == NULL) {
Cudd_RecursiveDeref(dd, res);
return(NULL);
}
cuddRef(add_scale);
scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
if (scaled == NULL) {
Cudd_RecursiveDeref(dd, add_scale);
Cudd_RecursiveDeref(dd, res);
return(NULL);
}
cuddRef(scaled);
Cudd_RecursiveDeref(dd, add_scale);
Cudd_RecursiveDeref(dd, res);
res = scaled;
cuddDeref(res);
}
return(res);
}
/* compute the cofactors */
if (topV == topA) {
At = cuddT(A);
Ae = cuddE(A);
} else {
At = Ae = A;
}
if (topV == topB) {
Bt = cuddT(B);
Be = cuddE(B);
} else {
Bt = Be = B;
}
t = addMMRecur(dd, At, Bt, (int)topV, vars);
if (t == NULL) return(NULL);
cuddRef(t);
e = addMMRecur(dd, Ae, Be, (int)topV, vars);
if (e == NULL) {
Cudd_RecursiveDeref(dd, t);
return(NULL);
}
cuddRef(e);
index = dd->invperm[topV];
if (vars[index] == 0) {
/* We have split on either the rows of A or the columns
** of B. We just need to connect the two subresults,
** which correspond to two submatrices of the result.
*/
res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
if (res == NULL) {
Cudd_RecursiveDeref(dd, t);
Cudd_RecursiveDeref(dd, e);
return(NULL);
}
开发者ID:maeon,项目名称:SBSAT,代码行数:67,代码来源:cuddMatMult.c
示例3: cuddAddOuterSumRecur
/**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 */
开发者ID:maeon,项目名称:SBSAT,代码行数:86,代码来源:cuddMatMult.c
示例4: Cudd_DelayedDerefBdd
/**Function********************************************************************
Synopsis [Decreases the reference count of BDD node n.]
Description [Enqueues node n for later dereferencing. If the queue
is full decreases the reference count of the oldest node N to make
room for n. If N dies, recursively decreases the reference counts of
its children. It is used to dispose of a BDD that is currently not
needed, but may be useful again in the near future. The dereferencing
proper is done as in Cudd_IterDerefBdd.]
SideEffects [None]
SeeAlso [Cudd_RecursiveDeref Cudd_IterDerefBdd]
******************************************************************************/
void
Cudd_DelayedDerefBdd(
DdManager * table,
DdNode * n)
{
DdNode *N;
int ord;
DdNodePtr *stack;
int SP;
unsigned int live = table->keys - table->dead;
if (live > table->peakLiveNodes) {
table->peakLiveNodes = live;
}
n = Cudd_Regular(n);
#ifdef DD_DEBUG
assert(n->ref != 0);
#endif
#ifdef DD_NO_DEATH_ROW
N = n;
#else
if (cuddIsConstant(n) || n->ref > 1) {
#ifdef DD_DEBUG
assert(n->ref != 1 && (!cuddIsConstant(n) || n == DD_ONE(table)));
#endif
cuddSatDec(n->ref);
return;
}
N = table->deathRow[table->nextDead];
if (N != NULL) {
#endif
#ifdef DD_DEBUG
assert(!Cudd_IsComplement(N));
#endif
stack = table->stack;
SP = 1;
do {
#ifdef DD_DEBUG
assert(N->ref != 0);
#endif
if (N->ref == 1) {
N->ref = 0;
table->dead++;
#ifdef DD_STATS
table->nodesDropped++;
#endif
ord = table->perm[N->index];
stack[SP++] = Cudd_Regular(cuddE(N));
table->subtables[ord].dead++;
N = cuddT(N);
} else {
cuddSatDec(N->ref);
N = stack[--SP];
}
} while (SP != 0);
#ifndef DD_NO_DEATH_ROW
}
table->deathRow[table->nextDead] = n;
/* Udate insertion point. */
table->nextDead++;
table->nextDead &= table->deadMask;
#if 0
if (table->nextDead == table->deathRowDepth) {
if (table->deathRowDepth < table->looseUpTo / 2) {
extern void (*MMoutOfMemory)(long);
void (*saveHandler)(long) = MMoutOfMemory;
DdNodePtr *newRow;
MMoutOfMemory = Cudd_OutOfMem;
newRow = REALLOC(DdNodePtr,table->deathRow,2*table->deathRowDepth);
MMoutOfMemory = saveHandler;
if (newRow == NULL) {
table->nextDead = 0;
} else {
int i;
table->memused += table->deathRowDepth;
i = table->deathRowDepth;
table->deathRowDepth <<= 1;
for (; i < table->deathRowDepth; i++) {
newRow[i] = NULL;
//.........这里部分代码省略.........
/**Function********************************************************************
Synopsis [Shrinks almost empty ZDD subtables at the end of reordering
to guarantee that they have a reasonable load factor.]
Description [Shrinks almost empty subtables at the end of reordering to
guarantee that they have a reasonable load factor. However, if there many
nodes are being reclaimed, then no resizing occurs. Returns 1 in case of
success; 0 otherwise.]
SideEffects [None]
******************************************************************************/
static int
zddReorderPostprocess(
DdManager * table)
{
int i, j, posn;
DdNodePtr *nodelist, *oldnodelist;
DdNode *node, *next;
unsigned int slots, oldslots;
extern DD_OOMFP MMoutOfMemory;
DD_OOMFP saveHandler;
#ifdef DD_VERBOSE
(void) fflush(table->out);
#endif
/* If we have very many reclaimed nodes, we do not want to shrink
** the subtables, because this will lead to more garbage
** collections. More garbage collections mean shorter mean life for
** nodes with zero reference count; hence lower probability of finding
** a result in the cache.
*/
if (table->reclaimed > table->allocated * 0.5) return(1);
/* Resize subtables. */
for (i = 0; i < table->sizeZ; i++) {
int shift;
oldslots = table->subtableZ[i].slots;
if (oldslots < table->subtableZ[i].keys * DD_MAX_SUBTABLE_SPARSITY ||
oldslots <= table->initSlots) continue;
oldnodelist = table->subtableZ[i].nodelist;
slots = oldslots >> 1;
saveHandler = MMoutOfMemory;
MMoutOfMemory = Cudd_OutOfMem;
nodelist = ALLOC(DdNodePtr, slots);
MMoutOfMemory = saveHandler;
if (nodelist == NULL) {
return(1);
}
table->subtableZ[i].nodelist = nodelist;
table->subtableZ[i].slots = slots;
table->subtableZ[i].shift++;
table->subtableZ[i].maxKeys = slots * DD_MAX_SUBTABLE_DENSITY;
#ifdef DD_VERBOSE
(void) fprintf(table->err,
"shrunk layer %d (%d keys) from %d to %d slots\n",
i, table->subtableZ[i].keys, oldslots, slots);
#endif
for (j = 0; (unsigned) j < slots; j++) {
nodelist[j] = NULL;
}
shift = table->subtableZ[i].shift;
for (j = 0; (unsigned) j < oldslots; j++) {
node = oldnodelist[j];
while (node != NULL) {
next = node->next;
posn = ddHash(cuddT(node), cuddE(node), shift);
node->next = nodelist[posn];
nodelist[posn] = node;
node = next;
}
}
FREE(oldnodelist);
table->memused += (slots - oldslots) * sizeof(DdNode *);
table->slots += slots - oldslots;
table->minDead = (unsigned) (table->gcFrac * (double) table->slots);
table->cacheSlack = (int) ddMin(table->maxCacheHard,
DD_MAX_CACHE_TO_SLOTS_RATIO*table->slots) -
2 * (int) table->cacheSlots;
}
/* We don't look at the constant subtable, because it is not
** affected by reordering.
*/
return(1);
} /* end of zddReorderPostprocess */
/**Function********************************************************************
Synopsis [Implements the recursive step of Cudd_bddXor.]
Description [Implements the recursive step of Cudd_bddXor by taking
the exclusive OR of two BDDs. Returns a pointer to the result is
successful; NULL otherwise.]
SideEffects [None]
SeeAlso [Cudd_bddXor]
******************************************************************************/
DdNode *
cuddBddXorRecur(
DdManager * manager,
DdNode * f,
DdNode * g)
{
DdNode *fv, *fnv, *G, *gv, *gnv;
DdNode *one, *zero, *r, *t, *e;
unsigned int topf, topg, 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 (f > g) { /* Try to increase cache efficiency and simplify tests. */
DdNode *tmp = f;
f = g;
g = tmp;
}
if (g == zero) return(f);
if (g == one) return(Cudd_Not(f));
if (Cudd_IsComplement(f)) {
f = Cudd_Not(f);
g = Cudd_Not(g);
}
/* Now the first argument is regular. */
if (f == one) return(Cudd_Not(g));
/* At this point f and g are not constant. */
/* Check cache. */
r = cuddCacheLookup2(manager, Cudd_bddXor, f, g);
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];
G = Cudd_Regular(g);
topg = manager->perm[G->index];
/* Compute cofactors. */
if (topf <= topg) {
index = f->index;
fv = cuddT(f);
fnv = cuddE(f);
} else {
index = G->index;
fv = fnv = f;
}
if (topg <= topf) {
gv = cuddT(G);
gnv = cuddE(G);
if (Cudd_IsComplement(g)) {
gv = Cudd_Not(gv);
gnv = Cudd_Not(gnv);
}
} else {
gv = gnv = g;
}
t = cuddBddXorRecur(manager, fv, gv);
if (t == NULL) return(NULL);
cuddRef(t);
e = cuddBddXorRecur(manager, fnv, gnv);
if (e == NULL) {
Cudd_IterDerefBdd(manager, t);
return(NULL);
}
cuddRef(e);
if (t == e) {
r = t;
} 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);
//.........这里部分代码省略.........
/**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)) {
//.........这里部分代码省略.........
请发表评论