You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							814 lines
						
					
					
						
							22 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							814 lines
						
					
					
						
							22 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddAnneal.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Reordering of DDs based on simulated annealing] | |
|  | |
|   Description [Internal procedures included in this file: | |
| 		<ul> | |
| 		<li> cuddAnnealing() | |
| 		</ul> | |
| 	       Static procedures included in this file: | |
| 		<ul> | |
| 		<li> stopping_criterion() | |
| 		<li> random_generator() | |
| 		<li> ddExchange() | |
| 		<li> ddJumpingAux() | |
| 		<li> ddJumpingUp() | |
| 		<li> ddJumpingDown() | |
| 		<li> siftBackwardProb() | |
| 		<li> copyOrder() | |
| 		<li> restoreOrder() | |
| 		</ul> | |
| 		] | |
|  | |
|   SeeAlso     [] | |
|  | |
|   Author      [Jae-Young Jang, Jorgen Sivesind] | |
|  | |
|   Copyright   [Copyright (c) 1995-2012, Regents of the University of Colorado | |
|  | |
|   All rights reserved. | |
|  | |
|   Redistribution and use in source and binary forms, with or without | |
|   modification, are permitted provided that the following conditions | |
|   are met: | |
|  | |
|   Redistributions of source code must retain the above copyright | |
|   notice, this list of conditions and the following disclaimer. | |
|  | |
|   Redistributions in binary form must reproduce the above copyright | |
|   notice, this list of conditions and the following disclaimer in the | |
|   documentation and/or other materials provided with the distribution. | |
|  | |
|   Neither the name of the University of Colorado nor the names of its | |
|   contributors may be used to endorse or promote products derived from | |
|   this software without specific prior written permission. | |
|  | |
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
|   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
|   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
|   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
|   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
|   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
|   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
|   POSSIBILITY OF SUCH DAMAGE.] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "util.h" | |
| #include "cuddInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Constant declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /* Annealing parameters */ | |
| #define BETA 0.6  | |
| #define ALPHA 0.90 | |
| #define EXC_PROB 0.4  | |
| #define JUMP_UP_PROB 0.36 | |
| #define MAXGEN_RATIO 15.0 | |
| #define STOP_TEMP 1.0 | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddAnneal.c,v 1.15 2012/02/05 01:07:18 fabio Exp $"; | |
| #endif | |
|  | |
| #ifdef DD_STATS | |
| extern	int	ddTotalNumberSwapping; | |
| extern	int	ddTotalNISwaps; | |
| static	int	tosses; | |
| static	int	acceptances; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| static int stopping_criterion (int c1, int c2, int c3, int c4, double temp); | |
| static double random_generator (void); | |
| static int ddExchange (DdManager *table, int x, int y, double temp); | |
| static int ddJumpingAux (DdManager *table, int x, int x_low, int x_high, double temp); | |
| static Move * ddJumpingUp (DdManager *table, int x, int x_low, int initial_size); | |
| static Move * ddJumpingDown (DdManager *table, int x, int x_high, int initial_size); | |
| static int siftBackwardProb (DdManager *table, Move *moves, int size, double temp); | |
| static void copyOrder (DdManager *table, int *array, int lower, int upper); | |
| static int restoreOrder (DdManager *table, int *array, int lower, int upper); | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Get new variable-order by simulated annealing algorithm.] | |
|  | |
|   Description [Get x, y by random selection. Choose either | |
|   exchange or jump randomly. In case of jump, choose between jump_up | |
|   and jump_down randomly. Do exchange or jump and get optimal case. | |
|   Loop until there is no improvement or temperature reaches | |
|   minimum. Returns 1 in case of success; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddAnnealing( | |
|   DdManager * table, | |
|   int  lower, | |
|   int  upper) | |
| { | |
|     int         nvars; | |
|     int         size; | |
|     int         x,y; | |
|     int         result; | |
|     int		c1, c2, c3, c4; | |
|     int		BestCost; | |
|     int		*BestOrder; | |
|     double	NewTemp, temp; | |
|     double	rand1; | |
|     int         innerloop, maxGen; | |
|     int         ecount, ucount, dcount; | |
|     | |
|     nvars = upper - lower + 1; | |
| 
 | |
|     result = cuddSifting(table,lower,upper); | |
| #ifdef DD_STATS | |
|     (void) fprintf(table->out,"\n"); | |
| #endif | |
|     if (result == 0) return(0); | |
| 
 | |
|     size = table->keys - table->isolated; | |
| 
 | |
|     /* Keep track of the best order. */ | |
|     BestCost = size; | |
|     BestOrder = ALLOC(int,nvars); | |
|     if (BestOrder == NULL) { | |
| 	table->errorCode = CUDD_MEMORY_OUT; | |
| 	return(0); | |
|     } | |
|     copyOrder(table,BestOrder,lower,upper); | |
| 
 | |
|     temp = BETA * size; | |
|     maxGen = (int) (MAXGEN_RATIO * nvars); | |
| 
 | |
|     c1 = size + 10; | |
|     c2 = c1 + 10; | |
|     c3 = size; | |
|     c4 = c2 + 10; | |
|     ecount = ucount = dcount = 0; | |
|   | |
|     while (!stopping_criterion(c1, c2, c3, c4, temp)) { | |
| #ifdef DD_STATS | |
| 	(void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", | |
| 		       temp,size,maxGen); | |
| 	tosses = acceptances = 0; | |
| #endif | |
| 	for (innerloop = 0; innerloop < maxGen; innerloop++) { | |
| 	    /* Choose x, y  randomly. */ | |
| 	    x = (int) Cudd_Random() % nvars; | |
| 	    do { | |
| 		y = (int) Cudd_Random() % nvars; | |
| 	    } while (x == y); | |
| 	    x += lower; | |
| 	    y += lower; | |
| 	    if (x > y) { | |
| 		int tmp = x; | |
| 		x = y; | |
| 		y = tmp; | |
| 	    } | |
| 
 | |
| 	    /* Choose move with roulette wheel. */ | |
| 	    rand1 = random_generator(); | |
| 	    if (rand1 < EXC_PROB) { | |
| 		result = ddExchange(table,x,y,temp);       /* exchange */ | |
| 		ecount++; | |
| #if 0 | |
| 		(void) fprintf(table->out, | |
| 			       "Exchange of %d and %d: size = %d\n", | |
| 			       x,y,table->keys - table->isolated); | |
| #endif | |
| 	    } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { | |
| 		result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ | |
| 		ucount++; | |
| #if 0 | |
| 		(void) fprintf(table->out, | |
| 			       "Jump up of %d to %d: size = %d\n", | |
| 			       y,x,table->keys - table->isolated); | |
| #endif | |
| 	    } else { | |
| 		result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ | |
| 		dcount++; | |
| #if 0 | |
| 		(void) fprintf(table->out, | |
| 			       "Jump down of %d to %d: size = %d\n", | |
| 			       x,y,table->keys - table->isolated); | |
| #endif | |
| 	    } | |
| 
 | |
| 	    if (!result) { | |
| 		FREE(BestOrder); | |
| 		return(0); | |
| 	    } | |
| 
 | |
| 	    size = table->keys - table->isolated;	/* keep current size */ | |
| 	    if (size < BestCost) {			/* update best order */ | |
| 		BestCost = size; | |
| 		copyOrder(table,BestOrder,lower,upper); | |
| 	    } | |
| 	} | |
| 	c1 = c2; | |
| 	c2 = c3; | |
| 	c3 = c4; | |
| 	c4 = size; | |
| 	NewTemp = ALPHA * temp; | |
| 	if (NewTemp >= 1.0) { | |
| 	    maxGen = (int)(log(NewTemp) / log(temp) * maxGen); | |
| 	} | |
| 	temp = NewTemp;	                /* control variable */ | |
| #ifdef DD_STATS | |
| 	(void) fprintf(table->out,"uphill = %d\taccepted = %d\n", | |
| 		       tosses,acceptances); | |
| 	fflush(table->out); | |
| #endif | |
|     } | |
| 
 | |
|     result = restoreOrder(table,BestOrder,lower,upper); | |
|     FREE(BestOrder); | |
|     if (!result) return(0); | |
| #ifdef DD_STATS | |
|     fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); | |
|     fprintf(table->out,"#:N_JUMPUP   %8d : total jumps up\n",ucount); | |
|     fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); | |
| #endif | |
|     return(1); | |
| 
 | |
