Beispiel #1
0
/**Function********************************************************************

  Synopsis    [Moves a variable to a specified position.]

  Description [If x==x_low, it executes jumping_down. If x==x_high, it
  executes jumping_up. This funcion is similar to ddSiftingAux. Returns
  1 in case of success; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
ddJumpingAux(
  DdManager * table,
  int  x,
  int  x_low,
  int  x_high,
  double  temp)
{
    Move       *move;
    Move       *moves;        /* list of moves */
    int        initial_size;
    int        result;

    initial_size = table->keys - table->isolated;

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

    moves = NULL;

    if (cuddNextLow(table,x) < x_low) {
	if (cuddNextHigh(table,x) > x_high) return(1);
	moves = ddJumpingDown(table,x,x_high,initial_size);
	/* after that point x --> x_high unless early termination */
	if (moves == NULL) goto ddJumpingAuxOutOfMem;
	/* move backward and stop at best position or accept uphill move */
	result = siftBackwardProb(table,moves,initial_size,temp);
	if (!result) goto ddJumpingAuxOutOfMem;
    } else if (cuddNextHigh(table,x) > x_high) {
	moves = ddJumpingUp(table,x,x_low,initial_size);
	/* after that point x --> x_low unless early termination */
	if (moves == NULL) goto ddJumpingAuxOutOfMem;
	/* move backward and stop at best position or accept uphill move */
	result = siftBackwardProb(table,moves,initial_size,temp);
	if (!result) goto ddJumpingAuxOutOfMem;
    } else {
	(void) fprintf(table->err,"Unexpected condition in ddJumping\n");
	goto ddJumpingAuxOutOfMem;
    }
    while (moves != NULL) {
	move = moves->next;
	cuddDeallocNode(table, (DdNode *) moves);
	moves = move;
    }
    return(1);

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

} /* end of ddJumpingAux */
Beispiel #2
0
/**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;
	cuddDeallocNode(table, (DdNode *) moves);
	moves = move;
    }
    return(NULL);

} /* end of ddJumpingDown */
Beispiel #3
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;
	cuddDeallocNode(table, (DdNode *) moves);
	moves = move;
    }
    return(1);

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

} /* end of ddExchange */
Beispiel #4
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 */
Beispiel #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 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 */
Beispiel #6
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 */