Exemple #1
0
/**Function********************************************************************

  Synopsis    [Decreases the reference count of node.]

  Description [Decreases the reference count of node. It is primarily
  used in recursive procedures to decrease the ref count of a result
  node before returning it. This accomplishes the goal of removing the
  protection applied by a previous Cudd_Ref.]

  SideEffects [None]

  SeeAlso     [Cudd_RecursiveDeref Cudd_RecursiveDerefZdd Cudd_Ref]

******************************************************************************/
void
Cudd_Deref(
  DdNode * node)
{
    node = Cudd_Regular(node);
    cuddSatDec(node->ref);

} /* end of Cudd_Deref */
Exemple #2
0
/**Function********************************************************************

  Synopsis    [Decreases the reference count of node n.]

  Description [Decreases the reference count of node n. If n dies,
  recursively decreases the reference counts of its children.  It is
  used to dispose of a DD that is no longer needed.]

  SideEffects [None]

  SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDerefZdd]

******************************************************************************/
void
Cudd_RecursiveDeref(
  DdManager * table,
  DdNode * n)
{
    DdNode *N;
    int ord;
    DdNodePtr *stack = table->stack;
    int SP = 1;

    unsigned int live = table->keys - table->dead;
    if (live > table->peakLiveNodes) {
        table->peakLiveNodes = live;
    }

    N = Cudd_Regular(n);

    do {
#ifdef DD_DEBUG
        assert(N->ref != 0);
#endif

        if (N->ref == 1) {
            N->ref = 0;
            table->dead++;
#ifdef DD_STATS
            table->nodesDropped++;
#endif
            if (cuddIsConstant(N)) {
                table->constants.dead++;
                N = stack[--SP];
            } else {
                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);

} /* end of Cudd_RecursiveDeref */
Exemple #3
0
/**Function********************************************************************

  Synopsis    [Brings children of a dead node back.]

  Description []

  SideEffects [None]

  SeeAlso     [cuddReclaimZdd]

******************************************************************************/
void
cuddReclaim(
  DdManager * table,
  DdNode * n)
{
    DdNode *N;
    int ord;
    DdNodePtr *stack = table->stack;
    int SP = 1;
    double initialDead = table->dead;

    N = Cudd_Regular(n);

#ifdef DD_DEBUG
    assert(N->ref == 0);
#endif

    do {
        if (N->ref == 0) {
            N->ref = 1;
            table->dead--;
            if (cuddIsConstant(N)) {
                table->constants.dead--;
                N = stack[--SP];
            } else {
                ord = table->perm[N->index];
                stack[SP++] = Cudd_Regular(cuddE(N));
                table->subtables[ord].dead--;
                N = cuddT(N);
            }
        } else {
            cuddSatInc(N->ref);
            N = stack[--SP];
        }
    } while (SP != 0);

    N = Cudd_Regular(n);
    cuddSatDec(N->ref);
    table->reclaimed += initialDead - table->dead;

} /* end of cuddReclaim */
Exemple #4
0
/**Function********************************************************************

  Synopsis    [Brings children of a dead ZDD node back.]

  Description []

  SideEffects [None]

  SeeAlso     [cuddReclaim]

******************************************************************************/
void
cuddReclaimZdd(
  DdManager * table,
  DdNode * n)
{
    DdNode *N;
    int ord;
    DdNodePtr *stack = table->stack;
    int SP = 1;

    N = n;

#ifdef DD_DEBUG
    assert(N->ref == 0);
#endif

    do {
        cuddSatInc(N->ref);

        if (N->ref == 1) {
            table->deadZ--;
            table->reclaimed++;
#ifdef DD_DEBUG
            assert(!cuddIsConstant(N));
#endif
            ord = table->permZ[N->index];
            stack[SP++] = cuddE(N);
            table->subtableZ[ord].dead--;
            N = cuddT(N);
        } else {
            N = stack[--SP];
        }
    } while (SP != 0);

    cuddSatDec(n->ref);

} /* end of cuddReclaimZdd */
Exemple #5
0
/**Function********************************************************************

  Synopsis    [Decreases the reference count of ZDD node n.]

  Description [Decreases the reference count of ZDD node n. If n dies,
  recursively decreases the reference counts of its children.  It is
  used to dispose of a ZDD that is no longer needed.]

  SideEffects [None]

  SeeAlso     [Cudd_Deref Cudd_Ref Cudd_RecursiveDeref]

******************************************************************************/
void
Cudd_RecursiveDerefZdd(
  DdManager * table,
  DdNode * n)
{
    DdNode *N;
    int ord;
    DdNodePtr *stack = table->stack;
    int SP = 1;

    N = n;

    do {
#ifdef DD_DEBUG
        assert(N->ref != 0);
#endif

        cuddSatDec(N->ref);
    
        if (N->ref == 0) {
            table->deadZ++;
#ifdef DD_STATS
            table->nodesDropped++;
#endif
#ifdef DD_DEBUG
            assert(!cuddIsConstant(N));
#endif
            ord = table->permZ[N->index];
            stack[SP++] = cuddE(N);
            table->subtableZ[ord].dead++;
            N = cuddT(N);
        } else {
            N = stack[--SP];
        }
    } while (SP != 0);

} /* end of Cudd_RecursiveDerefZdd */
Exemple #6
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_MinHammingDist.]

  Description [Performs the recursive step of Cudd_MinHammingDist.
  It is based on the following identity. Let H(f) be the
  minimum Hamming distance of the minterms of f from the reference
  minterm. Then:
  <xmp>
    H(f) = min(H(f0)+h0,H(f1)+h1)
  </xmp>
  where f0 and f1 are the two cofactors of f with respect to its top
  variable; h0 is 1 if the minterm assigns 1 to the top variable of f;
  h1 is 1 if the minterm assigns 0 to the top variable of f.
  The upper bound on the distance is used to bound the depth of the
  recursion.
  Returns the minimum distance unless it exceeds the upper bound or
  computation fails.]

  SideEffects [None]

  SeeAlso     [Cudd_MinHammingDist]

******************************************************************************/
static int
cuddMinHammingDistRecur(
  DdNode * f,
  int *minterm,
  DdHashTable * table,
  int upperBound)
{
    DdNode	*F, *Ft, *Fe;
    double	h, hT, hE;
    DdNode	*zero, *res;
    DdManager	*dd = table->manager;

    statLine(dd);
    if (upperBound == 0) return(0);

    F = Cudd_Regular(f);

    if (cuddIsConstant(F)) {
	zero = Cudd_Not(DD_ONE(dd));
	if (f == dd->background || f == zero) {
	    return(upperBound);
	} else {
	    return(0);
	}
    }
    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
      //Rob Apr 6 2001: might need to change this, not sure what it does.....
      h = (*cuddV(res)).get_val();
      if (res->ref == 0) {
	dd->dead++;
	dd->constants.dead++;
      }
      return((int) h);
    }

    Ft = cuddT(F); Fe = cuddE(F);
    if (Cudd_IsComplement(f)) {
	Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe);
    }
    if (minterm[F->index] == 0) {
	DdNode *temp = Ft;
	Ft = Fe; Fe = temp;
    }

    hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound);
    if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
    if (hT == 0) {
	hE = upperBound;
    } else {
	hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1);
	if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
    }
    h = ddMin(hT, hE + 1);

    if (F->ref != 1) {
	ptrint fanout = (ptrint) F->ref;
	cuddSatDec(fanout);
	Terminal hTerminal;
	hTerminal.set((double) h);
	res = cuddUniqueConst(dd,&hTerminal);
	//res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h);
	if (!cuddHashTableInsert1(table,f,res,fanout)) {
	    cuddRef(res); Cudd_RecursiveDeref(dd, res);
	    return(CUDD_OUT_OF_MEM);
	}
    }

    return((int) h);

} /* end of cuddMinHammingDistRecur */
Exemple #7
0
/**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 = ABC_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;
                }
                table->deadMask = table->deathRowDepth - 1;
                table->deathRow = newRow;
            }
        } else {
            table->nextDead = 0;
        }
    }
#endif
#endif

} /* end of Cudd_DelayedDerefBdd */
Exemple #8
0
/**Function********************************************************************

  Synopsis    [Swaps two adjacent variables.]

  Description [Swaps two adjacent variables. It assumes that no dead
  nodes are present on entry to this procedure.  The procedure then
  guarantees that no dead nodes will be present when it terminates.
  cuddZddSwapInPlace assumes that x &lt; y.  Returns the number of keys in
  the table if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
cuddZddSwapInPlace(
  DdManager * table,
  int  x,
  int  y)
{
    DdNodePtr	*xlist, *ylist;
    int		xindex, yindex;
    int		xslots, yslots;
    int		xshift, yshift;
    int         oldxkeys, oldykeys;
    int         newxkeys, newykeys;
    int		i;
    int		posn;
    DdNode	*f, *f1, *f0, *f11, *f10, *f01, *f00;
    DdNode	*newf1, *newf0, *next;
    DdNodePtr	g, *lastP, *previousP;

#ifdef DD_DEBUG
    assert(x < y);
    assert(cuddZddNextHigh(table,x) == y);
    assert(table->subtableZ[x].keys != 0);
    assert(table->subtableZ[y].keys != 0);
    assert(table->subtableZ[x].dead == 0);
    assert(table->subtableZ[y].dead == 0);
#endif

    zddTotalNumberSwapping++;

    /* Get parameters of x subtable. */
    xindex   = table->invpermZ[x];
    xlist    = table->subtableZ[x].nodelist;
    oldxkeys = table->subtableZ[x].keys;
    xslots   = table->subtableZ[x].slots;
    xshift   = table->subtableZ[x].shift;
    newxkeys = 0;

    yindex   = table->invpermZ[y];
    ylist    = table->subtableZ[y].nodelist;
    oldykeys = table->subtableZ[y].keys;
    yslots   = table->subtableZ[y].slots;
    yshift   = table->subtableZ[y].shift;
    newykeys = oldykeys;

    /* The nodes in the x layer that don't depend on y directly
    ** will stay there; the others are put in a chain.
    ** The chain is handled as a FIFO; g points to the beginning and
    ** last points to the end.
    */

    g = NULL;
    lastP = &g;
    for (i = 0; i < xslots; i++) {
	previousP = &(xlist[i]);
	f = *previousP;
	while (f != NULL) {
	    next = f->next;
	    f1 = cuddT(f); f0 = cuddE(f);
	    if ((f1->index != (DdHalfWord) yindex) &&
		(f0->index != (DdHalfWord) yindex)) { /* stays */
	        newxkeys++;
		*previousP = f;
		previousP = &(f->next);
	    } else {
		f->index = yindex;
		*lastP = f;
		lastP = &(f->next);
	    }
	    f = next;
	} /* while there are elements in the collision chain */
	*previousP = NULL;
    } /* for each slot of the x subtable */
    *lastP = NULL;


