/**Function******************************************************************** Synopsis [Selects two parents with the roulette wheel method.] Description [Selects two distinct parents with the roulette wheel method.] SideEffects [The indices of the selected parents are returned as side effects.] SeeAlso [] ******************************************************************************/ static int roulette( int * p1, int * p2) { double *wheel; double spin; int i; wheel = ALLOC(double,popsize); if (wheel == NULL) { return(0); } /* The fitness of an individual is the reciprocal of its size. */ wheel[0] = 1.0 / (double) STOREDD(0,numvars); for (i = 1; i < popsize; i++) { wheel[i] = wheel[i-1] + 1.0 / (double) STOREDD(i,numvars); } /* Get a random number between 0 and wheel[popsize-1] (that is, ** the sum of all fitness values. 2147483561 is the largest number ** returned by Cudd_Random. */ spin = wheel[numvars-1] * (double) Cudd_Random() / 2147483561.0; /* Find the lucky element by scanning the wheel. */ for (i = 0; i < popsize; i++) { if (spin <= wheel[i]) break; } *p1 = i; /* Repeat the process for the second parent, making sure it is ** distinct from the first. */ do { spin = wheel[popsize-1] * (double) Cudd_Random() / 2147483561.0; for (i = 0; i < popsize; i++) { if (spin <= wheel[i]) break; } } while (i == *p1); *p2 = i; FREE(wheel); return(1); } /* end of roulette */
/**Function******************************************************************** Synopsis [Random number generator.] Description [Returns a double precision value between 0.0 and 1.0.] SideEffects [None] SeeAlso [] ******************************************************************************/ static double random_generator( ) { return((double)(Cudd_Random() / 2147483561.0)); } /* end of random_generator */
/**Function******************************************************************** Synopsis [Generates a random number between 0 and the integer a.] Description [] SideEffects [None] SeeAlso [] ******************************************************************************/ static int rand_int( int a) { return(Cudd_Random() % (a+1)); } /* end of rand_int */
/**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 */
/**Function******************************************************************** Synopsis [Reorders variables by a sequence of (non-adjacent) swaps.] Description [Implementation of Plessier's algorithm that reorders variables by a sequence of (non-adjacent) swaps. <ol> <li> Select two variables (RANDOM or HEURISTIC). <li> Permute these variables. <li> If the nodes have decreased accept the permutation. <li> Otherwise reconstruct the original heap. <li> Loop. </ol> Returns 1 in case of success; 0 otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ int cuddZddSwapping( DdManager * table, int lower, int upper, Cudd_ReorderingType heuristic) { int i, j; int max, keys; int nvars; int x, y; int iterate; int previousSize; Move *moves, *move; int pivot; int modulo; int result; #ifdef DD_DEBUG /* Sanity check */ assert(lower >= 0 && upper < table->sizeZ && lower <= upper); #endif nvars = upper - lower + 1; iterate = nvars; for (i = 0; i < iterate; i++) { if (heuristic == CUDD_REORDER_RANDOM_PIVOT) { /* Find pivot <= id with maximum keys. */ for (max = -1, j = lower; j <= upper; j++) { if ((keys = table->subtableZ[j].keys) > max) { max = keys; pivot = j; } } modulo = upper - pivot; if (modulo == 0) { y = pivot; /* y = nvars-1 */ } else { /* y = random # from {pivot+1 .. nvars-1} */ y = pivot + 1 + (int) (Cudd_Random() % modulo); } modulo = pivot - lower - 1; if (modulo < 1) { /* if pivot = 1 or 0 */ x = lower; } else { do { /* x = random # from {0 .. pivot-2} */ x = (int) Cudd_Random() % modulo; } while (x == y); /* Is this condition really needed, since x and y are in regions separated by pivot? */ } } else { x = (int) (Cudd_Random() % nvars) + lower; do { y = (int) (Cudd_Random() % nvars) + lower; } while (x == y); } previousSize = table->keysZ; moves = zddSwapAny(table, x, y); if (moves == NULL) goto cuddZddSwappingOutOfMem; result = cuddZddSiftingBackward(table, moves, previousSize); if (!result) goto cuddZddSwappingOutOfMem; while (moves != NULL) { move = moves->next; cuddDeallocNode(table, (DdNode *) moves); moves = move; } #ifdef DD_STATS if (table->keysZ < (unsigned) previousSize) { (void) fprintf(table->out,"-"); } else if (table->keysZ > (unsigned) previousSize) { (void) fprintf(table->out,"+"); /* should never happen */ } else { (void) fprintf(table->out,"="); } fflush(table->out); #endif } return(1); cuddZddSwappingOutOfMem: while (moves != NULL) { move = moves->next; cuddDeallocNode(table, (DdNode *) moves); moves = move; } return(0); } /* end of cuddZddSwapping */