src/cuBdd/cuddAnneal.c File Reference

#include "util.h"
#include "cuddInt.h"
Include dependency graph for cuddAnneal.c:

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 MoveddJumpingUp (DdManager *table, int x, int x_low, int initial_size)
static MoveddJumpingDown (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 Documentation

#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.


Function Documentation

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 */

static Move * ddJumpingDown ( DdManager table,
int  x,
int  x_high,
int  initial_size 
) [static]

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 */

static Move * ddJumpingUp ( DdManager table,
int  x,
int  x_low,
int  initial_size 
) [static]

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 */

static int siftBackwardProb ( DdManager table,
Move moves,
int  size,
double  temp 
) [static]

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 */


Variable Documentation

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.


Generated on Tue Jan 12 13:57:17 2010 for glu-2.2 by  doxygen 1.6.1