#ifdef DD_COUNT
    table->swapSteps += oldxkeys - newxkeys;
#endif
    /* Take care of the x nodes that must be re-expressed.
    ** They form a linked list pointed by g. Their index has been
    ** changed to yindex already.
    */
    f = g;
    while (f != NULL) {
	next = f->next;
	/* Find f1, f0, f11, f10, f01, f00. */
	f1 = cuddT(f);
	if ((int) f1->index == yindex) {
	    f11 = cuddT(f1); f10 = cuddE(f1);
	} else {
	    f11 = empty; f10 = f1;
	}
	f0 = cuddE(f);
	if ((int) f0->index == yindex) {
	    f01 = cuddT(f0); f00 = cuddE(f0);
	} else {
	    f01 = empty; f00 = f0;
	}

	/* Decrease ref count of f1. */
	cuddSatDec(f1->ref);
	/* Create the new T child. */
	if (f11 == empty) {
	    if (f01 != empty) {
		newf1 = f01;
		cuddSatInc(newf1->ref);
	    }
	    /* else case was already handled when finding nodes
	    ** with both children below level y
	    */
	} else {
	    /* Check xlist for triple (xindex, f11, f01). */
	    posn = ddHash(f11, f01, xshift);
	    /* For each element newf1 in collision list xlist[posn]. */
	    newf1 = xlist[posn];
	    while (newf1 != NULL) {
		if (cuddT(newf1) == f11 && cuddE(newf1) == f01) {
		    cuddSatInc(newf1->ref);
		    break; /* match */
		}
		newf1 = newf1->next;
	    } /* while newf1 */
	    if (newf1 == NULL) {	/* no match */
		newf1 = cuddDynamicAllocNode(table);
		if (newf1 == NULL)
		    goto zddSwapOutOfMem;
		newf1->index = xindex; newf1->ref = 1;
		cuddT(newf1) = f11;
		cuddE(newf1) = f01;
		/* Insert newf1 in the collision list xlist[pos];
		** increase the ref counts of f11 and f01
		*/
		newxkeys++;
		newf1->next = xlist[posn];
		xlist[posn] = newf1;
		cuddSatInc(f11->ref);
		cuddSatInc(f01->ref);
	    }
	}
	cuddT(f) = newf1;

	/* Do the same for f0. */
	/* Decrease ref count of f0. */
	cuddSatDec(f0->ref);
	/* Create the new E child. */
	if (f10 == empty) {
	    newf0 = f00;
	    cuddSatInc(newf0->ref);
	} else {
	    /* Check xlist for triple (xindex, f10, f00). */
	    posn = ddHash(f10, f00, xshift);
	    /* For each element newf0 in collision list xlist[posn]. */
	    newf0 = xlist[posn];
	    while (newf0 != NULL) {
		if (cuddT(newf0) == f10 && cuddE(newf0) == f00) {
		    cuddSatInc(newf0->ref);
		    break; /* match */
		}
		newf0 = newf0->next;
	    } /* while newf0 */
	    if (newf0 == NULL) {	/* no match */
		newf0 = cuddDynamicAllocNode(table);
		if (newf0 == NULL)
		    goto zddSwapOutOfMem;
		newf0->index = xindex; newf0->ref = 1;
		cuddT(newf0) = f10; cuddE(newf0) = f00;
		/* Insert newf0 in the collision list xlist[posn];
		** increase the ref counts of f10 and f00.
		*/
		newxkeys++;
		newf0->next = xlist[posn];
		xlist[posn] = newf0;
		cuddSatInc(f10->ref);
		cuddSatInc(f00->ref);
	    }
	}
	cuddE(f) = newf0;

	/* Insert the modified f in ylist.
	** The modified f does not already exists in ylist.
	** (Because of the uniqueness of the cofactors.)
	*/
	posn = ddHash(newf1, newf0, yshift);
	newykeys++;
	f->next = ylist[posn];
	ylist[posn] = f;
	f = next;
    } /* while f != NULL */

    /* GC the y layer. */

    /* For each node f in ylist. */
    for (i = 0; i < yslots; i++) {
	previousP = &(ylist[i]);
	f = *previousP;
	while (f != NULL) {
	    next = f->next;
	    if (f->ref == 0) {
		cuddSatDec(cuddT(f)->ref);
		cuddSatDec(cuddE(f)->ref);
		cuddDeallocNode(table, f);
		newykeys--;
	    } else {
		*previousP = f;
		previousP = &(f->next);
	    }
	    f = next;
	} /* while f */
	*previousP = NULL;
    } /* for i */

    /* Set the appropriate fields in table. */
    table->subtableZ[x].nodelist = ylist;
    table->subtableZ[x].slots    = yslots;
    table->subtableZ[x].shift    = yshift;
    table->subtableZ[x].keys     = newykeys;
    table->subtableZ[x].maxKeys  = yslots * DD_MAX_SUBTABLE_DENSITY;

    table->subtableZ[y].nodelist = xlist;
    table->subtableZ[y].slots    = xslots;
    table->subtableZ[y].shift    = xshift;
    table->subtableZ[y].keys     = newxkeys;
    table->subtableZ[y].maxKeys  = xslots * DD_MAX_SUBTABLE_DENSITY;

    table->permZ[xindex] = y; table->permZ[yindex] = x;
    table->invpermZ[x] = yindex; table->invpermZ[y] = xindex;

    table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;

    /* Update univ section; univ[x] remains the same. */
    table->univ[y] = cuddT(table->univ[x]);

    return (table->keysZ);

