#include "util.h"
#include "cuddInt.h"
Go to the source code of this file.
Defines | |
#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 |
Functions | |
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) |
int | cuddAnnealing (DdManager *table, int lower, int upper) |
Variables | |
static char rcsid[] | DD_UNUSED = "$Id: cuddAnneal.c,v 1.14 2004/08/13 18:04:46 fabio Exp $" |
#define ALPHA 0.90 |
Definition at line 74 of file cuddAnneal.c.
#define BETA 0.6 |
CFile***********************************************************************
FileName [cuddAnneal.c]
PackageName [cudd]
Synopsis [Reordering of DDs based on simulated annealing]
Description [Internal procedures included in this file:
Static procedures included in this file:
]
SeeAlso []
Author [Jae-Young Jang, Jorgen Sivesind]
Copyright [Copyright (c) 1995-2004, 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.]
Definition at line 73 of file cuddAnneal.c.
#define EXC_PROB 0.4 |
Definition at line 75 of file cuddAnneal.c.
#define JUMP_UP_PROB 0.36 |
Definition at line 76 of file cuddAnneal.c.
#define MAXGEN_RATIO 15.0 |
Definition at line 77 of file cuddAnneal.c.
#define STOP_TEMP 1.0 |
Definition at line 78 of file cuddAnneal.c.
static void copyOrder | ( | DdManager * | table, | |
int * | array, | |||
int | lower, | |||
int | upper | |||
) | [static] |
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 []
Definition at line 758 of file cuddAnneal.c.
00763 { 00764 int i; 00765 int nvars; 00766 00767 nvars = upper - lower + 1; 00768 for (i = 0; i < nvars; i++) { 00769 array[i] = table->invperm[i+lower]; 00770 } 00771 00772 } /* end of copyOrder */
int cuddAnnealing | ( | DdManager * | table, | |
int | lower, | |||
int | upper | |||
) |
AutomaticEnd 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 []
Definition at line 154 of file cuddAnneal.c.
00158 { 00159 int nvars; 00160 int size; 00161 int x,y; 00162 int result; 00163 int c1, c2, c3, c4; 00164 int BestCost; 00165 int *BestOrder; 00166 double NewTemp, temp; 00167 double rand1; 00168 int innerloop, maxGen; 00169 int ecount, ucount, dcount; 00170 00171 nvars = upper - lower + 1; 00172 00173 result = cuddSifting(table,lower,upper); 00174 #ifdef DD_STATS 00175 (void) fprintf(table->out,"\n"); 00176 #endif 00177 if (result == 0) return(0); 00178 00179 size = table->keys - table->isolated; 00180 00181 /* Keep track of the best order. */ 00182 BestCost = size; 00183 BestOrder = ALLOC(int,nvars); 00184 if (BestOrder == NULL) { 00185 table->errorCode = CUDD_MEMORY_OUT; 00186 return(0); 00187 } 00188 copyOrder(table,BestOrder,lower,upper); 00189 00190 temp = BETA * size; 00191 maxGen = (int) (MAXGEN_RATIO * nvars); 00192 00193 c1 = size + 10; 00194 c2 = c1 + 10; 00195 c3 = size; 00196 c4 = c2 + 10; 00197 ecount = ucount = dcount = 0; 00198 00199 while (!stopping_criterion(c1, c2, c3, c4, temp)) { 00200 #ifdef DD_STATS 00201 (void) fprintf(table->out,"temp=%f\tsize=%d\tgen=%d\t", 00202 temp,size,maxGen); 00203 tosses = acceptances = 0; 00204 #endif 00205 for (innerloop = 0; innerloop < maxGen; innerloop++) { 00206 /* Choose x, y randomly. */ 00207 x = (int) Cudd_Random() % nvars; 00208 do { 00209 y = (int) Cudd_Random() % nvars; 00210 } while (x == y); 00211 x += lower; 00212 y += lower; 00213 if (x > y) { 00214 int tmp = x; 00215 x = y; 00216 y = tmp; 00217 } 00218 00219 /* Choose move with roulette wheel. */ 00220 rand1 = random_generator(); 00221 if (rand1 < EXC_PROB) { 00222 result = ddExchange(table,x,y,temp); /* exchange */ 00223 ecount++; 00224 #if 0 00225 (void) fprintf(table->out, 00226 "Exchange of %d and %d: size = %d\n", 00227 x,y,table->keys - table->isolated); 00228 #endif 00229 } else if (rand1 < EXC_PROB + JUMP_UP_PROB) { 00230 result = ddJumpingAux(table,y,x,y,temp); /* jumping_up */ 00231 ucount++; 00232 #if 0 00233 (void) fprintf(table->out, 00234 "Jump up of %d to %d: size = %d\n", 00235 y,x,table->keys - table->isolated); 00236 #endif 00237 } else { 00238 result = ddJumpingAux(table,x,x,y,temp); /* jumping_down */ 00239 dcount++; 00240 #if 0 00241 (void) fprintf(table->out, 00242 "Jump down of %d to %d: size = %d\n", 00243 x,y,table->keys - table->isolated); 00244 #endif 00245 } 00246 00247 if (!result) { 00248 FREE(BestOrder); 00249 return(0); 00250 } 00251 00252 size = table->keys - table->isolated; /* keep current size */ 00253 if (size < BestCost) { /* update best order */ 00254 BestCost = size; 00255 copyOrder(table,BestOrder,lower,upper); 00256 } 00257 } 00258 c1 = c2; 00259 c2 = c3; 00260 c3 = c4; 00261 c4 = size; 00262 NewTemp = ALPHA * temp; 00263 if (NewTemp >= 1.0) { 00264 maxGen = (int)(log(NewTemp) / log(temp) * maxGen); 00265 } 00266 temp = NewTemp; /* control variable */ 00267 #ifdef DD_STATS 00268 (void) fprintf(table->out,"uphill = %d\taccepted = %d\n", 00269 tosses,acceptances); 00270 fflush(table->out); 00271 #endif 00272 } 00273 00274 result = restoreOrder(table,BestOrder,lower,upper); 00275 FREE(BestOrder); 00276 if (!result) return(0); 00277 #ifdef DD_STATS 00278 fprintf(table->out,"#:N_EXCHANGE %8d : total exchanges\n",ecount); 00279 fprintf(table->out,"#:N_JUMPUP %8d : total jumps up\n",ucount); 00280 fprintf(table->out,"#:N_JUMPDOWN %8d : total jumps down",dcount); 00281 #endif 00282 return(1); 00283 00284 } /* end of cuddAnnealing */
static int ddExchange | ( | DdManager * | table, | |
int | x, | |||
int | y, | |||
double | temp | |||
) | [static] |
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 []
Definition at line 355 of file cuddAnneal.c.
00360 { 00361 Move *move,*moves; 00362 int tmp; 00363 int x_ref,y_ref; 00364 int x_next,y_next; 00365 int size, result; 00366 int initial_size, limit_size; 00367 00368 x_ref = x; 00369 y_ref = y; 00370 00371 x_next = cuddNextHigh(table,x); 00372 y_next = cuddNextLow(table,y); 00373 moves = NULL; 00374 initial_size = limit_size = table->keys - table->isolated; 00375 00376 for (;;) { 00377 if (x_next == y_next) { 00378 size = cuddSwapInPlace(table,x,x_next); 00379 if (size == 0) goto ddExchangeOutOfMem; 00380 move = (Move *)cuddDynamicAllocNode(table); 00381 if (move == NULL) goto ddExchangeOutOfMem; 00382 move->x = x; 00383 move->y = x_next; 00384 move->size = size; 00385 move->next = moves; 00386 moves = move; 00387 size = cuddSwapInPlace(table,y_next,y); 00388 if (size == 0) goto ddExchangeOutOfMem; 00389 move = (Move *)cuddDynamicAllocNode(table); 00390 if (move == NULL) goto ddExchangeOutOfMem; 00391 move->x = y_next; 00392 move->y = y; 00393 move->size = size; 00394 move->next = moves; 00395 moves = move; 00396 size = cuddSwapInPlace(table,x,x_next); 00397 if (size == 0) goto ddExchangeOutOfMem; 00398 move = (Move *)cuddDynamicAllocNode(table); 00399 if (move == NULL) goto ddExchangeOutOfMem; 00400 move->x = x; 00401 move->y = x_next; 00402 move->size = size; 00403 move->next = moves; 00404 moves = move; 00405 00406 tmp = x; 00407 x = y; 00408 y = tmp; 00409 } else if (x == y_next) { 00410 size = cuddSwapInPlace(table,x,x_next); 00411 if (size == 0) goto ddExchangeOutOfMem; 00412 move = (Move *)cuddDynamicAllocNode(table); 00413 if (move == NULL) goto ddExchangeOutOfMem; 00414 move->x = x; 00415 move->y = x_next; 00416 move->size = size; 00417 move->next = moves; 00418 moves = move; 00419 tmp = x; 00420 x = y; 00421 y = tmp; 00422 } else { 00423 size = cuddSwapInPlace(table,x,x_next); 00424 if (size == 0) goto ddExchangeOutOfMem; 00425 move = (Move *)cuddDynamicAllocNode(table); 00426 if (move == NULL) goto ddExchangeOutOfMem; 00427 move->x = x; 00428 move->y = x_next; 00429 move->size = size; 00430 move->next = moves; 00431 moves = move; 00432 size = cuddSwapInPlace(table,y_next,y); 00433 if (size == 0) goto ddExchangeOutOfMem; 00434 move = (Move *)cuddDynamicAllocNode(table); 00435 if (move == NULL) goto ddExchangeOutOfMem; 00436 move->x = y_next; 00437 move->y = y; 00438 move->size = size; 00439 move->next = moves; 00440 moves = move; 00441 x = x_next; 00442 y = y_next; 00443 } 00444 00445 x_next = cuddNextHigh(table,x); 00446 y_next = cuddNextLow(table,y); 00447 if (x_next > y_ref) break; 00448 00449 if ((double) size > DD_MAX_REORDER_GROWTH * (double) limit_size) { 00450 break; 00451 } else if (size < limit_size) { 00452 limit_size = size; 00453 } 00454 } 00455 00456 if (y_next>=x_ref) { 00457 size = cuddSwapInPlace(table,y_next,y); 00458 if (size == 0) goto ddExchangeOutOfMem; 00459 move = (Move *)cuddDynamicAllocNode(table); 00460 if (move == NULL) goto ddExchangeOutOfMem; 00461 move->x = y_next; 00462 move->y = y; 00463 move->size = size; 00464 move->next = moves; 00465 moves = move; 00466 } 00467 00468 /* move backward and stop at best position or accept uphill move */ 00469 result = siftBackwardProb(table,moves,initial_size,temp); 00470 if (!result) goto ddExchangeOutOfMem; 00471 00472 while (moves != NULL) { 00473 move = moves->next; 00474 cuddDeallocMove(table, moves); 00475 moves = move; 00476 } 00477 return(1); 00478 00479 ddExchangeOutOfMem: 00480 while (moves != NULL) { 00481 move = moves->next; 00482 cuddDeallocMove(table, moves); 00483 moves = move; 00484 } 00485 return(0); 00486 00487 } /* end of ddExchange */
static int ddJumpingAux | ( | DdManager * | table, | |
int | x, | |||
int | x_low, | |||
int | x_high, | |||
double | temp | |||
) | [static] |
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 []
Definition at line 504 of file cuddAnneal.c.
00510 { 00511 Move *move; 00512 Move *moves; /* list of moves */ 00513 int initial_size; 00514 int result; 00515 00516 initial_size = table->keys - table->isolated; 00517 00518 #ifdef DD_DEBUG 00519 assert(table->subtables[x].keys > 0); 00520 #endif 00521 00522 moves = NULL; 00523 00524 if (cuddNextLow(table,x) < x_low) { 00525 if (cuddNextHigh(table,x) > x_high) return(1); 00526 moves = ddJumpingDown(table,x,x_high,initial_size); 00527 /* after that point x --> x_high unless early termination */ 00528 if (moves == NULL) goto ddJumpingAuxOutOfMem; 00529 /* move backward and stop at best position or accept uphill move */ 00530 result = siftBackwardProb(table,moves,initial_size,temp); 00531 if (!result) goto ddJumpingAuxOutOfMem; 00532 } else if (cuddNextHigh(table,x) > x_high) { 00533 moves = ddJumpingUp(table,x,x_low,initial_size); 00534 /* after that point x --> x_low unless early termination */ 00535 if (moves == NULL) goto ddJumpingAuxOutOfMem; 00536 /* move backward and stop at best position or accept uphill move */ 00537 result = siftBackwardProb(table,moves,initial_size,temp); 00538 if (!result) goto ddJumpingAuxOutOfMem; 00539 } else { 00540 (void) fprintf(table->err,"Unexpected condition in ddJumping\n"); 00541 goto ddJumpingAuxOutOfMem; 00542 } 00543 while (moves != NULL) { 00544 move = moves->next; 00545 cuddDeallocMove(table, moves); 00546 moves = move; 00547 } 00548 return(1); 00549 00550 ddJumpingAuxOutOfMem: 00551 while (moves != NULL) { 00552 move = moves->next; 00553 cuddDeallocMove(table, moves); 00554 moves = move; 00555 } 00556 return(0); 00557 00558 } /* end of ddJumpingAux */
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 []
Definition at line 634 of file cuddAnneal.c.
00639 { 00640 Move *moves; 00641 Move *move; 00642 int y; 00643 int size; 00644 int limit_size = initial_size; 00645 00646 moves = NULL; 00647 y = cuddNextHigh(table,x); 00648 while (y <= x_high) { 00649 size = cuddSwapInPlace(table,x,y); 00650 if (size == 0) goto ddJumpingDownOutOfMem; 00651 move = (Move *)cuddDynamicAllocNode(table); 00652 if (move == NULL) goto ddJumpingDownOutOfMem; 00653 move->x = x; 00654 move->y = y; 00655 move->size = size; 00656 move->next = moves; 00657 moves = move; 00658 if ((double) size > table->maxGrowth * (double) limit_size) { 00659 break; 00660 } else if (size < limit_size) { 00661 limit_size = size; 00662 } 00663 x = y; 00664 y = cuddNextHigh(table,x); 00665 } 00666 return(moves); 00667 00668 ddJumpingDownOutOfMem: 00669 while (moves != NULL) { 00670 move = moves->next; 00671 cuddDeallocMove(table, moves); 00672 moves = move; 00673 } 00674 return(NULL); 00675 00676 } /* end of ddJumpingDown */
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 []
Definition at line 575 of file cuddAnneal.c.
00580 { 00581 Move *moves; 00582 Move *move; 00583 int y; 00584 int size; 00585 int limit_size = initial_size; 00586 00587 moves = NULL; 00588 y = cuddNextLow(table,x); 00589 while (y >= x_low) { 00590 size = cuddSwapInPlace(table,y,x); 00591 if (size == 0) goto ddJumpingUpOutOfMem; 00592 move = (Move *)cuddDynamicAllocNode(table); 00593 if (move == NULL) goto ddJumpingUpOutOfMem; 00594 move->x = y; 00595 move->y = x; 00596 move->size = size; 00597 move->next = moves; 00598 moves = move; 00599 if ((double) size > table->maxGrowth * (double) limit_size) { 00600 break; 00601 } else if (size < limit_size) { 00602 limit_size = size; 00603 } 00604 x = y; 00605 y = cuddNextLow(table,x); 00606 } 00607 return(moves); 00608 00609 ddJumpingUpOutOfMem: 00610 while (moves != NULL) { 00611 move = moves->next; 00612 cuddDeallocMove(table, moves); 00613 moves = move; 00614 } 00615 return(NULL); 00616 00617 } /* end of ddJumpingUp */
static double random_generator | ( | void | ) | [static] |
Function********************************************************************
Synopsis [Random number generator.]
Description [Returns a double precision value between 0.0 and 1.0.]
SideEffects [None]
SeeAlso []
Definition at line 335 of file cuddAnneal.c.
00336 { 00337 return((double)(Cudd_Random() / 2147483561.0)); 00338 00339 } /* end of random_generator */
static int restoreOrder | ( | DdManager * | table, | |
int * | array, | |||
int | lower, | |||
int | upper | |||
) | [static] |
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 []
Definition at line 788 of file cuddAnneal.c.
00793 { 00794 int i, x, y, size; 00795 int nvars = upper - lower + 1; 00796 00797 for (i = 0; i < nvars; i++) { 00798 x = table->perm[array[i]]; 00799 #ifdef DD_DEBUG 00800 assert(x >= lower && x <= upper); 00801 #endif 00802 y = cuddNextLow(table,x); 00803 while (y >= i + lower) { 00804 size = cuddSwapInPlace(table,y,x); 00805 if (size == 0) return(0); 00806 x = y; 00807 y = cuddNextLow(table,x); 00808 } 00809 } 00810 00811 return(1); 00812 00813 } /* end of restoreOrder */
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 []
Definition at line 694 of file cuddAnneal.c.
00699 { 00700 Move *move; 00701 int res; 00702 int best_size = size; 00703 double coin, threshold; 00704 00705 /* Look for best size during the last sifting */ 00706 for (move = moves; move != NULL; move = move->next) { 00707 if (move->size < best_size) { 00708 best_size = move->size; 00709 } 00710 } 00711 00712 /* If best_size equals size, the last sifting did not produce any 00713 ** improvement. We now toss a coin to decide whether to retain 00714 ** this change or not. 00715 */ 00716 if (best_size == size) { 00717 coin = random_generator(); 00718 #ifdef DD_STATS 00719 tosses++; 00720 #endif 00721 threshold = exp(-((double)(table->keys - table->isolated - size))/temp); 00722 if (coin < threshold) { 00723 #ifdef DD_STATS 00724 acceptances++; 00725 #endif 00726 return(1); 00727 } 00728 } 00729 00730 /* Either there was improvement, or we have decided not to 00731 ** accept the uphill move. Go to best position. 00732 */ 00733 res = table->keys - table->isolated; 00734 for (move = moves; move != NULL; move = move->next) { 00735 if (res == best_size) return(1); 00736 res = cuddSwapInPlace(table,(int)move->x,(int)move->y); 00737 if (!res) return(0); 00738 } 00739 00740 return(1); 00741 00742 } /* end of sift_backward_prob */
static int stopping_criterion | ( | int | c1, | |
int | c2, | |||
int | c3, | |||
int | c4, | |||
double | temp | |||
) | [static] |
AutomaticStart
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 []
Definition at line 305 of file cuddAnneal.c.
00311 { 00312 if (STOP_TEMP < temp) { 00313 return(0); 00314 } else if ((c1 == c2) && (c1 == c3) && (c1 == c4)) { 00315 return(1); 00316 } else { 00317 return(0); 00318 } 00319 00320 } /* end of stopping_criterion */
char rcsid [] DD_UNUSED = "$Id: cuddAnneal.c,v 1.14 2004/08/13 18:04:46 fabio Exp $" [static] |
Definition at line 95 of file cuddAnneal.c.