/**Function********************************************************************

  Synopsis    [This function is for jumping down.]

  Description [This is a simplified version of ddSiftingDown. It does not
  use lower bounding. Returns the set of moves in case of success; NULL
  if memory is full.]

  SideEffects [None]

  SeeAlso     []

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

    moves = NULL;
    y = cuddNextHigh(table,x);
    while (y <= x_high) {
	size = cuddSwapInPlace(table,x,y);
	if (size == 0) goto ddJumpingDownOutOfMem;
	move = (Move *)cuddDynamicAllocNode(table);
	if (move == NULL) goto ddJumpingDownOutOfMem;
	move->x = x;
	move->y = y;
	move->size = size;
	move->next = moves;
	moves = move;
	if ((double) size > table->maxGrowth * (double) limit_size) {
	    break;
	} else if (size < limit_size) {
	    limit_size = size;
	}
	x = y;
	y = cuddNextHigh(table,x);
    }
    return(moves);

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

} /* end of ddJumpingDown */
Example #2
0
/**Function********************************************************************

  Synopsis    [Sifts a variable down and applies the XOR transformation.]

  Description [Sifts a variable down. Moves x down until either it
  reaches the bound (xHigh) 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 *
cuddZddLinearDown(
  DdManager * table,
  int  x,
  int  xHigh,
  Move * prevMoves)
{
    Move	*moves;
    Move	*move;
    int		y;
    int		size, newsize;
    int		limitSize;

    moves = prevMoves;
    limitSize = table->keysZ;

    y = cuddZddNextHigh(table, x);
    while (y <= xHigh) {
	size = cuddZddSwapInPlace(table, x, y);
	if (size == 0)
	    goto cuddZddLinearDownOutOfMem;
	newsize = cuddZddLinearInPlace(table, x, y);
	if (newsize == 0)
	    goto cuddZddLinearDownOutOfMem;
	move = (Move *) cuddDynamicAllocNode(table);
	if (move == NULL)
	    goto cuddZddLinearDownOutOfMem;
	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 cuddZddLinearDownOutOfMem;
	    if (newsize != size) {
		(void) fprintf(table->err,"Change in size after identity transformation! From %d to %d\n",size,newsize);
	    }
	} 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;

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

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

} /* end of cuddZddLinearDown */
Example #3
0
/**Function********************************************************************

  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
  boundaries.]

  Description [Given xLow <= x <= xHigh moves x up and down between the
  boundaries. Finds the best position and does the required changes.
  Returns 1 if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
cuddZddLinearAux(
  DdManager * table,
  int  x,
  int  xLow,
  int  xHigh)
{
    Move	*move;
    Move	*moveUp;	/* list of up move */
    Move	*moveDown;	/* list of down move */

    int		initial_size;
    int		result;

    initial_size = table->keysZ;

#ifdef DD_DEBUG
    assert(table->subtableZ[x].keys > 0);
#endif

    moveDown = NULL;
    moveUp = NULL;

    if (x == xLow) {
	moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
	/* At this point x --> xHigh. */
	if (moveDown == (Move *) CUDD_OUT_OF_MEM)
	    goto cuddZddLinearAuxOutOfMem;
	/* Move backward and stop at best position. */
	result = cuddZddLinearBackward(table, initial_size, moveDown);
	if (!result)
	    goto cuddZddLinearAuxOutOfMem;

    } else if (x == xHigh) {
	moveUp = cuddZddLinearUp(table, x, xLow, NULL);
	/* At this point x --> xLow. */
	if (moveUp == (Move *) CUDD_OUT_OF_MEM)
	    goto cuddZddLinearAuxOutOfMem;
	/* Move backward and stop at best position. */
	result = cuddZddLinearBackward(table, initial_size, moveUp);
	if (!result)
	    goto cuddZddLinearAuxOutOfMem;

    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
	moveDown = cuddZddLinearDown(table, x, xHigh, NULL);
	/* At this point x --> xHigh. */
	if (moveDown == (Move *) CUDD_OUT_OF_MEM)
	    goto cuddZddLinearAuxOutOfMem;
	moveUp = cuddZddUndoMoves(table,moveDown);
#ifdef DD_DEBUG
	assert(moveUp == NULL || moveUp->x == x);
#endif
	moveUp = cuddZddLinearUp(table, x, xLow, moveUp);
	if (moveUp == (Move *) CUDD_OUT_OF_MEM)
	    goto cuddZddLinearAuxOutOfMem;
	/* Move backward and stop at best position. */
	result = cuddZddLinearBackward(table, initial_size, moveUp);
	if (!result)
	    goto cuddZddLinearAuxOutOfMem;

    } else {
	moveUp = cuddZddLinearUp(table, x, xLow, NULL);
	/* At this point x --> xHigh. */
	if (moveUp == (Move *) CUDD_OUT_OF_MEM)
	    goto cuddZddLinearAuxOutOfMem;
	/* Then move up. */
	moveDown = cuddZddUndoMoves(table,moveUp);
#ifdef DD_DEBUG
	assert(moveDown == NULL || moveDown->y == x);
#endif
	moveDown = cuddZddLinearDown(table, x, xHigh, moveDown);
	if (moveDown == (Move *) CUDD_OUT_OF_MEM)
	    goto cuddZddLinearAuxOutOfMem;
	/* Move backward and stop at best position. */
	result = cuddZddLinearBackward(table, initial_size, moveDown);
	if (!result)
	    goto cuddZddLinearAuxOutOfMem;
    }

    while (moveDown != NULL) {
	move = moveDown->next;
	cuddDeallocMove(table, moveDown);
	moveDown = move;
    }
    while (moveUp != NULL) {
	move = moveUp->next;
	cuddDeallocMove(table, moveUp);
	moveUp = move;
    }

    return(1);