| } /* end of cuddAnnealing */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of static functions                                            */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Checks termination condition.] | |
|  | |
|   Description [If temperature is STOP_TEMP or there is no improvement | |
|   then terminates. Returns 1 if the termination criterion is met; 0 | |
|   otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| stopping_criterion( | |
|   int  c1, | |
|   int  c2, | |
|   int  c3, | |
|   int  c4, | |
|   double  temp) | |
| { | |
|     if (STOP_TEMP < temp) { | |
| 	return(0); | |
|     } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { | |
| 	return(1); | |
|     } else { | |
| 	return(0); | |
|     } | |
| 
 | |
| } /* end of stopping_criterion */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Random number generator.] | |
|  | |
|   Description [Returns a double precision value between 0.0 and 1.0.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static double | |
| random_generator(void) | |
| { | |
|     return((double)(Cudd_Random() / 2147483561.0)); | |
| 
 | |
| } /* end of random_generator */ | |
| 
 | |
| 
 | |
| /**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 */ | |
| 
 | |
| 
 | |
| /**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; | |
| 	cuddDeallocMove(table, moves); | |
| 	moves = move; | |
|     } | |
|     return(1); | |
| 
 | |
| ddJumpingAuxOutOfMem: | |
|     while (moves != NULL) { | |
| 	move = moves->next; | |
| 	cuddDeallocMove(table, moves); | |
| 	moves = move; | |
|     } | |
|     return(0); | |
| 
 | |
| } /* end of ddJumpingAux */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [This function is for jumping up.] | |
|  | |
|   Description [This is a simplified version of ddSiftingUp. 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 * | |
| ddJumpingUp( | |
|   DdManager * table, | |
|   int  x, | |
|   int  x_low, | |
|   int  initial_size) | |
| { | |
|     Move       *moves; | |
|     Move       *move; | |
|     int        y; | |
|     int        size; | |
|     int        limit_size = initial_size; | |
| 
 | |
|     moves = NULL; | |
|     y = cuddNextLow(table,x); | |
|     while (y >= x_low) { | |
| 	size = cuddSwapInPlace(table,y,x); | |
| 	if (size == 0) goto ddJumpingUpOutOfMem; | |
| 	move = (Move *)cuddDynamicAllocNode(table); | |
| 	if (move == NULL) goto ddJumpingUpOutOfMem; | |
| 	move->x = y; | |
| 	move->y = x; | |
| 	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 = cuddNextLow(table,x); | |
|     } | |
|     return(moves); | |
| 
 | |
| ddJumpingUpOutOfMem: | |
|     while (moves != NULL) { | |
| 	move = moves->next; | |
| 	cuddDeallocMove(table, moves); | |
| 	moves = move; | |
|     } | |
|     return(NULL); | |
| 
 | |
| } /* end of ddJumpingUp */ | |
| 
 | |
| 
 | |
| /**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 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Returns the DD to the best position encountered during | |
|   sifting if there was improvement.] | |
|  | |
|   Description [Otherwise, "tosses a coin" to decide whether to keep | |
|   the current configuration or return the DD to the original | |
|   one. Returns 1 in case of success; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| siftBackwardProb( | |
|   DdManager * table, | |
|   Move * moves, | |
|   int  size, | |
|   double  temp) | |
| { | |
|     Move   *move; | |
|     int    res; | |
|     int    best_size = size; | |
|     double coin, threshold; | |
| 
 | |
|     /* Look for best size during the last sifting */ | |
|     for (move = moves; move != NULL; move = move->next) { | |
| 	if (move->size < best_size) { | |
| 	    best_size = move->size; | |
| 	} | |
|     } | |
|      | |
|     /* If best_size equals size, the last sifting did not produce any | |
|     ** improvement. We now toss a coin to decide whether to retain | |
|     ** this change or not. | |
|     */ | |
|     if (best_size == size) { | |
| 	coin = random_generator(); | |
| #ifdef DD_STATS | |
| 	tosses++; | |
| #endif | |
| 	threshold = exp(-((double)(table->keys - table->isolated - size))/temp); | |
| 	if (coin < threshold) { | |
| #ifdef DD_STATS | |
| 	    acceptances++; | |
| #endif | |
| 	    return(1); | |
| 	} | |
|     } | |
| 
 | |
|     /* Either there was improvement, or we have decided not to | |
|     ** accept the uphill move. Go to best position. | |
|     */ | |
|     res = table->keys - table->isolated; | |
|     for (move = moves; move != NULL; move = move->next) { | |
| 	if (res == best_size) return(1); | |
| 	res = cuddSwapInPlace(table,(int)move->x,(int)move->y); | |
| 	if (!res) return(0); | |
|     } | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of sift_backward_prob */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Copies the current variable order to array.] | |
|  | |
|   Description [Copies the current variable order to array. | |
|   At the same time inverts the permutation.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static void | |
| copyOrder( | |
|   DdManager * table, | |
|   int * array, | |
|   int  lower, | |
|   int  upper) | |
| { | |
|     int i; | |
|     int nvars; | |
| 
 | |
|     nvars = upper - lower + 1; | |
|     for (i = 0; i < nvars; i++) { | |
| 	array[i] = table->invperm[i+lower]; | |
|     } | |
| 
 | |
| } /* end of copyOrder */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Restores the variable order in array by a series of sifts up.] | |
|  | |
|   Description [Restores the variable order in array by a series of sifts up. | |
|   Returns 1 in case of success; 0 otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| static int | |
| restoreOrder( | |
|   DdManager * table, | |
|   int * array, | |
|   int  lower, | |
|   int  upper) | |
| { | |
|     int i, x, y, size; | |
|     int nvars = upper - lower + 1; | |
| 
 | |
|     for (i = 0; i < nvars; i++) { | |
| 	x = table->perm[array[i]]; | |
| #ifdef DD_DEBUG | |
|     assert(x >= lower && x <= upper); | |
| #endif | |
| 	y = cuddNextLow(table,x); | |
| 	while (y >= i + lower) { | |
| 	    size = cuddSwapInPlace(table,y,x); | |
| 	    if (size == 0) return(0); | |
| 	    x = y; | |
| 	    y = cuddNextLow(table,x); | |
| 	} | |
|     } | |
| 
 | |
|     return(1); | |
| 
 | |
| } /* end of restoreOrder */ | |
| 
 |