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

  Synopsis    [Sifts a variable up.]

  Description [Sifts a variable up. Moves y up until either it reaches
  the bound (x_low) or the size of the ZDD heap increases too much.
  Returns the set of moves in case of success; NULL if memory is full.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static Move *
cuddZddSiftingUp(
  DdManager * table,
  int  x,
  int  x_low,
  int  initial_size)
{
    Move	*moves;
    Move	*move;
    int		y;
    int		size;
    int		limit_size = initial_size;

    moves = NULL;
    y = cuddZddNextLow(table, x);
    while (y >= x_low) {
	size = cuddZddSwapInPlace(table, y, x);
	if (size == 0)
	    goto cuddZddSiftingUpOutOfMem;
	move = (Move *)cuddDynamicAllocNode(table);
	if (move == NULL)
	    goto cuddZddSiftingUpOutOfMem;
	move->x = y;
	move->y = x;
	move->size = size;
	move->next = moves;
	moves = move;

	if ((double)size > (double)limit_size * table->maxGrowth)
	    break;
        if (size < limit_size)
	    limit_size = size;

	x = y;
	y = cuddZddNextLow(table, x);
    }
    return(moves);

cuddZddSiftingUpOutOfMem:
    while (moves != NULL) {
	move = moves->next;
	cuddDeallocNode(table, (DdNode *)moves);
	moves = move;
    }
    return(NULL);

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

  Synopsis    [Moves one ZDD variable up.]

  Description [Takes a ZDD variable from position x and sifts it up to
  position xLow;  xLow should be less than or equal to x.
  Returns 1 if successful; 0 otherwise]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
zddSiftUp(
  DdManager * table,
  int  x,
  int  xLow)
{
    int        y;
    int        size;

    y = cuddZddNextLow(table,x);
    while (y >= xLow) {
	size = cuddZddSwapInPlace(table,y,x);
	if (size == 0) {
	    return(0);
	}
	x = y;
	y = cuddZddNextLow(table,x);
    }
    return(1);

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

  Synopsis [Moves x up until either it reaches the bound (x_low) or
  the size of the ZDD heap increases too much.]

  Description [Moves x up until either it reaches the bound (x_low) or
  the size of the ZDD heap increases too much. Assumes that x is the top
  of a symmetry group.  Checks x for symmetry to the adjacent
  variables. If symmetry is found, the symmetry group of x is merged
  with the symmetry group of the other variable. Returns the set of
  moves in case of success; ZDD_MV_OOM if memory is full.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static Move *
cuddZddSymmSifting_up(
  DdManager * table,
  int  x,
  int  x_low,
  int  initial_size)
{
    Move	*moves;
    Move	*move;
    int		y;
    int		size;
    int		limit_size = initial_size;
    int		i, gytop;

    moves = NULL;
    y = cuddZddNextLow(table, x);
    while (y >= x_low) {
	gytop = table->subtableZ[y].next;
	if (cuddZddSymmCheck(table, y, x)) {
	    /* Symmetry found, attach symm groups */
	    table->subtableZ[y].next = x;
	    i = table->subtableZ[x].next;
	    while (table->subtableZ[i].next != (unsigned) x)
		i = table->subtableZ[i].next;
	    table->subtableZ[i].next = gytop;
	}
	else if ((table->subtableZ[x].next == (unsigned) x) &&
	    (table->subtableZ[y].next == (unsigned) y)) {
	    /* x and y have self symmetry */
	    size = cuddZddSwapInPlace(table, y, x);
	    if (size == 0)
		goto cuddZddSymmSifting_upOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto cuddZddSymmSifting_upOutOfMem;
	    move->x = y;
	    move->y = x;
	    move->size = size;
	    move->next = moves;
	    moves = move;
	    if ((double)size >
		(double)limit_size * table->maxGrowth)
		return(moves);
	    if (size < limit_size)
		limit_size = size;
	}
	else { /* Group move */
	    size = zdd_group_move(table, y, x, &moves);
	    if ((double)size >
		(double)limit_size * table->maxGrowth)
		return(moves);
	    if (size < limit_size)
		limit_size = size;
	}
	x = gytop;
	y = cuddZddNextLow(table, x);
    }

    return(moves);

cuddZddSymmSifting_upOutOfMem:
    while (moves != NULL) {
	move = moves->next;
	cuddDeallocMove(table, moves);
	moves = move;
    }
    return(ZDD_MV_OOM);

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

  Synopsis    [Swaps any two variables.]

  Description [Swaps any two variables. Returns the set of moves.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static Move *
zddSwapAny(
  DdManager * table,
  int  x,
  int  y)
{
    Move	*move, *moves;
    int		tmp, size;
    int		x_ref, y_ref;
    int		x_next, y_next;
    int		limit_size;

    if (x > y) {	/* make x precede y */
	tmp = x; x = y;	y = tmp;
    }

    x_ref = x; y_ref = y;

    x_next = cuddZddNextHigh(table, x);
    y_next = cuddZddNextLow(table, y);
    moves = NULL;
    limit_size = table->keysZ;

    for (;;) {
	if (x_next == y_next) {	/* x < x_next = y_next < y */
	    size = cuddZddSwapInPlace(table, x, x_next);
	    if (size == 0)
		goto zddSwapAnyOutOfMem;
	    move = (Move *) cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto zddSwapAnyOutOfMem;
	    move->x = x;
	    move->y = x_next;
	    move->size = size;
	    move->next = moves;
	    moves = move;

	    size = cuddZddSwapInPlace(table, y_next, y);
	    if (size == 0)
		goto zddSwapAnyOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto zddSwapAnyOutOfMem;
	    move->x = y_next;
	    move->y = y;
	    move->size = size;
	    move->next = moves;
	    moves = move;

	    size = cuddZddSwapInPlace(table, x, x_next);
	    if (size == 0)
		goto zddSwapAnyOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto zddSwapAnyOutOfMem;
	    move->x = x;
	    move->y = x_next;
	    move->size = size;
	    move->next = moves;
	    moves = move;

	    tmp = x; x = y; y = tmp;

	} else if (x == y_next) { /* x = y_next < y = x_next */
	    size = cuddZddSwapInPlace(table, x, x_next);
	    if (size == 0)
		goto zddSwapAnyOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto zddSwapAnyOutOfMem;
	    move->x = x;
	    move->y = x_next;
	    move->size = size;
	    move->next = moves;
	    moves = move;

	    tmp = x; x = y;  y = tmp;
	} else {
	    size = cuddZddSwapInPlace(table, x, x_next);
	    if (size == 0)
		goto zddSwapAnyOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto zddSwapAnyOutOfMem;
	    move->x = x;
	    move->y = x_next;
	    move->size = size;
	    move->next = moves;
	    moves = move;

	    size = cuddZddSwapInPlace(table, y_next, y);
	    if (size == 0)
		goto zddSwapAnyOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto zddSwapAnyOutOfMem;
	    move->x = y_next;
	    move->y = y;
	    move->size = size;
	    move->next = moves;
	    moves = move;

	    x = x_next; y = y_next;
	}

	x_next = cuddZddNextHigh(table, x);
	y_next = cuddZddNextLow(table, y);
	if (x_next > y_ref)
	    break;	/* if x == y_ref */

	if ((double) size > table->maxGrowth * (double) limit_size)
	    break;
	if (size < limit_size)
	    limit_size = size;
    }
    if (y_next >= x_ref) {
	size = cuddZddSwapInPlace(table, y_next, y);
	if (size == 0)
	    goto zddSwapAnyOutOfMem;
	move = (Move *)cuddDynamicAllocNode(table);
	if (move == NULL)
	    goto zddSwapAnyOutOfMem;
	move->x = y_next;
	move->y = y;
	move->size = size;
	move->next = moves;
	moves = move;
    }

    return(moves);

zddSwapAnyOutOfMem:
    while (moves != NULL) {
	move = moves->next;
	cuddDeallocNode(table, (DdNode *)moves);
	moves = move;
    }
    return(NULL);

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

  Synopsis    [Sifts up a variable until either it reaches position xLow
  or the size of the DD heap increases too much.]

  Description [Sifts up a variable until either it reaches position
  xLow or the size of the DD heap increases too much. Assumes that y is
  the top of a group (or a singleton).  Checks y for aggregation to the
  adjacent variables. Records all the moves that are appended to the
  list of moves received as input and returned as a side effect.
  Returns 1 in case of success; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
zddGroupSiftingUp(
  DdManager * table,
  int  y,
  int  xLow,
  Move ** moves)
{
    Move *move;
    int  x;
    int  size;
    int  gxtop;
    int  limitSize;
    int  xindex, yindex;

    yindex = table->invpermZ[y];

    limitSize = table->keysZ;

    x = cuddZddNextLow(table,y);
    while (x >= xLow) {
        gxtop = table->subtableZ[x].next;
        if (table->subtableZ[x].next == (unsigned) x &&
	    table->subtableZ[y].next == (unsigned) y) {
            /* x and y are self groups */
	    xindex = table->invpermZ[x];
            size = cuddZddSwapInPlace(table,x,y);
#ifdef DD_DEBUG
            assert(table->subtableZ[x].next == (unsigned) x);
            assert(table->subtableZ[y].next == (unsigned) y);
#endif
            if (size == 0) goto zddGroupSiftingUpOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto zddGroupSiftingUpOutOfMem;
            move->x = x;
            move->y = y;
	    move->flags = MTR_DEFAULT;
            move->size = size;
            move->next = *moves;
            *moves = move;

#ifdef DD_DEBUG
	    if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingUp (2 single groups):\n");
#endif
            if ((double) size > (double) limitSize * table->maxGrowth)
		return(1);
            if (size < limitSize) limitSize = size;
        } else { /* group move */
            size = zddGroupMove(table,x,y,moves);
	    if (size == 0) goto zddGroupSiftingUpOutOfMem;
            if ((double) size > (double) limitSize * table->maxGrowth)
		return(1);
            if (size < limitSize) limitSize = size;
        }
        y = gxtop;
        x = cuddZddNextLow(table,y);
    }

    return(1);

zddGroupSiftingUpOutOfMem:
    while (*moves != NULL) {
        move = (*moves)->next;
        cuddDeallocNode(table, (DdNode *) *moves);
        *moves = move;
    }
    return(0);

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

  Synopsis    [Undoes the swap two groups.]

  Description [Undoes the swap two groups.  Returns 1 in case of
  success; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
zddGroupMoveBackward(
  DdManager * table,
  int  x,
  int  y)
{
    int size;
    int i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;


#if DD_DEBUG
    /* We assume that x < y */
    assert(x < y);
#endif

    /* Find top, bottom, and size for the two groups. */
    xbot = x;
    xtop = table->subtableZ[x].next;
    xsize = xbot - xtop + 1;
    ybot = y;
    while ((unsigned) ybot < table->subtableZ[ybot].next)
        ybot = table->subtableZ[ybot].next;
    ytop = y;
    ysize = ybot - ytop + 1;

    /* Sift the variables of the second group up through the first group */
    for (i = 1; i <= ysize; i++) {
        for (j = 1; j <= xsize; j++) {
            size = cuddZddSwapInPlace(table,x,y);
            if (size == 0)
                return(0);
            y = x;
            x = cuddZddNextLow(table,y);
        }
        y = ytop + i;
        x = cuddZddNextLow(table,y);
    }

    /* fix groups */
    y = xtop;
    for (i = 0; i < ysize - 1; i++) {
        table->subtableZ[y].next = cuddZddNextHigh(table,y);
        y = cuddZddNextHigh(table,y);
    }
    table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
                                    /* to its top */
    x = cuddZddNextHigh(table,y);
    newxtop = x;
    for (i = 0; i < xsize - 1; i++) {
        table->subtableZ[x].next = cuddZddNextHigh(table,x);
        x = cuddZddNextHigh(table,x);
    }
    table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
                                    /* to its top */
#ifdef DD_DEBUG
    if (pr > 0) (void) fprintf(table->out,"zddGroupMoveBackward:\n");
#endif

    return(1);

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

  Synopsis    [Swaps two groups and records the move.]

  Description [Swaps two groups and records the move. Returns the
  number of keys in the DD table in case of success; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
zddGroupMove(
  DdManager * table,
  int  x,
  int  y,
  Move ** moves)
{
    Move *move;
    int  size;
    int  i,j,xtop,xbot,xsize,ytop,ybot,ysize,newxtop;
    int  swapx = x, swapy = y;
#if defined(DD_DEBUG) && defined(DD_VERBOSE)
    int  initialSize,bestSize;
#endif

#if DD_DEBUG
    /* We assume that x < y */
    assert(x < y);
#endif
    /* Find top, bottom, and size for the two groups. */
    xbot = x;
    xtop = table->subtableZ[x].next;
    xsize = xbot - xtop + 1;
    ybot = y;
    while ((unsigned) ybot < table->subtableZ[ybot].next)
        ybot = table->subtableZ[ybot].next;
    ytop = y;
    ysize = ybot - ytop + 1;

#if defined(DD_DEBUG) && defined(DD_VERBOSE)
    initialSize = bestSize = table->keysZ;
#endif
    /* Sift the variables of the second group up through the first group */
    for (i = 1; i <= ysize; i++) {
        for (j = 1; j <= xsize; j++) {
            size = cuddZddSwapInPlace(table,x,y);
            if (size == 0) goto zddGroupMoveOutOfMem;
#if defined(DD_DEBUG) && defined(DD_VERBOSE)
	    if (size < bestSize)
		bestSize = size;
#endif
            swapx = x; swapy = y;
            y = x;
            x = cuddZddNextLow(table,y);
        }
        y = ytop + i;
        x = cuddZddNextLow(table,y);
    }
#if defined(DD_DEBUG) && defined(DD_VERBOSE)
    if ((bestSize < initialSize) && (bestSize < size))
	(void) fprintf(table->out,"Missed local minimum: initialSize:%d  bestSize:%d  finalSize:%d\n",initialSize,bestSize,size);
#endif

    /* fix groups */
    y = xtop; /* ytop is now where xtop used to be */
    for (i = 0; i < ysize - 1; i++) {
        table->subtableZ[y].next = cuddZddNextHigh(table,y);
        y = cuddZddNextHigh(table,y);
    }
    table->subtableZ[y].next = xtop; /* y is bottom of its group, join */
                                    /* it to top of its group */
    x = cuddZddNextHigh(table,y);
    newxtop = x;
    for (i = 0; i < xsize - 1; i++) {
        table->subtableZ[x].next = cuddZddNextHigh(table,x);
        x = cuddZddNextHigh(table,x);
    }
    table->subtableZ[x].next = newxtop; /* x is bottom of its group, join */
                                    /* it to top of its group */
#ifdef DD_DEBUG
    if (pr > 0) (void) fprintf(table->out,"zddGroupMove:\n");
#endif

    /* Store group move */
    move = (Move *) cuddDynamicAllocNode(table);
    if (move == NULL) goto zddGroupMoveOutOfMem;
    move->x = swapx;
    move->y = swapy;
    move->flags = MTR_DEFAULT;
    move->size = table->keysZ;
    move->next = *moves;
    *moves = move;

    return(table->keysZ);

zddGroupMoveOutOfMem:
    while (*moves != NULL) {
        move = (*moves)->next;
        cuddDeallocNode(table, (DdNode *) *moves);
        *moves = move;
    }
    return(0);

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

  Synopsis    [Sifts a variable up applying the XOR transformation.]

  Description [Sifts a variable up applying the XOR
  transformation. Moves y up until either it reaches the bound (xLow)
  or the size of the ZDD heap increases too much.  Returns the set of
  moves in case of success; NULL if memory is full.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static Move *
cuddZddLinearUp(
  DdManager * table,
  int  y,
  int  xLow,
  Move * prevMoves)
{
    Move	*moves;
    Move	*move;
    int		x;
    int		size, newsize;
    int		limitSize;

    moves = prevMoves;
    limitSize = table->keysZ;

    x = cuddZddNextLow(table, y);
    while (x >= xLow) {
	size = cuddZddSwapInPlace(table, x, y);
	if (size == 0)
	    goto cuddZddLinearUpOutOfMem;
	newsize = cuddZddLinearInPlace(table, x, y);
	if (newsize == 0)
	    goto cuddZddLinearUpOutOfMem;
	move = (Move *) cuddDynamicAllocNode(table);
	if (move == NULL)
	    goto cuddZddLinearUpOutOfMem;
	move->x = x;
	move->y = y;
	move->next = moves;
	moves = move;
	move->flags = CUDD_SWAP_MOVE;
	if (newsize > size) {
	    /* Undo transformation. The transformation we apply is
	    ** its own inverse. Hence, we just apply the transformation
	    ** again.
	    */
	    newsize = cuddZddLinearInPlace(table,x,y);
	    if (newsize == 0) goto cuddZddLinearUpOutOfMem;
#ifdef DD_DEBUG
	    if (newsize != size) {
		(void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
	    }
#endif
	} else {
	    size = newsize;
	    move->flags = CUDD_LINEAR_TRANSFORM_MOVE;
	}
	move->size = size;

	if ((double)size > (double)limitSize * table->maxGrowth)
	    break;
        if (size < limitSize)
	    limitSize = size;

	y = x;
	x = cuddZddNextLow(table, y);
    }
    return(moves);

cuddZddLinearUpOutOfMem:
    while (moves != NULL) {
	move = moves->next;
	cuddDeallocMove(table, moves);
	moves = move;
    }
    return((Move *) CUDD_OUT_OF_MEM);

} /* end of cuddZddLinearUp */