cuddZddLinearAuxOutOfMem:
    if (moveDown != (Move *) CUDD_OUT_OF_MEM) {
	while (moveDown != NULL) {
	    move = moveDown->next;
	    cuddDeallocMove(table, moveDown);
	    moveDown = move;
	}
    }
    if (moveUp != (Move *) CUDD_OUT_OF_MEM) {
	while (moveUp != NULL) {
	    move = moveUp->next;
	    cuddDeallocMove(table, moveUp);
	    moveUp = move;
	}
    }

    return(0);

} /* end of cuddZddLinearAux */
Example #4
0
/**Function********************************************************************

  Synopsis    [This function is for exchanging two variables, x and y.]

  Description [This is the same funcion as ddSwapping except for
  comparison expression.  Use probability function, exp(-size_change/temp).]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
ddExchange(
  DdManager * table,
  int  x,
  int  y,
  double  temp)
{
    Move       *move,*moves;
    int        tmp;
    int        x_ref,y_ref;
    int        x_next,y_next;
    int        size, result;
    int        initial_size, limit_size;

    x_ref = x;
    y_ref = y;

    x_next = cuddNextHigh(table,x);
    y_next = cuddNextLow(table,y);
    moves = NULL;
    initial_size = limit_size = table->keys - table->isolated;

    for (;;) {
        if (x_next == y_next) {
            size = cuddSwapInPlace(table,x,x_next);
            if (size == 0) goto ddExchangeOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto ddExchangeOutOfMem;
            move->x = x;
            move->y = x_next;
            move->size = size;
            move->next = moves;
            moves = move;
            size = cuddSwapInPlace(table,y_next,y);
            if (size == 0) goto ddExchangeOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto ddExchangeOutOfMem;
            move->x = y_next;
            move->y = y;
            move->size = size;
            move->next = moves;
            moves = move;
            size = cuddSwapInPlace(table,x,x_next);
            if (size == 0) goto ddExchangeOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto ddExchangeOutOfMem;
            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) {
            size = cuddSwapInPlace(table,x,x_next);
            if (size == 0) goto ddExchangeOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto ddExchangeOutOfMem;
            move->x = x;
            move->y = x_next;
            move->size = size;
            move->next = moves;
            moves = move;
            tmp = x;
            x = y;
            y = tmp;
        } else {
            size = cuddSwapInPlace(table,x,x_next);
            if (size == 0) goto ddExchangeOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto ddExchangeOutOfMem;
            move->x = x;
            move->y = x_next;
            move->size = size;
            move->next = moves;
            moves = move;
            size = cuddSwapInPlace(table,y_next,y);
            if (size == 0) goto ddExchangeOutOfMem;
            move = (Move *)cuddDynamicAllocNode(table);
            if (move == NULL) goto ddExchangeOutOfMem;
            move->x = y_next;
            move->y = y;
            move->size = size;
            move->next = moves;
            moves = move;
            x = x_next;
            y = y_next;
        }

        x_next = cuddNextHigh(table,x);
        y_next = cuddNextLow(table,y);
        if (x_next > y_ref) break;

        if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) {
            break;
        } else if (size < limit_size) {
            limit_size = size;
        }
    }

    if (y_next>=x_ref) {
        size = cuddSwapInPlace(table,y_next,y);
        if (size == 0) goto ddExchangeOutOfMem;
        move = (Move *)cuddDynamicAllocNode(table);
        if (move == NULL) goto ddExchangeOutOfMem;
        move->x = y_next;
        move->y = y;
        move->size = size;
        move->next = moves;
        moves = move;
    }

    /* move backward and stop at best position or accept uphill move */
    result = siftBackwardProb(table,moves,initial_size,temp);
    if (!result) goto ddExchangeOutOfMem;

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

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

} /* end of ddExchange */
Example #5
0
/**Function********************************************************************

  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
  boundaries.]

  Description [Given xLow <= x <= xHigh moves x up and down between the
  boundaries. Finds the best position and does the required changes.
  Assumes that x is either an isolated variable, or it is the bottom of
  a symmetry group. All symmetries may not have been found, because of
  exceeded growth limit. Returns 1 if successful; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
ddSymmSiftingConvAux(
  DdManager * table,
  int  x,
  int  xLow,
  int  xHigh)
{
    Move *move;
    Move *moveUp;	/* list of up moves */
    Move *moveDown;	/* list of down moves */
    int	 initialSize;
    int	 result;
    int  i;
    int  initGroupSize, finalGroupSize;


    initialSize = table->keys - table->isolated;

    moveDown = NULL;
    moveUp = NULL;

    if (x == xLow) { /* Sift down */
#ifdef DD_DEBUG
	/* x is bottom of symmetry group */
	assert((unsigned) x >= table->subtables[x].next);
#endif
	i = table->subtables[x].next;
	initGroupSize = x - i + 1;

	moveDown = ddSymmSiftingDown(table,x,xHigh);
	/* at this point x == xHigh, unless early term */
	if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
	if (moveDown == NULL) return(1);

	x = moveDown->y;
	i = x;
	while ((unsigned) i < table->subtables[i].next) {
	    i = table->subtables[i].next;
	}
#ifdef DD_DEBUG
	/* x should be the top of the symmetric group and i the bottom */
	assert((unsigned) i >= table->subtables[i].next);
	assert((unsigned) x == table->subtables[i].next);
#endif
	finalGroupSize = i - x + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetries detected, go back to best position */
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	} else {
	    initialSize = table->keys - table->isolated;
	    moveUp = ddSymmSiftingUp(table,x,xLow);
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	}
	if (!result) goto ddSymmSiftingConvAuxOutOfMem;

    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
	/* Find top of x's symm group */
	while ((unsigned) x < table->subtables[x].next)
	    x = table->subtables[x].next;
	i = x;				/* bottom */
	x = table->subtables[x].next;	/* top */

	if (x == xLow) return(1);

	initGroupSize = i - x + 1;

	moveUp = ddSymmSiftingUp(table,x,xLow);
	    /* at this point x == xLow, unless early term */
	if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;
	if (moveUp == NULL) return(1);

	x = moveUp->x;
	i = table->subtables[x].next;
#ifdef DD_DEBUG
	/* x should be the bottom of the symmetry group and i the top */
	assert((unsigned) x >= table->subtables[x].next);
	assert((unsigned) i == table->subtables[x].next);
