Example #1
0
/**Function********************************************************************

  Synopsis [Builds a DD from a given order.]

  Description [Builds a DD from a given order.  This procedure also
  sifts the final order and inserts into the array the size in nodes
  of the result. Returns 1 if successful; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static int
build_dd(
  DdManager * table,
  int  num /* the index of the individual to be built */,
  int  lower,
  int  upper)
{
    int 	i,j;		/* loop vars */
    int 	position;
    int		index;
    int		limit;		/* how large the DD for this order can grow */
    int		size;

    /* Check the computed table. If the order already exists, it
    ** suffices to copy the size from the existing entry.
    */
    if (computed && st_lookup_int(computed,(char *)&STOREDD(num,0),&index)) {
	STOREDD(num,numvars) = STOREDD(index,numvars);
#ifdef DD_STATS
	(void) fprintf(table->out,"\nCache hit for index %d", index);
#endif
	return(1);
    }

    /* Stop if the DD grows 20 times larges than the reference size. */
    limit = 20 * STOREDD(0,numvars);

    /* Sift up the variables so as to build the desired permutation.
    ** First the variable that has to be on top is sifted to the top.
    ** Then the variable that has to occupy the secon position is sifted
    ** up to the second position, and so on.
    */
    for (j = 0; j < numvars; j++) {
	i = STOREDD(num,j);
	position = table->perm[i];
	result = sift_up(table,position,j+lower);
	if (!result) return(0);
	size = table->keys - table->isolated;
	if (size > limit) break;
    }

    /* Sift the DD just built. */
#ifdef DD_STATS
    (void) fprintf(table->out,"\n");
#endif
    result = cuddSifting(table,lower,upper);
    if (!result) return(0);

    /* Copy order and size to table. */
    for (j = 0; j < numvars; j++) {
	STOREDD(num,j) = table->invperm[lower+j];
    }
    STOREDD(num,numvars) = table->keys - table->isolated; /* size of new DD */
    return(1);

} /* end of build_dd */
Example #2
0
/**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 */
Example #3
0
/**Function********************************************************************

  Synopsis    [Genetic algorithm for DD reordering.]

  Description [Genetic algorithm for DD reordering.
  The two children of a crossover will be stored in
  storedd[popsize] and storedd[popsize+1] --- the last two slots in the
  storedd array.  (This will make comparisons and replacement easy.)
  Returns 1 in case of success; 0 otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
int
cuddGa(
  DdManager * table /* manager */,
  int  lower /* lowest level to be reordered */,
  int  upper /* highest level to be reorderded */)
{
    int 	i,n,m;		/* dummy/loop vars */
    int		index;
#ifdef DD_STATS
    double	average_fitness;
#endif
    int		small;		/* index of smallest DD in population */

    /* Do an initial sifting to produce at least one reasonable individual. */
    if (!cuddSifting(table,lower,upper)) return(0);

    /* Get the initial values. */
    numvars = upper - lower + 1; /* number of variables to be reordered */
    if (table->populationSize == 0) {
	popsize = 3 * numvars;  /* population size is 3 times # of vars */
	if (popsize > 120) {
	    popsize = 120;	/* Maximum population size is 120 */
	}
    } else {
	popsize = table->populationSize;  /* user specified value */
    }
    if (popsize < 4) popsize = 4;	/* enforce minimum population size */

    /* Allocate population table. */
    storedd = ALLOC(int,(popsize+2)*(numvars+1));
    if (storedd == NULL) {
	table->errorCode = CUDD_MEMORY_OUT;
	return(0);
    }

    /* Initialize the computed table. This table is made up of two data
    ** structures: A hash table with the key given by the order, which says
    ** if a given order is present in the population; and the repeat
    ** vector, which says how many copies of a given order are stored in
    ** the population table. If there are multiple copies of an order, only
    ** one has a repeat count greater than 1. This copy is the one pointed
    ** by the computed table.
    */
    repeat = ALLOC(int,popsize);
    if (repeat == NULL) {
	table->errorCode = CUDD_MEMORY_OUT;
	FREE(storedd);
	return(0);
    }
    for (i = 0; i < popsize; i++) {
	repeat[i] = 0;
    }
    computed = st_init_table(array_compare,array_hash);
    if (computed == NULL) {
	table->errorCode = CUDD_MEMORY_OUT;
	FREE(storedd);
	FREE(repeat);
	return(0);
    }

    /* Copy the current DD and its size to the population table. */
    for (i = 0; i < numvars; i++) {
	STOREDD(0,i) = table->invperm[i+lower]; /* order of initial DD */
    }
    STOREDD(0,numvars) = table->keys - table->isolated; /* size of initial DD */

    /* Store the initial order in the computed table. */
    if (st_insert(computed,(char *)storedd,(char *) 0) == ST_OUT_OF_MEM) {
	FREE(storedd);
	FREE(repeat);
	st_free_table(computed);
	return(0);
    }
    repeat[0]++;

    /* Insert the reverse order as second element of the population. */
    for (i = 0; i < numvars; i++) {
	STOREDD(1,numvars-1-i) = table->invperm[i+lower]; /* reverse order */
    }

    /* Now create the random orders. make_random fills the population
    ** table with random permutations. The successive loop builds and sifts
    ** the DDs for the reverse order and each random permutation, and stores
    ** the results in the computed table.
    */
    if (!make_random(table,lower)) {
	table->errorCode = CUDD_MEMORY_OUT;
	FREE(storedd);
	FREE(repeat);
	st_free_table(computed);
	return(0);
    }
    for (i = 1; i < popsize; i++) {
	result = build_dd(table,i,lower,upper);	/* build and sift order */
	if (!result) {
	    FREE(storedd);
	    FREE(repeat);
	    st_free_table(computed);
	    return(0);
	}
	if (st_lookup_int(computed,(char *)&STOREDD(i,0),&index)) {
	    repeat[index]++;
	} else {
	    if (st_insert(computed,(char *)&STOREDD(i,0),(char *)(long)i) ==
	    ST_OUT_OF_MEM) {
		FREE(storedd);
		FREE(repeat);
		st_free_table(computed);
		return(0);
	    }
	    repeat[i]++;
	}
    }

#if 0
#ifdef DD_STATS
    /* Print the initial population. */
    (void) fprintf(table->out,"Initial population after sifting\n");
    for (m = 0; m < popsize; m++) {
	for (i = 0; i < numvars; i++) {
	    (void) fprintf(table->out," %2d",STOREDD(m,i));
	}
	(void) fprintf(table->out," : %3d (%d)\n",
		       STOREDD(m,numvars),repeat[m]);
    }
#endif
#endif

    small = find_best();
#ifdef DD_STATS
    average_fitness = find_average_fitness();
    (void) fprintf(table->out,"\nInitial population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
#endif

    /* Decide how many crossovers should be tried. */
    if (table->numberXovers == 0) {
	cross = 3*numvars;
	if (cross > 60) {	/* do a maximum of 50 crossovers */
	    cross = 60;
	}
    } else {
	cross = table->numberXovers;      /* use user specified value */
    }

    /* Perform the crossovers to get the best order. */
    for (m = 0; m < cross; m++) {
	if (!PMX(table->size)) {	/* perform one crossover */
	    table->errorCode = CUDD_MEMORY_OUT;
	    FREE(storedd);
	    FREE(repeat);
	    st_free_table(computed);
	    return(0);
	}
	/* The offsprings are left in the last two entries of the
	** population table. These are now considered in turn.
	*/
	for (i = popsize; i <= popsize+1; i++) {
	    result = build_dd(table,i,lower,upper); /* build and sift child */
	    if (!result) {
		FREE(storedd);
		FREE(repeat);
		st_free_table(computed);
		return(0);
	    }
	    large = largest();	/* find the largest DD in population */

	    /* If the new child is smaller than the largest DD in the current
	    ** population, enter it into the population in place of the
	    ** largest DD.
	    */
	    if (STOREDD(i,numvars) < STOREDD(large,numvars)) {
		/* Look up the largest DD in the computed table.
		** Decrease its repetition count. If the repetition count
		** goes to 0, remove the largest DD from the computed table.
		*/
		result = st_lookup_int(computed,(char *)&STOREDD(large,0),
				       &index);
		if (!result) {
		    FREE(storedd);
		    FREE(repeat);
		    st_free_table(computed);
		    return(0);
		}
		repeat[index]--;
		if (repeat[index] == 0) {
		    int *pointer = &STOREDD(index,0);
		    result = st_delete(computed, (char **)&pointer,NULL);
		    if (!result) {
			FREE(storedd);
			FREE(repeat);
			st_free_table(computed);
			return(0);
		    }
		}
		/* Copy the new individual to the entry of the
		** population table just made available and update the
		** computed table.
		*/
		for (n = 0; n <= numvars; n++) {
		    STOREDD(large,n) = STOREDD(i,n);
		}
		if (st_lookup_int(computed,(char *)&STOREDD(large,0),
				  &index)) {
		    repeat[index]++;
		} else {
		    if (st_insert(computed,(char *)&STOREDD(large,0),
		    (char *)(long)large) == ST_OUT_OF_MEM) {
			FREE(storedd);
			FREE(repeat);
			st_free_table(computed);
			return(0);
		    }
		    repeat[large]++;
		}
	    }
	}
    }

    /* Find the smallest DD in the population and build it;
    ** that will be the result.
    */
    small = find_best();

    /* Print stats on the final population. */
#ifdef DD_STATS
    average_fitness = find_average_fitness();
    (void) fprintf(table->out,"\nFinal population: best fitness = %d, average fitness %8.3f",STOREDD(small,numvars),average_fitness);
#endif

    /* Clean up, build the result DD, and return. */
    st_free_table(computed);
    computed = NULL;
    result = build_dd(table,small,lower,upper);
    FREE(storedd);
    FREE(repeat);
    return(result);

} /* end of cuddGa */