zddSwapOutOfMem:
    (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");

    return (0);

} /* end of cuddZddSwapInPlace */
Exemple #9
0
/**Function********************************************************************

  Synopsis    [Linearly combines two adjacent variables.]

  Description [Linearly combines two adjacent variables. It assumes
  that no dead nodes are present on entry to this procedure.  The
  procedure then guarantees that no dead nodes will be present when it
  terminates.  cuddZddLinearInPlace assumes that x &lt; y.  Returns the
  number of keys in the table if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     [cuddZddSwapInPlace cuddLinearInPlace]

******************************************************************************/
static int
cuddZddLinearInPlace(
  DdManager * table,
  int  x,
  int  y)
{
    DdNodePtr *xlist, *ylist;
    int		xindex, yindex;
    int		xslots, yslots;
    int		xshift, yshift;
    int         oldxkeys, oldykeys;
    int         newxkeys, newykeys;
    int		i;
    int		posn;
    DdNode	*f, *f1, *f0, *f11, *f10, *f01, *f00;
    DdNode	*newf1, *newf0, *g, *next, *previous;
    DdNode	*special;

#ifdef DD_DEBUG
    assert(x < y);
    assert(cuddZddNextHigh(table,x) == y);
    assert(table->subtableZ[x].keys != 0);
    assert(table->subtableZ[y].keys != 0);
    assert(table->subtableZ[x].dead == 0);
    assert(table->subtableZ[y].dead == 0);
#endif

    zddTotalNumberLinearTr++;

    /* Get parameters of x subtable. */
    xindex   = table->invpermZ[x];
    xlist    = table->subtableZ[x].nodelist;
    oldxkeys = table->subtableZ[x].keys;
    xslots   = table->subtableZ[x].slots;
    xshift   = table->subtableZ[x].shift;
    newxkeys = 0;

    /* Get parameters of y subtable. */
    yindex   = table->invpermZ[y];
    ylist    = table->subtableZ[y].nodelist;
    oldykeys = table->subtableZ[y].keys;
    yslots   = table->subtableZ[y].slots;
    yshift   = table->subtableZ[y].shift;
    newykeys = oldykeys;

    /* The nodes in the x layer are put in two chains.  The chain
    ** pointed by g holds the normal nodes. When re-expressed they stay
    ** in the x list. The chain pointed by special holds the elements
    ** that will move to the y list.
    */
    g = special = NULL;
    for (i = 0; i < xslots; i++) {
	f = xlist[i];
	if (f == NULL) continue;
	xlist[i] = NULL;
	while (f != NULL) {
	    next = f->next;
	    f1 = cuddT(f);
	    /* if (f1->index == yindex) */ cuddSatDec(f1->ref);
	    f0 = cuddE(f);
	    /* if (f0->index == yindex) */ cuddSatDec(f0->ref);
	    if ((int) f1->index == yindex && cuddE(f1) == empty &&
		(int) f0->index != yindex) {
		f->next = special;
		special = f;
	    } else {
		f->next = g;
		g = f;
	    }
	    f = next;
	} /* while there are elements in the collision chain */
    } /* for each slot of the x subtable */

    /* Mark y nodes with pointers from above x. We mark them by
    **  changing their index to x.
    */
    for (i = 0; i < yslots; i++) {
	f = ylist[i];
	while (f != NULL) {
	    if (f->ref != 0) {
		f->index = xindex;
	    }
	    f = f->next;
	} /* while there are elements in the collision chain */
    } /* for each slot of the y subtable */

    /* Move special nodes to the y list. */
    f = special;
    while (f != NULL) {
	next = f->next;
	f1 = cuddT(f);
	f11 = cuddT(f1);
	cuddT(f) = f11;
	cuddSatInc(f11->ref);
	f0 = cuddE(f);
	cuddSatInc(f0->ref);
	f->index = yindex;
	/* Insert at the beginning of the list so that it will be
	** found first if there is a duplicate. The duplicate will
	** eventually be moved or garbage collected. No node
	** re-expression will add a pointer to it.
	*/
	posn = ddHash(f11, f0, yshift);
	f->next = ylist[posn];
	ylist[posn] = f;
	newykeys++;
	f = next;
    }

    /* Take care of the remaining x nodes that must be re-expressed.
    ** They form a linked list pointed by g.
    */
    f = g;
    while (f != NULL) {
#ifdef DD_COUNT
	table->swapSteps++;
#endif
	next = f->next;
	/* Find f1, f0, f11, f10, f01, f00. */
	f1 = cuddT(f);
	if ((int) f1->index == yindex || (int) f1->index == xindex) {
	    f11 = cuddT(f1); f10 = cuddE(f1);
	} else {
	    f11 = empty; f10 = f1;
	}
	f0 = cuddE(f);
	if ((int) f0->index == yindex || (int) f0->index == xindex) {
	    f01 = cuddT(f0); f00 = cuddE(f0);
	} else {
	    f01 = empty; f00 = f0;
	}
	/* Create the new T child. */
	if (f01 == empty) {
	    newf1 = f10;
	    cuddSatInc(newf1->ref);
	} else {
	    /* Check ylist for triple (yindex, f01, f10). */
	    posn = ddHash(f01, f10, yshift);
	    /* For each element newf1 in collision list ylist[posn]. */
	    newf1 = ylist[posn];
	    /* Search the collision chain skipping the marked nodes. */
	    while (newf1 != NULL) {
		if (cuddT(newf1) == f01 && cuddE(newf1) == f10 &&
		    (int) newf1->index == yindex) {
		    cuddSatInc(newf1->ref);
		    break; /* match */
		}
		newf1 = newf1->next;
	    } /* while newf1 */
	    if (newf1 == NULL) {	/* no match */
		newf1 = cuddDynamicAllocNode(table);
		if (newf1 == NULL)
		    goto zddSwapOutOfMem;
		newf1->index = yindex; newf1->ref = 1;
		cuddT(newf1) = f01;
		cuddE(newf1) = f10;
		/* Insert newf1 in the collision list ylist[pos];
		** increase the ref counts of f01 and f10
		*/
		newykeys++;
		newf1->next = ylist[posn];
		ylist[posn] = newf1;
		cuddSatInc(f01->ref);
		cuddSatInc(f10->ref);
	    }
	}
	cuddT(f) = newf1;

	/* Do the same for f0. */
	/* Create the new E child. */
	if (f11 == empty) {
	    newf0 = f00;
	    cuddSatInc(newf0->ref);
	} else {
	    /* Check ylist for triple (yindex, f11, f00). */
	    posn = ddHash(f11, f00, yshift);
	    /* For each element newf0 in collision list ylist[posn]. */
	    newf0 = ylist[posn];
	    while (newf0 != NULL) {
		if (cuddT(newf0) == f11 && cuddE(newf0) == f00 &&
		    (int) newf0->index == yindex) {
		    cuddSatInc(newf0->ref);
		    break; /* match */
		}
		newf0 = newf0->next;
	    } /* while newf0 */
	    if (newf0 == NULL) {	/* no match */
		newf0 = cuddDynamicAllocNode(table);
		if (newf0 == NULL)
		    goto zddSwapOutOfMem;
		newf0->index = yindex; newf0->ref = 1;
		cuddT(newf0) = f11; cuddE(newf0) = f00;
		/* Insert newf0 in the collision list ylist[posn];
		** increase the ref counts of f11 and f00.
		*/
		newykeys++;
		newf0->next = ylist[posn];
		ylist[posn] = newf0;
		cuddSatInc(f11->ref);
		cuddSatInc(f00->ref);
	    }
	}
	cuddE(f) = newf0;

	/* Re-insert the modified f in xlist.
	** The modified f does not already exists in xlist.
	** (Because of the uniqueness of the cofactors.)
	*/
	posn = ddHash(newf1, newf0, xshift);
	newxkeys++;
	f->next = xlist[posn];
	xlist[posn] = f;
	f = next;
    } /* while f != NULL */

    /* GC the y layer and move the marked nodes to the x list. */

    /* For each node f in ylist. */
    for (i = 0; i < yslots; i++) {
	previous = NULL;
	f = ylist[i];
	while (f != NULL) {
	    next = f->next;
	    if (f->ref == 0) {
		cuddSatDec(cuddT(f)->ref);
		cuddSatDec(cuddE(f)->ref);
		cuddDeallocNode(table, f);
		newykeys--;
		if (previous == NULL)
		    ylist[i] = next;
		else
		    previous->next = next;
	    } else if ((int) f->index == xindex) { /* move marked node */
		if (previous == NULL)
		    ylist[i] = next;
		else
		    previous->next = next;
		f1 = cuddT(f);
		cuddSatDec(f1->ref);
		/* Check ylist for triple (yindex, f1, empty). */
		posn = ddHash(f1, empty, yshift);
		/* For each element newf1 in collision list ylist[posn]. */
		newf1 = ylist[posn];
		while (newf1 != NULL) {
		    if (cuddT(newf1) == f1 && cuddE(newf1) == empty &&
			(int) newf1->index == yindex) {
			cuddSatInc(newf1->ref);
			break; /* match */
		    }
		    newf1 = newf1->next;
		} /* while newf1 */
		if (newf1 == NULL) {	/* no match */
		    newf1 = cuddDynamicAllocNode(table);
		    if (newf1 == NULL)
			goto zddSwapOutOfMem;
		    newf1->index = yindex; newf1->ref = 1;
		    cuddT(newf1) = f1; cuddE(newf1) = empty;
		    /* Insert newf1 in the collision list ylist[posn];
		    ** increase the ref counts of f1 and empty.
		    */
		    newykeys++;
		    newf1->next = ylist[posn];
		    ylist[posn] = newf1;
		    if (posn == i && previous == NULL)
			previous = newf1;
		    cuddSatInc(f1->ref);
		    cuddSatInc(empty->ref);
		}
		cuddT(f) = newf1;
		f0 = cuddE(f);
		/* Insert f in x list. */
		posn = ddHash(newf1, f0, xshift);
		newxkeys++;
		newykeys--;
		f->next = xlist[posn];
		xlist[posn] = f;
	    } else {
		previous = f;
	    }
	    f = next;
	} /* while f */
    } /* for i */

    /* Set the appropriate fields in table. */
    table->subtableZ[x].keys     = newxkeys;
    table->subtableZ[y].keys     = newykeys;

    table->keysZ += newxkeys + newykeys - oldxkeys - oldykeys;

    /* Update univ section; univ[x] remains the same. */
    table->univ[y] = cuddT(table->univ[x]);

#if 0
    (void) fprintf(table->out,"x = %d  y = %d\n", x, y);
    (void) Cudd_DebugCheck(table);
    (void) Cudd_CheckKeys(table);
#endif

    return (table->keysZ);

zddSwapOutOfMem:
    (void) fprintf(table->err, "Error: cuddZddSwapInPlace out of memory\n");

    return (0);

} /* end of cuddZddLinearInPlace */
Exemple #10
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddVectorCompose.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddBddVectorComposeRecur(
  DdManager * dd /* DD manager */,
  DdHashTable * table /* computed table */,
  DdNode * f /* BDD in which to compose */,
  DdNode ** vector /* functions to be composed */,
  int deepest /* depth of the deepest substitution */)
{
    DdNode	*F,*T,*E;
    DdNode	*res;

    statLine(dd);
    F = Cudd_Regular(f);

    /* If we are past the deepest substitution, return f. */
    if (cuddI(dd,F->index) > deepest) {
	return(f);
    }

    /* If problem already solved, look up answer and return. */
    if ((res = cuddHashTableLookup1(table,F)) != NULL) {
#ifdef DD_DEBUG
	bddVectorComposeHits++;
#endif
	return(Cudd_NotCond(res,F != f));
    }

    /* Split and recur on children of this node. */
    T = cuddBddVectorComposeRecur(dd,table,cuddT(F),vector, deepest);
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddBddVectorComposeRecur(dd,table,cuddE(F),vector, deepest);
    if (E == NULL) {
	Cudd_IterDerefBdd(dd, T);
	return(NULL);
    }
    cuddRef(E);

    /* Call cuddBddIteRecur with the BDD that replaces the current top
    ** variable and the T and E we just created.
    */
    res = cuddBddIteRecur(dd,vector[F->index],T,E);
    if (res == NULL) {
	Cudd_IterDerefBdd(dd, T);
	Cudd_IterDerefBdd(dd, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(dd, T);
    Cudd_IterDerefBdd(dd, E);	

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (F->ref != 1) {
	ptrint fanout = (ptrint) F->ref;
	cuddSatDec(fanout);
	if (!cuddHashTableInsert1(table,F,res,fanout)) {
	    Cudd_IterDerefBdd(dd, res);
	    return(NULL);
	}
    }
    cuddDeref(res);
    return(Cudd_NotCond(res,F != f));

} /* end of cuddBddVectorComposeRecur */
Exemple #11
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addGeneralVectorCompose.]

  Description []

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddAddGeneralVectorComposeRecur(
  DdManager * dd /* DD manager */,
  DdHashTable * table /* computed table */,
  DdNode * f /* ADD in which to compose */,
  DdNode ** vectorOn /* functions to substitute for x_i */,
  DdNode ** vectorOff /* functions to substitute for x_i' */,
  int  deepest /* depth of deepest substitution */)
{
    DdNode	*T,*E,*t,*e;
    DdNode	*res;

    /* If we are past the deepest substitution, return f. */
    if (cuddI(dd,f->index) > deepest) {
	return(f);
    }

    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
#ifdef DD_DEBUG
	addGeneralVectorComposeHits++;
#endif
	return(res);
    }

    /* Split and recur on children of this node. */
    T = cuddAddGeneralVectorComposeRecur(dd,table,cuddT(f),
					 vectorOn,vectorOff,deepest);
    if (T == NULL)  return(NULL);
    cuddRef(T);
    E = cuddAddGeneralVectorComposeRecur(dd,table,cuddE(f),
					 vectorOn,vectorOff,deepest);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd, T);
	return(NULL);
    }
    cuddRef(E);

    /* Retrieve the compose ADDs for the current top variable and call
    ** cuddAddApplyRecur with the T and E we just created.
    */
    t = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOn[f->index],T);
    if (t == NULL) {
      Cudd_RecursiveDeref(dd,T);
      Cudd_RecursiveDeref(dd,E);
      return(NULL);
    }
    cuddRef(t);
    e = cuddAddApplyRecur(dd,Cudd_addTimes,vectorOff[f->index],E);
    if (e == NULL) {
      Cudd_RecursiveDeref(dd,T);
      Cudd_RecursiveDeref(dd,E);
      Cudd_RecursiveDeref(dd,t);
      return(NULL);
    }
    cuddRef(e);
    res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
    if (res == NULL) {
      Cudd_RecursiveDeref(dd,T);
      Cudd_RecursiveDeref(dd,E);
      Cudd_RecursiveDeref(dd,t);
      Cudd_RecursiveDeref(dd,e);
      return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd,T);
    Cudd_RecursiveDeref(dd,E);
    Cudd_RecursiveDeref(dd,t);
    Cudd_RecursiveDeref(dd,e);

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again
    */
    if (f->ref != 1) {
	ptrint fanout = (ptrint) f->ref;
	cuddSatDec(fanout);
	if (!cuddHashTableInsert1(table,f,res,fanout)) {
	    Cudd_RecursiveDeref(dd, res);
	    return(NULL);
	}
    }
    cuddDeref(res);
    return(res);

} /* end of cuddAddGeneralVectorComposeRecur */
Exemple #12
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_bddPermute.]

  Description [ Recursively puts the BDD in the order given in the array permut.
  Checks for trivial cases to terminate recursion, then splits on the
  children of this node.  Once the solutions for the children are
  obtained, it puts into the current position the node from the rest of
  the BDD that should be here. Then returns this BDD.
  The key here is that the node being visited is NOT put in its proper
  place by this instance, but rather is switched when its proper position
  is reached in the recursion tree.<p>
  The DdNode * that is returned is the same BDD as passed in as node,
  but in the new order.]

  SideEffects [None]

  SeeAlso     [Cudd_bddPermute cuddAddPermuteRecur]