#endif
	finalGroupSize = x - i + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetry groups detected, return to best position */
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	} else {
	    initialSize = table->keys - table->isolated;
	    moveDown = ddSymmSiftingDown(table,x,xHigh);
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	}
	if (!result)
	    goto ddSymmSiftingConvAuxOutOfMem;

    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */
	moveDown = ddSymmSiftingDown(table,x,xHigh);
	    /* at this point x == xHigh, unless early term */
	if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;

	if (moveDown != NULL) {
	    x = moveDown->y;
	    i = x;
	    while ((unsigned) i < table->subtables[i].next) {
		i = table->subtables[i].next;
	    }
	} else {
	    while ((unsigned) x < table->subtables[x].next)
		x = table->subtables[x].next;
	    i = x;
	    x = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x should be the top of the symmetry group and i the bottom */
	assert((unsigned) i >= table->subtables[i].next);
	assert((unsigned) x == table->subtables[i].next);
#endif
	initGroupSize = i - x + 1;

	moveUp = ddSymmSiftingUp(table,x,xLow);
	if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;

	if (moveUp != NULL) {
	    x = moveUp->x;
	    i = table->subtables[x].next;
	} else {
	    i = x;
	    while ((unsigned) x < table->subtables[x].next)
		x = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x should be the bottom of the symmetry group and i the top */
	assert((unsigned) x >= table->subtables[x].next);
	assert((unsigned) i == table->subtables[x].next);
#endif
	finalGroupSize = x - i + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetry groups detected, return to best position */
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	} else {
	    while (moveDown != NULL) {
		move = moveDown->next;
		cuddDeallocMove(table, moveDown);
		moveDown = move;
	    }
	    initialSize = table->keys - table->isolated;
	    moveDown = ddSymmSiftingDown(table,x,xHigh);
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	}
	if (!result) goto ddSymmSiftingConvAuxOutOfMem;

    } else { /* moving up first: shorter */
	/* Find top of x's symmetry group */
	x = table->subtables[x].next;

	moveUp = ddSymmSiftingUp(table,x,xLow);
	/* at this point x == xHigh, unless early term */
	if (moveUp == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;

	if (moveUp != NULL) {
	    x = moveUp->x;
	    i = table->subtables[x].next;
	} else {
	    i = x;
	    while ((unsigned) x < table->subtables[x].next)
		x = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x is bottom of the symmetry group and i is top */
	assert((unsigned) x >= table->subtables[x].next);
	assert((unsigned) i == table->subtables[x].next);
#endif
	initGroupSize = x - i + 1;

	moveDown = ddSymmSiftingDown(table,x,xHigh);
	if (moveDown == MV_OOM) goto ddSymmSiftingConvAuxOutOfMem;

	if (moveDown != NULL) {
	    x = moveDown->y;
	    i = x;
	    while ((unsigned) i < table->subtables[i].next) {
		i = table->subtables[i].next;
	    }
	} else {
	    i = x;
	    x = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x should be the top of the symmetry group and i the bottom */
	assert((unsigned) i >= table->subtables[i].next);
	assert((unsigned) x == table->subtables[i].next);
#endif
	finalGroupSize = i - x + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetries detected, go back to best position */
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	} else {
	    while (moveUp != NULL) {
		move = moveUp->next;
		cuddDeallocMove(table, moveUp);
		moveUp = move;
	    }
	    initialSize = table->keys - table->isolated;
	    moveUp = ddSymmSiftingUp(table,x,xLow);
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	}
	if (!result) goto ddSymmSiftingConvAuxOutOfMem;
    }

    while (moveDown != NULL) {
	move = moveDown->next;
	cuddDeallocMove(table, moveDown);
	moveDown = move;
    }
    while (moveUp != NULL) {
	move = moveUp->next;
	cuddDeallocMove(table, moveUp);
	moveUp = move;
    }

    return(1);

ddSymmSiftingConvAuxOutOfMem:
    if (moveDown != MV_OOM) {
	while (moveDown != NULL) {
	    move = moveDown->next;
	    cuddDeallocMove(table, moveDown);
	    moveDown = move;
	}
    }
    if (moveUp != MV_OOM) {
	while (moveUp != NULL) {
	    move = moveUp->next;
	    cuddDeallocMove(table, moveUp);
	    moveUp = move;
	}
    }

    return(0);

} /* end of ddSymmSiftingConvAux */
Example #6
0
/**Function********************************************************************

  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
  boundaries.]

  Description [Given xLow <= x <= xHigh moves x up and down between the
  boundaries. Finds the best position and does the required changes.
  Assumes that x is not part of a symmetry group. Returns 1 if
  successful; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
ddSymmSiftingAux(
  DdManager * table,
  int  x,
  int  xLow,
  int  xHigh)
{
    Move *move;
    Move *moveUp;	/* list of up moves */
    Move *moveDown;	/* list of down moves */
    int	 initialSize;
    int	 result;
    int  i;
    int  topbot;	/* index to either top or bottom of symmetry group */
    int  initGroupSize, finalGroupSize;


#ifdef DD_DEBUG
    /* check for previously detected symmetry */
    assert(table->subtables[x].next == (unsigned) x);
#endif

    initialSize = table->keys - table->isolated;

    moveDown = NULL;
    moveUp = NULL;

    if ((x - xLow) > (xHigh - x)) {
	/* Will go down first, unless x == xHigh:
	** Look for consecutive symmetries above x.
	*/
	for (i = x; i > xLow; i--) {
	    if (!cuddSymmCheck(table,i-1,i))
		break;
	    topbot = table->subtables[i-1].next; /* find top of i-1's group */
	    table->subtables[i-1].next = i;
	    table->subtables[x].next = topbot; /* x is bottom of group so its */
					       /* next is top of i-1's group */
	    i = topbot + 1; /* add 1 for i--; new i is top of symm group */
	}
    } else {
	/* Will go up first unless x == xlow:
	** Look for consecutive symmetries below x.
	*/
	for (i = x; i < xHigh; i++) {
	    if (!cuddSymmCheck(table,i,i+1))
		break;
	    /* find bottom of i+1's symm group */
	    topbot = i + 1;
	    while ((unsigned) topbot < table->subtables[topbot].next) {
		topbot = table->subtables[topbot].next;
	    }
	    table->subtables[topbot].next = table->subtables[i].next;
	    table->subtables[i].next = i + 1;
	    i = topbot - 1; /* subtract 1 for i++; new i is bottom of group */
	}
    }

    /* Now x may be in the middle of a symmetry group.
    ** Find bottom of x's symm group.
    */
    while ((unsigned) x < table->subtables[x].next)
	x = table->subtables[x].next;

    if (x == xLow) { /* Sift down */

#ifdef DD_DEBUG
	/* x must be a singleton */
	assert((unsigned) x == table->subtables[x].next);
#endif
	if (x == xHigh) return(1);	/* just one variable */

	initGroupSize = 1;

	moveDown = ddSymmSiftingDown(table,x,xHigh);
	    /* after this point x --> xHigh, unless early term */
	if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
	if (moveDown == NULL) return(1);

	x = moveDown->y;
	/* Find bottom of x's group */
	i = x;
	while ((unsigned) i < table->subtables[i].next) {
	    i = table->subtables[i].next;
	}
#ifdef DD_DEBUG
	/* x should be the top of the symmetry group and i the bottom */
	assert((unsigned) i >= table->subtables[i].next);
	assert((unsigned) x == table->subtables[i].next);
#endif
	finalGroupSize = i - x + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetry groups detected, return to best position */
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	} else {
	    initialSize = table->keys - table->isolated;
	    moveUp = ddSymmSiftingUp(table,x,xLow);
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	}
	if (!result) goto ddSymmSiftingAuxOutOfMem;

    } else if (cuddNextHigh(table,x) > xHigh) { /* Sift up */
	/* Find top of x's symm group */
	i = x;				/* bottom */
	x = table->subtables[x].next;	/* top */

	if (x == xLow) return(1); /* just one big group */

	initGroupSize = i - x + 1;

	moveUp = ddSymmSiftingUp(table,x,xLow);
	    /* after this point x --> xLow, unless early term */
	if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;
	if (moveUp == NULL) return(1);

	x = moveUp->x;
	/* Find top of x's group */
	i = table->subtables[x].next;
#ifdef DD_DEBUG
	/* x should be the bottom of the symmetry group and i the top */
	assert((unsigned) x >= table->subtables[x].next);
	assert((unsigned) i == table->subtables[x].next);
#endif
	finalGroupSize = x - i + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetry groups detected, return to best position */
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	} else {
	    initialSize = table->keys - table->isolated;
	    moveDown = ddSymmSiftingDown(table,x,xHigh);
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	}
	if (!result) goto ddSymmSiftingAuxOutOfMem;

    } else if ((x - xLow) > (xHigh - x)) { /* must go down first: shorter */

	moveDown = ddSymmSiftingDown(table,x,xHigh);
	/* at this point x == xHigh, unless early term */
	if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;

	if (moveDown != NULL) {
	    x = moveDown->y;	/* x is top here */
	    i = x;
	    while ((unsigned) i < table->subtables[i].next) {
		i = table->subtables[i].next;
	    }
	} else {
	    i = x;
	    while ((unsigned) i < table->subtables[i].next) {
		i = table->subtables[i].next;
	    }
	    x = table->subtables[i].next;
	}
#ifdef DD_DEBUG
	/* x should be the top of the symmetry group and i the bottom */
	assert((unsigned) i >= table->subtables[i].next);
	assert((unsigned) x == table->subtables[i].next);
#endif
	initGroupSize = i - x + 1;

	moveUp = ddSymmSiftingUp(table,x,xLow);
	if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;

	if (moveUp != NULL) {
	    x = moveUp->x;
	    i = table->subtables[x].next;
	} else {
	    i = x;
	    while ((unsigned) x < table->subtables[x].next)
		x = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x should be the bottom of the symmetry group and i the top */
	assert((unsigned) x >= table->subtables[x].next);
	assert((unsigned) i == table->subtables[x].next);
#endif
	finalGroupSize = x - i + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetry groups detected, return to best position */
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	} else {
	    while (moveDown != NULL) {
		move = moveDown->next;
		cuddDeallocMove(table, moveDown);
		moveDown = move;
	    }
	    initialSize = table->keys - table->isolated;
	    moveDown = ddSymmSiftingDown(table,x,xHigh);
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	}
	if (!result) goto ddSymmSiftingAuxOutOfMem;

    } else { /* moving up first: shorter */
	/* Find top of x's symmetry group */
	x = table->subtables[x].next;

	moveUp = ddSymmSiftingUp(table,x,xLow);
	/* at this point x == xHigh, unless early term */
	if (moveUp == MV_OOM) goto ddSymmSiftingAuxOutOfMem;

	if (moveUp != NULL) {
	    x = moveUp->x;
	    i = table->subtables[x].next;
	} else {
	    while ((unsigned) x < table->subtables[x].next)
		x = table->subtables[x].next;
	    i = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x is bottom of the symmetry group and i is top */
	assert((unsigned) x >= table->subtables[x].next);
	assert((unsigned) i == table->subtables[x].next);
#endif
	initGroupSize = x - i + 1;

	moveDown = ddSymmSiftingDown(table,x,xHigh);
	if (moveDown == MV_OOM) goto ddSymmSiftingAuxOutOfMem;

	if (moveDown != NULL) {
	    x = moveDown->y;
	    i = x;
	    while ((unsigned) i < table->subtables[i].next) {
		i = table->subtables[i].next;
	    }
	} else {
	    i = x;
	    x = table->subtables[x].next;
	}
#ifdef DD_DEBUG
	/* x should be the top of the symmetry group and i the bottom */
	assert((unsigned) i >= table->subtables[i].next);
	assert((unsigned) x == table->subtables[i].next);
#endif
	finalGroupSize = i - x + 1;

	if (initGroupSize == finalGroupSize) {
	    /* No new symmetries detected, go back to best position */
	    result = ddSymmSiftingBackward(table,moveDown,initialSize);
	} else {
	    while (moveUp != NULL) {
		move = moveUp->next;
		cuddDeallocMove(table, moveUp);
		moveUp = move;
	    }
	    initialSize = table->keys - table->isolated;
	    moveUp = ddSymmSiftingUp(table,x,xLow);
	    result = ddSymmSiftingBackward(table,moveUp,initialSize);
	}
	if (!result) goto ddSymmSiftingAuxOutOfMem;
    }

    while (moveDown != NULL) {
	move = moveDown->next;
	cuddDeallocMove(table, moveDown);
	moveDown = move;
    }
    while (moveUp != NULL) {
	move = moveUp->next;
	cuddDeallocMove(table, moveUp);
	moveUp = move;
    }

    return(1);

ddSymmSiftingAuxOutOfMem:
    if (moveDown != MV_OOM) {
	while (moveDown != NULL) {
	    move = moveDown->next;
	    cuddDeallocMove(table, moveDown);
	    moveDown = move;
	}
    }
    if (moveUp != MV_OOM) {
	while (moveUp != NULL) {
	    move = moveUp->next;
	    cuddDeallocMove(table, moveUp);
	    moveUp = move;
	}
    }

    return(0);

} /* end of ddSymmSiftingAux */
Example #7
0
/**Function********************************************************************

  Synopsis    [Sifts one variable up and down until it has taken all
  positions. Checks for aggregation.]

  Description [Sifts one variable up and down until it has taken all
  positions. Checks for aggregation. There may be at most two sweeps,
  even if the group grows.  Assumes that x is either an isolated
  variable, or it is the bottom of a group. All groups may not have
  been found. The variable being moved is returned to the best position
  seen during sifting.  Returns 1 in case of success; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
zddGroupSiftingAux(
  DdManager * table,
  int  x,
  int  xLow,
  int  xHigh)
{
    Move *move;
    Move *moves;	/* list of moves */
    int  initialSize;
    int  result;


#ifdef DD_DEBUG
    if (pr > 0) (void) fprintf(table->out,"zddGroupSiftingAux from %d to %d\n",xLow,xHigh);
    assert((unsigned) x >= table->subtableZ[x].next); /* x is bottom of group */
#endif

    initialSize = table->keysZ;
    moves = NULL;

    if (x == xLow) { /* Sift down */
#ifdef DD_DEBUG
	/* x must be a singleton */
	assert((unsigned) x == table->subtableZ[x].next);
#endif
	if (x == xHigh) return(1);	/* just one variable */

	if (!zddGroupSiftingDown(table,x,xHigh,&moves))
	    goto zddGroupSiftingAuxOutOfMem;
	/* at this point x == xHigh, unless early term */

	/* move backward and stop at best position */
	result = zddGroupSiftingBackward(table,moves,initialSize);
#ifdef DD_DEBUG
	assert(table->keysZ <= (unsigned) initialSize);
#endif
	if (!result) goto zddGroupSiftingAuxOutOfMem;

    } else if (cuddZddNextHigh(table,x) > xHigh) { /* Sift up */
#ifdef DD_DEBUG
	/* x is bottom of group */
	assert((unsigned) x >= table->subtableZ[x].next);
#endif
	/* Find top of x's group */
	x = table->subtableZ[x].next;

	if (!zddGroupSiftingUp(table,x,xLow,&moves))
	    goto zddGroupSiftingAuxOutOfMem;
	/* at this point x == xLow, unless early term */

	/* move backward and stop at best position */
	result = zddGroupSiftingBackward(table,moves,initialSize);
#ifdef DD_DEBUG
	assert(table->keysZ <= (unsigned) initialSize);
#endif
	if (!result) goto zddGroupSiftingAuxOutOfMem;

    } else if (x - xLow > xHigh - x) { /* must go down first: shorter */
	if (!zddGroupSiftingDown(table,x,xHigh,&moves))
	    goto zddGroupSiftingAuxOutOfMem;
	/* at this point x == xHigh, unless early term */

	/* Find top of group */
	if (moves) {
	    x = moves->y;
	}
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;
	x = table->subtableZ[x].next;
#ifdef DD_DEBUG
	/* x should be the top of a group */
	assert((unsigned) x <= table->subtableZ[x].next);
#endif

	if (!zddGroupSiftingUp(table,x,xLow,&moves))
	    goto zddGroupSiftingAuxOutOfMem;

	/* move backward and stop at best position */
	result = zddGroupSiftingBackward(table,moves,initialSize);
#ifdef DD_DEBUG
	assert(table->keysZ <= (unsigned) initialSize);
#endif
	if (!result) goto zddGroupSiftingAuxOutOfMem;

    } else { /* moving up first: shorter */
	/* Find top of x's group */
	x = table->subtableZ[x].next;

	if (!zddGroupSiftingUp(table,x,xLow,&moves))
	    goto zddGroupSiftingAuxOutOfMem;
	/* at this point x == xHigh, unless early term */

	if (moves) {
	    x = moves->x;
	}
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;
#ifdef DD_DEBUG
	/* x is bottom of a group */
	assert((unsigned) x >= table->subtableZ[x].next);
#endif

	if (!zddGroupSiftingDown(table,x,xHigh,&moves))
	    goto zddGroupSiftingAuxOutOfMem;

	/* move backward and stop at best position */
	result = zddGroupSiftingBackward(table,moves,initialSize);
#ifdef DD_DEBUG
	assert(table->keysZ <= (unsigned) initialSize);
#endif
	if (!result) goto zddGroupSiftingAuxOutOfMem;
    }

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

    return(1);

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

    return(0);

} /* end of zddGroupSiftingAux */
Example #8
0
/**Function********************************************************************

  Synopsis [Given x_low <= x <= x_high moves x up and down between the
  boundaries.]

  Description [Given x_low <= x <= x_high moves x up and down between the
  boundaries. Finds the best position and does the required changes.
  Assumes that x is not part of a symmetry group. Returns 1 if
  successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
cuddZddSymmSiftingAux(
  DdManager * table,
  int  x,
  int  x_low,
  int  x_high)
{
    Move *move;
    Move *move_up;	/* list of up move */
    Move *move_down;	/* list of down move */
    int	 initial_size;
    int	 result;
    int	 i;
    int  topbot;	/* index to either top or bottom of symmetry group */
    int	 init_group_size, final_group_size;

    initial_size = table->keysZ;

    move_down = NULL;
    move_up = NULL;

    /* Look for consecutive symmetries above x. */
    for (i = x; i > x_low; i--) {
	if (!cuddZddSymmCheck(table, i - 1, i))
            break;
	/* find top of i-1's symmetry */
	topbot = table->subtableZ[i - 1].next;
	table->subtableZ[i - 1].next = i;
	table->subtableZ[x].next = topbot;
	/* x is bottom of group so its symmetry is top of i-1's
	   group */
	i = topbot + 1; /* add 1 for i--, new i is top of symm group */
    }
    /* Look for consecutive symmetries below x. */
    for (i = x; i < x_high; i++) {
	if (!cuddZddSymmCheck(table, i, i + 1))
            break;
	/* find bottom of i+1's symm group */
	topbot = i + 1;
	while ((unsigned) topbot < table->subtableZ[topbot].next)
	    topbot = table->subtableZ[topbot].next;

	table->subtableZ[topbot].next = table->subtableZ[i].next;
	table->subtableZ[i].next = i + 1;
	i = topbot - 1; /* add 1 for i++,
			   new i is bottom of symm group */
    }

    /* Now x maybe in the middle of a symmetry group. */
    if (x == x_low) { /* Sift down */
	/* Find bottom of x's symm group */
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;

	i = table->subtableZ[x].next;
	init_group_size = x - i + 1;

	move_down = cuddZddSymmSifting_down(table, x, x_high,
	    initial_size);
	/* after that point x --> x_high, unless early term */
	if (move_down == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingAuxOutOfMem;

	if (move_down == NULL ||
	    table->subtableZ[move_down->y].next != move_down->y) {
	    /* symmetry detected may have to make another complete
	       pass */
            if (move_down != NULL)
		x = move_down->y;
	    else
		x = table->subtableZ[x].next;
	    i = x;
	    while ((unsigned) i < table->subtableZ[i].next) {
		i = table->subtableZ[i].next;
	    }
	    final_group_size = i - x + 1;

	    if (init_group_size == final_group_size) {
		/* No new symmetry groups detected,
		   return to best position */
		result = cuddZddSymmSiftingBackward(table,
		    move_down, initial_size);
	    }
	    else {
		initial_size = table->keysZ;
		move_up = cuddZddSymmSifting_up(table, x, x_low,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_down,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingAuxOutOfMem;
    }
    else if (x == x_high) { /* Sift up */
	/* Find top of x's symm group */
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;
	x = table->subtableZ[x].next;

	i = x;
	while ((unsigned) i < table->subtableZ[i].next) {
	    i = table->subtableZ[i].next;
	}
	init_group_size = i - x + 1;

	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
	/* after that point x --> x_low, unless early term */
	if (move_up == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingAuxOutOfMem;

	if (move_up == NULL ||
	    table->subtableZ[move_up->x].next != move_up->x) {
	    /* symmetry detected may have to make another complete
		pass */
            if (move_up != NULL)
		x = move_up->x;
	    else {
		while ((unsigned) x < table->subtableZ[x].next)
		    x = table->subtableZ[x].next;
	    }
	    i = table->subtableZ[x].next;
	    final_group_size = x - i + 1;

	    if (init_group_size == final_group_size) {
		/* No new symmetry groups detected,
		   return to best position */
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	    else {
		initial_size = table->keysZ;
		move_down = cuddZddSymmSifting_down(table, x, x_high,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_up,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingAuxOutOfMem;
    }
    else if ((x - x_low) > (x_high - x)) { /* must go down first:
						shorter */
	/* Find bottom of x's symm group */
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;

	move_down = cuddZddSymmSifting_down(table, x, x_high,
	    initial_size);
	/* after that point x --> x_high, unless early term */
	if (move_down == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingAuxOutOfMem;

	if (move_down != NULL) {
	    x = move_down->y;
	}
	else {
	    x = table->subtableZ[x].next;
	}
	i = x;
	while ((unsigned) i < table->subtableZ[i].next) {
	    i = table->subtableZ[i].next;
	}
	init_group_size = i - x + 1;

	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
	if (move_up == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingAuxOutOfMem;

	if (move_up == NULL ||
	    table->subtableZ[move_up->x].next != move_up->x) {
	    /* symmetry detected may have to make another complete
	       pass */
	    if (move_up != NULL) {
		x = move_up->x;
	    }
	    else {
		while ((unsigned) x < table->subtableZ[x].next)
		    x = table->subtableZ[x].next;
	    }
	    i = table->subtableZ[x].next;
	    final_group_size = x - i + 1;

	    if (init_group_size == final_group_size) {
		/* No new symmetry groups detected,
		   return to best position */
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	    else {
		while (move_down != NULL) {
		    move = move_down->next;
		    cuddDeallocMove(table, move_down);
		    move_down = move;
		}
		initial_size = table->keysZ;
		move_down = cuddZddSymmSifting_down(table, x, x_high,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_up,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingAuxOutOfMem;
    }
    else { /* moving up first:shorter */
        /* Find top of x's symmetry group */
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;
	x = table->subtableZ[x].next;

	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
	/* after that point x --> x_high, unless early term */
	if (move_up == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingAuxOutOfMem;

	if (move_up != NULL) {
	    x = move_up->x;
	}
	else {
	    while ((unsigned) x < table->subtableZ[x].next)
		x = table->subtableZ[x].next;
	}
	i = table->subtableZ[x].next;
	init_group_size = x - i + 1;

	move_down = cuddZddSymmSifting_down(table, x, x_high,
	    initial_size);
	if (move_down == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingAuxOutOfMem;

	if (move_down == NULL ||
	    table->subtableZ[move_down->y].next != move_down->y) {
	    /* symmetry detected may have to make another complete
	       pass */
            if (move_down != NULL) {
		x = move_down->y;
	    }
	    else {
		x = table->subtableZ[x].next;
	    }
	    i = x;
	    while ((unsigned) i < table->subtableZ[i].next) {
		i = table->subtableZ[i].next;
	    }
	    final_group_size = i - x + 1;

	    if (init_group_size == final_group_size) {
		/* No new symmetries detected,
		   go back to best position */
		result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
	    }
	    else {
		while (move_up != NULL) {
		    move = move_up->next;
		    cuddDeallocMove(table, move_up);
		    move_up = move;
		}
		initial_size = table->keysZ;
		move_up = cuddZddSymmSifting_up(table, x, x_low,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_down,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingAuxOutOfMem;
    }

    while (move_down != NULL) {
	move = move_down->next;
	cuddDeallocMove(table, move_down);
	move_down = move;
    }
    while (move_up != NULL) {
	move = move_up->next;
	cuddDeallocMove(table, move_up);
	move_up = move;
    }

    return(1);

cuddZddSymmSiftingAuxOutOfMem:
    if (move_down != ZDD_MV_OOM) {
	while (move_down != NULL) {
	    move = move_down->next;
	    cuddDeallocMove(table, move_down);
	    move_down = move;
	}
    }
    if (move_up != ZDD_MV_OOM) {
	while (move_up != NULL) {
	    move = move_up->next;
	    cuddDeallocMove(table, move_up);
	    move_up = move;
	}
    }

    return(0);

} /* end of cuddZddSymmSiftingAux */
Example #9
0
/**Function********************************************************************

  Synopsis    [Reorders variables by a sequence of (non-adjacent) swaps.]

  Description [Implementation of Plessier's algorithm that reorders
  variables by a sequence of (non-adjacent) swaps.
    <ol>
    <li> Select two variables (RANDOM or HEURISTIC).
    <li> Permute these variables.
    <li> If the nodes have decreased accept the permutation.
    <li> Otherwise reconstruct the original heap.
    <li> Loop.
    </ol>
  Returns 1 in case of success; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
cuddZddSwapping(
  DdManager * table,
  int lower,
  int upper,
  Cudd_ReorderingType heuristic)
{
    int	i, j;
    int max, keys;
    int nvars;
    int	x, y;
    int iterate;
    int previousSize;
    Move *moves, *move;
    int	pivot;
    int modulo;
    int result;

#ifdef DD_DEBUG
    /* Sanity check */
    assert(lower >= 0 && upper < table->sizeZ && lower <= upper);
#endif

    nvars = upper - lower + 1;
    iterate = nvars;

    for (i = 0; i < iterate; i++) {
	if (heuristic == CUDD_REORDER_RANDOM_PIVOT) {
	    /* Find pivot <= id with maximum keys. */
	    for (max = -1, j = lower; j <= upper; j++) {
		if ((keys = table->subtableZ[j].keys) > max) {
		    max = keys;
		    pivot = j;
		}
	    }

	    modulo = upper - pivot;
	    if (modulo == 0) {
		y = pivot;	/* y = nvars-1 */
	    } else {
		/* y = random # from {pivot+1 .. nvars-1} */
		y = pivot + 1 + (int) (Cudd_Random() % modulo);
	    }

	    modulo = pivot - lower - 1;
	    if (modulo < 1) {	/* if pivot = 1 or 0 */
		x = lower;
	    } else {
		do { /* x = random # from {0 .. pivot-2} */
		    x = (int) Cudd_Random() % modulo;
		} while (x == y);
		  /* Is this condition really needed, since x and y
		     are in regions separated by pivot? */
	    }
	} else {
	    x = (int) (Cudd_Random() % nvars) + lower;
	    do {
		y = (int) (Cudd_Random() % nvars) + lower;
	    } while (x == y);
	}

	previousSize = table->keysZ;
	moves = zddSwapAny(table, x, y);
	if (moves == NULL)
	    goto cuddZddSwappingOutOfMem;

	result = cuddZddSiftingBackward(table, moves, previousSize);
	if (!result)
	    goto cuddZddSwappingOutOfMem;

	while (moves != NULL) {
	    move = moves->next;
	    cuddDeallocMove(table, moves);
	    moves = move;
	}
#ifdef DD_STATS
	if (table->keysZ < (unsigned) previousSize) {
	    (void) fprintf(table->out,"-");
	} else if (table->keysZ > (unsigned) previousSize) {
	    (void) fprintf(table->out,"+");	/* should never happen */
	} else {
	    (void) fprintf(table->out,"=");
	}
	fflush(table->out);
#endif
    }

    return(1);

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

} /* end of cuddZddSwapping */
Example #10
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;
	cuddDeallocMove(table, moves);
	moves = move;
    }
    return(NULL);

} /* end of zddSwapAny */
Example #11
0
/**Function********************************************************************

  Synopsis    [Given xLow <= x <= xHigh moves x up and down between the
  boundaries.]

  Description [Given xLow <= x <= xHigh moves x up and down between the
  boundaries. Finds the best position and does the required changes.
  Returns 1 if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
cuddZddSiftingAux(
  DdManager * table,
  int  x,
  int  x_low,
  int  x_high)
{
    Move	*move;
    Move	*moveUp;	/* list of up move */
    Move	*moveDown;	/* list of down move */

    int		initial_size;
    int		result;

    initial_size = table->keysZ;

#ifdef DD_DEBUG
    assert(table->subtableZ[x].keys > 0);
#endif

    moveDown = NULL;
    moveUp = NULL;

    if (x == x_low) {
	moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
	/* after that point x --> x_high */
	if (moveDown == NULL)
	    goto cuddZddSiftingAuxOutOfMem;
	result = cuddZddSiftingBackward(table, moveDown,
	    initial_size);
	/* move backward and stop at best position */
	if (!result)
	    goto cuddZddSiftingAuxOutOfMem;

    }
    else if (x == x_high) {
	moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
	/* after that point x --> x_low */
	if (moveUp == NULL)
	    goto cuddZddSiftingAuxOutOfMem;
	result = cuddZddSiftingBackward(table, moveUp, initial_size);
	/* move backward and stop at best position */
	if (!result)
	    goto cuddZddSiftingAuxOutOfMem;
    }
    else if ((x - x_low) > (x_high - x)) {
	/* must go down first:shorter */
	moveDown = cuddZddSiftingDown(table, x, x_high, initial_size);
	/* after that point x --> x_high */
	if (moveDown == NULL)
	    goto cuddZddSiftingAuxOutOfMem;
	moveUp = cuddZddSiftingUp(table, moveDown->y, x_low,
	    initial_size);
	if (moveUp == NULL)
	    goto cuddZddSiftingAuxOutOfMem;
	result = cuddZddSiftingBackward(table, moveUp, initial_size);
	/* move backward and stop at best position */
	if (!result)
	    goto cuddZddSiftingAuxOutOfMem;
    }
    else {
	moveUp = cuddZddSiftingUp(table, x, x_low, initial_size);
	/* after that point x --> x_high */
	if (moveUp == NULL)
	    goto cuddZddSiftingAuxOutOfMem;
	moveDown = cuddZddSiftingDown(table, moveUp->x, x_high,
	    initial_size);
	/* then move up */
	if (moveDown == NULL)
	    goto cuddZddSiftingAuxOutOfMem;
	result = cuddZddSiftingBackward(table, moveDown,
	    initial_size);
	/* move backward and stop at best position */
	if (!result)
	    goto cuddZddSiftingAuxOutOfMem;
    }

    while (moveDown != NULL) {
	move = moveDown->next;
	cuddDeallocMove(table, moveDown);
	moveDown = move;
    }
    while (moveUp != NULL) {
	move = moveUp->next;
	cuddDeallocMove(table, moveUp);
	moveUp = move;
    }

    return(1);

cuddZddSiftingAuxOutOfMem:
    while (moveDown != NULL) {
	move = moveDown->next;
	cuddDeallocMove(table, moveDown);
	moveDown = move;
    }
    while (moveUp != NULL) {
	move = moveUp->next;
	cuddDeallocMove(table, moveUp);
	moveUp = move;
    }

    return(0);

} /* end of cuddZddSiftingAux */
Example #12
0
/**Function********************************************************************

  Synopsis    [Sifts down a variable until it reaches position xHigh.]

  Description [Sifts down a variable until it reaches position xHigh.
  Assumes that x is the bottom of a group (or a singleton).  Records
  all the moves.  Returns 1 in case of success; 0 otherwise.]

  SideEffects [None]

******************************************************************************/
static int
zddGroupSiftingDown(
  DdManager * table,
  int  x,
  int  xHigh,
  Move ** moves)
{
    Move *move;
    int  y;
    int  size;
    int  limitSize;
    int  gybot;


    /* Initialize R */
    limitSize = size = table->keysZ;
    y = cuddZddNextHigh(table,x);
    while (y <= xHigh) {
	/* Find bottom of y group. */
	gybot = table->subtableZ[y].next;
	while (table->subtableZ[gybot].next != (unsigned) y)
	    gybot = table->subtableZ[gybot].next;

	if (table->subtableZ[x].next == (unsigned) x &&
	    table->subtableZ[y].next == (unsigned) y) {
	    /* x and y are self groups */
	    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 zddGroupSiftingDownOutOfMem;

	    /* Record move. */
	    move = (Move *) cuddDynamicAllocNode(table);
	    if (move == NULL) goto zddGroupSiftingDownOutOfMem;
	    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,"zddGroupSiftingDown (2 single groups):\n");
#endif
	    if ((double) size > (double) limitSize * table->maxGrowth)
		return(1);
	    if (size < limitSize) limitSize = size;
	    x = y;
	    y = cuddZddNextHigh(table,x);
	} else { /* Group move */
	    size = zddGroupMove(table,x,y,moves);
	    if (size == 0) goto zddGroupSiftingDownOutOfMem;
	    if ((double) size > (double) limitSize * table->maxGrowth)
		return(1);
	    if (size < limitSize) limitSize = size;
	}
	x = gybot;
	y = cuddZddNextHigh(table,x);
    }

    return(1);

zddGroupSiftingDownOutOfMem:
    while (*moves != NULL) {
	move = (*moves)->next;
	cuddDeallocMove(table, *moves);
	*moves = move;
    }

    return(0);

} /* end of zddGroupSiftingDown */
Example #13
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;

    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 */
	    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;
	cuddDeallocMove(table, *moves);
	*moves = move;
    }
    return(0);

} /* end of zddGroupSiftingUp */
Example #14
0
/**Function********************************************************************

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

  Description [Moves x down until either it reaches the bound (x_high)
  or the size of the ZDD heap increases too much. Assumes that x is the
  bottom 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_down(
  DdManager * table,
  int  x,
  int  x_high,
  int  initial_size)
{
    Move	*moves;
    Move	*move;
    int		y;
    int		size;
    int		limit_size = initial_size;
    int		i, gxtop, gybot;

    moves = NULL;
    y = cuddZddNextHigh(table, x);
    while (y <= x_high) {
	gybot = table->subtableZ[y].next;
	while (table->subtableZ[gybot].next != (unsigned) y)
	    gybot = table->subtableZ[gybot].next;
	if (cuddZddSymmCheck(table, x, y)) {
	    /* Symmetry found, attach symm groups */
	    gxtop = table->subtableZ[x].next;
	    table->subtableZ[x].next = y;
	    i = table->subtableZ[y].next;
	    while (table->subtableZ[i].next != (unsigned) y)
		i = table->subtableZ[i].next;
	    table->subtableZ[i].next = gxtop;
	}
	else if ((table->subtableZ[x].next == (unsigned) x) &&
	    (table->subtableZ[y].next == (unsigned) y)) {
	    /* x and y have self symmetry */
	    size = cuddZddSwapInPlace(table, x, y);
	    if (size == 0)
		goto cuddZddSymmSifting_downOutOfMem;
	    move = (Move *)cuddDynamicAllocNode(table);
	    if (move == NULL)
		goto cuddZddSymmSifting_downOutOfMem;
	    move->x = x;
	    move->y = y;
	    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;
	    x = y;
	    y = cuddZddNextHigh(table, x);
	}
	else { /* Group move */
	    size = zdd_group_move(table, x, y, &moves);
	    if ((double)size >
		(double)limit_size * table->maxGrowth)
		return(moves);
	    if (size < limit_size)
		limit_size = size;
	}
	x = gybot;
	y = cuddZddNextHigh(table, x);
    }

    return(moves);

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

} /* end of cuddZddSymmSifting_down */
Example #15
0
/**Function********************************************************************

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

  Description [Moves x up until either it reaches the bound (xLow) or
  the size of the DD 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; MV_OOM if memory is full.]

  SideEffects [None]

******************************************************************************/
static Move *
ddSymmSiftingUp(
  DdManager * table,
  int  y,
  int  xLow)
{
    Move *moves;
    Move *move;
    int	 x;
    int	 size;
    int  i;
    int  gxtop,gybot;
    int  limitSize;
    int  xindex, yindex;
    int  zindex;
    int  z;
    int  isolated;
    int  L;	/* lower bound on DD size */
#ifdef DD_DEBUG
    int  checkL;
#endif


    moves = NULL;
    yindex = table->invperm[y];

    /* Initialize the lower bound.
    ** The part of the DD below the bottom of y' group will not change.
    ** The part of the DD above y that does not interact with y will not
    ** change. The rest may vanish in the best case, except for
    ** the nodes at level xLow, which will not vanish, regardless.
    */
    limitSize = L = table->keys - table->isolated;
    gybot = y;
    while ((unsigned) gybot < table->subtables[gybot].next)
	gybot = table->subtables[gybot].next;
    for (z = xLow + 1; z <= gybot; z++) {
	zindex = table->invperm[z];
	if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
	    isolated = table->vars[zindex]->ref == 1;
	    L -= table->subtables[z].keys - isolated;
	}
    }

    x = cuddNextLow(table,y);
    while (x >= xLow && L <= limitSize) {
#ifdef DD_DEBUG
	gybot = y;
	while ((unsigned) gybot < table->subtables[gybot].next)
	    gybot = table->subtables[gybot].next;
	checkL = table->keys - table->isolated;
	for (z = xLow + 1; z <= gybot; z++) {
	    zindex = table->invperm[z];
	    if (zindex == yindex || cuddTestInteract(table,zindex,yindex)) {
		isolated = table->vars[zindex]->ref == 1;
		checkL -= table->subtables[z].keys - isolated;
	    }
	}
	assert(L == checkL);
#endif
	gxtop = table->subtables[x].next;
	if (cuddSymmCheck(table,x,y)) {
	    /* Symmetry found, attach symm groups */
	    table->subtables[x].next = y;
	    i = table->subtables[y].next;
	    while (table->subtables[i].next != (unsigned) y)
		i = table->subtables[i].next;
	    table->subtables[i].next = gxtop;
	} else if (table->subtables[x].next == (unsigned) x &&
		   table->subtables[y].next == (unsigned) y) {
	    /* x and y have self symmetry */
	    xindex = table->invperm[x];
	    size = cuddSwapInPlace(table,x,y);
#ifdef DD_DEBUG
	    assert(table->subtables[x].next == (unsigned) x);
	    assert(table->subtables[y].next == (unsigned) y);
#endif
	    if (size == 0) goto ddSymmSiftingUpOutOfMem;
	    /* Update the lower bound. */
	    if (cuddTestInteract(table,xindex,yindex)) {
		isolated = table->vars[xindex]->ref == 1;
		L += table->subtables[y].keys - isolated;
	    }
	    move = (Move *) cuddDynamicAllocNode(table);
	    if (move == NULL) goto ddSymmSiftingUpOutOfMem;
	    move->x = x;
	    move->y = y;
	    move->size = size;
	    move->next = moves;
	    moves = move;
	    if ((double) size > (double) limitSize * table->maxGrowth)
		return(moves);
	    if (size < limitSize) limitSize = size;
	} else { /* Group move */
	    size = ddSymmGroupMove(table,x,y,&moves);
	    if (size == 0) goto ddSymmSiftingUpOutOfMem;
	    /* Update the lower bound. */
	    z = moves->y;
	    do {
		zindex = table->invperm[z];
		if (cuddTestInteract(table,zindex,yindex)) {
		    isolated = table->vars[zindex]->ref == 1;
		    L += table->subtables[z].keys - isolated;
		}
		z = table->subtables[z].next;
	    } while (z != (int) moves->y);
	    if ((double) size > (double) limitSize * table->maxGrowth)
		return(moves);
	    if (size < limitSize) limitSize = size;
	}
	y = gxtop;
	x = cuddNextLow(table,y);
    }

    return(moves);

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

} /* end of ddSymmSiftingUp */
Example #16
0
/**Function********************************************************************

  Synopsis [Swaps two groups.]

  Description [Swaps two groups. x is assumed to be the bottom variable
  of the first group. y is assumed to be the top variable of the second
  group.  Updates the list of moves. Returns the number of keys in the
  table if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
zdd_group_move(
  DdManager * table,
  int  x,
  int  y,
  Move ** moves)
{
    Move	*move;
    int		size;
    int		i, temp, gxtop, gxbot, gybot, yprev;
    int		swapx, swapy;

    /* NuSMV: add begin */
    swapy = 0;
    swapx = 0;
    /* NuSMV: add end */

#ifdef DD_DEBUG
    assert(x < y);	/* we assume that x < y */
#endif
    /* Find top and bottom for the two groups. */
    gxtop = table->subtableZ[x].next;
    gxbot = x;
    gybot = table->subtableZ[y].next;
    while (table->subtableZ[gybot].next != (unsigned) y)
	gybot = table->subtableZ[gybot].next;
    yprev = gybot;

    while (x <= y) {
	while (y > gxtop) {
	    /* Set correct symmetries. */
	    temp = table->subtableZ[x].next;
	    if (temp == x)
		temp = y;
	    i = gxtop;
	    for (;;) {
		if (table->subtableZ[i].next == (unsigned) x) {
		    table->subtableZ[i].next = y;
		    break;
		} else {
		    i = table->subtableZ[i].next;
		}
	    }
	    if (table->subtableZ[y].next != (unsigned) y) {
		table->subtableZ[x].next = table->subtableZ[y].next;
	    } else {
		table->subtableZ[x].next = x;
	    }

	    if (yprev != y) {
		table->subtableZ[yprev].next = x;
	    } else {
		yprev = x;
	    }
	    table->subtableZ[y].next = temp;

	    size = cuddZddSwapInPlace(table, x, y);
	    if (size == 0)
		goto zdd_group_moveOutOfMem;
            swapx = x;
	    swapy = y;
	    y = x;
	    x--;
	} /* while y > gxtop */

	/* Trying to find the next y. */
	if (table->subtableZ[y].next <= (unsigned) y) {
	    gybot = y;
	} else {
	    y = table->subtableZ[y].next;
	}

	yprev = gxtop;
	gxtop++;
	gxbot++;
	x = gxbot;
    } /* while x <= y, end of group movement */
    move = (Move *)cuddDynamicAllocNode(table);
    if (move == NULL)
	goto zdd_group_moveOutOfMem;
    move->x = swapx;
    move->y = swapy;
    move->size = table->keysZ;
    move->next = *moves;
    *moves = move;

    return(table->keysZ);

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

} /* end of zdd_group_move */
Example #17
0
/**Function********************************************************************

  Synopsis    [Moves x down until either it reaches the bound (xHigh) or
  the size of the DD heap increases too much.]

  Description [Moves x down until either it reaches the bound (xHigh)
  or the size of the DD heap increases too much. Assumes that x is the
  bottom 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; MV_OOM if memory is full.]

  SideEffects [None]

******************************************************************************/
static Move *
ddSymmSiftingDown(
  DdManager * table,
  int  x,
  int  xHigh)
{
    Move *moves;
    Move *move;
    int	 y;
    int	 size;
    int  limitSize;
    int  gxtop,gybot;
    int  R;	/* upper bound on node decrease */
    int  xindex, yindex;
    int  isolated;
    int  z;
    int  zindex;
#ifdef DD_DEBUG
    int  checkR;
#endif

    moves = NULL;
    /* Initialize R */
    xindex = table->invperm[x];
    gxtop = table->subtables[x].next;
    limitSize = size = table->keys - table->isolated;
    R = 0;
    for (z = xHigh; z > gxtop; z--) {
	zindex = table->invperm[z];
	if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
	    isolated = table->vars[zindex]->ref == 1;
	    R += table->subtables[z].keys - isolated;
	}
    }

    y = cuddNextHigh(table,x);
    while (y <= xHigh && size - R < limitSize) {
#ifdef DD_DEBUG
	gxtop = table->subtables[x].next;
	checkR = 0;
	for (z = xHigh; z > gxtop; z--) {
	    zindex = table->invperm[z];
	    if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
		isolated = table->vars[zindex]->ref == 1;
		checkR += table->subtables[z].keys - isolated;
	    }
	}
	assert(R == checkR);
#endif
	gybot = table->subtables[y].next;
	while (table->subtables[gybot].next != (unsigned) y)
	    gybot = table->subtables[gybot].next;
	if (cuddSymmCheck(table,x,y)) {
	    /* Symmetry found, attach symm groups */
	    gxtop = table->subtables[x].next;
	    table->subtables[x].next = y;
	    table->subtables[gybot].next = gxtop;
	} else if (table->subtables[x].next == (unsigned) x &&
		   table->subtables[y].next == (unsigned) y) {
	    /* x and y have self symmetry */
	    /* Update upper bound on node decrease. */
	    yindex = table->invperm[y];
	    if (cuddTestInteract(table,xindex,yindex)) {
		isolated = table->vars[yindex]->ref == 1;
		R -= table->subtables[y].keys - isolated;
	    }
	    size = cuddSwapInPlace(table,x,y);
#ifdef DD_DEBUG
	    assert(table->subtables[x].next == (unsigned) x);
	    assert(table->subtables[y].next == (unsigned) y);
#endif
	    if (size == 0) goto ddSymmSiftingDownOutOfMem;
	    move = (Move *) cuddDynamicAllocNode(table);
	    if (move == NULL) goto ddSymmSiftingDownOutOfMem;
	    move->x = x;
	    move->y = y;
	    move->size = size;
	    move->next = moves;
	    moves = move;
	    if ((double) size > (double) limitSize * table->maxGrowth)
		return(moves);
	    if (size < limitSize) limitSize = size;
	} else { /* Group move */
	    /* Update upper bound on node decrease: first phase. */
	    gxtop = table->subtables[x].next;
	    z = gxtop + 1;
	    do {
		zindex = table->invperm[z];
		if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
		    isolated = table->vars[zindex]->ref == 1;
		    R -= table->subtables[z].keys - isolated;
		}
		z++;
	    } while (z <= gybot);
	    size = ddSymmGroupMove(table,x,y,&moves);
	    if (size == 0) goto ddSymmSiftingDownOutOfMem;
	    if ((double) size > (double) limitSize * table->maxGrowth)
		return(moves);
	    if (size < limitSize) limitSize = size;
	    /* Update upper bound on node decrease: second phase. */
	    gxtop = table->subtables[gybot].next;
	    for (z = gxtop + 1; z <= gybot; z++) {
		zindex = table->invperm[z];
		if (zindex == xindex || cuddTestInteract(table,xindex,zindex)) {
		    isolated = table->vars[zindex]->ref == 1;
		    R += table->subtables[z].keys - isolated;
		}
	    }
	}
	x = gybot;
	y = cuddNextHigh(table,x);
    }

    return(moves);

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

} /* end of ddSymmSiftingDown */
Example #18
0
/**Function********************************************************************

  Synopsis [Given x_low <= x <= x_high moves x up and down between the
  boundaries.]

  Description [Given x_low <= x <= x_high moves x up and down between the
  boundaries. Finds the best position and does the required changes.
  Assumes that x is either an isolated variable, or it is the bottom of
  a symmetry group. All symmetries may not have been found, because of
  exceeded growth limit. Returns 1 if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
cuddZddSymmSiftingConvAux(
  DdManager * table,
  int  x,
  int  x_low,
  int  x_high)
{
    Move	*move;
    Move	*move_up;	/* list of up move */
    Move	*move_down;	/* list of down move */
    int		initial_size;
    int		result;
    int		i;
    int		init_group_size, final_group_size;

    initial_size = table->keysZ;

    move_down = NULL;
    move_up = NULL;

    if (x == x_low) { /* Sift down */
        i = table->subtableZ[x].next;
	init_group_size = x - i + 1;

	move_down = cuddZddSymmSifting_down(table, x, x_high,
	    initial_size);
	/* after that point x --> x_high, unless early term */
	if (move_down == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;

	if (move_down == NULL ||
	    table->subtableZ[move_down->y].next != move_down->y) {
	    /* symmetry detected may have to make another complete
		pass */
            if (move_down != NULL)
		x = move_down->y;
	    else {
		while ((unsigned) x < table->subtableZ[x].next)
		    x = table->subtableZ[x].next;
		x = table->subtableZ[x].next;
	    }
	    i = x;
	    while ((unsigned) i < table->subtableZ[i].next) {
		i = table->subtableZ[i].next;
	    }
	    final_group_size = i - x + 1;

	    if (init_group_size == final_group_size) {
		/* No new symmetries detected,
		   go back to best position */
		result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
	    }
	    else {
		initial_size = table->keysZ;
		move_up = cuddZddSymmSifting_up(table, x, x_low,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_down,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;
    }
    else if (x == x_high) { /* Sift up */
	/* Find top of x's symm group */
	while ((unsigned) x < table->subtableZ[x].next)
	    x = table->subtableZ[x].next;
	x = table->subtableZ[x].next;

	i = x;
	while ((unsigned) i < table->subtableZ[i].next) {
	    i = table->subtableZ[i].next;
	}
	init_group_size = i - x + 1;

	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
	/* after that point x --> x_low, unless early term */
	if (move_up == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;

	if (move_up == NULL ||
	    table->subtableZ[move_up->x].next != move_up->x) {
	    /* symmetry detected may have to make another complete
	       pass */
            if (move_up != NULL)
		x = move_up->x;
	    else {
		while ((unsigned) x < table->subtableZ[x].next)
		    x = table->subtableZ[x].next;
	    }
	    i = table->subtableZ[x].next;
	    final_group_size = x - i + 1;

	    if (init_group_size == final_group_size) {
		/* No new symmetry groups detected,
		   return to best position */
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	    else {
		initial_size = table->keysZ;
		move_down = cuddZddSymmSifting_down(table, x, x_high,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_up,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;
    }
    else if ((x - x_low) > (x_high - x)) { /* must go down first:
						shorter */
	move_down = cuddZddSymmSifting_down(table, x, x_high,
	    initial_size);
	/* after that point x --> x_high */
	if (move_down == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;

	if (move_down != NULL) {
	    x = move_down->y;
	}
	else {
	    while ((unsigned) x < table->subtableZ[x].next)
		x = table->subtableZ[x].next;
	    x = table->subtableZ[x].next;
	}
	i = x;
	while ((unsigned) i < table->subtableZ[i].next) {
	    i = table->subtableZ[i].next;
	}
	init_group_size = i - x + 1;

	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
	if (move_up == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;

	if (move_up == NULL ||
	    table->subtableZ[move_up->x].next != move_up->x) {
	    /* symmetry detected may have to make another complete
	       pass */
	    if (move_up != NULL) {
		x = move_up->x;
	    }
	    else {
		while ((unsigned) x < table->subtableZ[x].next)
		    x = table->subtableZ[x].next;
	    }
            i = table->subtableZ[x].next;
            final_group_size = x - i + 1;

            if (init_group_size == final_group_size) {
		/* No new symmetry groups detected,
		   return to best position */
                result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
            }
	    else {
		while (move_down != NULL) {
		    move = move_down->next;
		    cuddDeallocMove(table, move_down);
		    move_down = move;
		}
		initial_size = table->keysZ;
		move_down = cuddZddSymmSifting_down(table, x, x_high,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_up,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;
    }
    else { /* moving up first:shorter */
	/* Find top of x's symmetry group */
	x = table->subtableZ[x].next;

	move_up = cuddZddSymmSifting_up(table, x, x_low, initial_size);
	/* after that point x --> x_high, unless early term */
	if (move_up == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;

	if (move_up != NULL) {
	    x = move_up->x;
	}
	else {
	    while ((unsigned) x < table->subtableZ[x].next)
		x = table->subtableZ[x].next;
	}
        i = table->subtableZ[x].next;
        init_group_size = x - i + 1;

	move_down = cuddZddSymmSifting_down(table, x, x_high,
	    initial_size);
	if (move_down == ZDD_MV_OOM)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;

	if (move_down == NULL ||
	    table->subtableZ[move_down->y].next != move_down->y) {
	    /* symmetry detected may have to make another complete
	       pass */
            if (move_down != NULL) {
		x = move_down->y;
	    }
	    else {
		while ((unsigned) x < table->subtableZ[x].next)
		    x = table->subtableZ[x].next;
		x = table->subtableZ[x].next;
	    }
            i = x;
            while ((unsigned) i < table->subtableZ[i].next) {
                i = table->subtableZ[i].next;
            }
	    final_group_size = i - x + 1;

            if (init_group_size == final_group_size) {
		/* No new symmetries detected,
		   go back to best position */
                result = cuddZddSymmSiftingBackward(table, move_down,
		    initial_size);
            }
	    else {
		while (move_up != NULL) {
		    move = move_up->next;
		    cuddDeallocMove(table, move_up);
		    move_up = move;
		}
		initial_size = table->keysZ;
		move_up = cuddZddSymmSifting_up(table, x, x_low,
		    initial_size);
		result = cuddZddSymmSiftingBackward(table, move_up,
		    initial_size);
	    }
	}
	else {
	    result = cuddZddSymmSiftingBackward(table, move_down,
		initial_size);
	    /* move backward and stop at best position */
	}
	if (!result)
	    goto cuddZddSymmSiftingConvAuxOutOfMem;
    }

    while (move_down != NULL) {
	move = move_down->next;
	cuddDeallocMove(table, move_down);
	move_down = move;
    }
    while (move_up != NULL) {
	move = move_up->next;
	cuddDeallocMove(table, move_up);
	move_up = move;
    }

    return(1);

cuddZddSymmSiftingConvAuxOutOfMem:
    if (move_down != ZDD_MV_OOM) {
	while (move_down != NULL) {
	    move = move_down->next;
	    cuddDeallocMove(table, move_down);
	    move_down = move;
	}
    }
    if (move_up != ZDD_MV_OOM) {
	while (move_up != NULL) {
	    move = move_up->next;
	    cuddDeallocMove(table, move_up);
	    move_up = move;
	}
    }

    return(0);

} /* end of cuddZddSymmSiftingConvAux */
Example #19
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,swapy;
#if defined(DD_DEBUG) && defined(DD_VERBOSE)
    int  initialSize,bestSize;
#endif

#ifdef 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;
	cuddDeallocMove(table, *moves);
	*moves = move;
    }
    return(0);

} /* end of zddGroupMove */