******************************************************************************/
static DdNode *
cuddBddPermuteRecur(
  DdManager * manager /* DD manager */,
  DdHashTable * table /* computed table */,
  DdNode * node /* BDD to be reordered */,
  int * permut /* permutation array */)
{
    DdNode	*N,*T,*E;
    DdNode	*res;
    int		index;

    statLine(manager);
    N = Cudd_Regular(node);

    /* Check for terminal case of constant node. */
    if (cuddIsConstant(N)) {
	return(node);
    }

    /* If problem already solved, look up answer and return. */
    if (N->ref != 1 && (res = cuddHashTableLookup1(table,N)) != NULL) {
#ifdef DD_DEBUG
	bddPermuteRecurHits++;
#endif
	return(Cudd_NotCond(res,N != node));
    }

    /* Split and recur on children of this node. */
    T = cuddBddPermuteRecur(manager,table,cuddT(N),permut);
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddBddPermuteRecur(manager,table,cuddE(N),permut);
    if (E == NULL) {
	Cudd_IterDerefBdd(manager, T);
	return(NULL);
    }
    cuddRef(E);

    /* Move variable that should be in this position to this position
    ** by retrieving the single var BDD for that variable, and calling
    ** cuddBddIteRecur with the T and E we just created.
    */
    index = permut[N->index];
    res = cuddBddIteRecur(manager,manager->vars[index],T,E);
    if (res == NULL) {
	Cudd_IterDerefBdd(manager, T);
	Cudd_IterDerefBdd(manager, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_IterDerefBdd(manager, T);
    Cudd_IterDerefBdd(manager, E);

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (N->ref != 1) {
	ptrint fanout = (ptrint) N->ref;
	cuddSatDec(fanout);
	if (!cuddHashTableInsert1(table,N,res,fanout)) {
	    Cudd_IterDerefBdd(manager, res);
	    return(NULL);
	}
    }
    cuddDeref(res);
    return(Cudd_NotCond(res,N != node));

} /* end of cuddBddPermuteRecur */
Exemple #13
0
/**Function********************************************************************

  Synopsis    [Implements the recursive step of Cudd_addPermute.]

  Description [ Recursively puts the ADD in the order given in the
  array permut. Checks for trivial cases to terminate recursion, then
  splits on the children of this node.  Once the solutions for the
  children are obtained, it puts into the current position the node
  from the rest of the ADD that should be here. Then returns this ADD.
  The key here is that the node being visited is NOT put in its proper
  place by this instance, but rather is switched when its proper
  position is reached in the recursion tree.<p>
  The DdNode * that is returned is the same ADD as passed in as node,
  but in the new order.]

  SideEffects [None]

  SeeAlso     [Cudd_addPermute cuddBddPermuteRecur]

******************************************************************************/
static DdNode *
cuddAddPermuteRecur(
  DdManager * manager /* DD manager */,
  DdHashTable * table /* computed table */,
  DdNode * node /* ADD to be reordered */,
  int * permut /* permutation array */)
{
    DdNode	*T,*E;
    DdNode	*res,*var;
    int		index;
    
    statLine(manager);
    /* Check for terminal case of constant node. */
    if (cuddIsConstant(node)) {
	return(node);
    }

    /* If problem already solved, look up answer and return. */
    if (node->ref != 1 && (res = cuddHashTableLookup1(table,node)) != NULL) {
#ifdef DD_DEBUG
	addPermuteRecurHits++;
#endif
	return(res);
    }

    /* Split and recur on children of this node. */
    T = cuddAddPermuteRecur(manager,table,cuddT(node),permut);
    if (T == NULL) return(NULL);
    cuddRef(T);
    E = cuddAddPermuteRecur(manager,table,cuddE(node),permut);
    if (E == NULL) {
	Cudd_RecursiveDeref(manager, T);
	return(NULL);
    }
    cuddRef(E);

    /* Move variable that should be in this position to this position
    ** by creating a single var ADD for that variable, and calling
    ** cuddAddIteRecur with the T and E we just created.
    */
    index = permut[node->index];
    var = cuddUniqueInter(manager,index,DD_ONE(manager),DD_ZERO(manager));
    if (var == NULL) return(NULL);
    cuddRef(var);
    res = cuddAddIteRecur(manager,var,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(manager,var);
	Cudd_RecursiveDeref(manager, T);
	Cudd_RecursiveDeref(manager, E);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(manager,var);
    Cudd_RecursiveDeref(manager, T);
    Cudd_RecursiveDeref(manager, E);

    /* Do not keep the result if the reference count is only 1, since
    ** it will not be visited again.
    */
    if (node->ref != 1) {
	ptrint fanout = (ptrint) node->ref;
	cuddSatDec(fanout);
	if (!cuddHashTableInsert1(table,node,res,fanout)) {
	    Cudd_RecursiveDeref(manager, res);
	    return(NULL);
	}
    }
    cuddDeref(res);
    return(res);

} /* end of cuddAddPermuteRecur */